1 <?php
2 namespace apemsel\AttributedString;
3
4 /**
5 * BooleanArray
6 *
7 * A time efficient Attribute implementation using a standard PHP array of booleans
8 *
9 * @author Adrian Pemsel <apemsel@gmail.com>
10 */
11 class BooleanArray implements MutableAttribute
12 {
13 protected $attribute;
14 protected $length;
15
16 /**
17 * @param int length of array
18 */
19 public function __construct($length) {
20 $this->length = $length;
21 $this->attribute = array_fill(0, $length, false);
22 }
23
24 /**
25 * Returns the array as a visual string
26 *
27 * @return string array as visual string of 0s and 1s
28 */
29 public function __toString() {
30 return $this->toString();
31 }
32
33 /**
34 * Returns the array as a visual string with custom chars for 0s and 1s
35 *
36 * @param string $true representation of 1s
37 * @param string $true representation of 0s
38 * @return string array as visual string of the given representations
39 */
40 public function toString($true = "1", $false = "0") {
41 return implode("", array_map(function($v) use ($true, $false) {
42 return $v ? $true : $false;
43 }, $this->attribute));
44 }
45
46 /**
47 * Set given range to a state
48 *
49 * @param int $from start offset
50 * @param int $to end offset
51 * @param bool $state set state to true (default) or false
52 */
53 public function setRange($from, $to, $state = true) {
54 // Set attribute state for given range
55 $this->attribute = array_replace($this->attribute, array_fill($from, $to-$from+1, $state));
56 }
57
58 /**
59 * Search inside bitmap for ranges with the given state
60 *
61 * @param int $offset start offset
62 * @param bool $returnLength if true (default is false), return an array with position and length of the found range
63 * @param bool $state the state to look for (default is true)
64 * @param bool $strict perform strict comparison during search
65 * @return int|int[] either position or position and lenght in an array
66 */
67 public function search($offset = 0, $returnLength = false, $state = true, $strict = true) {
68 $a = $this->attribute;
69 if ($offset) {
70 $a = array_slice($a, $offset, NULL, true);
71 }
72
73 $pos = array_search($state, $a, $strict);
74
75 if ($returnLength) {
76 if (false === $pos) {
77 return false;
78 }
79
80 $a = array_slice($a, $pos - $offset);
81 $length = array_search(!$state, $a, $strict);
82 $length = $length ? $length : $this->length - $pos;
83 return [$pos, $length];
84 } else {
85 return $pos;
86 }
87 }
88
89 // MutableAttribute interface
90
91 /**
92 * Insert a piece into the array at given offset with a given state and length
93 *
94 * @param int $offset offset
95 * @param int $length length of inserted piece
96 * @param bool $state state of inserted piece
97 */
98 public function insert($offset, $length, $state) {
99 $this->length += $length;
100 array_splice($this->attribute, $offset, 0, array_fill(0, $length, $state));
101 }
102
103 /**
104 * Delete a piece of the array at given offset with a given length
105 *
106 * @param int $offset offset
107 * @param int $length length of inserted piece
108 */
109 public function delete($offset, $length) {
110 $this->length -= $length;
111 array_splice($this->attribute, $offset, $length);
112 }
113
114 // ArrayAccess interface
115
116 /**
117 * Check if the given offset exists in the array
118 *
119 * @param int $offset offset
120 * @return bool does the offset exist
121 */
122 public function offsetExists($offset) {
123 return $offset < $this->length;
124 }
125
126 /**
127 * Get bool at given offset
128 *
129 * @param int $offset offset
130 * @return bool bit at given offset
131 */
132 public function offsetGet($offset)
133 {
134 return $this->attribute[$offset];
135 }
136
137 /**
138 * Set bool at given offset
139 *
140 * @param int $offset offset
141 * @param bool $value bit at given offset
142 */
143 public function offsetSet($offset, $value)
144 {
145 $this->attribute[$offset] = $value;
146 }
147
148 /**
149 * Unset bit at given offset
150 *
151 * @param int $offset offset
152 */
153 public function offsetUnset($offset) {
154 unset($this->attribute[$offset]);
155 }
156
157 // Countable interface
158
159 /**
160 * Return array length
161 *
162 * @return int array length
163 */
164 public function count() {
165 return $this->length;
166 }
167 }
168