PageRenderTime 55ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/core/src/main/php/lang/types/Bytes.class.php

http://github.com/xp-framework/xp-framework
PHP | 185 lines | 88 code | 15 blank | 82 comment | 21 complexity | e6511170f2684319d2481699482169a6 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /* This class is part of the XP framework
  3. *
  4. * $Id$
  5. */
  6. uses('lang.types.Byte');
  7. /**
  8. * Represents a list of bytes
  9. *
  10. * @test xp://net.xp_framework.unittest.core.types.BytesTest
  11. * @purpose Wrapper type
  12. */
  13. class Bytes extends Object implements ArrayAccess, IteratorAggregate {
  14. protected
  15. $iterator = NULL;
  16. public
  17. $buffer = '',
  18. $size = 0;
  19. /**
  20. * Returns input as byte
  21. *
  22. * @param var in
  23. * @return string
  24. */
  25. protected function asByte($in) {
  26. return is_int($in) && -1 < $in && $in < 256
  27. ? chr($in)
  28. : ($in instanceof Byte ? chr($in->value) : $in{0})
  29. ;
  30. }
  31. /**
  32. * Constructor
  33. *
  34. * @param var initial default NULL
  35. * @throws lang.IllegalArgumentException in case argument is of incorrect type.
  36. */
  37. public function __construct($initial= NULL) {
  38. if (NULL === $initial) {
  39. // Intentionally empty
  40. } else if (is_array($initial)) {
  41. $this->buffer= implode('', array_map(array($this, 'asByte'), $initial));
  42. } else if (is_string($initial)) {
  43. $this->buffer= $initial;
  44. } else {
  45. throw new IllegalArgumentException('Expected either Byte[], char[], int[] or string but was '.xp::typeOf($initial));
  46. }
  47. $this->size= strlen($this->buffer);
  48. }
  49. /**
  50. * Returns an iterator for use in foreach()
  51. *
  52. * @see php://language.oop5.iterations
  53. * @return php.Iterator
  54. */
  55. public function getIterator() {
  56. if (!$this->iterator) $this->iterator= newinstance('Iterator', array($this), '{
  57. private $i= 0, $v;
  58. public function __construct($v) { $this->v= $v; }
  59. public function current() { $n= ord($this->v->buffer{$this->i}); return new Byte($n < 128 ? $n : $n - 256); }
  60. public function key() { return $this->i; }
  61. public function next() { $this->i++; }
  62. public function rewind() { $this->i= 0; }
  63. public function valid() { return $this->i < $this->v->size; }
  64. }');
  65. return $this->iterator;
  66. }
  67. /**
  68. * = list[] overloading
  69. *
  70. * @param int offset
  71. * @return lang.types.Byte
  72. * @throws lang.IndexOutOfBoundsException if offset does not exist
  73. */
  74. public function offsetGet($offset) {
  75. if ($offset >= $this->size || $offset < 0) {
  76. raise('lang.IndexOutOfBoundsException', 'Offset '.$offset.' out of bounds');
  77. }
  78. $n= ord($this->buffer{$offset});
  79. return new Byte($n < 128 ? $n : $n - 256);
  80. }
  81. /**
  82. * list[]= overloading
  83. *
  84. * @param int offset
  85. * @param var value
  86. * @throws lang.IllegalArgumentException if key is neither numeric (set) nor NULL (add)
  87. * @throws lang.IndexOutOfBoundsException if key does not exist
  88. */
  89. public function offsetSet($offset, $value) {
  90. if (NULL === $offset) {
  91. $this->buffer.= $this->asByte($value);
  92. $this->size++;
  93. } else if ($offset >= $this->size || $offset < 0) {
  94. raise('lang.IndexOutOfBoundsException', 'Offset '.$offset.' out of bounds');
  95. } else {
  96. $this->buffer{$offset}= $this->asByte($value);
  97. }
  98. }
  99. /**
  100. * isset() overloading
  101. *
  102. * @param int offset
  103. * @return bool
  104. */
  105. public function offsetExists($offset) {
  106. return ($offset >= 0 && $offset < $this->size);
  107. }
  108. /**
  109. * unset() overloading
  110. *
  111. * @param int offset
  112. * @throws lang.IndexOutOfBoundsException if offset does not exist
  113. */
  114. public function offsetUnset($offset) {
  115. if ($offset >= $this->size || $offset < 0) {
  116. raise('lang.IndexOutOfBoundsException', 'Offset '.$offset.' out of bounds');
  117. }
  118. $this->buffer= (
  119. substr($this->buffer, 0, $offset).
  120. substr($this->buffer, $offset+ 1, $this->size)
  121. );
  122. $this->size--;
  123. }
  124. /**
  125. * Returns this byte list's size
  126. *
  127. * @return string
  128. */
  129. public function size() {
  130. return $this->size;
  131. }
  132. /**
  133. * Returns whether a given object is equal to this object
  134. *
  135. * @param lang.Generic cmp
  136. * @return bool
  137. */
  138. public function equals($cmp) {
  139. return (
  140. $cmp instanceof self &&
  141. $this->size === $cmp->size &&
  142. $this->buffer === $cmp->buffer
  143. );
  144. }
  145. /**
  146. * Returns a hashcode for this bytes object
  147. *
  148. * @return string
  149. */
  150. public function hashCode() {
  151. return md5($this->buffer);
  152. }
  153. /**
  154. * Returns a string representation of this string.
  155. *
  156. * @return string
  157. */
  158. public function toString() {
  159. return $this->getClassName().'('.$this->size.')@{'.addcslashes($this->buffer, "\0..\37\177..\377").'}';
  160. }
  161. /**
  162. * String conversion overloading. This is for use with fwrite()
  163. *
  164. * @return string
  165. */
  166. public function __toString() {
  167. return $this->buffer;
  168. }
  169. }
  170. ?>