Passed
Push — develop ( 0a2079...d3d0ba )
by Christophe
02:28
created
src/SortedCollection/SubSet.php 1 patch
Indentation   +276 added lines, -276 removed lines patch added patch discarded remove patch
@@ -34,294 +34,294 @@
 block discarded – undo
34 34
  */
35 35
 class SubSet extends AbstractSet
36 36
 {
37
-    /**
38
-     * When the from or to value is unused
39
-     *
40
-     * @since 1.0.0
41
-     */
42
-    private const UNUSED = 0;
37
+	/**
38
+	 * When the from or to value is unused
39
+	 *
40
+	 * @since 1.0.0
41
+	 */
42
+	private const UNUSED = 0;
43 43
 
44
-    /**
45
-     * When the from or to value is inclusive
46
-     *
47
-     * @since 1.0.0
48
-     */
49
-    private const INCLUSIVE = 1;
44
+	/**
45
+	 * When the from or to value is inclusive
46
+	 *
47
+	 * @since 1.0.0
48
+	 */
49
+	private const INCLUSIVE = 1;
50 50
 
51
-    /**
52
-     * When the from or to value is exclusive
53
-     *
54
-     * @since 1.0.0
55
-     */
56
-    private const EXCLUSIVE = 2;
51
+	/**
52
+	 * When the from or to value is exclusive
53
+	 *
54
+	 * @since 1.0.0
55
+	 */
56
+	private const EXCLUSIVE = 2;
57 57
 
58
-    /**
59
-     * @var SortedSet  Internal set
60
-     *
61
-     * @since 1.0.0
62
-     */
63
-    private $set;
58
+	/**
59
+	 * @var SortedSet  Internal set
60
+	 *
61
+	 * @since 1.0.0
62
+	 */
63
+	private $set;
64 64
 
65
-    /**
66
-     * Magic get method
67
-     *
68
-     * @param string $property The property
69
-     *
70
-     * @return mixed The value associated to the property
71
-     *
72
-     * @since 1.0.0
73
-     */
74
-    public function __get($property)
75
-    {
76
-        switch ($property) {
77
-            case 'from':
78
-                return $this->getMap()->fromKey;
79
-            case 'to':
80
-                return $this->getMap()->toKey;
81
-            case 'fromInclusive':
82
-                return $this->getMap()->fromInclusive;
83
-            case 'toInclusive':
84
-                return $this->getMap()->toInclusive;
85
-            case 'set':
86
-                return $this->set;
87
-            default:
88
-                return parent::__get($property);
89
-        }
90
-    }
65
+	/**
66
+	 * Magic get method
67
+	 *
68
+	 * @param string $property The property
69
+	 *
70
+	 * @return mixed The value associated to the property
71
+	 *
72
+	 * @since 1.0.0
73
+	 */
74
+	public function __get($property)
75
+	{
76
+		switch ($property) {
77
+			case 'from':
78
+				return $this->getMap()->fromKey;
79
+			case 'to':
80
+				return $this->getMap()->toKey;
81
+			case 'fromInclusive':
82
+				return $this->getMap()->fromInclusive;
83
+			case 'toInclusive':
84
+				return $this->getMap()->toInclusive;
85
+			case 'set':
86
+				return $this->set;
87
+			default:
88
+				return parent::__get($property);
89
+		}
90
+	}
91 91
 
92
-    /**
93
-     * Magic set method
94
-     *
95
-     * @param string $property The property
96
-     * @param mixed  $value    The new value
97
-     *
98
-     * @throws RuntimeException If the property does not exist
99
-     *
100
-     * @return void
101
-     *
102
-     * @since 1.0.0
103
-     */
104
-    public function __set($property, $value)
105
-    {
106
-        switch ($property) {
107
-            case 'from':
108
-                $this->getMap()->fromKey = $value;
109
-                break;
110
-            case 'to':
111
-                $this->getMap()->toKey = $value;
112
-                break;
113
-            case 'fromInclusive':
114
-                $this->getMap()->fromInclusive = $value;
115
-                break;
116
-            case 'toInclusive':
117
-                $this->getMap()->toInclusive = $value;
118
-                break;
119
-            default:
120
-                throw new \RuntimeException('Undefined property');
121
-        }
122
-    }
92
+	/**
93
+	 * Magic set method
94
+	 *
95
+	 * @param string $property The property
96
+	 * @param mixed  $value    The new value
97
+	 *
98
+	 * @throws RuntimeException If the property does not exist
99
+	 *
100
+	 * @return void
101
+	 *
102
+	 * @since 1.0.0
103
+	 */
104
+	public function __set($property, $value)
105
+	{
106
+		switch ($property) {
107
+			case 'from':
108
+				$this->getMap()->fromKey = $value;
109
+				break;
110
+			case 'to':
111
+				$this->getMap()->toKey = $value;
112
+				break;
113
+			case 'fromInclusive':
114
+				$this->getMap()->fromInclusive = $value;
115
+				break;
116
+			case 'toInclusive':
117
+				$this->getMap()->toInclusive = $value;
118
+				break;
119
+			default:
120
+				throw new \RuntimeException('Undefined property');
121
+		}
122
+	}
123 123
 
124
-    /**
125
-     * Magic unset method
126
-     *
127
-     * @param string $property The property
128
-     *
129
-     * @throws RuntimeException If the property does not exist
130
-     *
131
-     * @return void
132
-     *
133
-     * @since 1.0.0
134
-     */
135
-    public function __unset($property)
136
-    {
137
-        switch ($property) {
138
-            case 'from':
139
-                unset($this->getMap()->fromKey);
140
-                break;
141
-            case 'to':
142
-                unset($this->getMap()->toKey);
143
-                break;
144
-            case 'fromInclusive':
145
-                unset($this->getMap()->fromInclusive);
146
-                break;
147
-            case 'toInclusive':
148
-                unset($this->getMap()->toInclusive);
149
-                break;
150
-            default:
151
-                throw new \RuntimeException('Undefined property');
152
-        }
153
-    }
124
+	/**
125
+	 * Magic unset method
126
+	 *
127
+	 * @param string $property The property
128
+	 *
129
+	 * @throws RuntimeException If the property does not exist
130
+	 *
131
+	 * @return void
132
+	 *
133
+	 * @since 1.0.0
134
+	 */
135
+	public function __unset($property)
136
+	{
137
+		switch ($property) {
138
+			case 'from':
139
+				unset($this->getMap()->fromKey);
140
+				break;
141
+			case 'to':
142
+				unset($this->getMap()->toKey);
143
+				break;
144
+			case 'fromInclusive':
145
+				unset($this->getMap()->fromInclusive);
146
+				break;
147
+			case 'toInclusive':
148
+				unset($this->getMap()->toInclusive);
149
+				break;
150
+			default:
151
+				throw new \RuntimeException('Undefined property');
152
+		}
153
+	}
154 154
 
155
-    /**
156
-     * Magic isset method
157
-     *
158
-     * @param string $property The property
159
-     *
160
-     * @return boolean
161
-     *
162
-     * @since 1.0.0
163
-     */
164
-    public function __isset($property)
165
-    {
166
-        switch ($property) {
167
-            case 'from':
168
-                return isset($this->getMap()->fromKey);
169
-            case 'to':
170
-                return isset($this->getMap()->toKey);
171
-            case 'fromInclusive':
172
-                return isset($this->getMap()->fromInclusive);
173
-            case 'toInclusive':
174
-                return isset($this->getMap()->toInclusive);
175
-            default:
176
-                return false;
177
-        }
178
-    }
155
+	/**
156
+	 * Magic isset method
157
+	 *
158
+	 * @param string $property The property
159
+	 *
160
+	 * @return boolean
161
+	 *
162
+	 * @since 1.0.0
163
+	 */
164
+	public function __isset($property)
165
+	{
166
+		switch ($property) {
167
+			case 'from':
168
+				return isset($this->getMap()->fromKey);
169
+			case 'to':
170
+				return isset($this->getMap()->toKey);
171
+			case 'fromInclusive':
172
+				return isset($this->getMap()->fromInclusive);
173
+			case 'toInclusive':
174
+				return isset($this->getMap()->toInclusive);
175
+			default:
176
+				return false;
177
+		}
178
+	}
179 179
 
180
-    /**
181
-     * Constructor
182
-     *
183
-     * @param SortedSet $set        Internal set
184
-     * @param mixed     $from       The from element
185
-     * @param integer   $fromOption The option for from (SubSet::UNUSED, SubSet::INCLUSIVE or SubSet::EXCLUSIVE)
186
-     * @param mixed     $to         The to element
187
-     * @param integer   $toOption   The option for to (SubSet::UNUSED, SubSet::INCLUSIVE or SubSet::EXCLUSIVE)
188
-     *
189
-     * @since 1.0.0
190
-     */
191
-    protected function __construct(SortedSet $set, $from, $fromOption, $to, $toOption)
192
-    {
193
-        if ($fromOption == self::UNUSED) {
194
-            if ($toOption == self::UNUSED) {
195
-                $this->setMap(SubMap::view($set->getMap()));
196
-            } else {
197
-                $this->setMap(SubMap::head($set->getMap(), $to, $toOption == self::INCLUSIVE));
198
-            }
199
-        } elseif ($toOption == self::UNUSED) {
200
-            $this->setMap(SubMap::tail($set->getMap(), $from, $fromOption == self::INCLUSIVE));
201
-        } else {
202
-            $this->setMap(
203
-                SubMap::create($set->getMap(), $from, $to, $fromOption == self::INCLUSIVE, $toOption == self::INCLUSIVE)
204
-            );
205
-        }
180
+	/**
181
+	 * Constructor
182
+	 *
183
+	 * @param SortedSet $set        Internal set
184
+	 * @param mixed     $from       The from element
185
+	 * @param integer   $fromOption The option for from (SubSet::UNUSED, SubSet::INCLUSIVE or SubSet::EXCLUSIVE)
186
+	 * @param mixed     $to         The to element
187
+	 * @param integer   $toOption   The option for to (SubSet::UNUSED, SubSet::INCLUSIVE or SubSet::EXCLUSIVE)
188
+	 *
189
+	 * @since 1.0.0
190
+	 */
191
+	protected function __construct(SortedSet $set, $from, $fromOption, $to, $toOption)
192
+	{
193
+		if ($fromOption == self::UNUSED) {
194
+			if ($toOption == self::UNUSED) {
195
+				$this->setMap(SubMap::view($set->getMap()));
196
+			} else {
197
+				$this->setMap(SubMap::head($set->getMap(), $to, $toOption == self::INCLUSIVE));
198
+			}
199
+		} elseif ($toOption == self::UNUSED) {
200
+			$this->setMap(SubMap::tail($set->getMap(), $from, $fromOption == self::INCLUSIVE));
201
+		} else {
202
+			$this->setMap(
203
+				SubMap::create($set->getMap(), $from, $to, $fromOption == self::INCLUSIVE, $toOption == self::INCLUSIVE)
204
+			);
205
+		}
206 206
 
207
-        $this->set = $set;
208
-    }
207
+		$this->set = $set;
208
+	}
209 209
 
210
-    /**
211
-     * Create
212
-     *
213
-     * @param SortedSet $set           Internal set
214
-     * @param mixed     $from          The from element
215
-     * @param mixed     $to            The to element
216
-     * @param boolean   $fromInclusive The inclusive flag for from
217
-     * @param boolean   $toInclusive   The inclusive flag for to
218
-     *
219
-     * @return SubSet A new sub set
220
-     *
221
-     * @since 1.0.0
222
-     */
223
-    public static function create(SortedSet $set, $from, $to, $fromInclusive = true, $toInclusive = false)
224
-    {
225
-        return new static(
226
-            $set,
227
-            $from,
228
-            $fromInclusive ? self::INCLUSIVE : self::EXCLUSIVE,
229
-            $to,
230
-            $toInclusive ? self::INCLUSIVE : self::EXCLUSIVE
231
-        );
232
-    }
210
+	/**
211
+	 * Create
212
+	 *
213
+	 * @param SortedSet $set           Internal set
214
+	 * @param mixed     $from          The from element
215
+	 * @param mixed     $to            The to element
216
+	 * @param boolean   $fromInclusive The inclusive flag for from
217
+	 * @param boolean   $toInclusive   The inclusive flag for to
218
+	 *
219
+	 * @return SubSet A new sub set
220
+	 *
221
+	 * @since 1.0.0
222
+	 */
223
+	public static function create(SortedSet $set, $from, $to, $fromInclusive = true, $toInclusive = false)
224
+	{
225
+		return new static(
226
+			$set,
227
+			$from,
228
+			$fromInclusive ? self::INCLUSIVE : self::EXCLUSIVE,
229
+			$to,
230
+			$toInclusive ? self::INCLUSIVE : self::EXCLUSIVE
231
+		);
232
+	}
233 233
 
234
-    /**
235
-     * Head
236
-     *
237
-     * @param SortedSet $set         Internal set
238
-     * @param mixed     $to          The to element
239
-     * @param boolean   $toInclusive The inclusive flag for to
240
-     *
241
-     * @return SubSet A new head set
242
-     *
243
-     * @since 1.0.0
244
-     */
245
-    public static function head(SortedSet $set, $to, $toInclusive = false)
246
-    {
247
-        return new static($set, null, self::UNUSED, $to, $toInclusive ? self::INCLUSIVE : self::EXCLUSIVE);
248
-    }
234
+	/**
235
+	 * Head
236
+	 *
237
+	 * @param SortedSet $set         Internal set
238
+	 * @param mixed     $to          The to element
239
+	 * @param boolean   $toInclusive The inclusive flag for to
240
+	 *
241
+	 * @return SubSet A new head set
242
+	 *
243
+	 * @since 1.0.0
244
+	 */
245
+	public static function head(SortedSet $set, $to, $toInclusive = false)
246
+	{
247
+		return new static($set, null, self::UNUSED, $to, $toInclusive ? self::INCLUSIVE : self::EXCLUSIVE);
248
+	}
249 249
 
250
-    /**
251
-     * Tail
252
-     *
253
-     * @param SortedSet $set           Internal set
254
-     * @param mixed     $from          The from element
255
-     * @param boolean   $fromInclusive The inclusive flag for from
256
-     *
257
-     * @return SubSet A new tail set
258
-     *
259
-     * @since 1.0.0
260
-     */
261
-    public static function tail(SortedSet $set, $from, $fromInclusive = true)
262
-    {
263
-        return new static($set, $from, $fromInclusive ? self::INCLUSIVE : self::EXCLUSIVE, null, self::UNUSED);
264
-    }
250
+	/**
251
+	 * Tail
252
+	 *
253
+	 * @param SortedSet $set           Internal set
254
+	 * @param mixed     $from          The from element
255
+	 * @param boolean   $fromInclusive The inclusive flag for from
256
+	 *
257
+	 * @return SubSet A new tail set
258
+	 *
259
+	 * @since 1.0.0
260
+	 */
261
+	public static function tail(SortedSet $set, $from, $fromInclusive = true)
262
+	{
263
+		return new static($set, $from, $fromInclusive ? self::INCLUSIVE : self::EXCLUSIVE, null, self::UNUSED);
264
+	}
265 265
 
266
-    /**
267
-     * View
268
-     *
269
-     * @param SortedSet $set Internal set
270
-     *
271
-     * @return SubSet A new sub set
272
-     *
273
-     * @since 1.0.0
274
-     */
275
-    public static function view(SortedSet $set)
276
-    {
277
-        return new static($set, null, self::UNUSED, null, self::UNUSED);
278
-    }
266
+	/**
267
+	 * View
268
+	 *
269
+	 * @param SortedSet $set Internal set
270
+	 *
271
+	 * @return SubSet A new sub set
272
+	 *
273
+	 * @since 1.0.0
274
+	 */
275
+	public static function view(SortedSet $set)
276
+	{
277
+		return new static($set, null, self::UNUSED, null, self::UNUSED);
278
+	}
279 279
 
280
-    /**
281
-     * Serialize the object
282
-     *
283
-     * @return array Array of values
284
-     *
285
-     * @since 1.0.0
286
-     */
287
-    public function jsonSerialize()
288
-    {
289
-        if (isset($this->from)) {
290
-            if (isset($this->to)) {
291
-                return array(
292
-                    'SubSet' => array(
293
-                        'set' => $this->set->jsonSerialize(),
294
-                        'from' => $this->from,
295
-                        'fromInclusive' => $this->fromInclusive,
296
-                        'to' => $this->to,
297
-                        'toInclusive' => $this->toInclusive,
298
-                    )
299
-                );
300
-            } else {
301
-                return array(
302
-                    'TailSet' => array(
303
-                        'set' => $this->set->jsonSerialize(),
304
-                        'from' => $this->from,
305
-                        'fromInclusive' => $this->fromInclusive,
306
-                    )
307
-                );
308
-            }
309
-        } else {
310
-            if (isset($this->to)) {
311
-                return array(
312
-                    'HeadSet' => array(
313
-                        'set' => $this->set->jsonSerialize(),
314
-                        'to' => $this->to,
315
-                        'toInclusive' => $this->toInclusive,
316
-                    )
317
-                );
318
-            } else {
319
-                return array(
320
-                    'ViewSet' => array(
321
-                        'set' => $this->set->jsonSerialize(),
322
-                    )
323
-                );
324
-            }
325
-        }
326
-    }
280
+	/**
281
+	 * Serialize the object
282
+	 *
283
+	 * @return array Array of values
284
+	 *
285
+	 * @since 1.0.0
286
+	 */
287
+	public function jsonSerialize()
288
+	{
289
+		if (isset($this->from)) {
290
+			if (isset($this->to)) {
291
+				return array(
292
+					'SubSet' => array(
293
+						'set' => $this->set->jsonSerialize(),
294
+						'from' => $this->from,
295
+						'fromInclusive' => $this->fromInclusive,
296
+						'to' => $this->to,
297
+						'toInclusive' => $this->toInclusive,
298
+					)
299
+				);
300
+			} else {
301
+				return array(
302
+					'TailSet' => array(
303
+						'set' => $this->set->jsonSerialize(),
304
+						'from' => $this->from,
305
+						'fromInclusive' => $this->fromInclusive,
306
+					)
307
+				);
308
+			}
309
+		} else {
310
+			if (isset($this->to)) {
311
+				return array(
312
+					'HeadSet' => array(
313
+						'set' => $this->set->jsonSerialize(),
314
+						'to' => $this->to,
315
+						'toInclusive' => $this->toInclusive,
316
+					)
317
+				);
318
+			} else {
319
+				return array(
320
+					'ViewSet' => array(
321
+						'set' => $this->set->jsonSerialize(),
322
+					)
323
+				);
324
+			}
325
+		}
326
+	}
327 327
 }
Please login to merge, or discard this patch.
src/SortedCollection/AbstractMap.php 1 patch
Indentation   +366 added lines, -366 removed lines patch added patch discarded remove patch
@@ -35,395 +35,395 @@
 block discarded – undo
35 35
  */
36 36
 abstract class AbstractMap implements SortedMap
