4
4
5
5
use PhpTrees \RopeNode ;
6
6
7
- class Rope
7
+ class Rope implements \ArrayAccess
8
8
{
9
9
/* the root of the tree */
10
10
private $ root = null ;
@@ -49,7 +49,11 @@ public function length() : int
49
49
*/
50
50
public function insert (string $ value , int $ index = null ) : void
51
51
{
52
- if ($ index > $ this ->length ()) {
52
+ if ($ index === null ) {
53
+ $ index = $ this ->length ();
54
+ }
55
+
56
+ if ($ index >= $ this ->length ()) {
53
57
$ r = concatRope ($ this , new Rope ($ value ));
54
58
}
55
59
else {
@@ -93,9 +97,9 @@ public function index(int $index, RopeNode $node = null) : ?string
93
97
* splits the given node at the given position into 2 nodes
94
98
* @param int $index the index to split at
95
99
* @param RopeNode $node the recursive node to search
96
- * @return RopeNode returns the location of the split (the new parent of the newly created nodes)
100
+ * @return RopeNode returns a reference to the location of the split (the new parent of the newly created nodes)
97
101
*/
98
- public function splitNodeAtPosition (int $ index , RopeNode $ node = null ) : ?RopeNode
102
+ public function & splitNodeAtPosition (int $ index , RopeNode $ node = null ) : ?RopeNode
99
103
{
100
104
if ($ node === null ) {
101
105
$ node = $ this ->root ;
@@ -212,7 +216,7 @@ public function getRoot() : ?RopeNode
212
216
* @param RopeNode $node the node to recurse on
213
217
* @return RopeNode the node of the given index
214
218
*/
215
- private function getNodeOfIndex (int &$ index , RopeNode $ node = null ) : ?RopeNode
219
+ private function & getNodeOfIndex (int &$ index , RopeNode $ node = null ) : ?RopeNode
216
220
{
217
221
if ($ node === null ) {
218
222
$ node = $ this ->root ;
@@ -235,10 +239,6 @@ private function getNodeOfIndex(int &$index, RopeNode $node = null) : ?RopeNode
235
239
return null ;
236
240
}
237
241
238
- // THOUGHTS
239
- // this could implement PHP ArrayAccess interface (offsetExists, offsetGet, offsetSet, offsetUnset)
240
- // is there need to implement iterators here>
241
-
242
242
///////////////////////////////
243
243
//php functions
244
244
//////////////////////////////
@@ -251,4 +251,86 @@ public function __toString() : string
251
251
{
252
252
return $ this ->toString ();
253
253
}
254
+
255
+ /**
256
+ * clones the current rope
257
+ */
258
+ public function __clone ()
259
+ {
260
+ if ($ this ->root !== null ) {
261
+ $ this ->root = clone $ this ->root ;
262
+ }
263
+ }
264
+
265
+ /**
266
+ * check if the given offset exists in the Rope
267
+ * @param mixed $offset the offset to check for
268
+ * @return bool true if the given offset exists
269
+ */
270
+ public function offsetExists ($ offset ) : bool
271
+ {
272
+ if (is_int ($ offset )) {
273
+ if ($ offset <= $ this ->length ()) {
274
+ return true ;
275
+ }
276
+ return false ;
277
+ } else {
278
+ throw new \Exception ('Rope offset must be an integer ' );
279
+ }
280
+ }
281
+
282
+ /**
283
+ * gets the index of the rope
284
+ * @param mixed $offset the offset to check
285
+ */
286
+ public function offsetGet ($ offset )
287
+ {
288
+ if (is_int ($ offset )) {
289
+ return $ this ->index ($ offset );
290
+ }
291
+ else {
292
+ throw new \Exception ('Rope offset must be an integer ' );
293
+ }
294
+ }
295
+
296
+ /**
297
+ *
298
+ */
299
+ public function offsetSet ($ offset , $ value ) : void
300
+ {
301
+ if ($ offset === null && is_string ($ value )) {
302
+ $ this ->insert ($ value );
303
+ return ;
304
+ }
305
+
306
+ if (is_int ($ offset )) {
307
+ if (is_string ($ value ) && strlen ($ value ) === 1 ) {
308
+ $ index = $ offset ;
309
+ $ node = &$ this ->getNodeOfIndex ($ index );
310
+ $ v = substr_replace ($ node ->getValue (), $ value , $ index , 1 );
311
+ $ node ->changeValue ($ v );
312
+
313
+ }
314
+ else {
315
+ throw new \Exception ("Value must be a 1 char string " );
316
+ }
317
+ }
318
+ else {
319
+ throw new \Exception ('Rope offset must be an integer ' );
320
+ }
321
+ }
322
+
323
+ /**
324
+ * removes the character from the given index
325
+ * @param mixed $offset the offset to remove the character from
326
+ */
327
+ public function offsetUnset ($ offset ) : void
328
+ {
329
+ if (is_int ($ offset )) {
330
+ $ this ->removeSubstr ($ offset , 1 );
331
+ }
332
+ else {
333
+ throw new \Exception ('Rope offset must be an integer ' );
334
+ }
335
+ }
254
336
}
0 commit comments