1 <?php
2 namespace apemsel\AttributedString;
3
4 5 6 7 8 9 10
11 class Bitmap implements Attribute
12 {
13 protected $bitmap;
14 protected $length;
15
16 17 18
19 public function __construct($length) {
20 $this->length = $length;
21 $this->bitmap = str_repeat(chr(0), ceil($this->length / 8));
22 }
23
24 25 26 27 28
29 public function __toString() {
30 return $this->toString();
31 }
32
33 34 35 36 37 38 39
40 public function toString($true = "1", $false = "0") {
41 $string = str_repeat($false, $this->length);
42 for ($offset = 0; $offset < $this->length; $offset++) {
43 if (ord($this->bitmap[(int) ($offset / 8)]) & (1 << $offset % 8)) {
44 $string[$offset] = $true;
45 }
46 }
47
48 return $string;
49 }
50
51 52 53 54 55 56 57
58 public function setRange($from, $to, $state = true) {
59
60 for($i = $from; $i <= $to; $i++) {
61 $this->offsetSet($i, $state);
62 }
63 }
64
65 66 67 68 69 70 71 72 73
74 public function search($offset = 0, $returnLength = false, $state = true, $strict = true) {
75 for ($i = $offset; $i < $this->length; $i++) {
76 if (($strict and $this->offsetGet($i) === $state) or (!$strict and $this->offsetGet($i) == $state)) {
77 if ($returnLength) {
78 $length = $this->search($i, false, !$state, $strict);
79 $length = $length ? $length - $i : $this->length - $i;
80
81 return [$i, $length];
82 } else {
83 return $i;
84 }
85 }
86 }
87
88 return false;
89 }
90
91
92
93 94 95 96 97 98
99 public function offsetExists($offset) {
100 return is_int($offset) && $offset >= 0 && $offset < $this->length;
101 }
102
103 104 105 106 107 108
109 public function offsetGet($offset)
110 {
111 if ($this->offsetExists($offset)) {
112 return (bool) (ord($this->bitmap[(int) ($offset / 8)]) & (1 << $offset % 8));
113 } else {
114 throw new \OutOfRangeException();
115 }
116 }
117
118 119 120 121 122 123
124 public function offsetSet($offset, $value)
125 {
126 if ($this->offsetExists($offset)) {
127 $index = (int) ($offset / 8);
128 if ($value) {
129 $this->bitmap[$index] = chr(ord($this->bitmap[$index]) | (1 << $offset % 8));
130 } else {
131 $this->bitmap[$index] = chr(ord($this->bitmap[$index]) & ~(1 << $offset % 8));
132 }
133 } else {
134 throw new \OutOfRangeException();
135 }
136 }
137
138 139 140 141 142
143 public function offsetUnset($offset) {
144 throw new \RuntimeException("Bitmap does not support offsetUnset");
145 }
146
147
148
149 150 151 152 153
154 public function count() {
155 return $this->length;
156 }
157 }
158