37 37
 {
38
-    /**
39
-     * Magic get method
40
-     *
41
-     * @param string $property The property
42
-     *
43
-     * @throws RuntimeException If the property does not exist
44
-     *
45
-     * @return mixed The value associated to the property
46
-     *
47
-     * @since 1.0.0
48
-     */
49
-    public function __get($property)
50
-    {
51
-        switch ($property) {
52
-            case 'comparator':
53
-                return $this->comparator();
54
-            case 'firstKey':
55
-                return $this->firstKey();
56
-            case 'lastKey':
57
-                return $this->lastKey();
58
-            case 'firstValue':
59
-                return $this->firstValue();
60
-            case 'lastValue':
61
-                return $this->lastValue();
62
-            case 'first':
63
-                return $this->first();
64
-            case 'last':
65
-                return $this->last();
66
-            case 'keys':
67
-                return $this->keys();
68
-            case 'values':
69
-                return $this->values();
70
-            case 'count':
71
-                return $this->count();
72
-            default:
73
-                throw new \RuntimeException('Undefined property');
74
-        }
75
-    }
38
+	/**
39
+	 * Magic get method
40
+	 *
41
+	 * @param string $property The property
42
+	 *
43
+	 * @throws RuntimeException If the property does not exist
44
+	 *
45
+	 * @return mixed The value associated to the property
46
+	 *
47
+	 * @since 1.0.0
48
+	 */
49
+	public function __get($property)
50
+	{
51
+		switch ($property) {
52
+			case 'comparator':
53
+				return $this->comparator();
54
+			case 'firstKey':
55
+				return $this->firstKey();
56
+			case 'lastKey':
57
+				return $this->lastKey();
58
+			case 'firstValue':
59
+				return $this->firstValue();
60
+			case 'lastValue':
61
+				return $this->lastValue();
62
+			case 'first':
63
+				return $this->first();
64
+			case 'last':
65
+				return $this->last();
66
+			case 'keys':
67
+				return $this->keys();
68
+			case 'values':
69
+				return $this->values();
70
+			case 'count':
71
+				return $this->count();
72
+			default:
73
+				throw new \RuntimeException('Undefined property');
74
+		}
75
+	}
76 76
 
77
-    /**
78
-     * Get the first key
79
-     *
80
-     * @return mixed The first key
81
-     *
82
-     * @throws OutOfBoundsException If there is no element
83
-     *
84
-     * @since 1.0.0
85
-     */
86
-    public function firstKey()
87
-    {
88
-        return $this->first()->key;
89
-    }
77
+	/**
78
+	 * Get the first key
79
+	 *
80
+	 * @return mixed The first key
81
+	 *
82
+	 * @throws OutOfBoundsException If there is no element
83
+	 *
84
+	 * @since 1.0.0
85
+	 */
86
+	public function firstKey()
87
+	{
88
+		return $this->first()->key;
89
+	}
90 90
 
91
-    /**
92
-     * Get the first value
93
-     *
94
-     * @return mixed The first value
95
-     *
96
-     * @throws OutOfBoundsException If there is no element
97
-     *
98
-     * @since 1.0.0
99
-     */
100
-    public function firstValue()
101
-    {
102
-        return $this->first()->value;
103
-    }
91
+	/**
92
+	 * Get the first value
93
+	 *
94
+	 * @return mixed The first value
95
+	 *
96
+	 * @throws OutOfBoundsException If there is no element
97
+	 *
98
+	 * @since 1.0.0
99
+	 */
100
+	public function firstValue()
101
+	{
102
+		return $this->first()->value;
103
+	}
104 104
 
105
-    /**
106
-     * Get the last key
107
-     *
108
-     * @return mixed The last key
109
-     *
110
-     * @throws OutOfBoundsException If there is no element
111
-     *
112
-     * @since 1.0.0
113
-     */
114
-    public function lastKey()
115
-    {
116
-        return $this->last()->key;
117
-    }
105
+	/**
106
+	 * Get the last key
107
+	 *
108
+	 * @return mixed The last key
109
+	 *
110
+	 * @throws OutOfBoundsException If there is no element
111
+	 *
112
+	 * @since 1.0.0
113
+	 */
114
+	public function lastKey()
115
+	{
116
+		return $this->last()->key;
117
+	}
118 118
 
119
-    /**
120
-     * Get the last value
121
-     *
122
-     * @return mixed The last value
123
-     *
124
-     * @throws OutOfBoundsException If there is no element
125
-     *
126
-     * @since 1.0.0
127
-     */
128
-    public function lastValue()
129
-    {
130
-        return $this->last()->value;
131
-    }
119
+	/**
120
+	 * Get the last value
121
+	 *
122
+	 * @return mixed The last value
123
+	 *
124
+	 * @throws OutOfBoundsException If there is no element
125
+	 *
126
+	 * @since 1.0.0
127
+	 */
128
+	public function lastValue()
129
+	{
130
+		return $this->last()->value;
131
+	}
132 132
 
133
-    /**
134
-     * Returns the greatest key lesser than the given key
135
-     *
136
-     * @param mixed $key The searched key
137
-     *
138
-     * @return mixed The found key
139
-     *
140
-     * @throws OutOfBoundsException If there is no lower element
141
-     *
142
-     * @since 1.0.0
143
-     */
144
-    public function lowerKey($key)
145
-    {
146
-        return $this->lower($key)->key;
147
-    }
133
+	/**
134
+	 * Returns the greatest key lesser than the given key
135
+	 *
136
+	 * @param mixed $key The searched key
137
+	 *
138
+	 * @return mixed The found key
139
+	 *
140
+	 * @throws OutOfBoundsException If there is no lower element
141
+	 *
142
+	 * @since 1.0.0
143
+	 */
144
+	public function lowerKey($key)
145
+	{
146
+		return $this->lower($key)->key;
147
+	}
148 148
 
149
-    /**
150
-     * Returns the value whose key is the greatest key lesser than the given key
151
-     *
152
-     * @param mixed $key The searched key
153
-     *
154
-     * @return mixed The found value
155
-     *
156
-     * @throws OutOfBoundsException If there is no lower element
157
-     *
158
-     * @since 1.0.0
159
-     */
160
-    public function lowerValue($key)
161
-    {
162
-        return $this->lower($key)->value;
163
-    }
149
+	/**
150
+	 * Returns the value whose key is the greatest key lesser than the given key
151
+	 *
152
+	 * @param mixed $key The searched key
153
+	 *
154
+	 * @return mixed The found value
155
+	 *
156
+	 * @throws OutOfBoundsException If there is no lower element
157
+	 *
158
+	 * @since 1.0.0
159
+	 */
160
+	public function lowerValue($key)
161
+	{
162
+		return $this->lower($key)->value;
163
+	}
164 164
 
165
-    /**
166
-     * Returns the greatest key lesser than or equal to the given key
167
-     *
168
-     * @param mixed $key The searched key
169
-     *
170
-     * @return mixed The found key
171
-     *
172
-     * @throws OutOfBoundsException If there is no floor element
173
-     *
174
-     * @since 1.0.0
175
-     */
176
-    public function floorKey($key)
177
-    {
178
-        return $this->floor($key)->key;
179
-    }
165
+	/**
166
+	 * Returns the greatest key lesser than or equal to the given key
167
+	 *
168
+	 * @param mixed $key The searched key
169
+	 *
170
+	 * @return mixed The found key
171
+	 *
172
+	 * @throws OutOfBoundsException If there is no floor element
173
+	 *
174
+	 * @since 1.0.0
175
+	 */
176
+	public function floorKey($key)
177
+	{
178
+		return $this->floor($key)->key;
179
+	}
180 180
 
181
-    /**
182
-     * Returns the value whose key is the greatest key lesser than or equal to the given key
183
-     *
184
-     * @param mixed $key The searched key
185
-     *
186
-     * @return mixed The found value
187
-     *
188
-     * @throws OutOfBoundsException If there is no floor element
189
-     *
190
-     * @since 1.0.0
191
-     */
192
-    public function floorValue($key)
193
-    {
194
-        return $this->floor($key)->value;
195
-    }
181
+	/**
182
+	 * Returns the value whose key is the greatest key lesser than or equal to the given key
183
+	 *
184
+	 * @param mixed $key The searched key
185
+	 *
186
+	 * @return mixed The found value
187
+	 *
188
+	 * @throws OutOfBoundsException If there is no floor element
189
+	 *
190
+	 * @since 1.0.0
191
+	 */
192
+	public function floorValue($key)
193
+	{
194
+		return $this->floor($key)->value;
195
+	}
196 196
 
197
-    /**
198
-     * Returns the key equal to the given key
199
-     *
200
-     * @param mixed $key The searched key
201
-     *
202
-     * @return mixed The found key
203
-     *
204
-     * @throws OutOfBoundsException If there is no such element
205
-     *
206
-     * @since 1.0.0
207
-     */
208
-    public function findKey($key)
209
-    {
210
-        return $this->find($key)->key;
211
-    }
197
+	/**
198
+	 * Returns the key equal to the given key
199
+	 *
200
+	 * @param mixed $key The searched key
201
+	 *
202
+	 * @return mixed The found key
203
+	 *
204
+	 * @throws OutOfBoundsException If there is no such element
205
+	 *
206
+	 * @since 1.0.0
207
+	 */
208
+	public function findKey($key)
209
+	{
210
+		return $this->find($key)->key;
211
+	}
212 212
 
213
-    /**
214
-     * Returns the value whose key equal to the given key
215
-     *
216
-     * @param mixed $key The searched key
217
-     *
218
-     * @return mixed The found value
219
-     *
220
-     * @throws OutOfBoundsException If there is no such element
221
-     *
222
-     * @since 1.0.0
223
-     */
224
-    public function findValue($key)
225
-    {
226
-        return $this->find($key)->value;
227
-    }
213
+	/**
214
+	 * Returns the value whose key equal to the given key
215
+	 *
216
+	 * @param mixed $key The searched key
217
+	 *
218
+	 * @return mixed The found value
219
+	 *
220
+	 * @throws OutOfBoundsException If there is no such element
221
+	 *
222
+	 * @since 1.0.0
223
+	 */
224
+	public function findValue($key)
225
+	{
226
+		return $this->find($key)->value;
227
+	}
228 228
 
229
-    /**
230
-     * Returns the lowest key greater than or equal to the given key
231
-     *
232
-     * @param mixed $key The searched key
233
-     *
234
-     * @return mixed The found key
235
-     *
236
-     * @throws OutOfBoundsException If there is no ceiling element
237
-     *
238
-     * @since 1.0.0
239
-     */
240
-    public function ceilingKey($key)
241
-    {
242
-        return $this->ceiling($key)->key;
243
-    }
229
+	/**
230
+	 * Returns the lowest key greater than or equal to the given key
231
+	 *
232
+	 * @param mixed $key The searched key
233
+	 *
234
+	 * @return mixed The found key
235
+	 *
236
+	 * @throws OutOfBoundsException If there is no ceiling element
237
+	 *
238
+	 * @since 1.0.0
239
+	 */
240
+	public function ceilingKey($key)
241
+	{
242
+		return $this->ceiling($key)->key;
243
+	}
244 244
 
245
-    /**
246
-     * Returns the value whose key is the lowest key greater than or equal to the given key
247
-     *
248
-     * @param mixed $key The searched key
249
-     *
250
-     * @return mixed The found value
251
-     *
252
-     * @throws OutOfBoundsException If there is no ceiling element
253
-     *
254
-     * @since 1.0.0
255
-     */
256
-    public function ceilingValue($key)
257
-    {
258
-        return $this->ceiling($key)->value;
259
-    }
245
+	/**
246
+	 * Returns the value whose key is the lowest key greater than or equal to the given key
247
+	 *
248
+	 * @param mixed $key The searched key
249
+	 *
250
+	 * @return mixed The found value
251
+	 *
252
+	 * @throws OutOfBoundsException If there is no ceiling element
253
+	 *
254
+	 * @since 1.0.0
255
+	 */
256
+	public function ceilingValue($key)
257
+	{
258
+		return $this->ceiling($key)->value;
259
+	}
260 260
 
261
-    /**
262
-     * Returns the lowest key greater than to the given key
263
-     *
264
-     * @param mixed $key The searched key
265
-     *
266
-     * @return mixed The found key
267
-     *
268
-     * @throws OutOfBoundsException If there is no higher element
269
-     *
270
-     * @since 1.0.0
271
-     */
272
-    public function higherKey($key)
273
-    {
274
-        return $this->higher($key)->key;
275
-    }
261
+	/**
262
+	 * Returns the lowest key greater than to the given key
263
+	 *
264
+	 * @param mixed $key The searched key
265
+	 *
266
+	 * @return mixed The found key
267
+	 *
268
+	 * @throws OutOfBoundsException If there is no higher element
269
+	 *
270
+	 * @since 1.0.0
271
+	 */
272
+	public function higherKey($key)
273
+	{
274
+		return $this->higher($key)->key;
275
+	}
276 276
 
277
-    /**
278
-     * Returns the value whose key is the lowest key greater than to the given key
279
-     *
280
-     * @param mixed $key The searched key
281
-     *
282
-     * @return mixed The found value
283
-     *
284
-     * @throws OutOfBoundsException If there is no higher element
285
-     *
286
-     * @since 1.0.0
287
-     */
288
-    public function higherValue($key)
289
-    {
290
-        return $this->higher($key)->value;
291
-    }
277
+	/**
278
+	 * Returns the value whose key is the lowest key greater than to the given key
279
+	 *
280
+	 * @param mixed $key The searched key
281
+	 *
282
+	 * @return mixed The found value
283
+	 *
284
+	 * @throws OutOfBoundsException If there is no higher element
285
+	 *
286
+	 * @since 1.0.0
287
+	 */
288
+	public function higherValue($key)
289
+	{
290
+		return $this->higher($key)->value;
291
+	}
292 292
 
293
-    /**
294
-     * Keys iterator
295
-     *
296
-     * @return Iterator The keys iterator
297
-     *
298
-     * @since 1.0.0
299
-     */
300
-    public function keys()
301
-    {
302
-        return Iterator::keys($this);
303
-    }
293
+	/**
294
+	 * Keys iterator
295
+	 *
296
+	 * @return Iterator The keys iterator
297
+	 *
298
+	 * @since 1.0.0
299
+	 */
300
+	public function keys()
301
+	{
302
+		return Iterator::keys($this);
303
+	}
304 304
 
305
-    /**
306
-     * Values iterator
307
-     *
308
-     * @return Iterator The values iterator
309
-     *
310
-     * @since 1.0.0
311
-     */
312
-    public function values()
313
-    {
314
-        return Iterator::values($this);
315
-    }
305
+	/**
306
+	 * Values iterator
307
+	 *
308
+	 * @return Iterator The values iterator
309
+	 *
310
+	 * @since 1.0.0
311
+	 */
312
+	public function values()
313
+	{
314
+		return Iterator::values($this);
315
+	}
316 316
 
317
-    /**
318
-     * Convert the object to a string
319
-     *
320
-     * @return string String representation of the object
321
-     *
322
-     * @since 1.0.0
323
-     */
324
-    public function __toString()
325
-    {
326
-        return json_encode($this->toArray());
327
-    }
317
+	/**
318
+	 * Convert the object to a string
319
+	 *
320
+	 * @return string String representation of the object
321
+	 *
322
+	 * @since 1.0.0
323
+	 */
324
+	public function __toString()
325
+	{
326
+		return json_encode($this->toArray());
327
+	}
328 328
 
329
-    /**
330
-     * Convert the object to an array
331
-     *
332
-     * @return array Array representation of the object
333
-     *
334
-     * @since 1.0.0
335
-     */
336
-    public function toArray()
337
-    {
338
-        $array = array();
329
+	/**
330
+	 * Convert the object to an array
331
+	 *
332
+	 * @return array Array representation of the object
333
+	 *
334
+	 * @since 1.0.0
335
+	 */
336
+	public function toArray()
337
+	{
338
+		$array = array();
339 339
 
340
-        foreach ($this as $key => $value) {
341
-            $array[$key] = $value;
342
-        }
340
+		foreach ($this as $key => $value) {
341
+			$array[$key] = $value;
342
+		}
343 343
 
344
-        return $array;
345
-    }
344
+		return $array;
345
+	}
346 346
 
347
-    /**
348
-     * Create an iterator
349
-     *
350
-     * @return Iterator A new iterator
351
-     *
352
-     * @since 1.0.0
353
-     */
354
-    public function getIterator()
355
-    {
356
-        return Iterator::create($this);
357
-    }
347
+	/**
348
+	 * Create an iterator
349
+	 *
350
+	 * @return Iterator A new iterator
351
+	 *
352
+	 * @since 1.0.0
353
+	 */
354
+	public function getIterator()
355
+	{
356
+		return Iterator::create($this);
357
+	}
358 358
 
359
-    /**
360
-     * Get the value for a key
361
-     *
362
-     * @param mixed $key The key
363
-     *
364
-     * @return mixed The found value
365
-     *
366
-     * @throws OutOfRangeException If there is no such element
367
-     *
368
-     * @since 1.0.0
369
-     */
370
-    public function offsetGet($key)
371
-    {
372
-        try {
373
-            return $this->find($key)->value;
374
-        } catch (\OutOfBoundsException $e) {
375
-            throw new \OutOfRangeException('Undefined offset');
376
-        }
377
-    }
359
+	/**
360
+	 * Get the value for a key
361
+	 *
362
+	 * @param mixed $key The key
363
+	 *
364
+	 * @return mixed The found value
365
+	 *
366
+	 * @throws OutOfRangeException If there is no such element
367
+	 *
368
+	 * @since 1.0.0
369
+	 */
370
+	public function offsetGet($key)
371
+	{
372
+		try {
373
+			return $this->find($key)->value;
374
+		} catch (\OutOfBoundsException $e) {
375
+			throw new \OutOfRangeException('Undefined offset');
376
+		}
377
+	}
378 378
 
379
-    /**
380
-     * Test the existence of a key
381
-     *
382
-     * @param mixed $key The key
383
-     *
384
-     * @return boolean TRUE if the key exists, false otherwise
385
-     *
386
-     * @since 1.0.0
387
-     */
388
-    public function offsetExists($key)
389
-    {
390
-        try {
391
-            return (bool) $this->find($key);
392
-        } catch (\OutOfBoundsException $e) {
393
-            return false;
394
-        }
395
-    }
379
+	/**
380
+	 * Test the existence of a key
381
+	 *
382
+	 * @param mixed $key The key
383
+	 *
384
+	 * @return boolean TRUE if the key exists, false otherwise
385
+	 *
386
+	 * @since 1.0.0
387
+	 */
388
+	public function offsetExists($key)
389
+	{
390
+		try {
391
+			return (bool) $this->find($key);
392
+		} catch (\OutOfBoundsException $e) {
393
+			return false;
394
+		}
395
+	}
396 396
 
397
-    /**
398
-     * Set the value for a key
399
-     *
400
-     * @param mixed $key   The key
401
-     * @param mixed $value The value
402
-     *
403
-     * @return void
404
-     *
405
-     * @throws RuntimeOperation The operation is not supported by this class
406
-     *
407
-     * @since 1.0.0
408
-     */
409
-    public function offsetSet($key, $value)
410
-    {
411
-        throw new \RuntimeException('Unsupported operation');
412
-    }
397
+	/**
398
+	 * Set the value for a key
399
+	 *
400
+	 * @param mixed $key   The key
401
+	 * @param mixed $value The value
402
+	 *
403
+	 * @return void
404
+	 *
405
+	 * @throws RuntimeOperation The operation is not supported by this class
406
+	 *
407
+	 * @since 1.0.0
408
+	 */
409
+	public function offsetSet($key, $value)
410
+	{
411
+		throw new \RuntimeException('Unsupported operation');
412
+	}
413 413
 
414
-    /**
415
-     * Unset the existence of a key
416
-     *
417
-     * @param mixed $key The key
418
-     *
419
-     * @return void
420
-     *
421
-     * @throws RuntimeOperation The operation is not supported by this class
422
-     *
423
-     * @since 1.0.0
424
-     */
425
-    public function offsetUnset($key)
426
-    {
427
-        throw new \RuntimeException('Unsupported operation');
428
-    }
414
+	/**
415
+	 * Unset the existence of a key
416
+	 *
417
+	 * @param mixed $key The key
418
+	 *
419
+	 * @return void
420
+	 *
421
+	 * @throws RuntimeOperation The operation is not supported by this class
422
+	 *
423
+	 * @since 1.0.0
424
+	 */
425
+	public function offsetUnset($key)
426
+	{
427
+		throw new \RuntimeException('Unsupported operation');
428
+	}
429 429
 }
Please login to merge, or discard this patch.
src/SortedCollection/TreeNode.php 1 patch
Indentation   +539 added lines, -539 removed lines patch added patch discarded remove patch
@@ -30,543 +30,543 @@
 block discarded – undo
30 30
  */
31 31
 class TreeNode implements \Countable
