CaseInsensitiveArray.php 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. <?php
  2. namespace Curl;
  3. #[AllowDynamicProperties]
  4. class CaseInsensitiveArray implements \ArrayAccess, \Countable, \Iterator
  5. {
  6. /**
  7. * @var mixed[] Data storage with lowercase keys.
  8. * @see offsetSet()
  9. * @see offsetExists()
  10. * @see offsetUnset()
  11. * @see offsetGet()
  12. * @see count()
  13. * @see current()
  14. * @see next()
  15. * @see key()
  16. */
  17. private $data = array();
  18. /**
  19. * @var string[] Case-sensitive keys.
  20. * @see offsetSet()
  21. * @see offsetUnset()
  22. * @see key()
  23. */
  24. private $keys = array();
  25. /**
  26. * Construct
  27. *
  28. * Allow creating an empty array or converting an existing array to a
  29. * case-insensitive array. Caution: Data may be lost when converting
  30. * case-sensitive arrays to case-insensitive arrays.
  31. *
  32. * @param mixed[] $initial (optional) Existing array to convert.
  33. *
  34. * @return CaseInsensitiveArray
  35. *
  36. * @access public
  37. */
  38. public function __construct(array $initial = null)
  39. {
  40. if ($initial !== null) {
  41. foreach ($initial as $key => $value) {
  42. $this->offsetSet($key, $value);
  43. }
  44. }
  45. }
  46. /**
  47. * Offset Set
  48. *
  49. * Set data at a specified offset. Converts the offset to lowercase, and
  50. * stores the case-sensitive offset and the data at the lowercase indexes in
  51. * $this->keys and @this->data.
  52. *
  53. * @see https://secure.php.net/manual/en/arrayaccess.offsetset.php
  54. *
  55. * @param string $offset The offset to store the data at (case-insensitive).
  56. * @param mixed $value The data to store at the specified offset.
  57. *
  58. * @return void
  59. *
  60. * @access public
  61. */
  62. public function offsetSet($offset, $value)
  63. {
  64. if ($offset === null) {
  65. $this->data[] = $value;
  66. } else {
  67. $offsetlower = strtolower($offset);
  68. $this->data[$offsetlower] = $value;
  69. $this->keys[$offsetlower] = $offset;
  70. }
  71. }
  72. /**
  73. * Offset Exists
  74. *
  75. * Checks if the offset exists in data storage. The index is looked up with
  76. * the lowercase version of the provided offset.
  77. *
  78. * @see https://secure.php.net/manual/en/arrayaccess.offsetexists.php
  79. *
  80. * @param string $offset Offset to check
  81. *
  82. * @return bool If the offset exists.
  83. *
  84. * @access public
  85. */
  86. public function offsetExists($offset)
  87. {
  88. return (bool) array_key_exists(strtolower($offset), $this->data);
  89. }
  90. /**
  91. * Offset Unset
  92. *
  93. * Unsets the specified offset. Converts the provided offset to lowercase,
  94. * and unsets the case-sensitive key, as well as the stored data.
  95. *
  96. * @see https://secure.php.net/manual/en/arrayaccess.offsetunset.php
  97. *
  98. * @param string $offset The offset to unset.
  99. *
  100. * @return void
  101. *
  102. * @access public
  103. */
  104. public function offsetUnset($offset)
  105. {
  106. $offsetlower = strtolower($offset);
  107. unset($this->data[$offsetlower]);
  108. unset($this->keys[$offsetlower]);
  109. }
  110. /**
  111. * Offset Get
  112. *
  113. * Return the stored data at the provided offset. The offset is converted to
  114. * lowercase and the lookup is done on the data store directly.
  115. *
  116. * @see https://secure.php.net/manual/en/arrayaccess.offsetget.php
  117. *
  118. * @param string $offset Offset to lookup.
  119. *
  120. * @return mixed The data stored at the offset.
  121. *
  122. * @access public
  123. */
  124. public function offsetGet($offset)
  125. {
  126. $offsetlower = strtolower($offset);
  127. return isset($this->data[$offsetlower]) ? $this->data[$offsetlower] : null;
  128. }
  129. /**
  130. * Count
  131. *
  132. * @see https://secure.php.net/manual/en/countable.count.php
  133. *
  134. * @param void
  135. *
  136. * @return int The number of elements stored in the array.
  137. *
  138. * @access public
  139. */
  140. public function count()
  141. {
  142. return (int) count($this->data);
  143. }
  144. /**
  145. * Current
  146. *
  147. * @see https://secure.php.net/manual/en/iterator.current.php
  148. *
  149. * @param void
  150. *
  151. * @return mixed Data at the current position.
  152. *
  153. * @access public
  154. */
  155. public function current()
  156. {
  157. return current($this->data);
  158. }
  159. /**
  160. * Next
  161. *
  162. * @see https://secure.php.net/manual/en/iterator.next.php
  163. *
  164. * @param void
  165. *
  166. * @return void
  167. *
  168. * @access public
  169. */
  170. public function next()
  171. {
  172. next($this->data);
  173. }
  174. /**
  175. * Key
  176. *
  177. * @see https://secure.php.net/manual/en/iterator.key.php
  178. *
  179. * @param void
  180. *
  181. * @return mixed Case-sensitive key at current position.
  182. *
  183. * @access public
  184. */
  185. public function key()
  186. {
  187. $key = key($this->data);
  188. return isset($this->keys[$key]) ? $this->keys[$key] : $key;
  189. }
  190. /**
  191. * Valid
  192. *
  193. * @see https://secure.php.net/manual/en/iterator.valid.php
  194. *
  195. * @return bool If the current position is valid.
  196. *
  197. * @access public
  198. */
  199. public function valid()
  200. {
  201. return (bool) (key($this->data) !== null);
  202. }
  203. /**
  204. * Rewind
  205. *
  206. * @see https://secure.php.net/manual/en/iterator.rewind.php
  207. *
  208. * @param void
  209. *
  210. * @return void
  211. *
  212. * @access public
  213. */
  214. public function rewind()
  215. {
  216. reset($this->data);
  217. }
  218. }