PageRenderTime 41ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://gitlab.com/Blueprint-Marketing/hhvm
PHP | 214 lines | 135 code | 17 blank | 62 comment | 24 complexity | 6f85b4692739985325902cff1a4c7379 MD5 | raw file
  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. } else {
  61. throw new \InvalidArgumentException(
  62. 'Parameter must be an array or an instance of Traversable');
  63. }
  64. }
  65. /**
  66. * Append a copy of a value to the end of the Vector, assigning the next
  67. * available integer key. "$vec->add($v)" is semantically equivalent to
  68. * "$vec[] = $v" (except that add() returns the Vector).
  69. */
  70. public function add($value) {
  71. $this->hacklib_expireAllIterators();
  72. $this->container[]= $value;
  73. return $this;
  74. }
  75. /**
  76. * Adds the keys of the specified container to this Vector and returns
  77. * the Vector.
  78. */
  79. public function addAllKeysOf($it) {
  80. if (is_array($it) || $it instanceof \Traversable) {
  81. foreach ($it as $k => $v) {
  82. $this->add($k);
  83. }
  84. return $this;
  85. } elseif (is_null($it)) {
  86. return $this;
  87. } else {
  88. throw new \InvalidArgumentException(
  89. 'Parameter must be a container (array or collection)');
  90. }
  91. }
  92. /**
  93. * Removes the specified key from this Vector. This will cause elements
  94. * with higher keys to be renumbered.
  95. */
  96. public function removeKey($k) {
  97. if ($k >= 0 && $k < count($this->container)) {
  98. array_splice($this->container, $k, 1);
  99. $this->hacklib_expireAllIterators();
  100. }
  101. return $this;
  102. }
  103. /**
  104. * Remove the last element of this Vector and return it. This function
  105. * throws an exception if this Vector is empty.
  106. */
  107. public function pop() {
  108. if (!$this->container) {
  109. throw new \InvalidOperationException('Cannot pop empty '.get_class($this));
  110. }
  111. $this->hacklib_expireAllIterators();
  112. return array_pop($this->container);
  113. }
  114. /**
  115. * Resize this Vector to contain 'sz' elements. If 'sz' is smaller than
  116. * the current size of this Vector, elements are removed from the end of
  117. * this Vector. If 'sz' is greater than the current size of this Vector,
  118. * this Vector is extended by appending as many copies of 'value' as
  119. * needed to reach a size of 'sz' elements.
  120. */
  121. public function resize($sz, $value) {
  122. if ($sz > self::MAX_SIZE) {
  123. throw new \InvalidArgumentException(
  124. "Parameter sz must be at most ".self::MAX_SIZE."; $sz passed");
  125. }
  126. if ($this->count() === $sz) {
  127. return;
  128. }
  129. $this->hacklib_expireAllIterators();
  130. if ($this->count() > $sz) {
  131. array_splice($this->container, $sz);
  132. } else {
  133. $this->container = array_pad($this->container, $sz, $value);
  134. }
  135. }
  136. /**
  137. * Reserves enough memory to accommodate 'sz' elements. If 'sz' is less
  138. * than or equal to the current capacity of this VectorLike, does nothing.
  139. */
  140. public function reserve($sz) {
  141. if ($sz < 0) {
  142. throw new \InvalidArgumentException(
  143. 'Parameter sz must be a non-negative integer');
  144. }
  145. if ($sz > self::MAX_SIZE) {
  146. throw new \InvalidArgumentException(
  147. "Parameter sz must be at most ".self::MAX_SIZE."; $sz passed");
  148. }
  149. if ($sz > $this->count()) {
  150. $this->hacklib_expireAllIterators();
  151. }
  152. // do nothing for now. in the future we can store size separately and
  153. // pad the array
  154. }
  155. /**
  156. * Reverse the elements of this Vector in place.
  157. */
  158. public function reverse() {
  159. $this->container = array_reverse($this->container);
  160. if ($this->count() > 1) {
  161. $this->hacklib_expireAllIterators();
  162. }
  163. }
  164. /**
  165. * Splice this Vector in place. This function provides the functionality
  166. * of array_splice() for Vectors. Note that this function modifies this
  167. * Vector in place.
  168. */
  169. public function splice($offset, $len = null) {
  170. if (!is_int($offset)) {
  171. throw new \InvalidArgumentException(
  172. 'Parameter offset must be an integer');
  173. }
  174. if (!is_null($len) && !is_int($len)) {
  175. throw new \InvalidArgumentException(
  176. 'Parameter len must be null or an integer');
  177. }
  178. $removed = is_null($len) ? array_splice($this->container, $offset) :
  179. array_splice($this->container, $offset, $len);
  180. if (count($removed) > 0) {
  181. $this->hacklib_expireAllIterators();
  182. }
  183. }
  184. /**
  185. * Shuffles the values of the Vector randomly in place.
  186. */
  187. public function shuffle() {
  188. shuffle($this->container);
  189. if ($this->count() > 1) {
  190. $this->hacklib_expireAllIterators();
  191. }
  192. }
  193. protected function hacklib_isImmutable() {
  194. return false;
  195. }
  196. }
  197. }