32 32
 {
33
-    /**
34
-     * @var integer  Information associated to that node.
35
-     *                   Bits of order 0 and 1 are reserved for the existence of left and right tree.
36
-     *                   Other bits are for the balance
37
-     *
38
-     * @since 1.0.0
39
-     */
40
-    private $information = 0;
41
-
42
-    /**
43
-     * @var TreeNode  Left|Predecessor node
44
-     *
45
-     * @since 1.0.0
46
-     */
47
-    private $left;
48
-
49
-    /**
50
-     * @var TreeNode  Right|Successor node
51
-     *
52
-     * @since 1.0.0
53
-     */
54
-    private $right;
55
-
56
-    /**
57
-     * @var mixed  Node key
58
-     *
59
-     * @since 1.0.0
60
-     */
61
-    private $key;
62
-
63
-    /**
64
-     * @var mixed  Node value
65
-     *
66
-     * @since 1.0.0
67
-     */
68
-    public $value;
69
-
70
-    /**
71
-     * Create a node
72
-     *
73
-     * @param mixed $key   The node key
74
-     * @param mixed $value The node value
75
-     *
76
-     * @return A new node
77
-     *
78
-     * @since 1.0.0
79
-     */
80
-    public static function create($key, $value)
81
-    {
82
-        return new static($key, $value);
83
-    }
84
-
85
-    /**
86
-     * Constructor
87
-     *
88
-     * @param mixed    $key         The node key
89
-     * @param mixed    $value       The node value
90
-     * @param TreeNode $predecessor The left node
91
-     * @param TreeNode $successor   The right node
92
-     *
93
-     * @since 1.0.0
94
-     */
95
-    protected function __construct($key, $value, $predecessor = null, $successor = null)
96
-    {
97
-        $this->key = $key;
98
-        $this->value = $value;
99
-        $this->left = $predecessor;
100
-        $this->right = $successor;
101
-    }
102
-
103
-    /**
104
-     * Magic get method
105
-     *
106
-     * @param string $property The node property
107
-     *
108
-     * @return mixed The value associated to the property
109
-     *
110
-     * @throws RuntimeException If the property is undefined
111
-     *
112
-     * @since 1.0.0
113
-     */
114
-    public function __get($property)
115
-    {
116
-        switch ($property) {
117
-            case 'first':
118
-                return $this->first();
119
-            case 'last':
120
-                return $this->last();
121
-            case 'predecessor':
122
-                return $this->predecessor();
123
-            case 'successor':
124
-                return $this->successor();
125
-            case 'key':
126
-                return $this->key;
127
-            case 'count':
128
-                return $this->count();
129
-            default:
130
-                throw new \RuntimeException('Undefined property');
131
-        }
132
-    }
133
-
134
-    /**
135
-     * Get the first node
136
-     *
137
-     * @return the first node
138
-     *
139
-     * @since 1.0.0
140
-     */
141
-    public function first()
142
-    {
143
-        $node = $this;
144
-
145
-        while ($node->information & 2) {
146
-            $node = $node->left;
147
-        }
148
-
149
-        return $node;
150
-    }
151
-
152
-    /**
153
-     * Get the last node
154
-     *
155
-     * @return the last node
156
-     *
157
-     * @since 1.0.0
158
-     */
159
-    public function last()
160
-    {
161
-        $node = $this;
162
-
163
-        while ($node->information & 1) {
164
-            $node = $node->right;
165
-        }
166
-
167
-        return $node;
168
-    }
169
-
170
-    /**
171
-     * Get the predecessor
172
-     *
173
-     * @return the predecessor node
174
-     *
175
-     * @since 1.0.0
176
-     */
177
-    public function predecessor()
178
-    {
179
-        if ($this->information & 2) {
180
-            $node = $this->left;
181
-
182
-            while ($node->information & 1) {
183
-                $node = $node->right;
184
-            }
185
-
186
-            return $node;
187
-        } else {
188
-            return $this->left;
189
-        }
190
-    }
191
-
192
-    /**
193
-     * Get the successor
194
-     *
195
-     * @return the successor node
196
-     *
197
-     * @since 1.0.0
198
-     */
199
-    public function successor()
200
-    {
201
-        if ($this->information & 1) {
202
-            $node = $this->right;
203
-
204
-            while ($node->information & 2) {
205
-                $node = $node->left;
206
-            }
207
-
208
-            return $node;
209
-        } else {
210
-            return $this->right;
211
-        }
212
-    }
213
-
214
-    /**
215
-     * Count the number of key/value pair
216
-     *
217
-     * @return integer
218
-     *
219
-     * @since 1.0.0
220
-     */
221
-    public function count()
222
-    {
223
-        $count = 1;
224
-
225
-        if ($this->information & 2) {
226
-            $count += $this->left->count;
227
-        }
228
-
229
-        if ($this->information & 1) {
230
-            $count += $this->right->count;
231
-        }
232
-
233
-        return $count;
234
-    }
235
-
236
-    /**
237
-     * Get the node for a key
238
-     *
239
-     * @param mixed    $key        The key
240
-     * @param callable $comparator The comparator function
241
-     * @param integer  $type       The operation type
242
-     *                             -2 for the
243
-     *                             greatest key
244
-     *                             lesser than the
245
-     *                             given key -1 for
246
-     *                             the greatest key
247
-     *                             lesser than or
248
-     *                             equal to the given
249
-     *                             key 0 for the
250
-     *                             given key +1 for
251
-     *                             the lowest key
252
-     *                             greater than or
253
-     *                             equal to the given
254
-     *                             key +2 for the
255
-     *                             lowest key greater
256
-     *                             than the given key
257
-     *
258
-     * @return mixed The node or null if not found
259
-     *
260
-     * @since 1.0.0
261
-     */
262
-    public function find($key, $comparator, $type = 0)
263
-    {
264
-        $node = $this;
265
-
266
-        while (true) {
267
-            $cmp = call_user_func($comparator, $key, $node->key);
268
-
269
-            if ($cmp < 0 && $node->information & 2) {
270
-                $node = $node->left;
271
-            } elseif ($cmp > 0 && $node->information & 1) {
272
-                $node = $node->right;
273
-            } else {
274
-                break;
275
-            }
276
-        }
277
-
278
-        if ($cmp < 0) {
279
-            if ($type < 0) {
280
-                return $node->left;
281
-            } elseif ($type > 0) {
282
-                return $node;
283
-            } else {
284
-                return null;
285
-            }
286
-        } elseif ($cmp > 0) {
287
-            if ($type < 0) {
288
-                return $node;
289
-            } elseif ($type > 0) {
290
-                return $node->right;
291
-            } else {
292
-                return null;
293
-            }
294
-        } else {
295
-            if ($type < -1) {
296
-                return $node->predecessor;
297
-            } elseif ($type > 1) {
298
-                return $node->successor;
299
-            } else {
300
-                return $node;
301
-            }
302
-        }
303
-    }
304
-
305
-    /**
306
-     * Rotate the node to the left
307
-     *
308
-     * @return TreeNode The rotated node
309
-     *
310
-     * @since 1.0.0
311
-     */
312
-    private function rotateLeft()
313
-    {
314
-        $right = $this->right;
315
-
316
-        if ($right->information & 2) {
317
-            $this->right = $right->left;
318
-            $right->left = $this;
319
-        } else {
320
-            $right->information |= 2;
321
-            $this->information &= ~ 1;
322
-        }
323
-
324
-        $this->information -= 4;
325
-
326
-        if ($right->information >= 4) {
327
-            $this->information -= $right->information & ~3;
328
-        }
329
-
330
-        $right->information -= 4;
331
-
332
-        if ($this->information < 0) {
333
-            $right->information += $this->information & ~3;
334
-        }
335
-
336
-        return $right;
337
-    }
338
-
339
-    /**
340
-     * Rotate the node to the right
341
-     *
342
-     * @return TreeNode The rotated node
343
-     *
344
-     * @since 1.0.0
345
-     */
346
-    private function rotateRight()
347
-    {
348
-        $left = $this->left;
349
-
350
-        if ($left->information & 1) {
351
-            $this->left = $left->right;
352
-            $left->right = $this;
353
-        } else {
354
-            $this->information &= ~ 2;
355
-            $left->information |= 1;
356
-        }
357
-
358
-        $this->information += 4;
359
-
360
-        if ($left->information < 0) {
361
-            $this->information -= $left->information & ~3;
362
-        }
363
-
364
-        $left->information += 4;
365
-
366
-        if ($this->information >= 4) {
367
-            $left->information += $this->information & ~3;
368
-        }
369
-
370
-        return $left;
371
-    }
372
-
373
-    /**
374
-     * Increment the balance of the node
375
-     *
376
-     * @return TreeNode $this or a rotated version of $this
377
-     *
378
-     * @since 1.0.0
379
-     */
380
-    private function incBalance()
381
-    {
382
-        $this->information += 4;
383
-
384
-        if ($this->information >= 8) {
385
-            if ($this->right->information < 0) {
386
-                $this->right = $this->right->rotateRight();
387
-            }
388
-
389
-            return $this->rotateLeft();
390
-        }
391
-
392
-        return $this;
393
-    }
394
-
395
-    /**
396
-     * Decrement the balance of the node
397
-     *
398
-     * @return TreeNode $this or a rotated version of $this
399
-     *
400
-     * @since 1.0.0
401
-     */
402
-    private function decBalance()
403
-    {
404
-        $this->information -= 4;
405
-
406
-        if ($this->information < - 4) {
407
-            if ($this->left->information >= 4) {
408
-                $this->left = $this->left->rotateLeft();
409
-            }
410
-
411
-            return $this->rotateRight();
412
-        }
413
-
414
-        return $this;
415
-    }
416
-
417
-    /**
418
-     * Insert a key/value pair
419
-     *
420
-     * @param mixed    $key        The key
421
-     * @param mixed    $value      The value
422
-     * @param callable $comparator The comparator function
423
-     *
424
-     * @return TreeNode The new root
425
-     *
426
-     * @since 1.0.0
427
-     */
428
-    public function insert($key, $value, $comparator)
429
-    {
430
-        $node = $this;
431
-        $cmp = call_user_func($comparator, $key, $this->key);
432
-
433
-        if ($cmp < 0) {
434
-            if ($this->information & 2) {
435
-                $leftBalance = $this->left->information & ~3;
436
-                $this->left = $this->left->insert($key, $value, $comparator);
437
-
438
-                if (($this->left->information & ~3) && ($this->left->information & ~3) != $leftBalance) {
439
-                    $node = $this->decBalance();
440
-                }
441
-            } else {
442
-                $this->left = new static($key, $value, $this->left, $this);
443
-                $this->information |= 2;
444
-                $node = $this->decBalance();
445
-            }
446
-        } elseif ($cmp > 0) {
447
-            if ($this->information & 1) {
448
-                $rightBalance = $this->right->information & ~3;
449
-                $this->right = $this->right->insert($key, $value, $comparator);
450
-
451
-                if (($this->right->information & ~3) && ($this->right->information & ~3) != $rightBalance) {
452
-                    $node = $this->incBalance();
453
-                }
454
-            } else {
455
-                $this->right = new static($key, $value, $this, $this->right);
456
-                $this->information |= 1;
457
-                $node = $this->incBalance();
458
-            }
459
-        } else {
460
-            $this->value = $value;
461
-        }
462
-
463
-        return $node;
464
-    }
465
-
466
-    /**
467
-     * Pull up the left most node of a node
468
-     *
469
-     * @return TreeNode The new root
470
-     *
471
-     * @since 1.0.0
472
-     */
473
-    private function pullUpLeftMost()
474
-    {
475
-        if ($this->information & 2) {
476
-            $leftBalance = $this->left->information & ~3;
477
-            $this->left = $this->left->pullUpLeftMost();
478
-
479
-            if (!($this->information & 2) || $leftBalance != 0 && ($this->left->information & ~3) == 0) {
480
-                return $this->incBalance();
481
-            } else {
482
-                return $this;
483
-            }
484
-        } else {
485
-            $this->left->key = $this->key;
486
-            $this->left->value = $this->value;
487
-
488
-            if ($this->information & 1) {
489
-                $this->right->left = $this->left;
490
-
491
-                return $this->right;
492
-            } else {
493
-                if ($this->left->right == $this) {
494
-                    $this->left->information &= ~ 1;
495
-
496
-                    return $this->right;
497
-                } else {
498
-                    $this->right->information &= ~ 2;
499
-
500
-                    return $this->left;
501
-                }
502
-            }
503
-        }
504
-    }
505
-
506
-    /**
507
-     * Remove a key
508
-     *
509
-     * @param mixed    $key        The key
510
-     * @param callable $comparator The comparator function
511
-     *
512
-     * @return TreeNode The new root
513
-     *
514
-     * @since 1.0.0
515
-     */
516
-    public function remove($key, $comparator)
517
-    {
518
-        $cmp = call_user_func($comparator, $key, $this->key);
519
-
520
-        if ($cmp < 0) {
521
-            if ($this->information & 2) {
522
-                $leftBalance = $this->left->information & ~3;
523
-                $this->left = $this->left->remove($key, $comparator);
524
-
525
-                if (!($this->information & 2) || $leftBalance != 0 && ($this->left->information & ~3) == 0) {
526
-                    return $this->incBalance();
527
-                }
528
-            }
529
-        } elseif ($cmp > 0) {
530
-            if ($this->information & 1) {
531
-                $rightBalance = $this->right->information & ~3;
532
-                $this->right = $this->right->remove($key, $comparator);
533
-
534
-                if (!($this->information & 1) || $rightBalance != 0 && ($this->right->information & ~3) == 0) {
535
-                    return $this->decBalance();
536
-                }
537
-            }
538
-        } else {
539
-            if ($this->information & 1) {
540
-                $rightBalance = $this->right->information & ~3;
541
-                $this->right = $this->right->pullUpLeftMost();
542
-
543
-                if (!($this->information & 1) || $rightBalance != 0 && ($this->right->information & ~3) == 0) {
544
-                    return $this->decBalance();
545
-                }
546
-            } else {
547
-                $left = $this->left;
548
-                $right = $this->right;
549
-
550
-                if ($this->information & 2) {
551
-                    $left->right = $right;
552
-
553
-                    return $left;
554
-                } else {
555
-                    if ($left && $left->right == $this) {
556
-                        $left->information &= ~ 1;
557
-
558
-                        return $right;
559
-                    } elseif ($right && $right->left == $this) {
560
-                        $right->information &= ~ 2;
561
-
562
-                        return $left;
563
-                    } else {
564
-                        return null;
565
-                    }
566
-                }
567
-            }
568
-        }
569
-
570
-        return $this;
571
-    }
33
+	/**
34
+	 * @var integer  Information associated to that node.
35
+	 *                   Bits of order 0 and 1 are reserved for the existence of left and right tree.
36
+	 *                   Other bits are for the balance
37
+	 *
38
+	 * @since 1.0.0
39
+	 */
40
+	private $information = 0;
41
+
42
+	/**
43
+	 * @var TreeNode  Left|Predecessor node
44
+	 *
45
+	 * @since 1.0.0
46
+	 */
47
+	private $left;
48
+
49
+	/**
50
+	 * @var TreeNode  Right|Successor node
51
+	 *
52
+	 * @since 1.0.0
53
+	 */
54
+	private $right;
55
+
56
+	/**
57
+	 * @var mixed  Node key
58
+	 *
59
+	 * @since 1.0.0
60
+	 */
61
+	private $key;
62
+
63
+	/**
64
+	 * @var mixed  Node value
65
+	 *
66
+	 * @since 1.0.0
67
+	 */
68
+	public $value;
69
+
70
+	/**
71
+	 * Create a node
72
+	 *
73
+	 * @param mixed $key   The node key
74
+	 * @param mixed $value The node value
75
+	 *
76
+	 * @return A new node
77
+	 *
78
+	 * @since 1.0.0
79
+	 */
80
+	public static function create($key, $value)
81
+	{
82
+		return new static($key, $value);
83
+	}
84
+
85
+	/**
86
+	 * Constructor
87
+	 *
88
+	 * @param mixed    $key         The node key
89
+	 * @param mixed    $value       The node value
90
+	 * @param TreeNode $predecessor The left node
91
+	 * @param TreeNode $successor   The right node
92
+	 *
93
+	 * @since 1.0.0
94
+	 */
95
+	protected function __construct($key, $value, $predecessor = null, $successor = null)
96
+	{
97
+		$this->key = $key;
98
+		$this->value = $value;
99
+		$this->left = $predecessor;
100
+		$this->right = $successor;
101
+	}
102
+
103
+	/**
104
+	 * Magic get method
105
+	 *
106
+	 * @param string $property The node property
107
+	 *
108
+	 * @return mixed The value associated to the property
109
+	 *
110
+	 * @throws RuntimeException If the property is undefined
111
+	 *
112
+	 * @since 1.0.0
113
+	 */
114
+	public function __get($property)
115
+	{
116
+		switch ($property) {
117
+			case 'first':
118
+				return $this->first();
119
+			case 'last':
120
+				return $this->last();
121
+			case 'predecessor':
122
+				return $this->predecessor();
123
+			case 'successor':
124
+				return $this->successor();
125
+			case 'key':
126
+				return $this->key;
127
+			case 'count':
128
+				return $this->count();
129
+			default:
130
+				throw new \RuntimeException('Undefined property');
131
+		}
132
+	}
133
+
134
+	/**
135
+	 * Get the first node
136
+	 *
137
+	 * @return the first node
138
+	 *
139
+	 * @since 1.0.0
140
+	 */
141
+	public function first()
142
+	{
143
+		$node = $this;
144
+
145
+		while ($node->information & 2) {
146
+			$node = $node->left;
147
+		}
148
+
149
+		return $node;
150
+	}
151
+
152
+	/**
153
+	 * Get the last node
154
+	 *
155
+	 * @return the last node
156
+	 *
157
+	 * @since 1.0.0
158
+	 */
159
+	public function last()
160
+	{
161
+		$node = $this;
162
+
163
+		while ($node->information & 1) {
164
+			$node = $node->right;
165
+		}
166
+
167
+		return $node;
168
+	}
169
+
170
+	/**
171
+	 * Get the predecessor
172
+	 *
173
+	 * @return the predecessor node
174
+	 *
175
+	 * @since 1.0.0
176
+	 */
177
+	public function predecessor()
178
+	{
179
+		if ($this->information & 2) {
180
+			$node = $this->left;
181
+
182
+			while ($node->information & 1) {
183
+				$node = $node->right;
184
+			}
185
+
186
+			return $node;
187
+		} else {
188
+			return $this->left;
189
+		}
190
+	}
191
+
192
+	/**
193
+	 * Get the successor
194
+	 *
195
+	 * @return the successor node
196
+	 *
197
+	 * @since 1.0.0
198
+	 */
199
+	public function successor()
200
+	{
201
+		if ($this->information & 1) {
202
+			$node = $this->right;
203
+
204
+			while ($node->information & 2) {
205
+				$node = $node->left;
206
+			}
207
+
208
+			return $node;
209
+		} else {
210
+			return $this->right;
211
+		}
212
+	}
213
+
214
+	/**
215
+	 * Count the number of key/value pair
216
+	 *
217
+	 * @return integer
218
+	 *
219
+	 * @since 1.0.0
220
+	 */
221
+	public function count()
222
+	{
223
+		$count = 1;
224
+
225
+		if ($this->information & 2) {
226
+			$count += $this->left->count;
227
+		}
228
+
229
+		if ($this->information & 1) {
230
+			$count += $this->right->count;
231
+		}
232
+
233
+		return $count;
234
+	}
235
+
236
+	/**
237
+	 * Get the node for a key
238
+	 *
239
+	 * @param mixed    $key        The key
240
+	 * @param callable $comparator The comparator function
241
+	 * @param integer  $type       The operation type
242
+	 *                             -2 for the
243
+	 *                             greatest key
244
+	 *                             lesser than the
245
+	 *                             given key -1 for
246
+	 *                             the greatest key
247
+	 *                             lesser than or
248
+	 *                             equal to the given
249
+	 *                             key 0 for the
250
+	 *                             given key +1 for
251
+	 *                             the lowest key
252
+	 *                             greater than or
253
+	 *                             equal to the given
254
+	 *                             key +2 for the
255
+	 *                             lowest key greater
256
+	 *                             than the given key
257
+	 *
258
+	 * @return mixed The node or null if not found
259
+	 *
260
+	 * @since 1.0.0
261
+	 */
262
+	public function find($key, $comparator, $type = 0)
263
+	{
264
+		$node = $this;
265
+
266
+		while (true) {
267
+			$cmp = call_user_func($comparator, $key, $node->key);
268
+
269
+			if ($cmp < 0 && $node->information & 2) {
270
+				$node = $node->left;
271
+			} elseif ($cmp > 0 && $node->information & 1) {
272
+				$node = $node->right;
273
+			} else {
274
+				break;
275
+			}
276
+		}
277
+
278
+		if ($cmp < 0) {
279
+			if ($type < 0) {
280
+				return $node->left;
281
+			} elseif ($type > 0) {
282
+				return $node;
283
+			} else {
284
+				return null;
285
+			}
286
+		} elseif ($cmp > 0) {
287
+			if ($type < 0) {
288
+				return $node;
289
+			} elseif ($type > 0) {
290
+				return $node->right;
291
+			} else {
292
+				return null;
293
+			}
294
+		} else {
295
+			if ($type < -1) {
296
+				return $node->predecessor;
297
+			} elseif ($type > 1) {
298
+				return $node->successor;
299
+			} else {
300
+				return $node;
301
+			}
302
+		}
303
+	}
304
+
305
+	/**
306
+	 * Rotate the node to the left
307
+	 *
308
+	 * @return TreeNode The rotated node
309
+	 *
310
+	 * @since 1.0.0
311
+	 */
312
+	private function rotateLeft()
313
+	{
314
+		$right = $this->right;
315
+
316
+		if ($right->information & 2) {
317
+			$this->right = $right->left;
318
+			$right->left = $this;
319
+		} else {
320
+			$right->information |= 2;
321
+			$this->information &= ~ 1;
322
+		}
323
+
324
+		$this->information -= 4;
325
+
326
+		if ($right->information >= 4) {
327
+			$this->information -= $right->information & ~3;
328
+		}
329
+
330
+		$right->information -= 4;
331
+
332
+		if ($this->information < 0) {
333
+			$right->information += $this->information & ~3;
334
+		}
335
+
336
+		return $right;
337
+	}
338
+
339
+	/**
340
+	 * Rotate the node to the right
341
+	 *
342
+	 * @return TreeNode The rotated node
343
+	 *
344
+	 * @since 1.0.0
345
+	 */
346
+	private function rotateRight()
347
+	{
348
+		$left = $this->left;
349
+
350
+		if ($left->information & 1) {
351
+			$this->left = $left->right;
352
+			$left->right = $this;
353
+		} else {
354
+			$this->information &= ~ 2;
355
+			$left->information |= 1;
356
+		}
357
+
358
+		$this->information += 4;
359
+
360
+		if ($left->information < 0) {
361
+			$this->information -= $left->information & ~3;
362
+		}
363
+
364
+		$left->information += 4;
365
+
366
+		if ($this->information >= 4) {
367
+			$left->information += $this->information & ~3;
368
+		}
369
+
370
+		return $left;
371
+	}
372
+
373
+	/**
374
+	 * Increment the balance of the node
375
+	 *
376
+	 * @return TreeNode $this or a rotated version of $this
377
+	 *
378
+	 * @since 1.0.0
379
+	 */
380
+	private function incBalance()
381
+	{
382
+		$this->information += 4;
383
+
384
+		if ($this->information >= 8) {
385
+			if ($this->right->information < 0) {
386
+				$this->right = $this->right->rotateRight();
387
+			}
388
+
389
+			return $this->rotateLeft();
390
+		}
391
+
392
+		return $this;
393
+	}
394
+
395
+	/**
396
+	 * Decrement the balance of the node
397
+	 *
398
+	 * @return TreeNode $this or a rotated version of $this
399
+	 *
400
+	 * @since 1.0.0
401
+	 */
402
+	private function decBalance()
403
+	{
404
+		$this->information -= 4;
405
+
406
+		if ($this->information < - 4) {
407
+			if ($this->left->information >= 4) {
408
+				$this->left = $this->left->rotateLeft();
409
+			}
410
+
411
+			return $this->rotateRight();
412
+		}
413
+
414
+		return $this;
415
+	}
416
+
417
+	/**
418
+	 * Insert a key/value pair
419
+	 *
420
+	 * @param mixed    $key        The key
421
+	 * @param mixed    $value      The value
422
+	 * @param callable $comparator The comparator function
423
+	 *
424
+	 * @return TreeNode The new root
425
+	 *
426
+	 * @since 1.0.0
427
+	 */
428
+	public function insert($key, $value, $comparator)
429
+	{
430
+		$node = $this;
431
+		$cmp = call_user_func($comparator, $key, $this->key);
432
+
433
+		if ($cmp < 0) {
434
+			if ($this->information & 2) {
435
+				$leftBalance = $this->left->information & ~3;
436
+				$this->left = $this->left->insert($key, $value, $comparator);
437
+
438
+				if (($this->left->information & ~3) && ($this->left->information & ~3) != $leftBalance) {
439
+					$node = $this->decBalance();
440
+				}
441
+			} else {
442
+				$this->left = new static($key, $value, $this->left, $this);
443
+				$this->information |= 2;
444
+				$node = $this->decBalance();
445
+			}
446
+		} elseif ($cmp > 0) {
447
+			if ($this->information & 1) {
448
+				$rightBalance = $this->right->information & ~3;
449
+				$this->right = $this->right->insert($key, $value, $comparator);
450
+
451
+				if (($this->right->information & ~3) && ($this->right->information & ~3) != $rightBalance) {
452
+					$node = $this->incBalance();
453
+				}
454
+			} else {
455
+				$this->right = new static($key, $value, $this, $this->right);
456
+				$this->information |= 1;
457
+				$node = $this->incBalance();
458
+			}
459
+		} else {
460
+			$this->value = $value;
461
+		}
462
+
463
+		return $node;
464
+	}
465
+
466
+	/**
467
+	 * Pull up the left most node of a node
468
+	 *
469
+	 * @return TreeNode The new root
470
+	 *
471
+	 * @since 1.0.0
472
+	 */
473
+	private function pullUpLeftMost()
474
+	{
475
+		if ($this->information & 2) {
476
+			$leftBalance = $this->left->information & ~3;
477
+			$this->left = $this->left->pullUpLeftMost();
478
+
479
+			if (!($this->information & 2) || $leftBalance != 0 && ($this->left->information & ~3) == 0) {
480
+				return $this->incBalance();
481
+			} else {
482
+				return $this;
483
+			}
484
+		} else {
485
+			$this->left->key = $this->key;
486
+			$this->left->value = $this->value;
487
+
488
+			if ($this->information & 1) {
489
+				$this->right->left = $this->left;
490
+
491
+				return $this->right;
492
+			} else {
493
+				if ($this->left->right == $this) {
494
+					$this->left->information &= ~ 1;
495
+
496
+					return $this->right;
497
+				} else {
498
+					$this->right->information &= ~ 2;
499
+
500
+					return $this->left;
501
+				}
502
+			}
503
+		}
504
+	}
505
+
506
+	/**
507
+	 * Remove a key
508
+	 *
509
+	 * @param mixed    $key        The key
510
+	 * @param callable $comparator The comparator function
511
+	 *
512
+	 * @return TreeNode The new root
513
+	 *
514
+	 * @since 1.0.0
515
+	 */
516
+	public function remove($key, $comparator)
517
+	{
518
+		$cmp = call_user_func($comparator, $key, $this->key);
519
+
520
+		if ($cmp < 0) {
521
+			if ($this->information & 2) {
522
+				$leftBalance = $this->left->information & ~3;
523
+				$this->left = $this->left->remove($key, $comparator);
524
+
525
+				if (!($this->information & 2) || $leftBalance != 0 && ($this->left->information & ~3) == 0) {
526
+					return $this->incBalance();
527
+				}
528
+			}
529
+		} elseif ($cmp > 0) {
530
+			if ($this->information & 1) {
531
+				$rightBalance = $this->right->information & ~3;
532
+				$this->right = $this->right->remove($key, $comparator);
533
+
534
+				if (!($this->information & 1) || $rightBalance != 0 && ($this->right->information & ~3) == 0) {
535
+					return $this->decBalance();
536
+				}
537
+			}
538
+		} else {
539
+			if ($this->information & 1) {
540
+				$rightBalance = $this->right->information & ~3;
541
+				$this->right = $this->right->pullUpLeftMost();
542
+
543
+				if (!($this->information & 1) || $rightBalance != 0 && ($this->right->information & ~3) == 0) {
544
+					return $this->decBalance();
545
+				}
546
+			} else {
547
+				$left = $this->left;
548
+				$right = $this->right;
549
+
550
+				if ($this->information & 2) {
551
+					$left->right = $right;
552
+
553
+					return $left;
554
+				} else {
555
+					if ($left && $left->right == $this) {
556
+						$left->information &= ~ 1;
557
+
558
+						return $right;
559
+					} elseif ($right && $right->left == $this) {
560
+						$right->information &= ~ 2;
561
+
562
+						return $left;
563
+					} else {
564
+						return null;
565
+					}
566
+				}
567
+			}
568
+		}
569
+
570
+		return $this;
571
+	}
572 572
 }
