PageRenderTime 44ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/hphp/hack/src/h2tp/resources/containers/helper_traits/hacklib_vectorLike.php

http://github.com/facebook/hiphop-php
PHP | 221 lines | 142 code | 17 blank | 62 comment | 22 complexity | b146f90432d6f9b904ffb771c717ad58 MD5 | raw file
Possible License(s): LGPL-2.1, BSD-2-Clause, BSD-3-Clause, MPL-2.0-no-copyleft-exception, MIT, LGPL-2.0, Apache-2.0
  1. <?php
  2. /**
  3. * Copyright (c) 2014, Facebook, Inc.
  4. * All rights reserved.
  5. *
  6. * This source code is licensed under the BSD-style license found in the
  7. * LICENSE file in the "hack" directory of this source tree. An additional grant
  8. * of patent rights can be found in the PATENTS file in the same directory.
  9. *
  10. */
  11. namespace HH {
  12. require_once(__DIR__.SEP.'..'.SEP.'hacklib_iterator.php');
  13. require_once(__DIR__.SEP.'hacklib_constVectorLike.php');
  14. require_once(__DIR__.SEP.'hacklib_commonMutableContainerMethods.php');
  15. /**
  16. * Trait that implements all mutating methods of Vectors.
  17. */
  18. trait HACKLIB_VectorLike {
  19. use HACKLIB_ConstVectorLike;
  20. use HACKLIB_CommonMutableContainerMethods;
  21. /**
  22. * identical to at, implemented for ArrayAccess
  23. */
  24. public function &offsetGet($offset) {
  25. $this->hacklib_validateKeyType($offset);
  26. $this->hacklib_validateKeyBounds($offset);
  27. return $this->container[$offset];
  28. }
  29. public function offsetSet($offset, $value) {
  30. if (is_null($offset)) {
  31. $this->add($value);
  32. } else {
  33. $this->set($offset, $value);
  34. }
  35. }
  36. public function offsetUnset($offset) {
  37. throw new \RuntimeException(
  38. 'Cannot unset an element of a '.get_class($this));
  39. }
  40. /**
  41. * Stores a value into the Vector with the specified key, overwriting the
  42. * previous value associated with the key. If the key is not present,
  43. * an exception is thrown. "$vec->set($k,$v)" is semantically equivalent
  44. * to "$vec[$k] = $v" (except that set() returns the Vector).
  45. */
  46. public function set($k, $v) {
  47. $this->hacklib_validateKeyType($k);
  48. $this->hacklib_validateKeyBounds($k);
  49. $this->container[$k] = $v;
  50. return $this;
  51. }
  52. public function setAll($it) {
  53. if (is_array($it) || $it instanceof \Traversable) {
  54. foreach ($it as $k => $v) {
  55. $this->set($k, $v);
  56. }
  57. return $this;
  58. } elseif (is_null($it)) {
  59. return $this;
  60. }
  61. throw new \InvalidArgumentException(\sprintf(
  62. 'Parameter must be an array or an instance of Traversable, got %s',
  63. is_object($it) ? get_class($it) : gettype($it),
  64. ));
  65. }
  66. /**
  67. * Append a copy of a value to the end of the Vector, assigning the next
  68. * available integer key. "$vec->add($v)" is semantically equivalent to
  69. * "$vec[] = $v" (except that add() returns the Vector).
  70. */
  71. public function add($value) {
  72. $this->hacklib_expireAllIterators();
  73. $this->container[]= $value;
  74. return $this;
  75. }
  76. /**
  77. * Adds the keys of the specified container to this Vector and returns
  78. * the Vector.
  79. */
  80. public function addAllKeysOf($it) {
  81. if (is_array($it) || $it instanceof \Traversable) {
  82. foreach ($it as $k => $v) {
  83. $this->add($k);
  84. }
  85. return $this;
  86. } elseif (is_null($it)) {
  87. return $this;
  88. }
  89. throw new \InvalidArgumentException(\sprintf(
  90. 'Parameter must be a container (array or collection), got %s',
  91. is_object($it) ? get_class($it) : gettype($it),
  92. ));
  93. }
  94. /**
  95. * Removes the specified key from this Vector. This will cause elements
  96. * with higher keys to be renumbered.
  97. */
  98. public function removeKey($k) {
  99. if ($k >= 0 && $k < count($this->container)) {
  100. array_splice($this->container, $k, 1);
  101. $this->hacklib_expireAllIterators();
  102. }
  103. return $this;
  104. }
  105. /**
  106. * Remove the last element of this Vector and return it. This function
  107. * throws an exception if this Vector is empty.
  108. */
  109. public function pop() {
  110. if (!$this->container) {
  111. throw new \InvalidOperationException('Cannot pop empty '.get_class($this));
  112. }
  113. $this->hacklib_expireAllIterators();
  114. return array_pop($this->container);
  115. }
  116. /**
  117. * Resize this Vector to contain 'sz' elements. If 'sz' is smaller than
  118. * the current size of this Vector, elements are removed from the end of
  119. * this Vector. If 'sz' is greater than the current size of this Vector,
  120. * this Vector is extended by appending as many copies of 'value' as
  121. * needed to reach a size of 'sz' elements.
  122. */
  123. public function resize($sz, $value) {
  124. if ($sz > self::MAX_SIZE) {
  125. throw new \InvalidArgumentException(
  126. "Parameter sz must be at most ".self::MAX_SIZE."; $sz passed");
  127. }
  128. if ($this->count() === $sz) {
  129. return;
  130. }
  131. $this->hacklib_expireAllIterators();
  132. if ($this->count() > $sz) {
  133. array_splice($this->container, $sz);
  134. } else {
  135. $this->container = array_pad($this->container, $sz, $value);
  136. }
  137. }
  138. /**
  139. * Reserves enough memory to accommodate 'sz' elements. If 'sz' is less
  140. * than or equal to the current capacity of this VectorLike, does nothing.
  141. */
  142. public function reserve($sz) {
  143. if ($sz < 0) {
  144. throw new \InvalidArgumentException(
  145. 'Parameter sz must be a non-negative integer, got '. $sz,
  146. );
  147. }
  148. if ($sz > self::MAX_SIZE) {
  149. throw new \InvalidArgumentException(
  150. "Parameter sz must be at most ".self::MAX_SIZE."; $sz passed");
  151. }
  152. if ($sz > $this->count()) {
  153. $this->hacklib_expireAllIterators();
  154. }
  155. // do nothing for now. in the future we can store size separately and
  156. // pad the array
  157. }
  158. /**
  159. * Reverse the elements of this Vector in place.
  160. */
  161. public function reverse() {
  162. $this->container = array_reverse($this->container);
  163. if ($this->count() > 1) {
  164. $this->hacklib_expireAllIterators();
  165. }
  166. }
  167. /**
  168. * Splice this Vector in place. This function provides the functionality
  169. * of array_splice() for Vectors. Note that this function modifies this
  170. * Vector in place.
  171. */
  172. public function splice($offset, $len = null) {
  173. if (!is_int($offset)) {
  174. throw new \InvalidArgumentException(\sprintf(
  175. 'Parameter offset must be an integer, got %s',
  176. is_object($object) ? get_class($object) : gettype($object),
  177. );
  178. }
  179. if (!is_null($len) && !is_int($len)) {
  180. throw new \InvalidArgumentException(\sprintf(
  181. 'Parameter len must be null or an integer, got %s',
  182. is_object($len) ? get_class($len) : gettype($len),
  183. ));
  184. }
  185. $removed = is_null($len) ? array_splice($this->container, $offset) :
  186. array_splice($this->container, $offset, $len);
  187. if (count($removed) > 0) {
  188. $this->hacklib_expireAllIterators();
  189. }
  190. }
  191. /**
  192. * Shuffles the values of the Vector randomly in place.
  193. */
  194. public function shuffle() {
  195. shuffle($this->container);
  196. if ($this->count() > 1) {
  197. $this->hacklib_expireAllIterators();
  198. }
  199. }
  200. protected function hacklib_isImmutable() {
  201. return false;
  202. }
  203. }
  204. }