RepeatedField.php 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. <?php
  2. // Protocol Buffers - Google's data interchange format
  3. // Copyright 2008 Google Inc. All rights reserved.
  4. // https://developers.google.com/protocol-buffers/
  5. //
  6. // Redistribution and use in source and binary forms, with or without
  7. // modification, are permitted provided that the following conditions are
  8. // met:
  9. //
  10. // * Redistributions of source code must retain the above copyright
  11. // notice, this list of conditions and the following disclaimer.
  12. // * Redistributions in binary form must reproduce the above
  13. // copyright notice, this list of conditions and the following disclaimer
  14. // in the documentation and/or other materials provided with the
  15. // distribution.
  16. // * Neither the name of Google Inc. nor the names of its
  17. // contributors may be used to endorse or promote products derived from
  18. // this software without specific prior written permission.
  19. //
  20. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. /**
  32. * RepeatedField and RepeatedFieldIter are used by generated protocol message
  33. * classes to manipulate repeated fields.
  34. */
  35. namespace Google\Protobuf\Internal;
  36. use Google\Protobuf\Internal\GPBType;
  37. use Google\Protobuf\Internal\GPBUtil;
  38. /**
  39. * RepeatedFieldIter is used to iterate RepeatedField. It is also need for the
  40. * foreach syntax.
  41. */
  42. class RepeatedFieldIter implements \Iterator
  43. {
  44. /**
  45. * @ignore
  46. */
  47. private $position;
  48. /**
  49. * @ignore
  50. */
  51. private $container;
  52. /**
  53. * Create iterator instance for RepeatedField.
  54. *
  55. * @param RepeatedField The RepeatedField instance for which this iterator
  56. * is created.
  57. * @ignore
  58. */
  59. public function __construct($container)
  60. {
  61. $this->position = 0;
  62. $this->container = $container;
  63. }
  64. /**
  65. * Reset the status of the iterator
  66. *
  67. * @return void
  68. */
  69. public function rewind()
  70. {
  71. $this->position = 0;
  72. }
  73. /**
  74. * Return the element at the current position.
  75. *
  76. * @return object The element at the current position.
  77. */
  78. public function current()
  79. {
  80. return $this->container[$this->position];
  81. }
  82. /**
  83. * Return the current position.
  84. *
  85. * @return integer The current position.
  86. */
  87. public function key()
  88. {
  89. return $this->position;
  90. }
  91. /**
  92. * Move to the next position.
  93. *
  94. * @return void
  95. */
  96. public function next()
  97. {
  98. ++$this->position;
  99. }
  100. /**
  101. * Check whether there are more elements to iterate.
  102. *
  103. * @return bool True if there are more elements to iterate.
  104. */
  105. public function valid()
  106. {
  107. return isset($this->container[$this->position]);
  108. }
  109. }
  110. /**
  111. * RepeatedField is used by generated protocol message classes to manipulate
  112. * repeated fields. It can be used like native PHP array.
  113. */
  114. class RepeatedField implements \ArrayAccess, \IteratorAggregate, \Countable
  115. {
  116. /**
  117. * @ignore
  118. */
  119. private $container;
  120. /**
  121. * @ignore
  122. */
  123. private $type;
  124. /**
  125. * @ignore
  126. */
  127. private $klass;
  128. /**
  129. * Constructs an instance of RepeatedField.
  130. *
  131. * @param long $type Type of the stored element.
  132. * @param string $klass Message/Enum class name (message/enum fields only).
  133. * @ignore
  134. */
  135. public function __construct($type, $klass = null)
  136. {
  137. $this->container = [];
  138. $this->type = $type;
  139. $this->klass = $klass;
  140. }
  141. /**
  142. * @ignore
  143. */
  144. public function getType()
  145. {
  146. return $this->type;
  147. }
  148. /**
  149. * @ignore
  150. */
  151. public function getClass()
  152. {
  153. return $this->klass;
  154. }
  155. /**
  156. * Return the element at the given index.
  157. *
  158. * This will also be called for: $ele = $arr[0]
  159. *
  160. * @param long $offset The index of the element to be fetched.
  161. * @return object The stored element at given index.
  162. * @throws ErrorException Invalid type for index.
  163. * @throws ErrorException Non-existing index.
  164. */
  165. public function offsetGet($offset)
  166. {
  167. return $this->container[$offset];
  168. }
  169. /**
  170. * Assign the element at the given index.
  171. *
  172. * This will also be called for: $arr []= $ele and $arr[0] = ele
  173. *
  174. * @param long $offset The index of the element to be assigned.
  175. * @param object $value The element to be assigned.
  176. * @return void
  177. * @throws ErrorException Invalid type for index.
  178. * @throws ErrorException Non-existing index.
  179. * @throws ErrorException Incorrect type of the element.
  180. */
  181. public function offsetSet($offset, $value)
  182. {
  183. switch ($this->type) {
  184. case GPBType::INT32:
  185. GPBUtil::checkInt32($value);
  186. break;
  187. case GPBType::UINT32:
  188. GPBUtil::checkUint32($value);
  189. break;
  190. case GPBType::INT64:
  191. GPBUtil::checkInt64($value);
  192. break;
  193. case GPBType::UINT64:
  194. GPBUtil::checkUint64($value);
  195. break;
  196. case GPBType::FLOAT:
  197. GPBUtil::checkFloat($value);
  198. break;
  199. case GPBType::DOUBLE:
  200. GPBUtil::checkDouble($value);
  201. break;
  202. case GPBType::BOOL:
  203. GPBUtil::checkBool($value);
  204. break;
  205. case GPBType::STRING:
  206. GPBUtil::checkString($value, true);
  207. break;
  208. case GPBType::MESSAGE:
  209. if (is_null($value)) {
  210. trigger_error("RepeatedField element cannot be null.",
  211. E_USER_ERROR);
  212. }
  213. GPBUtil::checkMessage($value, $this->klass);
  214. break;
  215. default:
  216. break;
  217. }
  218. if (is_null($offset)) {
  219. $this->container[] = $value;
  220. } else {
  221. $count = count($this->container);
  222. if (!is_numeric($offset) || $offset < 0 || $offset >= $count) {
  223. trigger_error(
  224. "Cannot modify element at the given index",
  225. E_USER_ERROR);
  226. return;
  227. }
  228. $this->container[$offset] = $value;
  229. }
  230. }
  231. /**
  232. * Remove the element at the given index.
  233. *
  234. * This will also be called for: unset($arr)
  235. *
  236. * @param long $offset The index of the element to be removed.
  237. * @return void
  238. * @throws ErrorException Invalid type for index.
  239. * @throws ErrorException The element to be removed is not at the end of the
  240. * RepeatedField.
  241. */
  242. public function offsetUnset($offset)
  243. {
  244. $count = count($this->container);
  245. if (!is_numeric($offset) || $count === 0 || $offset !== $count - 1) {
  246. trigger_error(
  247. "Cannot remove element at the given index",
  248. E_USER_ERROR);
  249. return;
  250. }
  251. array_pop($this->container);
  252. }
  253. /**
  254. * Check the existence of the element at the given index.
  255. *
  256. * This will also be called for: isset($arr)
  257. *
  258. * @param long $offset The index of the element to be removed.
  259. * @return bool True if the element at the given offset exists.
  260. * @throws ErrorException Invalid type for index.
  261. */
  262. public function offsetExists($offset)
  263. {
  264. return isset($this->container[$offset]);
  265. }
  266. /**
  267. * @ignore
  268. */
  269. public function getIterator()
  270. {
  271. return new RepeatedFieldIter($this->container);
  272. }
  273. /**
  274. * Return the number of stored elements.
  275. *
  276. * This will also be called for: count($arr)
  277. *
  278. * @return integer The number of stored elements.
  279. */
  280. public function count()
  281. {
  282. return count($this->container);
  283. }
  284. }