Please login to merge, or discard this patch.
src/SortedCollection/SortedMap.php 1 patch
Indentation   +116 added lines, -116 removed lines patch added patch discarded remove patch
@@ -24,130 +24,130 @@
 block discarded – undo
24 24
  */
25 25
 interface SortedMap extends SortedCollection
26 26
 {
27
-    /**
28
-     * Get the first key or throw an exception if there is no element
29
-     *
30
-     * @return mixed The first key
31
-     *
32
-     * @throws OutOfBoundsException If there is no element
33
-     *
34
-     * @since 1.0.0
35
-     */
36
-    public function firstKey();
27
+	/**
28
+	 * Get the first key or throw an exception if there is no element
29
+	 *
30
+	 * @return mixed The first key
31
+	 *
32
+	 * @throws OutOfBoundsException If there is no element
33
+	 *
34
+	 * @since 1.0.0
35
+	 */
36
+	public function firstKey();
37 37
 
38
-    /**
39
-     * Get the last key or throw an exception if there is no element
40
-     *
41
-     * @return mixed The last key
42
-     *
43
-     * @throws OutOfBoundsException If there is no element
44
-     *
45
-     * @since 1.0.0
46
-     */
47
-    public function lastKey();
38
+	/**
39
+	 * Get the last key or throw an exception if there is no element
40
+	 *
41
+	 * @return mixed The last key
42
+	 *
43
+	 * @throws OutOfBoundsException If there is no element
44
+	 *
45
+	 * @since 1.0.0
46
+	 */
47
+	public function lastKey();
48 48
 
49
-    /**
50
-     * Returns the greatest key lesser than the given key or throw an exception if there is no such key
51
-     *
52
-     * @param mixed $key The searched key
53
-     *
54
-     * @return mixed The found key
55
-     *
56
-     * @throws OutOfBoundsException If there is no lower element
57
-     *
58
-     * @since 1.0.0
59
-     */
60
-    public function lowerKey($key);
49
+	/**
50
+	 * Returns the greatest key lesser than the given key or throw an exception if there is no such key
51
+	 *
52
+	 * @param mixed $key The searched key
53
+	 *
54
+	 * @return mixed The found key
55
+	 *
56
+	 * @throws OutOfBoundsException If there is no lower element
57
+	 *
58
+	 * @since 1.0.0
59
+	 */
60
+	public function lowerKey($key);
61 61
 
62
-    /**
63
-     * Returns the greatest key lesser than or equal to the given key or throw an exception if there is no such key
64
-     *
65
-     * @param mixed $key The searched key
66
-     *
67
-     * @return mixed The found key
68
-     *
69
-     * @throws OutOfBoundsException If there is no floor element
70
-     *
71
-     * @since 1.0.0
72
-     */
73
-    public function floorKey($key);
62
+	/**
63
+	 * Returns the greatest key lesser than or equal to the given key or throw an exception if there is no such key
64
+	 *
65
+	 * @param mixed $key The searched key
66
+	 *
67
+	 * @return mixed The found key
68
+	 *
69
+	 * @throws OutOfBoundsException If there is no floor element
70
+	 *
71
+	 * @since 1.0.0
72
+	 */
73
+	public function floorKey($key);
74 74
 
75
-    /**
76
-     * Returns the key equal to the given key or throw an exception if there is no such key
77
-     *
78
-     * @param mixed $key The searched key
79
-     *
80
-     * @return mixed The found key
81
-     *
82
-     * @throws OutOfBoundsException If there is no such element
83
-     *
84
-     * @since 1.0.0
85
-     */
86
-    public function findKey($key);
75
+	/**
76
+	 * Returns the key equal to the given key or throw an exception if there is no such key
77
+	 *
78
+	 * @param mixed $key The searched key
79
+	 *
80
+	 * @return mixed The found key
81
+	 *
82
+	 * @throws OutOfBoundsException If there is no such element
83
+	 *
84
+	 * @since 1.0.0
85
+	 */
86
+	public function findKey($key);
87 87
 
88
-    /**
89
-     * Returns the lowest key greater than or equal to the given key or throw an exception if there is no such key
90
-     *
91
-     * @param mixed $key The searched key
92
-     *
93
-     * @return mixed The found key
94
-     *
95
-     * @throws OutOfBoundsException If there is no ceiling element
96
-     *
97
-     * @since 1.0.0
98
-     */
99
-    public function ceilingKey($key);
88
+	/**
89
+	 * Returns the lowest key greater than or equal to the given key or throw an exception if there is no such key
90
+	 *
91
+	 * @param mixed $key The searched key
92
+	 *
93
+	 * @return mixed The found key
94
+	 *
95
+	 * @throws OutOfBoundsException If there is no ceiling element
96
+	 *
97
+	 * @since 1.0.0
98
+	 */
99
+	public function ceilingKey($key);
100 100
 
101
-    /**
102
-     * Returns the lowest key greater than to the given key or throw an exception if there is no such key
103
-     *
104
-     * @param mixed $key The searched key
105
-     *
106
-     * @return mixed The found key
107
-     *
108
-     * @throws OutOfBoundsException If there is no higher element
109
-     *
110
-     * @since 1.0.0
111
-     */
112
-    public function higherKey($key);
101
+	/**
102
+	 * Returns the lowest key greater than to the given key or throw an exception if there is no such key
103
+	 *
104
+	 * @param mixed $key The searched key
105
+	 *
106
+	 * @return mixed The found key
107
+	 *
108
+	 * @throws OutOfBoundsException If there is no higher element
109
+	 *
110
+	 * @since 1.0.0
111
+	 */
112
+	public function higherKey($key);
113 113
 
114
-    /**
115
-     * Get the predecessor node
116
-     *
117
-     * @param TreeNode $node A tree node member of the underlying TreeMap
118
-     *
119
-     * @return mixed The predecessor node
120
-     *
121
-     * @since 1.0.0
122
-     */
123
-    public function predecessor($node);
114
+	/**
115
+	 * Get the predecessor node
116
+	 *
117
+	 * @param TreeNode $node A tree node member of the underlying TreeMap
118
+	 *
119
+	 * @return mixed The predecessor node
120
+	 *
121
+	 * @since 1.0.0
122
+	 */
123
+	public function predecessor($node);
124 124
 
125
-    /**
126
-     * Get the successor node
127
-     *
128
-     * @param TreeNode $node A tree node member of the underlying TreeMap
129
-     *
130
-     * @return mixed The successor node
131
-     *
132
-     * @since 1.0.0
133
-     */
134
-    public function successor($node);
125
+	/**
126
+	 * Get the successor node
127
+	 *
128
+	 * @param TreeNode $node A tree node member of the underlying TreeMap
129
+	 *
130
+	 * @return mixed The successor node
131
+	 *
132
+	 * @since 1.0.0
133
+	 */
134
+	public function successor($node);
135 135
 
136
-    /**
137
-     * Keys generator
138
-     *
139
-     * @return mixed The keys generator
140
-     *
141
-     * @since 1.0.0
142
-     */
143
-    public function keys();
136
+	/**
137
+	 * Keys generator
138
+	 *
139
+	 * @return mixed The keys generator
140
+	 *
141
+	 * @since 1.0.0
142
+	 */
143
+	public function keys();
144 144
 
145
-    /**
146
-     * Values generator
147
-     *
148
-     * @return mixed The values generator
149
-     *
150
-     * @since 1.0.0
151
-     */
152
-    public function values();
145
+	/**
146
+	 * Values generator
147
+	 *
148
+	 * @return mixed The values generator
149
+	 *
150
+	 * @since 1.0.0
151
+	 */
152
+	public function values();
153 153
 }
Please login to merge, or discard this patch.
src/SortedCollection/SubMap.php 1 patch
Indentation   +787 added lines, -787 removed lines patch added patch discarded remove patch
@@ -40,791 +40,791 @@
 block discarded – undo
40 40
  */
41 41
 class SubMap extends AbstractMap
42 42
 {
43
-    /**
44
-     * When the from or to key is unused
45
-     *
46
-     * @since 1.0.0
47
-     */
48
-    private const UNUSED = 0;
49
-
50
-    /**
51
-     * When the from or to key is inclusive
52
-     *
53
-     * @since 1.0.0
54
-     */
55
-    private const INCLUSIVE = 1;
56
-
57
-    /**
58
-     * When the from or to key is exclusive
59
-     *
60
-     * @since 1.0.0
61
-     */
62
-    private const EXCLUSIVE = 2;
63
-
64
-    /**
65
-     * @var SortedMap  Internal map
66
-     *
67
-     * @since 1.0.0
68
-     */
69
-    private $map;
70
-
71
-    /**
72
-     * @var integer  from option
73
-     *
74
-     * @since 1.0.0
75
-     */
76
-    private $fromOption;
77
-
78
-    /**
79
-     * @var mixed  from key
80
-     *
81
-     * @since 1.0.0
82
-     */
83
-    private $fromKey;
84
-
85
-    /**
86
-     * @var integer  to option
87
-     *
88
-     * @since 1.0.0
89
-     */
90
-    private $toOption;
91
-
92
-    /**
93
-     * @var mixed  to key
94
-     *
95
-     * @since 1.0.0
96
-     */
97
-    private $toKey;
98
-
99
-    /**
100
-     * @var boolean  Empty flag
101
-     *
102
-     * @since 1.0.0
103
-     */
104
-    private $empty;
105
-
106
-    /**
107
-     * Magic get method
108
-     *
109
-     * @param string $property The property
110
-     *
111
-     * @throws RuntimeException If the property does not exist
112
-     *
113
-     * @return mixed The value associated to the property
114
-     *
115
-     * @since 1.0.0
116
-     */
117
-    public function __get($property)
118
-    {
119
-        switch ($property) {
120
-            case 'fromKey':
121
-                if ($this->fromOption == self::UNUSED) {
122
-                     throw new \RuntimeException('Undefined property');
123
-                } else {
124
-                    return $this->fromKey;
125
-                }
126
-
127
-            case 'toKey':
128
-                if ($this->toOption == self::UNUSED) {
129
-                    throw new \RuntimeException('Undefined property');
130
-                } else {
131
-                    return $this->toKey;
132
-                }
133
-
134
-            case 'fromInclusive':
135
-                if ($this->fromOption == self::UNUSED) {
136
-                    throw new \RuntimeException('Undefined property');
137
-                } else {
138
-                    return $this->fromOption == self::INCLUSIVE;
139
-                }
140
-
141
-            case 'toInclusive':
142
-                if ($this->toOption == self::UNUSED) {
143
-                    throw new \RuntimeException('Undefined property');
144
-                } else {
145
-                    return $this->toOption == self::INCLUSIVE;
146
-                }
147
-
148
-            case 'map':
149
-                return $this->map;
150
-            default:
151
-                return parent::__get($property);
152
-        }
153
-    }
154
-
155
-    /**
156
-     * Magic set method
157
-     *
158
-     * @param string $property The property
159
-     * @param mixed  $value    The new value
160
-     *
161
-     * @throws RuntimeException If the property does not exist
162
-     *
163
-     * @return void
164
-     *
165
-     * @since 1.0.0
166
-     */
167
-    public function __set($property, $value)
168
-    {
169
-        switch ($property) {
170
-            case 'fromKey':
171
-                $this->fromKey = $value;
172
-
173
-                if ($this->fromOption == self::UNUSED) {
174
-                     $this->fromOption = self::INCLUSIVE;
175
-                }
176
-                break;
177
-            case 'toKey':
178
-                $this->toKey = $value;
179
-
180
-                if ($this->toOption == self::UNUSED) {
181
-                    $this->toOption = self::EXCLUSIVE;
182
-                }
183
-                break;
184
-            case 'fromInclusive':
185
-                if ($this->fromOption == self::UNUSED) {
186
-                    throw new \RuntimeException('Undefined property');
187
-                } else {
188
-                    $this->fromOption = $value ? self::INCLUSIVE : self::EXCLUSIVE;
189
-                }
190
-                break;
191
-            case 'toInclusive':
192
-                if ($this->toOption == self::UNUSED) {
193
-                    throw new \RuntimeException('Undefined property');
194
-                } else {
195
-                    $this->toOption = $value ? self::INCLUSIVE : self::EXCLUSIVE;
196
-                }
197
-                break;
198
-            default:
199
-                throw new \RuntimeException('Undefined property');
200
-        }
201
-
202
-        $this->setEmpty();
203
-    }
204
-
205
-    /**
206
-     * Magic unset method
207
-     *
208
-     * @param string $property The property
209
-     *
210
-     * @throws RuntimeException If the property does not exist
211
-     *
212
-     * @return void
213
-     *
214
-     * @since 1.0.0
215
-     */
216
-    public function __unset($property)
217
-    {
218
-        switch ($property) {
219
-            case 'fromKey':
220
-            case 'fromInclusive':
221
-                $this->fromOption = self::UNUSED;
222
-                break;
223
-            case 'toKey':
224
-            case 'toInclusive':
225
-                $this->toOption = self::UNUSED;
226
-                break;
227
-            default:
228
-                throw new \RuntimeException('Undefined property');
229
-        }
230
-    }
231
-
232
-    /**
233
-     * Magic isset method
234
-     *
235
-     * @param string $property The property
236
-     *
237
-     * @return boolean
238
-     *
239
-     * @since 1.0.0
240
-     */
241
-    public function __isset($property)
242
-    {
243
-        switch ($property) {
244
-            case 'fromKey':
245
-            case 'fromInclusive':
246
-                return $this->fromOption != self::UNUSED;
247
-            case 'toKey':
248
-            case 'toInclusive':
249
-                return $this->toOption != self::UNUSED;
250
-            default:
251
-                return false;
252
-        }
253
-    }
254
-
255
-    /**
256
-     * Constructor
257
-     *
258
-     * @param SortedMap $map        Internal map
259
-     * @param mixed     $fromKey    The from key
260
-     * @param integer   $fromOption The option for from (SubMap::UNUSED, SubMap::INCLUSIVE or SubMap::EXCLUSIVE)
261
-     * @param mixed     $toKey      The to key
262
-     * @param integer   $toOption   The option for to (SubMap::UNUSED, SubMap::INCLUSIVE or SubMap::EXCLUSIVE)
263
-     *
264
-     * @since 1.0.0
265
-     */
266
-    protected function __construct(SortedMap $map, $fromKey, $fromOption, $toKey, $toOption)
267
-    {
268
-        $this->map = $map;
269
-        $this->fromKey = $fromKey;
270
-        $this->fromOption = $fromOption;
271
-        $this->toKey = $toKey;
272
-        $this->toOption = $toOption;
273
-        $this->setEmpty();
274
-    }
275
-
276
-    /**
277
-     * Set the empty flag
278
-     *
279
-     * @return void
280
-     *
281
-     * @since 1.0.0
282
-     */
283
-    protected function setEmpty()
284
-    {
285
-        if ($this->fromOption != self::UNUSED && $this->toOption != self::UNUSED) {
286
-            $cmp = call_user_func($this->map->comparator(), $this->fromKey, $this->toKey);
287
-
288
-            $this->empty = $cmp > 0
289
-              || $cmp == 0 && ($this->fromOption == self::EXCLUSIVE || $this->toOption == self::EXCLUSIVE);
290
-        } else {
291
-            $this->empty = false;
292
-        }
293
-    }
294
-
295
-    /**
296
-     * Create
297
-     *
298
-     * @param SortedMap $map           A sorted map
299
-     * @param mixed     $fromKey       The from key
300
-     * @param mixed     $toKey         The to key
301
-     * @param boolean   $fromInclusive The inclusive flag for from
302
-     * @param boolean   $toInclusive   The inclusive flag for to
303
-     *
304
-     * @return SubMap A new sub map
305
-     *
306
-     * @since 1.0.0
307
-     */
308
-    public static function create(SortedMap $map, $fromKey, $toKey, $fromInclusive = true, $toInclusive = false)
309
-    {
310
-        return new static(
311
-            $map,
312
-            $fromKey,
313
-            $fromInclusive ? self::INCLUSIVE : self::EXCLUSIVE,
314
-            $toKey,
315
-            $toInclusive ? self::INCLUSIVE : self::EXCLUSIVE
316
-        );
317
-    }
318
-
319
-    /**
320
-     * Return a head portion of a sorted map
321
-     *
322
-     * @param SortedMap $map         A sorted map
323
-     * @param mixed     $toKey       The to key
324
-     * @param boolean   $toInclusive The inclusive flag for to
325
-     *
326
-     * @return SubMap A new head map
327
-     *
328
-     * @since 1.0.0
329
-     */
330
-    public static function head(SortedMap $map, $toKey, $toInclusive = false)
331
-    {
332
-        return new static($map, null, self::UNUSED, $toKey, $toInclusive ? self::INCLUSIVE : self::EXCLUSIVE);
333
-    }
334
-
335
-    /**
336
-     * Return a tail portion of a sorted map
337
-     *
338
-     * @param SortedMap $map           A sorted map
339
-     * @param mixed     $fromKey       The from key
340
-     * @param boolean   $fromInclusive The inclusive flag for from
341
-     *
342
-     * @return SubMap A new tail map
343
-     *
344
-     * @since 1.0.0
345
-     */
346
-    public static function tail(SortedMap $map, $fromKey, $fromInclusive = true)
347
-    {
348
-        return new static($map, $fromKey, $fromInclusive ? self::INCLUSIVE : self::EXCLUSIVE, null, self::UNUSED);
349
-    }
350
-
351
-    /**
352
-     * Return a view of the map
353
-     *
354
-     * @param SortedMap $map A sorted map
355
-     *
356
-     * @return SubMap A new sub map
357
-     *
358
-     * @since 1.0.0
359
-     */
360
-    public static function view(SortedMap $map)
361
-    {
362
-        return new static($map, null, self::UNUSED, null, self::UNUSED);
363
-    }
364
-
365
-    /**
366
-     * Get the comparator
367
-     *
368
-     * @return callable The comparator
369
-     *
370
-     * @since 1.0.0
371
-     */
372
-    public function comparator()
373
-    {
374
-        return $this->map->comparator();
375
-    }
376
-
377
-    /**
378
-     * Get the first element
379
-     *
380
-     * @return mixed The first element
381
-     *
382
-     * @throws OutOfBoundsException If there is no element
383
-     *
384
-     * @since 1.0.0
385
-     */
386
-    public function first()
387
-    {
388
-        if ($this->empty) {
389
-            throw new \OutOfBoundsException('First element unexisting');
390
-        }
391
-
392
-        switch ($this->fromOption) {
393
-            case self::INCLUSIVE:
394
-                $first = $this->map->ceiling($this->fromKey);
395
-                break;
396
-            case self::EXCLUSIVE:
397
-                $first = $this->map->higher($this->fromKey);
398
-                break;
399
-            default:
400
-                $first = $this->map->first();
401
-                break;
402
-        }
403
-
404
-        return $first;
405
-    }
406
-
407
-    /**
408
-     * Get the last element
409
-     *
410
-     * @return mixed The last element
411
-     *
412
-     * @throws OutOfBoundsException If there is no element
413
-     *
414
-     * @since 1.0.0
415
-     */
416
-    public function last()
417
-    {
418
-        if ($this->empty) {
419
-            throw new \OutOfBoundsException('Last element unexisting');
420
-        }
421
-
422
-        switch ($this->toOption) {
423
-            case self::INCLUSIVE:
424
-                $last = $this->map->floor($this->toKey);
425
-                break;
426
-            case self::EXCLUSIVE:
427
-                $last = $this->map->lower($this->toKey);
428
-                break;
429
-            default:
430
-                $last = $this->map->last();
431
-                break;
432
-        }
433
-
434
-        return $last;
435
-    }
436
-
437
-    /**
438
-     * Get the predecessor element
439
-     *
440
-     * @param TreeNode $element A tree node member of the underlying TreeMap
441
-     *
442
-     * @return mixed The predecessor element
443
-     *
444
-     * @throws OutOfBoundsException If there is no predecessor
445
-     *
446
-     * @since 1.0.0
447
-     */
448
-    public function predecessor($element)
449
-    {
450
-        $predecessor = $this->map->predecessor($element);
451
-
452
-        if ($predecessor) {
453
-            switch ($this->fromOption) {
454
-                case self::INCLUSIVE:
455
-                    if (call_user_func($this->map->comparator(), $predecessor->key, $this->fromKey) < 0) {
456
-                        throw new \OutOfBoundsException('Predecessor element unexisting');
457
-                    }
458
-                    break;
459
-                case self::EXCLUSIVE:
460
-                    if (call_user_func($this->map->comparator(), $predecessor->key, $this->fromKey) <= 0) {
461
-                        throw new \OutOfBoundsException('Predecessor element unexisting');
462
-                    }
463
-                    break;
464
-            }
465
-        }
466
-
467
-        return $predecessor;
468
-    }
469
-
470
-    /**
471
-     * Get the successor element
472
-     *
473
-     * @param TreeNode $element A tree node member of the underlying TreeMap
474
-     *
475
-     * @return mixed The successor element
476
-     *
477
-     * @throws OutOfBoundsException If there is no successor
478
-     *
479
-     * @since 1.0.0
480
-     */
481
-    public function successor($element)
482
-    {
483
-        $successor = $this->map->successor($element);
484
-
485
-        if ($successor) {
486
-            switch ($this->toOption) {
487
-                case self::INCLUSIVE:
488
-                    if (call_user_func($this->map->comparator(), $successor->key, $this->toKey) > 0) {
489
-                        throw new \OutOfBoundsException('Successor element unexisting');
490
-                    }
491
-                    break;
492
-                case self::EXCLUSIVE:
493
-                    if (call_user_func($this->map->comparator(), $successor->key, $this->toKey) >= 0) {
494
-                        throw new \OutOfBoundsException('Successor element unexisting');
495
-                    }
496
-                    break;
497
-            }
498
-        }
499
-
500
-        return $successor;
501
-    }
502
-
503
-    /**
504
-     * Returns the element whose key is the greatest key lesser than the given key
505
-     *
506
-     * @param mixed $key The searched key
507
-     *
508
-     * @return mixed The found element
509
-     *
510
-     * @throws OutOfBoundsException If there is no lower element
511
-     *
512
-     * @since 1.0.0
513
-     */
514
-    public function lower($key)
515
-    {
516
-        if ($this->empty) {
517
-            throw new \OutOfBoundsException('Lower element unexisting');
518
-        }
519
-
520
-        switch ($this->fromOption) {
521
-            case self::UNUSED:
522
-                $lower = $this->map->lower($key);
523
-                break;
524
-            default:
525
-                if (call_user_func($this->map->comparator(), $key, $this->fromKey) <= 0) {
526
-                    throw new \OutOfBoundsException('Lower element unexisting');
527
-                } else {
528
-                    $lower = $this->map->lower($key);
529
-
530
-                    if (
531
-                        $this->fromOption == self::EXCLUSIVE
532
-                          && call_user_func($this->map->comparator(), $lower->key, $this->fromKey) <= 0
533
-                    ) {
534
-                        throw new \OutOfBoundsException('Lower element unexisting');
535
-                    }
536
-                }
537
-                break;
538
-        }
539
-
540
-        if ($lower) {
541
-            switch ($this->toOption) {
542
-                case self::INCLUSIVE:
543
-                    if (call_user_func($this->map->comparator(), $lower->key, $this->toKey) > 0) {
544
-                          $lower = $this->last();
545
-                    }
546
-                    break;
547
-                case self::EXCLUSIVE:
548
-                    if (call_user_func($this->map->comparator(), $lower->key, $this->toKey) >= 0) {
549
-                        $lower = $this->last();
550
-                    }
551
-                    break;
552
-            }
553
-        }
554
-
555
-        return $lower;
556
-    }
557
-
558
-    /**
559
-     * Returns the element whose key is the greatest key lesser than or equal to the given key
560
-     *
561
-     * @param mixed $key The searched key
562
-     *
563
-     * @return mixed The found element
564
-     *
565
-     * @throws OutOfBoundsException If there is no floor element
566
-     *
567
-     * @since 1.0.0
568
-     */
569
-    public function floor($key)
570
-    {
571
-        if ($this->empty) {
572
-            throw new \OutOfBoundsException('Floor element unexisting');
573
-        }
574
-
575
-        switch ($this->fromOption) {
576
-            case self::INCLUSIVE:
577
-                if (call_user_func($this->map->comparator(), $key, $this->fromKey) < 0) {
578
-                    throw new \OutOfBoundsException('Floor element unexisting');
579
-                } else {
580
-                    $floor = $this->map->floor($key);
581
-                }
582
-                break;
583
-            case self::EXCLUSIVE:
584
-                if (call_user_func($this->map->comparator(), $key, $this->fromKey) <= 0) {
585
-                    throw new \OutOfBoundsException('Floor element unexisting');
586
-                } else {
587
-                    $floor = $this->map->floor($key);
588
-                }
589
-                break;
590
-            default:
591
-                $floor = $this->map->floor($key);
592
-                break;
593
-        }
594
-
595
-        if ($floor) {
596
-            switch ($this->toOption) {
597
-                case self::INCLUSIVE:
598
-                    if (call_user_func($this->map->comparator(), $floor->key, $this->toKey) > 0) {
599
-                          $floor = $this->last();
600
-                    }
601
-                    break;
602
-                case self::EXCLUSIVE:
603
-                    if (call_user_func($this->map->comparator(), $floor->key, $this->toKey) >= 0) {
604
-                        $floor = $this->last();
605
-                    }
606
-                    break;
607
-            }
608
-        }
609
-
610
-        return $floor;
611
-    }
612
-
613
-    /**
614
-     * Returns the element whose key is equal to the given key
615
-     *
616
-     * @param mixed $key The searched key
617
-     *
618
-     * @return mixed The found element
619
-     *
620
-     * @throws OutOfBoundsException  If there is no such element
621
-     *
622
-     * @since 1.0.0
623
-     */
624
-    public function find($key)
625
-    {
626
-        switch ($this->fromOption) {
627
-            case self::INCLUSIVE:
628
-                if (call_user_func($this->map->comparator(), $key, $this->fromKey) < 0) {
629
-                     throw new \OutOfBoundsException('Element unexisting');
630
-                }
631
-                break;
632
-            case self::EXCLUSIVE:
633
-                if (call_user_func($this->map->comparator(), $key, $this->fromKey) <= 0) {
634
-                    throw new \OutOfBoundsException('Element unexisting');
635
-                }
636
-                break;
637
-        }
638
-
639
-        switch ($this->toOption) {
640
-            case self::INCLUSIVE:
641
-                if (call_user_func($this->map->comparator(), $key, $this->toKey) > 0) {
642
-                    throw new \OutOfBoundsException('Element unexisting');
643
-                }
644
-                break;
645
-            case self::EXCLUSIVE:
646
-                if (call_user_func($this->map->comparator(), $key, $this->toKey) >= 0) {
647
-                    throw new \OutOfBoundsException('Element unexisting');
648
-                }
649
-                break;
650
-        }
651
-
652
-        return $this->map->find($key);
653
-    }
654
-
655
-    /**
656
-     * Returns the element whose key is the lowest key greater than or equal to the given key
657
-     *
658
-     * @param mixed $key The searched key
659
-     *
660
-     * @return mixed The found element
661
-     *
662
-     * @throws OutOfBoundsException If there is no ceiling element
663
-     *
664
-     * @since 1.0.0
665
-     */
666
-    public function ceiling($key)
667
-    {
668
-        if ($this->empty) {
669
-            throw new \OutOfBoundsException('Ceiling element unexisting');
670
-        }
671
-
672
-        switch ($this->toOption) {
673
-            case self::INCLUSIVE:
674
-                if (call_user_func($this->map->comparator(), $key, $this->toKey) > 0) {
675
-                    throw new \OutOfBoundsException('Ceiling element unexisting');
676
-                } else {
677
-                    $ceiling = $this->map->ceiling($key);
678
-                }
679
-                break;
680
-            case self::EXCLUSIVE:
681
-                if (call_user_func($this->map->comparator(), $key, $this->toKey) >= 0) {
682
-                    throw new \OutOfBoundsException('Ceiling element unexisting');
683
-                } else {
684
-                    $ceiling = $this->map->ceiling($key);
685
-                }
686
-                break;
687
-            default:
688
-                $ceiling = $this->map->ceiling($key);
689
-                break;
690
-        }
691
-
692
-        if ($ceiling) {
693
-            switch ($this->fromOption) {
694
-                case self::INCLUSIVE:
695
-                    if (call_user_func($this->map->comparator(), $ceiling->key, $this->fromKey) < 0) {
696
-                          $ceiling = $this->first();
697
-                    }
698
-                    break;
699
-                case self::EXCLUSIVE:
700
-                    if (call_user_func($this->map->comparator(), $ceiling->key, $this->fromKey) <= 0) {
701
-                        $ceiling = $this->first();
702
-                    }
703
-                    break;
704
-            }
705
-        }
706
-
707
-        return $ceiling;
708
-    }
709
-
710
-    /**
711
-     * Returns the element whose key is the lowest key greater than to the given key
712
-     *
713
-     * @param mixed $key The searched key
714
-     *
715
-     * @return mixed The found element
716
-     *
717
-     * @throws OutOfBoundsException If there is no higher element
718
-     *
719
-     * @since 1.0.0
720
-     */
721
-    public function higher($key)
722
-    {
723
-        if ($this->empty) {
724
-            throw new \OutOfBoundsException('Higher element unexisting');
725
-        }
726
-
727
-        switch ($this->toOption) {
728
-            case self::UNUSED:
729
-                $higher = $this->map->higher($key);
730
-                break;
731
-            default:
732
-                if (call_user_func($this->map->comparator(), $key, $this->toKey) >= 0) {
733
-                    throw new \OutOfBoundsException('Higher element unexisting');
734
-                } else {
735
-                    $higher = $this->map->higher($key);
736
-
737
-                    if (
738
-                        $this->toOption == self::EXCLUSIVE
739
-                          && call_user_func($this->map->comparator(), $higher->key, $this->toKey) >= 0
740
-                    ) {
741
-                        throw new \OutOfBoundsException('Higher element unexisting');
742
-                    }
743
-                }
744
-                break;
745
-        }
746
-
747
-        if ($higher) {
748
-            switch ($this->fromOption) {
749
-                case self::INCLUSIVE:
750
-                    if (call_user_func($this->map->comparator(), $higher->key, $this->fromKey) < 0) {
751
-                          $higher = $this->first();
752
-                    }
753
-                    break;
754
-                case self::EXCLUSIVE:
755
-                    if (call_user_func($this->map->comparator(), $higher->key, $this->fromKey) <= 0) {
756
-                        $higher = $this->first();
757
-                    }
758
-                    break;
759
-            }
760
-        }
761
-
762
-        return $higher;
763
-    }
764
-
765
-    /**
766
-     * Serialize the object
767
-     *
768
-     * @return array Array of values
769
-     *
770
-     * @since 1.0.0
771
-     */
772
-    public function jsonSerialize()
773
-    {
774
-        if ($this->fromOption == self::UNUSED) {
775
-            if ($this->toOption == self::UNUSED) {
776
-                return array(
777
-                    'ViewMap' => array(
778
-                        'map' => $this->map->jsonSerialize(),
779
-                     )
780
-                );
781
-            } else {
782
-                return array(
783
-                    'HeadMap' => array(
784
-                        'map' => $this->map->jsonSerialize(),
785
-                        'toKey' => $this->toKey,
786
-                        'toInclusive' => $this->toOption == self::INCLUSIVE,
787
-                    )
788
-                );
789
-            }
790
-        } else {
791
-            if ($this->toOption == self::UNUSED) {
792
-                return array(
793
-                    'TailMap' => array(
794
-                        'map' => $this->map->jsonSerialize(),
795
-                        'fromKey' => $this->fromKey,
796
-                        'fromInclusive' => $this->fromOption == self::INCLUSIVE,
797
-                    )
798
-                );
799
-            } else {
800
-                return array(
801
-                    'SubMap' => array(
802
-                        'map' => $this->map->jsonSerialize(),
803
-                        'fromKey' => $this->fromKey,
804
-                        'fromInclusive' => $this->fromOption == self::INCLUSIVE,
805
-                        'toKey' => $this->toKey,
806
-                        'toInclusive' => $this->toOption == self::INCLUSIVE,
807
-                    )
808
-                );
809
-            }
810
-        }
811
-    }
812
-
813
-    /**
814
-     * Count the number of key/value pairs
815
-     *
816
-     * @return integer
817
-     *
818
-     * @since 1.0.0
819
-     */
820
-    public function count()
821
-    {
822
-        $count = 0;
823
-
824
-        foreach ($this as $value) {
825
-            $count++;
826
-        }
827
-
828
-        return $count;
829
-    }
43
+	/**
44
+	 * When the from or to key is unused
45
+	 *
46
+	 * @since 1.0.0
47
+	 */
48
+	private const UNUSED = 0;
49
+
50
+	/**
51
+	 * When the from or to key is inclusive
52
+	 *
53
+	 * @since 1.0.0
54
+	 */
55
+	private const INCLUSIVE = 1;
56
+
57
+	/**
58
+	 * When the from or to key is exclusive
59
+	 *
60
+	 * @since 1.0.0
61
+	 */
62
+	private const EXCLUSIVE = 2;
63
+
64
+	/**
65
+	 * @var SortedMap  Internal map
66
+	 *
67
+	 * @since 1.0.0
68
+	 */
69
+	private $map;
70
+
71
+	/**
72
+	 * @var integer  from option
73
+	 *
74
+	 * @since 1.0.0
75
+	 */
76
+	private $fromOption;
77
+
78
+	/**
79
+	 * @var mixed  from key
80
+	 *
81
+	 * @since 1.0.0
82
+	 */
83
+	private $fromKey;
84
+
85
+	/**
86
+	 * @var integer  to option
87
+	 *
88
+	 * @since 1.0.0
89
+	 */
90
+	private $toOption;
91
+
92
+	/**
93
+	 * @var mixed  to key
94
+	 *
95
+	 * @since 1.0.0
96
+	 */
97
+	private $toKey;
98
+
99
+	/**
100
+	 * @var boolean  Empty flag
101
+	 *
102
+	 * @since 1.0.0
103
+	 */
104
+	private $empty;
105
+
106
+	/**
107
+	 * Magic get method
108
+	 *
109
+	 * @param string $property The property
110
+	 *
111
+	 * @throws RuntimeException If the property does not exist
112
+	 *
113
+	 * @return mixed The value associated to the property
114
+	 *
115
+	 * @since 1.0.0
116
+	 */
117
+	public function __get($property)
118
+	{
119
+		switch ($property) {
120
+			case 'fromKey':
121
+				if ($this->fromOption == self::UNUSED) {
122
+					 throw new \RuntimeException('Undefined property');
123
+				} else {
124
+					return $this->fromKey;
125
+				}
126
+
127
+			case 'toKey':
128
+				if ($this->toOption == self::UNUSED) {
129
+					throw new \RuntimeException('Undefined property');
130
+				} else {
131
+					return $this->toKey;
132
+				}
133
+
134
+			case 'fromInclusive':
135
+				if ($this->fromOption == self::UNUSED) {
136
+					throw new \RuntimeException('Undefined property');
137
+				} else {
138
+					return $this->fromOption == self::INCLUSIVE;
139
+				}
140
+
141
+			case 'toInclusive':
142
+				if ($this->toOption == self::UNUSED) {
143
+					throw new \RuntimeException('Undefined property');
144
+				} else {
145
+					return $this->toOption == self::INCLUSIVE;
146
+				}
147
+
148
+			case 'map':
149
+				return $this->map;
150
+			default:
151
+				return parent::__get($property);
152
+		}
153
+	}
154
+
155
+	/**
156
+	 * Magic set method
157
+	 *
158
+	 * @param string $property The property
159
+	 * @param mixed  $value    The new value
160
+	 *
161
+	 * @throws RuntimeException If the property does not exist
162
+	 *
163
+	 * @return void
164
+	 *
165
+	 * @since 1.0.0
166
+	 */
167
+	public function __set($property, $value)
168
+	{
169
+		switch ($property) {
170
+			case 'fromKey':
171
+				$this->fromKey = $value;
172
+
173
+				if ($this->fromOption == self::UNUSED) {
174
+					 $this->fromOption = self::INCLUSIVE;
175
+				}
176
+				break;
177
+			case 'toKey':
178
+				$this->toKey = $value;
179
+
180
+				if ($this->toOption == self::UNUSED) {
181
+					$this->toOption = self::EXCLUSIVE;
182
+				}
183
+				break;
184
+			case 'fromInclusive':
185
+				if ($this->fromOption == self::UNUSED) {
186
+					throw new \RuntimeException('Undefined property');
187
+				} else {
188
+					$this->fromOption = $value ? self::INCLUSIVE : self::EXCLUSIVE;
189
+				}
190
+				break;
191
+			case 'toInclusive':
192
+				if ($this->toOption == self::UNUSED) {
193
+					throw new \RuntimeException('Undefined property');
194
+				} else {
195
+					$this->toOption = $value ? self::INCLUSIVE : self::EXCLUSIVE;
196
+				}
197
+				break;
198
+			default:
199
+				throw new \RuntimeException('Undefined property');
200
+		}
201
+
202
+		$this->setEmpty();
203
+	}
204
+
205
+	/**
206
+	 * Magic unset method
207
+	 *
208
+	 * @param string $property The property
209
+	 *
210
+	 * @throws RuntimeException If the property does not exist
211
+	 *
212
+	 * @return void
213
+	 *
214
+	 * @since 1.0.0
215
+	 */
216
+	public function __unset($property)
217
+	{
218
+		switch ($property) {
219
+			case 'fromKey':
220
+			case 'fromInclusive':
221
+				$this->fromOption = self::UNUSED;
222
+				break;
223
+			case 'toKey':
224
+			case 'toInclusive':
225
+				$this->toOption = self::UNUSED;
226
+				break;
227
+			default:
228
+				throw new \RuntimeException('Undefined property');
229
+		}
230
+	}
231
+
232
+	/**
233
+	 * Magic isset method
234
+	 *
235
+	 * @param string $property The property
236
+	 *
237
+	 * @return boolean
238
+	 *
239
+	 * @since 1.0.0
240
+	 */
241
+	public function __isset($property)
242
+	{
243
+		switch ($property) {
244
+			case 'fromKey':
245
+			case 'fromInclusive':
246
+				return $this->fromOption != self::UNUSED;
247
+			case 'toKey':
248
+			case 'toInclusive':
249
+				return $this->toOption != self::UNUSED;
250
+			default:
251
+				return false;
252
+		}
253
+	}
254
+
255
+	/**
256
+	 * Constructor
257
+	 *
258
+	 * @param SortedMap $map        Internal map
259
+	 * @param mixed     $fromKey    The from key
260
+	 * @param integer   $fromOption The option for from (SubMap::UNUSED, SubMap::INCLUSIVE or SubMap::EXCLUSIVE)
261
+	 * @param mixed     $toKey      The to key
262
+	 * @param integer   $toOption   The option for to (SubMap::UNUSED, SubMap::INCLUSIVE or SubMap::EXCLUSIVE)
263
+	 *
264
+	 * @since 1.0.0
265
+	 */
266
+	protected function __construct(SortedMap $map, $fromKey, $fromOption, $toKey, $toOption)
267
+	{
268
+		$this->map = $map;
269
+		$this->fromKey = $fromKey;
270
+		$this->fromOption = $fromOption;
271
+		$this->toKey = $toKey;
272
+		$this->toOption = $toOption;
273
+		$this->setEmpty();
274
+	}
275
+
276
+	/**
277
+	 * Set the empty flag
278
+	 *
279
+	 * @return void
280
+	 *
281
+	 * @since 1.0.0
282
+	 */
283
+	protected function setEmpty()
284
+	{
285
+		if ($this->fromOption != self::UNUSED && $this->toOption != self::UNUSED) {
286
+			$cmp = call_user_func($this->map->comparator(), $this->fromKey, $this->toKey);
287
+
288
+			$this->empty = $cmp > 0
289
+			  || $cmp == 0 && ($this->fromOption == self::EXCLUSIVE || $this->toOption == self::EXCLUSIVE);
290
+		} else {
291
+			$this->empty = false;
292
+		}
293
+	}
294
+
295
+	/**
296
+	 * Create
297
+	 *
298
+	 * @param SortedMap $map           A sorted map
299
+	 * @param mixed     $fromKey       The from key
300
+	 * @param mixed     $toKey         The to key
301
+	 * @param boolean   $fromInclusive The inclusive flag for from
302
+	 * @param boolean   $toInclusive   The inclusive flag for to
303
+	 *
304
+	 * @return SubMap A new sub map
305
+	 *
306
+	 * @since 1.0.0
307
+	 */
308
+	public static function create(SortedMap $map, $fromKey, $toKey, $fromInclusive = true, $toInclusive = false)
309
+	{
310
+		return new static(
311
+			$map,
312
+			$fromKey,
313
+			$fromInclusive ? self::INCLUSIVE : self::EXCLUSIVE,
314
+			$toKey,
315
+			$toInclusive ? self::INCLUSIVE : self::EXCLUSIVE
316
+		);
317
+	}
318
+
319
+	/**
320
+	 * Return a head portion of a sorted map
321
+	 *
322
+	 * @param SortedMap $map         A sorted map
323
+	 * @param mixed     $toKey       The to key
324
+	 * @param boolean   $toInclusive The inclusive flag for to
325
+	 *
326
+	 * @return SubMap A new head map
327
+	 *
328
+	 * @since 1.0.0
329
+	 */
330
+	public static function head(SortedMap $map, $toKey, $toInclusive = false)
331
+	{
332
+		return new static($map, null, self::UNUSED, $toKey, $toInclusive ? self::INCLUSIVE : self::EXCLUSIVE);
333
+	}
334
+
335
+	/**
336
+	 * Return a tail portion of a sorted map
337
+	 *
338
+	 * @param SortedMap $map           A sorted map
339
+	 * @param mixed     $fromKey       The from key
340
+	 * @param boolean   $fromInclusive The inclusive flag for from
341
+	 *
342
+	 * @return SubMap A new tail map
343
+	 *
344
+	 * @since 1.0.0
345
+	 */
346
+	public static function tail(SortedMap $map, $fromKey, $fromInclusive = true)
347
+	{
348
+		return new static($map, $fromKey, $fromInclusive ? self::INCLUSIVE : self::EXCLUSIVE, null, self::UNUSED);
349
+	}
350
+
351
+	/**
352
+	 * Return a view of the map
353
+	 *
354
+	 * @param SortedMap $map A sorted map
355
+	 *
356
+	 * @return SubMap A new sub map
357
+	 *
358
+	 * @since 1.0.0
359
+	 */
360
+	public static function view(SortedMap $map)
361
+	{
362
+		return new static($map, null, self::UNUSED, null, self::UNUSED);
363
+	}
364
+
365
+	/**
366
+	 * Get the comparator
367
+	 *
368
+	 * @return callable The comparator
369
+	 *
370
+	 * @since 1.0.0
371
+	 */
372
+	public function comparator()
373
+	{
374
+		return $this->map->comparator();
375
+	}
376
+
377
+	/**
378
+	 * Get the first element
379
+	 *
380
+	 * @return mixed The first element
381
+	 *
382
+	 * @throws OutOfBoundsException If there is no element
383
+	 *
384
+	 * @since 1.0.0
385
+	 */
386
+	public function first()
387
+	{
388
+		if ($this->empty) {
389
+			throw new \OutOfBoundsException('First element unexisting');
390
+		}
391
+
392
+		switch ($this->fromOption) {
393
+			case self::INCLUSIVE:
394
+				$first = $this->map->ceiling($this->fromKey);
395
+				break;
396
+			case self::EXCLUSIVE:
397
+				$first = $this->map->higher($this->fromKey);
398
+				break;
399
+			default:
400
+				$first = $this->map->first();
401
+				break;
402
+		}
403
+
404
+		return $first;
405
+	}
406
+
407
+	/**
408
+	 * Get the last element
409
+	 *
410
+	 * @return mixed The last element
411
+	 *
412
+	 * @throws OutOfBoundsException If there is no element
413
+	 *
414
+	 * @since 1.0.0
415
+	 */
416
+	public function last()
417
+	{
418
+		if ($this->empty) {
419
+			throw new \OutOfBoundsException('Last element unexisting');
420
+		}
421
+
422
+		switch ($this->toOption) {
423
+			case self::INCLUSIVE:
424
+				$last = $this->map->floor($this->toKey);
425
+				break;
426
+			case self::EXCLUSIVE:
427
+				$last = $this->map->lower($this->toKey);
428
+				break;
429
+			default:
430
+				$last = $this->map->last();
431
+				break;
432
+		}
433
+
434
+		return $last;
435
+	}
436
+
437
+	/**
438
+	 * Get the predecessor element
439
+	 *
440
+	 * @param TreeNode $element A tree node member of the underlying TreeMap
441
+	 *
442
+	 * @return mixed The predecessor element
443
+	 *
444
+	 * @throws OutOfBoundsException If there is no predecessor
445
+	 *
446
+	 * @since 1.0.0
447
+	 */
448
+	public function predecessor($element)
449
+	{
450
+		$predecessor = $this->map->predecessor($element);
451
+
452
+		if ($predecessor) {
453
+			switch ($this->fromOption) {
454
+				case self::INCLUSIVE:
455
+					if (call_user_func($this->map->comparator(), $predecessor->key, $this->fromKey) < 0) {
456
+						throw new \OutOfBoundsException('Predecessor element unexisting');
457
+					}
458
+					break;
459
+				case self::EXCLUSIVE:
460
+					if (call_user_func($this->map->comparator(), $predecessor->key, $this->fromKey) <= 0) {
461
+						throw new \OutOfBoundsException('Predecessor element unexisting');
462
+					}
463
+					break;
464
+			}
465
+		}
466
+
467
+		return $predecessor;
468
+	}
469
+
470
+	/**
471
+	 * Get the successor element
472
+	 *
473
+	 * @param TreeNode $element A tree node member of the underlying TreeMap
474
+	 *
475
+	 * @return mixed The successor element
476
+	 *
477
+	 * @throws OutOfBoundsException If there is no successor
478
+	 *
479
+	 * @since 1.0.0
480
+	 */
481
+	public function successor($element)
482
+	{
483
+		$successor = $this->map->successor($element);
484
+
485
+		if ($successor) {
486
+			switch ($this->toOption) {
487
+				case self::INCLUSIVE:
488
+					if (call_user_func($this->map->comparator(), $successor->key, $this->toKey) > 0) {
489
+						throw new \OutOfBoundsException('Successor element unexisting');
490
+					}
491
+					break;
492
+				case self::EXCLUSIVE:
493
+					if (call_user_func($this->map->comparator(), $successor->key, $this->toKey) >= 0) {
494
+						throw new \OutOfBoundsException('Successor element unexisting');
495
+					}
496
+					break;
497
+			}
498
+		}
499
+
500
+		return $successor;
501
+	}
502
+
503
+	/**
504
+	 * Returns the element whose key is the greatest key lesser than the given key
505
+	 *
506
+	 * @param mixed $key The searched key
507
+	 *
508
+	 * @return mixed The found element
509
+	 *
510
+	 * @throws OutOfBoundsException If there is no lower element
511
+	 *
512
+	 * @since 1.0.0
513
+	 */
514
+	public function lower($key)
515
+	{
516
+		if ($this->empty) {
517
+			throw new \OutOfBoundsException('Lower element unexisting');
518
+		}
519
+
520
+		switch ($this->fromOption) {
521
+			case self::UNUSED:
522
+				$lower = $this->map->lower($key);
523
+				break;
524
+			default:
525
+				if (call_user_func($this->map->comparator(), $key, $this->fromKey) <= 0) {
526
+					throw new \OutOfBoundsException('Lower element unexisting');
527
+				} else {
528
+					$lower = $this->map->lower($key);
529
+
530
+					if (
531
+						$this->fromOption == self::EXCLUSIVE
532
+						  && call_user_func($this->map->comparator(), $lower->key, $this->fromKey) <= 0
533
+					) {
534
+						throw new \OutOfBoundsException('Lower element unexisting');
535
+					}
536
+				}
537
+				break;
538
+		}
539
+
540
+		if ($lower) {
541
+			switch ($this->toOption) {
542
+				case self::INCLUSIVE:
543
+					if (call_user_func($this->map->comparator(), $lower->key, $this->toKey) > 0) {
544
+						  $lower = $this->last();
545
+					}
546
+					break;
547
+				case self::EXCLUSIVE:
548
+					if (call_user_func($this->map->comparator(), $lower->key, $this->toKey) >= 0) {
549
+						$lower = $this->last();
550
+					}
551
+					break;
552
+			}
553
+		}
554
+
555
+		return $lower;
556
+	}
557
+
558
+	/**
559
+	 * Returns the element whose key is the greatest key lesser than or equal to the given key
560
+	 *
561
+	 * @param mixed $key The searched key
562
+	 *
563
+	 * @return mixed The found element
564
+	 *
565
+	 * @throws OutOfBoundsException If there is no floor element
566
+	 *
567
+	 * @since 1.0.0
568
+	 */
569
+	public function floor($key)
570
+	{
571
+		if ($this->empty) {
572
+			throw new \OutOfBoundsException('Floor element unexisting');
573
+		}
574
+
575
+		switch ($this->fromOption) {
576
+			case self::INCLUSIVE:
577
+				if (call_user_func($this->map->comparator(), $key, $this->fromKey) < 0) {
578
+					throw new \OutOfBoundsException('Floor element unexisting');
579
+				} else {
580
+					$floor = $this->map->floor($key);
581
+				}
582
+				break;
583
+			case self::EXCLUSIVE:
584
+				if (call_user_func($this->map->comparator(), $key, $this->fromKey) <= 0) {
585
+					throw new \OutOfBoundsException('Floor element unexisting');
586
+				} else {
587
+					$floor = $this->map->floor($key);
588
+				}
589
+				break;
590
+			default:
591
+				$floor = $this->map->floor($key);
592
+				break;
593
+		}
594
+
595
+		if ($floor) {
596
+			switch ($this->toOption) {
597
+				case self::INCLUSIVE:
598
+					if (call_user_func($this->map->comparator(), $floor->key, $this->toKey) > 0) {
599
+						  $floor = $this->last();
600
+					}
601
+					break;
602
+				case self::EXCLUSIVE:
603
+					if (call_user_func($this->map->comparator(), $floor->key, $this->toKey) >= 0) {
604
+						$floor = $this->last();
605
+					}
606
+					break;
607
+			}
608
+		}
609
+
610
+		return $floor;
611
+	}
612
+
613
+	/**
614
+	 * Returns the element whose key is equal to the given key
615
+	 *
616
+	 * @param mixed $key The searched key
617
+	 *
618
+	 * @return mixed The found element
619
+	 *
620
+	 * @throws OutOfBoundsException  If there is no such element
621
+	 *
622
+	 * @since 1.0.0
623
+	 */
624
+	public function find($key)
625
+	{
626
+		switch ($this->fromOption) {
627
+			case self::INCLUSIVE:
628
+				if (call_user_func($this->map->comparator(), $key, $this->fromKey) < 0) {
629
+					 throw new \OutOfBoundsException('Element unexisting');
630
+				}
631
+				break;
632
+			case self::EXCLUSIVE:
633
+				if (call_user_func($this->map->comparator(), $key, $this->fromKey) <= 0) {
634
+					throw new \OutOfBoundsException('Element unexisting');
635
+				}
636
+				break;
637
+		}
638
+
639
+		switch ($this->toOption) {
640
+			case self::INCLUSIVE:
641
+				if (call_user_func($this->map->comparator(), $key, $this->toKey) > 0) {
642
+					throw new \OutOfBoundsException('Element unexisting');
643
+				}
644
+				break;
645
+			case self::EXCLUSIVE:
646
+				if (call_user_func($this->map->comparator(), $key, $this->toKey) >= 0) {
647
+					throw new \OutOfBoundsException('Element unexisting');
648
+				}
649
+				break;
650
+		}
651
+
652
+		return $this->map->find($key);
653
+	}
654
+
655
+	/**
656
+	 * Returns the element whose key is the lowest key greater than or equal to the given key
657
+	 *
658
+	 * @param mixed $key The searched key
659
+	 *
660
+	 * @return mixed The found element
661
+	 *
662
+	 * @throws OutOfBoundsException If there is no ceiling element
663
+	 *
664
+	 * @since 1.0.0
665
+	 */
666
+	public function ceiling($key)
667
+	{
668
+		if ($this->empty) {
669
+			throw new \OutOfBoundsException('Ceiling element unexisting');
670
+		}
671
+
672
+		switch ($this->toOption) {
673
+			case self::INCLUSIVE:
674
+				if (call_user_func($this->map->comparator(), $key, $this->toKey) > 0) {
675
+					throw new \OutOfBoundsException('Ceiling element unexisting');
676
+				} else {
677
+					$ceiling = $this->map->ceiling($key);
678
+				}
679
+				break;
680
+			case self::EXCLUSIVE:
681
+				if (call_user_func($this->map->comparator(), $key, $this->toKey) >= 0) {
682
+					throw new \OutOfBoundsException('Ceiling element unexisting');
683
+				} else {
684
+					$ceiling = $this->map->ceiling($key);
685
+				}
686
+				break;
687
+			default:
688
+				$ceiling = $this->map->ceiling($key);
689
+				break;
690
+		}
691
+
692
+		if ($ceiling) {
693
+			switch ($this->fromOption) {
694
+				case self::INCLUSIVE:
695
+					if (call_user_func($this->map->comparator(), $ceiling->key, $this->fromKey) < 0) {
696
+						  $ceiling = $this->first();
697
+					}
698
+					break;
699
+				case self::EXCLUSIVE:
700
+					if (call_user_func($this->map->comparator(), $ceiling->key, $this->fromKey) <= 0) {
701
+						$ceiling = $this->first();
702
+					}
703
+					break;
704
+			}
705
+		}
706
+
707
+		return $ceiling;
708
+	}
709
+
710
+	/**
711
+	 * Returns the element whose key is the lowest key greater than to the given key
712
+	 *
713
+	 * @param mixed $key The searched key
714
+	 *
715
+	 * @return mixed The found element
716
+	 *
717
+	 * @throws OutOfBoundsException If there is no higher element
718
+	 *
719
+	 * @since 1.0.0
720
+	 */
721
+	public function higher($key)
722
+	{
723
+		if ($this->empty) {
724
+			throw new \OutOfBoundsException('Higher element unexisting');
725
+		}
726
+
727
+		switch ($this->toOption) {
728
+			case self::UNUSED:
729
+				$higher = $this->map->higher($key);
730
+				break;
731
+			default:
732
+				if (call_user_func($this->map->comparator(), $key, $this->toKey) >= 0) {
733
+					throw new \OutOfBoundsException('Higher element unexisting');
734
+				} else {
735
+					$higher = $this->map->higher($key);
736
+
737
+					if (
738
+						$this->toOption == self::EXCLUSIVE
739
+						  && call_user_func($this->map->comparator(), $higher->key, $this->toKey) >= 0
740
+					) {
741
+						throw new \OutOfBoundsException('Higher element unexisting');
742
+					}
743
+				}
744
+				break;
745
+		}
746
+
747
+		if ($higher) {
748
+			switch ($this->fromOption) {
749
+				case self::INCLUSIVE:
750
+					if (call_user_func($this->map->comparator(), $higher->key, $this->fromKey) < 0) {
751
+						  $higher = $this->first();
752
+					}
753
+					break;
754
+				case self::EXCLUSIVE:
755
+					if (call_user_func($this->map->comparator(), $higher->key, $this->fromKey) <= 0) {
756
+						$higher = $this->first();
757
+					}
758
+					break;
759
+			}
760
+		}
761
+
762
+		return $higher;
763
+	}
764
+
765
+	/**
766
+	 * Serialize the object
767
+	 *
768
+	 * @return array Array of values
769
+	 *
770
+	 * @since 1.0.0
771
+	 */
772
+	public function jsonSerialize()
773
+	{
774
+		if ($this->fromOption == self::UNUSED) {
775
+			if ($this->toOption == self::UNUSED) {
776
+				return array(
777
+					'ViewMap' => array(
778
+						'map' => $this->map->jsonSerialize(),
779
+					 )
780
+				);
781
+			} else {
782
+				return array(
783
+					'HeadMap' => array(
784
+						'map' => $this->map->jsonSerialize(),
785
+						'toKey' => $this->toKey,
786
+						'toInclusive' => $this->toOption == self::INCLUSIVE,
787
+					)
788
+				);
789
+			}
790
+		} else {
791
+			if ($this->toOption == self::UNUSED) {
792
+				return array(
793
+					'TailMap' => array(
794
+						'map' => $this->map->jsonSerialize(),
795
+						'fromKey' => $this->fromKey,
796
+						'fromInclusive' => $this->fromOption == self::INCLUSIVE,
797
+					)
798
+				);
799
+			} else {
800
+				return array(
801
+					'SubMap' => array(
802
+						'map' => $this->map->jsonSerialize(),
803
+						'fromKey' => $this->fromKey,
804
+						'fromInclusive' => $this->fromOption == self::INCLUSIVE,
805
+						'toKey' => $this->toKey,
806
+						'toInclusive' => $this->toOption == self::INCLUSIVE,
807
+					)
808
+				);
809
+			}
810
+		}
811
+	}
812
+
813
+	/**
814
+	 * Count the number of key/value pairs
815
+	 *
816
+	 * @return integer
817
+	 *
818
+	 * @since 1.0.0
819
+	 */
820
+	public function count()
821
+	{
822
+		$count = 0;
823
+
824
+		foreach ($this as $value) {
825
+			$count++;
826
+		}
827
+
828
+		return $count;
829
+	}
830 830
 }
Please login to merge, or discard this patch.
src/SortedCollection/ReversedMap.php 1 patch
Indentation   +226 added lines, -226 removed lines patch added patch discarded remove patch
@@ -36,246 +36,246 @@
 block discarded – undo
36 36
  */
37 37
 class ReversedMap extends AbstractMap
38 38
 {
39
-    /**
40
-     * @var SortedMap  Internal map
41
-     *
42
-     * @since 1.0.0
43
-     */
44
-    private $map;
39
+	/**
40
+	 * @var SortedMap  Internal map
41
+	 *
42
+	 * @since 1.0.0
43
+	 */
44
+	private $map;
45 45
 
46
-    /**
47
-     * @var callable  Comparator function
48
-     *
49
-     * @param mixed $key1 First key
50
-     * @param mixed $key2 Second key
51
-     *
52
-     * @return integer negative if $key1 is lesser than $key2,
53
-     *                 0 if $key1 is equal to $key2,
54
-     *                 positive if $key1 is greater than $key2
55
-     *
56
-     * @since 1.0.0
57
-     */
58
-    private $comparator;
46
+	/**
47
+	 * @var callable  Comparator function
48
+	 *
49
+	 * @param mixed $key1 First key
50
+	 * @param mixed $key2 Second key
51
+	 *
52
+	 * @return integer negative if $key1 is lesser than $key2,
53
+	 *                 0 if $key1 is equal to $key2,
54
+	 *                 positive if $key1 is greater than $key2
55
+	 *
56
+	 * @since 1.0.0
57
+	 */
58
+	private $comparator;
59 59
 
60
-    /**
61
-     * Constructor
62
-     *
63
-     * @param SortedMap $map Internal map
64
-     *
65
-     * @since 1.0.0
66
-     */
67
-    protected function __construct(SortedMap $map)
68
-    {
69
-        $this->map = $map;
70
-        $this->comparator = function ($key1, $key2) {
71
-            return - call_user_func($this->map->comparator, $key1, $key2);
72
-        };
73
-    }
60
+	/**
61
+	 * Constructor
62
+	 *
63
+	 * @param SortedMap $map Internal map
64
+	 *
65
+	 * @since 1.0.0
66
+	 */
67
+	protected function __construct(SortedMap $map)
68
+	{
69
+		$this->map = $map;
70
+		$this->comparator = function ($key1, $key2) {
71
+			return - call_user_func($this->map->comparator, $key1, $key2);
72
+		};
73
+	}
74 74
 
75
-    /**
76
-     * Create
77
-     *
78
-     * @param SortedMap $map Internal map
79
-     *
80
-     * @return ReversedMap A new reversed map
81
-     *
82
-     * @since 1.0.0
83
-     */
84
-    public static function create(SortedMap $map)
85
-    {
86
-        return new static($map);
87
-    }
75
+	/**
76
+	 * Create
77
+	 *
78
+	 * @param SortedMap $map Internal map
79
+	 *
80
+	 * @return ReversedMap A new reversed map
81
+	 *
82
+	 * @since 1.0.0
83
+	 */
84
+	public static function create(SortedMap $map)
85
+	{
86
+		return new static($map);
87
+	}
88 88
 
89
-    /**
90
-     * Magic get method
91
-     *
92
-     * @param string $property The property
93
-     *
94
-     * @return mixed The value associated to the property
95
-     *
96
-     * @since 1.0.0
97
-     */
98
-    public function __get($property)
99
-    {
100
-        switch ($property) {
101
-            case 'map':
102
-                return $this->map;
103
-            default:
104
-                return parent::__get($property);
105
-        }
106
-    }
89
+	/**
90
+	 * Magic get method
91
+	 *
92
+	 * @param string $property The property
93
+	 *
94
+	 * @return mixed The value associated to the property
95
+	 *
96
+	 * @since 1.0.0
97
+	 */
98
+	public function __get($property)
99
+	{
100
+		switch ($property) {
101
+			case 'map':
102
+				return $this->map;
103
+			default:
104
+				return parent::__get($property);
105
+		}
106
+	}
107 107
 
108
-    /**
109
-     * Get the comparator
110
-     *
111
-     * @return callable The comparator
112
-     *
113
-     * @since 1.0.0
114
-     */
115
-    public function comparator()
116
-    {
117
-        return $this->comparator;
118
-    }
108
+	/**
109
+	 * Get the comparator
110
+	 *
111
+	 * @return callable The comparator
112
+	 *
113
+	 * @since 1.0.0
114
+	 */
115
+	public function comparator()
116
+	{
117
+		return $this->comparator;
118
+	}
119 119
 
120
-    /**
121
-     * Get the first element
122
-     *
123
-     * @return mixed The first element
124
-     *
125
-     * @throws OutOfBoundsException If there is no element
126
-     *
127
-     * @since 1.0.0
128
-     */
129
-    public function first()
130
-    {
131
-        return $this->map->last();
132
-    }
120
+	/**
121
+	 * Get the first element
122
+	 *
123
+	 * @return mixed The first element
124
+	 *
125
+	 * @throws OutOfBoundsException If there is no element
126
+	 *
127
+	 * @since 1.0.0
128
+	 */
129
+	public function first()
130
+	{
131
+		return $this->map->last();
132
+	}
133 133
 
134
-    /**
135
-     * Get the last element
136
-     *
137
-     * @return mixed The last element
138
-     *
139
-     * @throws OutOfBoundsException If there is no element
140
-     *
141
-     * @since 1.0.0
142
-     */
143
-    public function last()
144
-    {
145
-        return $this->map->first();
146
-    }
134
+	/**
135
+	 * Get the last element
136
+	 *
137
+	 * @return mixed The last element
138
+	 *
139
+	 * @throws OutOfBoundsException If there is no element
140
+	 *
141
+	 * @since 1.0.0
142
+	 */
143
+	public function last()
144
+	{
145
+		return $this->map->first();
146
+	}
147 147
 
148
-    /**
149
-     * Get the predecessor element
150
-     *
151
-     * @param TreeNode $element A tree node member of the underlying TreeMap
152
-     *
153
-     * @return mixed The predecessor element
154
-     *
155
-     * @throws OutOfBoundsException If there is no predecessor
156
-     *
157
-     * @since 1.0.0
158
-     */
159
-    public function predecessor($element)
160
-    {
161
-        return $this->map->successor($element);
162
-    }
148
+	/**
149
+	 * Get the predecessor element
150
+	 *
151
+	 * @param TreeNode $element A tree node member of the underlying TreeMap
152
+	 *
153
+	 * @return mixed The predecessor element
154
+	 *
155
+	 * @throws OutOfBoundsException If there is no predecessor
156
+	 *
157
+	 * @since 1.0.0
158
+	 */
159
+	public function predecessor($element)
160
+	{
161
+		return $this->map->successor($element);
162
+	}
163 163
 
164
-    /**
165
-     * Get the successor element
166
-     *
167
-     * @param TreeNode $element A tree node member of the underlying TreeMap
168
-     *
169
-     * @return mixed The successor element
170
-     *
171
-     * @throws OutOfBoundsException If there is no successor
172
-     */
173
-    public function successor($element)
174
-    {
175
-        return $this->map->predecessor($element);
176
-    }
164
+	/**
165
+	 * Get the successor element
166
+	 *
167
+	 * @param TreeNode $element A tree node member of the underlying TreeMap
168
+	 *
169
+	 * @return mixed The successor element
170
+	 *
171
+	 * @throws OutOfBoundsException If there is no successor
172
+	 */
173
+	public function successor($element)
174
+	{
175
+		return $this->map->predecessor($element);
176
+	}
177 177
 
178
-    /**
179
-     * Returns the element whose key is the greatest key lesser than the given key
180
-     *
181
-     * @param mixed $key The searched key
182
-     *
183
-     * @return mixed The found element
184
-     *
185
-     * @throws OutOfBoundsException If there is no lower element
186
-     *
187
-     * @since 1.0.0
188
-     */
189
-    public function lower($key)
190
-    {
191
-        return $this->map->higher($key);
192
-    }
178
+	/**
179
+	 * Returns the element whose key is the greatest key lesser than the given key
180
+	 *
181
+	 * @param mixed $key The searched key
182
+	 *
183
+	 * @return mixed The found element
184
+	 *
185
+	 * @throws OutOfBoundsException If there is no lower element
186
+	 *
187
+	 * @since 1.0.0
188
+	 */
189
+	public function lower($key)
190
+	{
191
+		return $this->map->higher($key);
192
+	}
193 193
 
194
-    /**
195
-     * Returns the element whose key is the greatest key lesser than or equal to the given key
196
-     *
197
-     * @param mixed $key The searched key
198
-     *
199
-     * @return mixed The found element
200
-     *
201
-     * @throws OutOfBoundsException If there is no floor element
202
-     *
203
-     * @since 1.0.0
204
-     */
205
-    public function floor($key)
206
-    {
207
-        return $this->map->ceiling($key);
208
-    }
194
+	/**
195
+	 * Returns the element whose key is the greatest key lesser than or equal to the given key
196
+	 *
197
+	 * @param mixed $key The searched key
198
+	 *
199
+	 * @return mixed The found element
200
+	 *
201
+	 * @throws OutOfBoundsException If there is no floor element
202
+	 *
203
+	 * @since 1.0.0
204
+	 */
205
+	public function floor($key)
206
+	{
207
+		return $this->map->ceiling($key);
208
+	}
209 209
 
210
-    /**
211
-     * Returns the element whose key is equal to the given key
212
-     *
213
-     * @param mixed $key The searched key
214
-     *
215
-     * @return mixed The found element
216
-     *
217
-     * @throws OutOfBoundsException If there is no such element
218
-     *
219
-     * @since 1.0.0
220
-     */
221
-    public function find($key)
222
-    {
223
-        return $this->map->find($key);
224
-    }
210
+	/**
211
+	 * Returns the element whose key is equal to the given key
212
+	 *
213
+	 * @param mixed $key The searched key
214
+	 *
215
+	 * @return mixed The found element
216
+	 *
217
+	 * @throws OutOfBoundsException If there is no such element
218
+	 *
219
+	 * @since 1.0.0
220
+	 */
221
+	public function find($key)
222
+	{
223
+		return $this->map->find($key);
224
+	}
225 225
 
226
-    /**
227
-     * Returns the element whose key is the lowest key greater than or equal to the given key
228
-     *
229
-     * @param mixed $key The searched key
230
-     *
231
-     * @return mixed The found element
232
-     *
233
-     * @throws OutOfBoundsException If there is no ceiling element
234
-     *
235
-     * @since 1.0.0
236
-     */
237
-    public function ceiling($key)
238
-    {
239
-        return $this->map->floor($key);
240
-    }
226
+	/**
227
+	 * Returns the element whose key is the lowest key greater than or equal to the given key
228
+	 *
229
+	 * @param mixed $key The searched key
230
+	 *
231
+	 * @return mixed The found element
232
+	 *
233
+	 * @throws OutOfBoundsException If there is no ceiling element
234
+	 *
235
+	 * @since 1.0.0
236
+	 */
237
+	public function ceiling($key)
238
+	{
239
+		return $this->map->floor($key);
240
+	}
241 241
 
242
-    /**
243
-     * Returns the element whose key is the lowest key greater than to the given key
244
-     *
245
-     * @param mixed $key The searched key
246
-     *
247
-     * @return mixed The found element
248
-     *
249
-     * @throws OutOfBoundsException If there is no higher element
250
-     *
251
-     * @since 1.0.0
252
-     */
253
-    public function higher($key)
254
-    {
255
-        return $this->map->lower($key);
256
-    }
242
+	/**
243
+	 * Returns the element whose key is the lowest key greater than to the given key
244
+	 *
245
+	 * @param mixed $key The searched key
246
+	 *
247
+	 * @return mixed The found element
248
+	 *
249
+	 * @throws OutOfBoundsException If there is no higher element
250
+	 *
251
+	 * @since 1.0.0
252
+	 */
253
+	public function higher($key)
254
+	{
255
+		return $this->map->lower($key);
256
+	}
257 257
 
258
-    /**
259
-     * Serialize the object
260
-     *
261
-     * @return array Array of values
262
-     *
263
-     * @since 1.0.0
264
-     */
265
-    public function jsonSerialize()
266
-    {
267
-        return array('ReversedMap' => $this->map->jsonSerialize());
268
-    }
258
+	/**
259
+	 * Serialize the object
260
+	 *
261
+	 * @return array Array of values
262
+	 *
263
+	 * @since 1.0.0
264
+	 */
265
+	public function jsonSerialize()
266
+	{
267
+		return array('ReversedMap' => $this->map->jsonSerialize());
268
+	}
269 269
 
270
-    /**
271
-     * Count the number of key/value pairs
272
-     *
273
-     * @return integer
274
-     *
275
-     * @since 1.0.0
276
-     */
277
-    public function count()
278
-    {
279
-        return $this->map->count();
280
-    }
270
+	/**
271
+	 * Count the number of key/value pairs
272
+	 *
273
+	 * @return integer
274
+	 *
275
+	 * @since 1.0.0
276
+	 */
277
+	public function count()
278
+	{
279
+		return $this->map->count();
280
+	}
281 281
 }
Please login to merge, or discard this patch.
src/SortedCollection/AbstractSet.php 1 patch
Indentation   +278 added lines, -278 removed lines patch added patch discarded remove patch
@@ -29,304 +29,304 @@
 block discarded – undo
29 29
  */
30 30
 abstract class AbstractSet implements SortedSet
31 31
 {
32
-    /**
33
-     * @var SortedMap  Underlying map
34
-     *
35
-     * @since 1.0.0
36
-     */
37
-    private $map;
32
+	/**
33
+	 * @var SortedMap  Underlying map
34
+	 *
35
+	 * @since 1.0.0
36
+	 */
37
+	private $map;
38 38
 
39
-    /**
40
-     * Get the map
41
-     *
42
-     * @return SortedMap The underlying map
43
-     *
44
-     * @since 1.0.0
45
-     */
46
-    protected function getMap()
47
-    {
48
-        return $this->map;
49
-    }
39
+	/**
40
+	 * Get the map
41
+	 *
42
+	 * @return SortedMap The underlying map
43
+	 *
44
+	 * @since 1.0.0
45
+	 */
46
+	protected function getMap()
47
+	{
48
+		return $this->map;
49
+	}
50 50
 
51
-    /**
52
-     * Set the map
53
-     *
54
-     * @param SortedMap $map The underlying map
55
-     *
56
-     * @return AbstractSet $this for chaining
57
-     *
58
-     * @since 1.0.0
59
-     */
60
-    protected function setMap(SortedMap $map)
61
-    {
62
-        $this->map = $map;
51
+	/**
52
+	 * Set the map
53
+	 *
54
+	 * @param SortedMap $map The underlying map
55
+	 *
56
+	 * @return AbstractSet $this for chaining
57
+	 *
58
+	 * @since 1.0.0
59
+	 */
60
+	protected function setMap(SortedMap $map)
61
+	{
62
+		$this->map = $map;
63 63
 
64
-        return $this;
65
-    }
64
+		return $this;
65
+	}
66 66
 
67
-    /**
68
-     * Magic get method
69
-     *
70
-     * @param string $property The property
71
-     *
72
-     * @throws RuntimeException If the property does not exist
73
-     *
74
-     * @return mixed The value associated to the property
75
-     *
76
-     * @since 1.0.0
77
-     */
78
-    public function __get($property)
79
-    {
80
-        switch ($property) {
81
-            case 'comparator':
82
-                return $this->comparator();
83
-            case 'first':
84
-                return $this->first();
85
-            case 'last':
86
-                return $this->last();
87
-            case 'count':
88
-                return $this->count();
89
-            default:
90
-                throw new \RuntimeException('Undefined property');
91
-        }
92
-    }
67
+	/**
68
+	 * Magic get method
69
+	 *
70
+	 * @param string $property The property
71
+	 *
72
+	 * @throws RuntimeException If the property does not exist
73
+	 *
74
+	 * @return mixed The value associated to the property
75
+	 *
76
+	 * @since 1.0.0
77
+	 */
78
+	public function __get($property)
79
+	{
80
+		switch ($property) {
81
+			case 'comparator':
82
+				return $this->comparator();
83
+			case 'first':
84
+				return $this->first();
85
+			case 'last':
86
+				return $this->last();
87
+			case 'count':
88
+				return $this->count();
89
+			default:
90
+				throw new \RuntimeException('Undefined property');
91
+		}
92
+	}
93 93
 
94
-    /**
95
-     * Get the comparator
96
-     *
97
-     * @return callable The comparator
98
-     *
99
-     * @since 1.0.0
100
-     */
101
-    public function comparator()
102
-    {
103
-        return $this->map->comparator();
104
-    }
94
+	/**
95
+	 * Get the comparator
96
+	 *
97
+	 * @return callable The comparator
98
+	 *
99
+	 * @since 1.0.0
100
+	 */
101
+	public function comparator()
102
+	{
103
+		return $this->map->comparator();
104
+	}
105 105
 
106
-    /**
107
-     * Get the first element
108
-     *
109
-     * @return mixed The first element
110
-     *
111
-     * @throws OutOfBoundsException If there is no element
112
-     *
113
-     * @since 1.0.0
114
-     */
115
-    public function first()
116
-    {
117
-        return $this->map->firstKey();
118
-    }
106
+	/**
107
+	 * Get the first element
108
+	 *
109
+	 * @return mixed The first element
110
+	 *
111
+	 * @throws OutOfBoundsException If there is no element
112
+	 *
113
+	 * @since 1.0.0
114
+	 */
115
+	public function first()
116
+	{
117
+		return $this->map->firstKey();
118
+	}
119 119
 
120
-    /**
121
-     * Get the last element
122
-     *
123
-     * @return mixed The last element
124
-     *
125
-     * @throws OutOfBoundsException If there is no element
126
-     *
127
-     * @since 1.0.0
128
-     */
129
-    public function last()
130
-    {
131
-        return $this->map->lastKey();
132
-    }
120
+	/**
121
+	 * Get the last element
122
+	 *
123
+	 * @return mixed The last element
124
+	 *
125
+	 * @throws OutOfBoundsException If there is no element
126
+	 *
127
+	 * @since 1.0.0
128
+	 */
129
+	public function last()
130
+	{
131
+		return $this->map->lastKey();
132
+	}
133 133
 
134
-    /**
135
-     * Returns the greatest element lesser than the given element
136
-     *
137
-     * @param mixed $element The searched element
138
-     *
139
-     * @return mixed The found element
140
-     *
141
-     * @throws OutOfBoundsException If there is no lower element
142
-     *
143
-     * @since 1.0.0
144
-     */
145
-    public function lower($element)
146
-    {
147
-        return $this->map->lowerKey($element);
148
-    }
134
+	/**
135
+	 * Returns the greatest element lesser than the given element
136
+	 *
137
+	 * @param mixed $element The searched element
138
+	 *
139
+	 * @return mixed The found element
140
+	 *
141
+	 * @throws OutOfBoundsException If there is no lower element
142
+	 *
143
+	 * @since 1.0.0
144
+	 */
145
+	public function lower($element)
146
+	{
147
+		return $this->map->lowerKey($element);
148
+	}
149 149
 
150
-    /**
151
-     * Returns the greatest element lesser than or equal to the given element
152
-     *
153
-     * @param mixed $element The searched element
154
-     *
155
-     * @return mixed The found element
156
-     *
157
-     * @throws OutOfBoundsException If there is no floor element
158
-     *
159
-     * @since 1.0.0
160
-     */
161
-    public function floor($element)
162
-    {
163
-        return $this->map->floorKey($element);
164
-    }
150
+	/**
151
+	 * Returns the greatest element lesser than or equal to the given element
152
+	 *
153
+	 * @param mixed $element The searched element
154
+	 *
155
+	 * @return mixed The found element
156
+	 *
157
+	 * @throws OutOfBoundsException If there is no floor element
158
+	 *
159
+	 * @since 1.0.0
160
+	 */
161
+	public function floor($element)
162
+	{
163
+		return $this->map->floorKey($element);
164
+	}
165 165
 
166
-    /**
167
-     * Returns the element equal to the given element
168
-     *
169
-     * @param mixed $element The searched element
170
-     *
171
-     * @return mixed The found element
172
-     *
173
-     * @throws OutOfBoundsException If there is no such element
174
-     *
175
-     * @since 1.0.0
176
-     */
177
-    public function find($element)
178
-    {
179
-        return $this->map->findKey($element);
180
-    }
166
+	/**
167
+	 * Returns the element equal to the given element
168
+	 *
169
+	 * @param mixed $element The searched element
170
+	 *
171
+	 * @return mixed The found element
172
+	 *
173
+	 * @throws OutOfBoundsException If there is no such element
174
+	 *
175
+	 * @since 1.0.0
176
+	 */
177
+	public function find($element)
178
+	{
179
+		return $this->map->findKey($element);
180
+	}
181 181
 
182
-    /**
183
-     * Returns the lowest element greater than or equal to the given element
184
-     *
185
-     * @param mixed $element The searched element
186
-     *
187
-     * @return mixed The found element
188
-     *
189
-     * @throws OutOfBoundsException If there is no ceiling element
190
-     *
191
-     * @since 1.0.0
192
-     */
193
-    public function ceiling($element)
194
-    {
195
-        return $this->map->ceilingKey($element);
196
-    }
182
+	/**
183
+	 * Returns the lowest element greater than or equal to the given element
184
+	 *
185
+	 * @param mixed $element The searched element
186
+	 *
187
+	 * @return mixed The found element
188
+	 *
189
+	 * @throws OutOfBoundsException If there is no ceiling element
190
+	 *
191
+	 * @since 1.0.0
192
+	 */
193
+	public function ceiling($element)
194
+	{
195
+		return $this->map->ceilingKey($element);
196
+	}
197 197
 
198
-    /**
199
-     * Returns the lowest element greater than to the given element
200
-     *
201
-     * @param mixed $element The searched element
202
-     *
203
-     * @return mixed The found element
204
-     *
205
-     * @throws OutOfBoundsException If there is no higher element
206
-     *
207
-     * @since 1.0.0
208
-     */
209
-    public function higher($element)
210
-    {
211
-        return $this->map->higherKey($element);
212
-    }
198
+	/**
199
+	 * Returns the lowest element greater than to the given element
200
+	 *
201
+	 * @param mixed $element The searched element
202
+	 *
203
+	 * @return mixed The found element
204
+	 *
205
+	 * @throws OutOfBoundsException If there is no higher element
206
+	 *
207
+	 * @since 1.0.0
208
+	 */
209
+	public function higher($element)
210
+	{
211
+		return $this->map->higherKey($element);
212
+	}
213 213
 
214
-    /**
215
-     * Convert the object to a string
216
-     *
217
-     * @return string String representation of the object
218
-     *
219
-     * @since 1.0.0
220
-     */
221
-    public function __toString()
222
-    {
223
-        return json_encode($this->toArray());
224
-    }
214
+	/**
215
+	 * Convert the object to a string
216
+	 *
217
+	 * @return string String representation of the object
218
+	 *
219
+	 * @since 1.0.0
220
+	 */
221
+	public function __toString()
222
+	{
223
+		return json_encode($this->toArray());
224
+	}
225 225
 
226
-    /**
227
-     * Convert the object to an array
228
-     *
229
-     * @return array Array representation of the object
230
-     *
231
-     * @since 1.0.0
232
-     */
233
-    public function toArray()
234
-    {
235
-        $array = array();
226
+	/**
227
+	 * Convert the object to an array
228
+	 *
229
+	 * @return array Array representation of the object
230
+	 *
231
+	 * @since 1.0.0
232
+	 */
233
+	public function toArray()
234
+	{
235
+		$array = array();
236 236
 
237
-        foreach ($this as $value) {
238
-            $array[] = $value;
239
-        }
237
+		foreach ($this as $value) {
238
+			$array[] = $value;
239
+		}
240 240
 
241
-        return $array;
242
-    }
241
+		return $array;
242
+	}
243 243
 
244
-    /**
245
-     * Create an iterator
246
-     *
247
-     * @return Iterator A new iterator
248
-     *
249
-     * @since 1.0.0
250
-     */
251
-    public function getIterator()
252
-    {
253
-        return Iterator::keys($this->map);
254
-    }
244
+	/**
245
+	 * Create an iterator
246
+	 *
247
+	 * @return Iterator A new iterator
248
+	 *
249
+	 * @since 1.0.0
250
+	 */
251
+	public function getIterator()
252
+	{
253
+		return Iterator::keys($this->map);
254
+	}
255 255
 
256
-    /**
257
-     * Get the value for an element
258
-     *
259
-     * @param mixed $element The element
260
-     *
261
-     * @return mixed The found value
262
-     *
263
-     * @since 1.0.0
264
-     */
265
-    public function offsetGet($element)
266
-    {
267
-        try {
268
-            return (bool) $this->map->find($element);
269
-        } catch (\OutOfBoundsException $e) {
270
-            return false;
271
-        }
272
-    }
256
+	/**
257
+	 * Get the value for an element
258
+	 *
259
+	 * @param mixed $element The element
260
+	 *
261
+	 * @return mixed The found value
262
+	 *
263
+	 * @since 1.0.0
264
+	 */
265
+	public function offsetGet($element)
266
+	{
267
+		try {
268
+			return (bool) $this->map->find($element);
269
+		} catch (\OutOfBoundsException $e) {
270
+			return false;
271
+		}
272
+	}
273 273
 
274
-    /**
275
-     * Test the existence of an element
276
-     *
277
-     * @param mixed $element The element
278
-     *
279
-     * @return boolean TRUE if the element exists, false otherwise
280
-     *
281
-     * @since 1.0.0
282
-     */
283
-    public function offsetExists($element)
284
-    {
285
-        return $this->offsetGet($element);
286
-    }
274
+	/**
275
+	 * Test the existence of an element
276
+	 *
277
+	 * @param mixed $element The element
278
+	 *
279
+	 * @return boolean TRUE if the element exists, false otherwise
280
+	 *
281
+	 * @since 1.0.0
282
+	 */
283
+	public function offsetExists($element)
284
+	{
285
+		return $this->offsetGet($element);
286
+	}
287 287
 
288
-    /**
289
-     * Set the value for an element
290
-     *
291
-     * @param mixed $element The element
292
-     * @param mixed $value   The value
293
-     *
294
-     * @return void
295
-     *
296
-     * @throws RuntimeOperation The operation is not supported by this class
297
-     *
298
-     * @since 1.0.0
299
-     */
300
-    public function offsetSet($element, $value)
301
-    {
302
-        throw new \RuntimeException('Unsupported operation');
303
-    }
288
+	/**
289
+	 * Set the value for an element
290
+	 *
291
+	 * @param mixed $element The element
292
+	 * @param mixed $value   The value
293
+	 *
294
+	 * @return void
295
+	 *
296
+	 * @throws RuntimeOperation The operation is not supported by this class
297
+	 *
298
+	 * @since 1.0.0
299
+	 */
300
+	public function offsetSet($element, $value)
301
+	{
302
+		throw new \RuntimeException('Unsupported operation');
303
+	}
304 304
 
305
-    /**
306
-     * Unset the existence of an element
307
-     *
308
-     * @param mixed $element The element
309
-     *
310
-     * @return void
311
-     *
312
-     * @throws RuntimeOperation The operation is not supported by this class
313
-     *
314
-     * @since 1.0.0
315
-     */
316
-    public function offsetUnset($element)
317
-    {
318
-        throw new \RuntimeException('Unsupported operation');
319
-    }
305
+	/**
306
+	 * Unset the existence of an element
307
+	 *
308
+	 * @param mixed $element The element
309
+	 *
310
+	 * @return void
311
+	 *
312
+	 * @throws RuntimeOperation The operation is not supported by this class
313
+	 *
314
+	 * @since 1.0.0
315
+	 */
316
+	public function offsetUnset($element)
317
+	{
318
+		throw new \RuntimeException('Unsupported operation');
319
+	}
320 320
 
321
-    /**
322
-     * Count the number of elements
323
-     *
324
-     * @return integer
325
-     *
326
-     * @since 1.0.0
327
-     */
328
-    public function count()
329
-    {
330
-        return count($this->map);
331
-    }
321
+	/**
322
+	 * Count the number of elements
323
+	 *
324
+	 * @return integer
325
+	 *
326
+	 * @since 1.0.0
327
+	 */
328
+	public function count()
329
+	{
330
+		return count($this->map);
331
+	}
332 332
 }
Please login to merge, or discard this patch.
src/SortedCollection/TreeMap.php 1 patch
Indentation   +410 added lines, -410 removed lines patch added patch discarded remove patch
@@ -35,414 +35,414 @@
 block discarded – undo
35 35
  */
36 36
 class TreeMap extends AbstractMap
37 37
 {
38
-    /**
39
-     * @var TreeNode  Root of the tree
40
-     *
41
-     * @since 1.0.0
42
-     */
43
-    private $root;
44
-
45
-    /**
46
-     * @var callable  Comparator function
47
-     *
48
-     * @param mixed $key1 First key
49
-     * @param mixed $key2 Second key
50
-     *
51
-     * @return integer negative if $key1 is lesser than $key2,
52
-     *                  0 if $key1 is equal to $key2,
53
-     *                  positive if $key1 is greater than $key2
54
-     *
55
-     * @since 1.0.0
56
-     */
57
-    private $comparator;
58
-
59
-    /**
60
-     * Constructor
61
-     *
62
-     * @param callable $comparator Comparison function
63
-     *
64
-     * @since 1.0.0
65
-     */
66
-    protected function __construct($comparator = null)
67
-    {
68
-        if ($comparator == null) {
69
-            $this->comparator = function ($key1, $key2) {
70
-                return $key1 - $key2;
71
-            };
72
-        } else {
73
-            $this->comparator = $comparator;
74
-        }
75
-    }
76
-
77
-    /**
78
-     * Create
79
-     *
80
-     * @param callable $comparator Comparison function
81
-     *
82
-     * @return TreeMap A new TreeMap
83
-     *
84
-     * @since 1.0.0
85
-     */
86
-    public static function create($comparator = null)
87
-    {
88
-        return new static($comparator);
89
-    }
90
-
91
-    /**
92
-     * Get the comparator
93
-     *
94
-     * @return callable The comparator
95
-     *
96
-     * @since 1.0.0
97
-     */
98
-    public function comparator()
99
-    {
100
-        return $this->comparator;
101
-    }
102
-
103
-    /**
104
-     * Get the first element
105
-     *
106
-     * @return mixed The first element
107
-     *
108
-     * @throws OutOfBoundsException If there is no element
109
-     *
110
-     * @since 1.0.0
111
-     */
112
-    public function first()
113
-    {
114
-        if ($this->root) {
115
-            return $this->root->first;
116
-        } else {
117
-            throw new \OutOfBoundsException('First element unexisting');
118
-        }
119
-    }
120
-
121
-    /**
122
-     * Get the last element
123
-     *
124
-     * @return mixed The last element
125
-     *
126
-     * @throws OutOfBoundsException If there is no element
127
-     *
128
-     * @since 1.0.0
129
-     */
130
-    public function last()
131
-    {
132
-        if ($this->root) {
133
-            return $this->root->last;
134
-        } else {
135
-            throw new \OutOfBoundsException('Last element unexisting');
136
-        }
137
-    }
138
-
139
-    /**
140
-     * Get the predecessor element
141
-     *
142
-     * @param TreeNode $element A tree node member of the underlying TreeMap
143
-     *
144
-     * @return mixed The predecessor element
145
-     *
146
-     * @throws OutOfBoundsException  If there is no predecessor
147
-     *
148
-     * @since 1.0.0
149
-     */
150
-    public function predecessor($element)
151
-    {
152
-        $predecessor = $element->predecessor;
153
-
154
-        if ($predecessor) {
155
-            return $predecessor;
156
-        } else {
157
-            throw new \OutOfBoundsException('Predecessor element unexisting');
158
-        }
159
-    }
160
-
161
-    /**
162
-     * Get the successor element
163
-     *
164
-     * @param TreeNode $element A tree node member of the underlying TreeMap
165
-     *
166
-     * @return mixed The successor element
167
-     *
168
-     * @throws OutOfBoundsException If there is no successor
169
-     *
170
-     * @since 1.0.0
171
-     */
172
-    public function successor($element)
173
-    {
174
-        $successor = $element->successor;
175
-
176
-        if ($successor) {
177
-            return $successor;
178
-        } else {
179
-            throw new \OutOfBoundsException('Successor element unexisting');
180
-        }
181
-    }
182
-
183
-    /**
184
-     * Returns the element whose key is the greatest key lesser than the given key
185
-     *
186
-     * @param mixed $key The searched key
187
-     *
188
-     * @return mixed The found element
189
-     *
190
-     * @throws OutOfBoundsException If there is no lower element
191
-     *
192
-     * @since 1.0.0
193
-     */
194
-    public function lower($key)
195
-    {
196
-        if ($this->root) {
197
-            $lower = $this->root->find($key, $this->comparator, -2);
198
-        } else {
199
-            $lower = null;
200
-        }
201
-
202
-        if ($lower) {
203
-            return $lower;
204
-        } else {
205
-            throw new \OutOfBoundsException('Lower element unexisting');
206
-        }
207
-    }
208
-
209
-    /**
210
-     * Returns the element whose key is the greatest key lesser than or equal to the given key
211
-     *
212
-     * @param mixed $key The searched key
213
-     *
214
-     * @return mixed The found element
215
-     *
216
-     * @throws OutOfBoundsException If there is no floor element
217
-     *
218
-     * @since 1.0.0
219
-     */
220
-    public function floor($key)
221
-    {
222
-        if ($this->root) {
223
-            $floor = $this->root->find($key, $this->comparator, -1);
224
-        } else {
225
-            $floor = null;
226
-        }
227
-
228
-        if ($floor) {
229
-            return $floor;
230
-        } else {
231
-            throw new \OutOfBoundsException('Floor element unexisting');
232
-        }
233
-    }
234
-
235
-    /**
236
-     * Returns the element whose key is equal to the given key
237
-     *
238
-     * @param mixed $key The searched key
239
-     *
240
-     * @return mixed The found element
241
-     *
242
-     * @throws OutOfBoundsException If there is no such element
243
-     *
244
-     * @since 1.0.0
245
-     */
246
-    public function find($key)
247
-    {
248
-        if ($this->root) {
249
-            $find = $this->root->find($key, $this->comparator, 0);
250
-        } else {
251
-            $find = null;
252
-        }
253
-
254
-        if ($find) {
255
-            return $find;
256
-        } else {
257
-            throw new \OutOfBoundsException('Element unexisting');
258
-        }
259
-    }
260
-
261
-    /**
262
-     * Returns the element whose key is the lowest key greater than or equal to the given key
263
-     *
264
-     * @param mixed $key The searched key
265
-     *
266
-     * @return mixed The found element
267
-     *
268
-     * @throws OutOfBoundsException If there is no ceiling element
269
-     *
270
-     * @since 1.0.0
271
-     */
272
-    public function ceiling($key)
273
-    {
274
-        if ($this->root) {
275
-            $ceiling = $this->root->find($key, $this->comparator, 1);
276
-        } else {
277
-            $ceiling = null;
278
-        }
279
-
280
-        if ($ceiling) {
281
-            return $ceiling;
282
-        } else {
283
-            throw new \OutOfBoundsException('Ceiling element unexisting');
284
-        }
285
-    }
286
-
287
-    /**
288
-     * Returns the element whose key is the lowest key greater than to the given key
289
-     *
290
-     * @param mixed $key The searched key
291
-     *
292
-     * @return mixed The found element
293
-     *
294
-     * @throws OutOfBoundsException If there is no higher element
295
-     *
296
-     * @since 1.0.0
297
-     */
298
-    public function higher($key)
299
-    {
300
-        if ($this->root) {
301
-            $higher = $this->root->find($key, $this->comparator, 2);
302
-        } else {
303
-            $higher = null;
304
-        }
305
-
306
-        if ($higher) {
307
-            return $higher;
308
-        } else {
309
-            throw new \OutOfBoundsException('Higher element unexisting');
310
-        }
311
-    }
312
-
313
-    /**
314
-     * Put values in the map
315
-     *
316
-     * @param \Traversable $traversable Values to put in the map
317
-     *
318
-     * @return TreeMap $this for chaining
319
-     *
320
-     * @since 1.0.0
321
-     */
322
-    public function put($traversable = array())
323
-    {
324
-        foreach ($traversable as $key => $value) {
325
-            $this[$key] = $value;
326
-        }
327
-
328
-        return $this;
329
-    }
330
-
331
-    /**
332
-     * Clear the map
333
-     *
334
-     * @return TreeMap $this for chaining
335
-     *
336
-     * @since 1.0.0
337
-     */
338
-    public function clear()
339
-    {
340
-        $this->root = null;
341
-
342
-        return $this;
343
-    }
344
-
345
-    /**
346
-     * Initialise the map
347
-     *
348
-     * @param \Traversable $traversable Values to initialise the map
349
-     *
350
-     * @return TreeMap $this for chaining
351
-     *
352
-     * @since 1.0.0
353
-     */
354
-    public function initialise($traversable = array())
355
-    {
356
-        return $this->clear()->put($traversable);
357
-    }
358
-
359
-    /**
360
-     * Clone the map
361
-     *
362
-     * @return void
363
-     *
364
-     * @since 1.0.0
365
-     */
366
-    public function __clone()
367
-    {
368
-        if ($this->root != null) {
369
-            $root = $this->root;
370
-            $this->root = null;
371
-            $node = $root->first;
372
-
373
-            while ($node != null) {
374
-                $this[$node->key] = $node->value;
375
-                $node = $node->successor;
376
-            }
377
-        }
378
-    }
379
-
380
-    /**
381
-     * Serialize the object
382
-     *
383
-     * @return array Array of values
384
-     *
385
-     * @since 1.0.0
386
-     */
387
-    public function jsonSerialize()
388
-    {
389
-        $array = array();
390
-
391
-        foreach ($this as $key => $value) {
392
-            $array[$key] = $value;
393
-        }
394
-
395
-        return array('TreeMap' => $array);
396
-    }
397
-
398
-    /**
399
-     * Set the value for a key
400
-     *
401
-     * @param mixed $key   The key
402
-     * @param mixed $value The value
403
-     *
404
-     * @return void
405
-     *
406
-     * @since 1.0.0
407
-     */
408
-    public function offsetSet($key, $value)
409
-    {
410
-        if ($this->root) {
411
-            $this->root = $this->root->insert($key, $value, $this->comparator);
412
-        } else {
413
-            $this->root = TreeNode::create($key, $value);
414
-        }
415
-    }
416
-
417
-    /**
418
-     * Unset the existence of a key
419
-     *
420
-     * @param mixed $key The key
421
-     *
422
-     * @return void
423
-     *
424
-     * @since 1.0.0
425
-     */
426
-    public function offsetUnset($key)
427
-    {
428
-        if ($this->root) {
429
-            $this->root = $this->root->remove($key, $this->comparator);
430
-        }
431
-    }
432
-
433
-    /**
434
-     * Count the number of key/value pairs
435
-     *
436
-     * @return integer
437
-     *
438
-     * @since 1.0.0
439
-     */
440
-    public function count()
441
-    {
442
-        if ($this->root) {
443
-            return count($this->root);
444
-        } else {
445
-            return 0;
446
-        }
447
-    }
38
+	/**
39
+	 * @var TreeNode  Root of the tree
40
+	 *
41
+	 * @since 1.0.0
42
+	 */
43
+	private $root;
44
+
45
+	/**
46
+	 * @var callable  Comparator function
47
+	 *
48
+	 * @param mixed $key1 First key
49
+	 * @param mixed $key2 Second key
50
+	 *
51
+	 * @return integer negative if $key1 is lesser than $key2,
52
+	 *                  0 if $key1 is equal to $key2,
53
+	 *                  positive if $key1 is greater than $key2
54
+	 *
55
+	 * @since 1.0.0
56
+	 */
57
+	private $comparator;
58
+
59
+	/**
60
+	 * Constructor
61
+	 *
62
+	 * @param callable $comparator Comparison function
63
+	 *
64
+	 * @since 1.0.0
65
+	 */
66
+	protected function __construct($comparator = null)
67
+	{
68
+		if ($comparator == null) {
69
+			$this->comparator = function ($key1, $key2) {
70
+				return $key1 - $key2;
71
+			};
72
+		} else {
73
+			$this->comparator = $comparator;
74
+		}
75
+	}
76
+
77
+	/**
78
+	 * Create
79
+	 *
80
+	 * @param callable $comparator Comparison function
81
+	 *
82
+	 * @return TreeMap A new TreeMap
83
+	 *
84
+	 * @since 1.0.0
85
+	 */
86
+	public static function create($comparator = null)
87
+	{
88
+		return new static($comparator);
89
+	}
90
+
91
+	/**
92
+	 * Get the comparator
93
+	 *
94
+	 * @return callable The comparator
95
+	 *
96
+	 * @since 1.0.0
97
+	 */
98
+	public function comparator()
99
+	{
100
+		return $this->comparator;
101
+	}
102
+
103
+	/**
104
+	 * Get the first element
105
+	 *
106
+	 * @return mixed The first element
107
+	 *
108
+	 * @throws OutOfBoundsException If there is no element
109
+	 *
110
+	 * @since 1.0.0
111
+	 */
112
+	public function first()
113
+	{
114
+		if ($this->root) {
115
+			return $this->root->first;
116
+		} else {
117
+			throw new \OutOfBoundsException('First element unexisting');
118
+		}
119
+	}
120
+
121
+	/**
122
+	 * Get the last element
123
+	 *
124
+	 * @return mixed The last element
125
+	 *
126
+	 * @throws OutOfBoundsException If there is no element
127
+	 *
128
+	 * @since 1.0.0
129
+	 */
130
+	public function last()
131
+	{
132
+		if ($this->root) {
133
+			return $this->root->last;
134
+		} else {
135
+			throw new \OutOfBoundsException('Last element unexisting');
136
+		}
137
+	}
138
+
139
+	/**
140
+	 * Get the predecessor element
141
+	 *
142
+	 * @param TreeNode $element A tree node member of the underlying TreeMap
143
+	 *
144
+	 * @return mixed The predecessor element
145
+	 *
146
+	 * @throws OutOfBoundsException  If there is no predecessor
147
+	 *
148
+	 * @since 1.0.0
149
+	 */
150
+	public function predecessor($element)
151
+	{
152
+		$predecessor = $element->predecessor;
153
+
154
+		if ($predecessor) {
155
+			return $predecessor;
156
+		} else {
157
+			throw new \OutOfBoundsException('Predecessor element unexisting');
158
+		}
159
+	}
160
+
161
+	/**
162
+	 * Get the successor element
163
+	 *
164
+	 * @param TreeNode $element A tree node member of the underlying TreeMap
165
+	 *
166
+	 * @return mixed The successor element
167
+	 *
168
+	 * @throws OutOfBoundsException If there is no successor
169
+	 *
170
+	 * @since 1.0.0
171
+	 */
172
+	public function successor($element)
173
+	{
174
+		$successor = $element->successor;
175
+
176
+		if ($successor) {
177
+			return $successor;
178
+		} else {
179
+			throw new \OutOfBoundsException('Successor element unexisting');
180
+		}
181
+	}
182
+
183
+	/**
184
+	 * Returns the element whose key is the greatest key lesser than the given key
185
+	 *
186
+	 * @param mixed $key The searched key
187
+	 *
188
+	 * @return mixed The found element
189
+	 *
190
+	 * @throws OutOfBoundsException If there is no lower element
191
+	 *
192
+	 * @since 1.0.0
193
+	 */
194
+	public function lower($key)
195
+	{
196
+		if ($this->root) {
197
+			$lower = $this->root->find($key, $this->comparator, -2);
198
+		} else {
199
+			$lower = null;
200
+		}
201
+
202
+		if ($lower) {
203
+			return $lower;
204
+		} else {
205
+			throw new \OutOfBoundsException('Lower element unexisting');
206
+		}
207
+	}
208
+
209
+	/**
210
+	 * Returns the element whose key is the greatest key lesser than or equal to the given key
211
+	 *
212
+	 * @param mixed $key The searched key
213
+	 *
214
+	 * @return mixed The found element
215
+	 *
216
+	 * @throws OutOfBoundsException If there is no floor element
217
+	 *
218
+	 * @since 1.0.0
219
+	 */
220
+	public function floor($key)
221
+	{
222
+		if ($this->root) {
223
+			$floor = $this->root->find($key, $this->comparator, -1);
224
+		} else {
225
+			$floor = null;
226
+		}
227
+
228
+		if ($floor) {
229
+			return $floor;
230
+		} else {
231
+			throw new \OutOfBoundsException('Floor element unexisting');
232
+		}
233
+	}
234
+
235
+	/**
236
+	 * Returns the element whose key is equal to the given key
237
+	 *
238
+	 * @param mixed $key The searched key
239
+	 *
240
+	 * @return mixed The found element
241
+	 *
242
+	 * @throws OutOfBoundsException If there is no such element
243
+	 *
244
+	 * @since 1.0.0
245
+	 */
246
+	public function find($key)
247
+	{
248
+		if ($this->root) {
249
+			$find = $this->root->find($key, $this->comparator, 0);
250
+		} else {
251
+			$find = null;
252
+		}
253
+
254
+		if ($find) {
255
+			return $find;
256
+		} else {
257
+			throw new \OutOfBoundsException('Element unexisting');
258
+		}
259
+	}
260
+
261
+	/**
262
+	 * Returns the element whose key is the lowest key greater than or equal to the given key
263
+	 *
264
+	 * @param mixed $key The searched key
265
+	 *
266
+	 * @return mixed The found element
267
+	 *
268
+	 * @throws OutOfBoundsException If there is no ceiling element
269
+	 *
270
+	 * @since 1.0.0
271
+	 */
272
+	public function ceiling($key)
273
+	{
274
+		if ($this->root) {
275
+			$ceiling = $this->root->find($key, $this->comparator, 1);
276
+		} else {
277
+			$ceiling = null;
278
+		}
279
+
280
+		if ($ceiling) {
281
+			return $ceiling;
282
+		} else {
283
+			throw new \OutOfBoundsException('Ceiling element unexisting');
284
+		}
285
+	}
286
+
287
+	/**
288
+	 * Returns the element whose key is the lowest key greater than to the given key
289
+	 *
290
+	 * @param mixed $key The searched key
291
+	 *
292
+	 * @return mixed The found element
293
+	 *
294
+	 * @throws OutOfBoundsException If there is no higher element
295
+	 *
296
+	 * @since 1.0.0
297
+	 */
298
+	public function higher($key)
299
+	{
300
+		if ($this->root) {
301
+			$higher = $this->root->find($key, $this->comparator, 2);
302
+		} else {
303
+			$higher = null;
304
+		}
305
+
306
+		if ($higher) {
307
+			return $higher;
308
+		} else {
309
+			throw new \OutOfBoundsException('Higher element unexisting');
310
+		}
311
+	}
312
+
313
+	/**
314
+	 * Put values in the map
315
+	 *
316
+	 * @param \Traversable $traversable Values to put in the map
317
+	 *
318
+	 * @return TreeMap $this for chaining
319
+	 *
320
+	 * @since 1.0.0
321
+	 */
322
+	public function put($traversable = array())
323
+	{
324
+		foreach ($traversable as $key => $value) {
325
+			$this[$key] = $value;
326
+		}
327
+
328
+		return $this;
329
+	}
330
+
331
+	/**
332
+	 * Clear the map
333
+	 *
334
+	 * @return TreeMap $this for chaining
335
+	 *
336
+	 * @since 1.0.0
337
+	 */
338
+	public function clear()
339
+	{
340
+		$this->root = null;
341
+
342
+		return $this;
343
+	}
344
+
345
+	/**
346
+	 * Initialise the map
347
+	 *
348
+	 * @param \Traversable $traversable Values to initialise the map
349
+	 *
350
+	 * @return TreeMap $this for chaining
351
+	 *
352
+	 * @since 1.0.0
353
+	 */
354
+	public function initialise($traversable = array())
355
+	{
356
+		return $this->clear()->put($traversable);
357
+	}
358
+
359
+	/**
360
+	 * Clone the map
361
+	 *
362
+	 * @return void
363
+	 *
364
+	 * @since 1.0.0
365
+	 */
366
+	public function __clone()
367
+	{
368
+		if ($this->root != null) {
369
+			$root = $this->root;
370
+			$this->root = null;
371
+			$node = $root->first;
372
+
373
+			while ($node != null) {
374
+				$this[$node->key] = $node->value;
375
+				$node = $node->successor;
376
+			}
377
+		}
378
+	}
379
+
380
+	/**
381
+	 * Serialize the object
382
+	 *
383
+	 * @return array Array of values
384
+	 *
385
+	 * @since 1.0.0
386
+	 */
387
+	public function jsonSerialize()
388
+	{
389
+		$array = array();
390
+
391
+		foreach ($this as $key => $value) {
392
+			$array[$key] = $value;
393
+		}
394
+
395
+		return array('TreeMap' => $array);
396
+	}
397
+
398
+	/**
399
+	 * Set the value for a key
400
+	 *
401
+	 * @param mixed $key   The key
402
+	 * @param mixed $value The value
403
+	 *
404
+	 * @return void
405
+	 *
406
+	 * @since 1.0.0
407
+	 */
408
+	public function offsetSet($key, $value)
409
+	{
410
+		if ($this->root) {
411
+			$this->root = $this->root->insert($key, $value, $this->comparator);
412
+		} else {
413
+			$this->root = TreeNode::create($key, $value);
414
+		}
415
+	}
416
+
417
+	/**
418
+	 * Unset the existence of a key
419
+	 *
420
+	 * @param mixed $key The key
421
+	 *
422
+	 * @return void
423
+	 *
424
+	 * @since 1.0.0
425
+	 */
426
+	public function offsetUnset($key)
427
+	{
428
+		if ($this->root) {
429
+			$this->root = $this->root->remove($key, $this->comparator);
430
+		}
431
+	}
432
+
433
+	/**
434
+	 * Count the number of key/value pairs
435
+	 *
436
+	 * @return integer
437
+	 *
438
+	 * @since 1.0.0
439
+	 */
440
+	public function count()
441
+	{
442
+		if ($this->root) {
443
+			return count($this->root);
444
+		} else {
445
+			return 0;
446
+		}
447
+	}
448 448
 }
Please login to merge, or discard this patch.
src/SortedCollection/SortedCollection.php 1 patch
Indentation   +88 added lines, -88 removed lines patch added patch discarded remove patch
@@ -31,99 +31,99 @@
 block discarded – undo
31 31
  */
32 32
 interface SortedCollection extends \ArrayAccess, \Countable, \IteratorAggregate, \JsonSerializable
33 33
 {
34
-    /**
35
-     * Get the comparator
36
-     *
37
-     * @return callable The comparator
38
-     *
39
-     * @since 1.0.0
40
-     */
41
-    public function comparator();
34
+	/**
35
+	 * Get the comparator
36
+	 *
37
+	 * @return callable The comparator
38
+	 *
39
+	 * @since 1.0.0
40
+	 */
41
+	public function comparator();
42 42
 
43
-    /**
44
-     * Get the first element
45
-     *
46
-     * @return mixed The first element
47
-     *
48
-     * @throws OutOfBoundsException If there is no element
49
-     *
50
-     * @since 1.0.0
51
-     */
52
-    public function first();
43
+	/**
44
+	 * Get the first element
45
+	 *
46
+	 * @return mixed The first element
47
+	 *
48
+	 * @throws OutOfBoundsException If there is no element
49
+	 *
50
+	 * @since 1.0.0
51
+	 */
52
+	public function first();
53 53
 
54
-    /**
55
-     * Get the last element
56
-     *
57
-     * @return mixed The last element
58
-     *
59
-     * @throws OutOfBoundsException If there is no element
60
-     *
61
-     * @since 1.0.0
62
-     */
63
-    public function last();
54
+	/**
55
+	 * Get the last element
56
+	 *
57
+	 * @return mixed The last element
58
+	 *
59
+	 * @throws OutOfBoundsException If there is no element
60
+	 *
61
+	 * @since 1.0.0
62
+	 */
63
+	public function last();
64 64
 
65
-    /**
66
-     * Returns the greatest element lesser than the given key
67
-     *
68
-     * @param mixed $key The searched key
69
-     *
70
-     * @return mixed The found node
71
-     *
72
-     * @throws OutOfBoundsException If there is no lower element
73
-     *
74
-     * @since 1.0.0
75
-     */
76
-    public function lower($key);
65
+	/**
66
+	 * Returns the greatest element lesser than the given key
67
+	 *
68
+	 * @param mixed $key The searched key
69
+	 *
70
+	 * @return mixed The found node
71
+	 *
72
+	 * @throws OutOfBoundsException If there is no lower element
73
+	 *
74
+	 * @since 1.0.0
75
+	 */
76
+	public function lower($key);
77 77
 
78
-    /**
79
-     * Returns the greatest element lesser than or equal to the given key
80
-     *
81
-     * @param mixed $key The searched key
82
-     *
83
-     * @return mixed The found node
84
-     *
85
-     * @throws OutOfBoundsException If there is no floor element
86
-     *
87
-     * @since 1.0.0
88
-     */
89
-    public function floor($key);
78
+	/**
79
+	 * Returns the greatest element lesser than or equal to the given key
80
+	 *
81
+	 * @param mixed $key The searched key
82
+	 *
83
+	 * @return mixed The found node
84
+	 *
85
+	 * @throws OutOfBoundsException If there is no floor element
86
+	 *
87
+	 * @since 1.0.0
88
+	 */
89
+	public function floor($key);
90 90
 
91
-    /**
92
-     * Returns the element equal to the given key
93
-     *
94
-     * @param mixed $key The searched key
95
-     *
96
-     * @return mixed The found node
97
-     *
98
-     * @throws OutOfBoundsException If there is no such element
99
-     *
100
-     * @since 1.0.0
101
-     */
102
-    public function find($key);
91
+	/**
92
+	 * Returns the element equal to the given key
93
+	 *
94
+	 * @param mixed $key The searched key
95
+	 *
96
+	 * @return mixed The found node
97
+	 *
98
+	 * @throws OutOfBoundsException If there is no such element
99
+	 *
100
+	 * @since 1.0.0
101
+	 */
102
+	public function find($key);
103 103
 
104
-    /**
105
-     * Returns the lowest element greater than or equal to the given key
106
-     *
107
-     * @param mixed $key The searched key
108
-     *
109
-     * @return mixed The found node
110
-     *
111
-     * @throws OutOfBoundsException If there is no ceiling element
112
-     *
113
-     * @since 1.0.0
114
-     */
115
-    public function ceiling($key);
104
+	/**
105
+	 * Returns the lowest element greater than or equal to the given key
106
+	 *
107
+	 * @param mixed $key The searched key
108
+	 *
109
+	 * @return mixed The found node
110
+	 *
111
+	 * @throws OutOfBoundsException If there is no ceiling element
112
+	 *
113
+	 * @since 1.0.0
114
+	 */
115
+	public function ceiling($key);
116 116
 
117
-    /**
118
-     * Returns the lowest element greater than to the given key
119
-     *
120
-     * @param mixed $key The searched key
121
-     *
122
-     * @return mixed The found node
123
-     *
124
-     * @throws OutOfBoundsException If there is no higher element
125
-     *
126
-     * @since 1.0.0
127
-     */
128
-    public function higher($key);
117
+	/**
118
+	 * Returns the lowest element greater than to the given key
119
+	 *
120
+	 * @param mixed $key The searched key
121
+	 *
122
+	 * @return mixed The found node
123
+	 *
124
+	 * @throws OutOfBoundsException If there is no higher element
125
+	 *
126
+	 * @since 1.0.0
127
+	 */
128
+	public function higher($key);
129 129
 }
Please login to merge, or discard this patch.