@@ -285,7 +285,7 @@ protected function __construct(SortedMap $map, $fromKey, $fromOption, $toKey, $t
285285 protected function setEmpty ()
286286 {
287287 if ($ this ->fromOption != self ::UNUSED && $ this ->toOption != self ::UNUSED ) {
288- $ cmp = call_user_func ( $ this ->mapInternal -> comparator (), $ this ->fromKey , $ this ->toKey );
288+ $ cmp = $ this ->compareKeys ( $ this ->fromKey , $ this ->toKey );
289289
290290 $ this ->empty = $ cmp > 0
291291 || $ cmp == 0 && ($ this ->fromOption == self ::EXCLUSIVE || $ this ->toOption == self ::EXCLUSIVE );
@@ -294,6 +294,143 @@ protected function setEmpty()
294294 }
295295 }
296296
297+ /**
298+ * Compare 2 keys using the map comparator
299+ *
300+ * @param mixed $key1 First key
301+ * @param mixed $key2 Second key
302+ *
303+ * @return integer Comparison result
304+ *
305+ * @since 1.0.0
306+ */
307+ private function compareKeys ($ key1 , $ key2 )
308+ {
309+ return call_user_func ($ this ->mapInternal ->comparator (), $ key1 , $ key2 );
310+ }
311+
312+ /**
313+ * Validate lower() input against the lower bound
314+ *
315+ * @param mixed $key The searched key
316+ *
317+ * @return void
318+ *
319+ * @throws OutOfBoundsException If lower bound excludes the key
320+ *
321+ * @since 1.0.0
322+ */
323+ private function assertLowerAllowed ($ key )
324+ {
325+ if ($ this ->fromOption != self ::UNUSED && $ this ->compareKeys ($ key , $ this ->fromKey ) <= 0 ) {
326+ throw new \OutOfBoundsException ('Lower element unexisting ' );
327+ }
328+ }
329+
330+ /**
331+ * Validate higher() input against the upper bound
332+ *
333+ * @param mixed $key The searched key
334+ *
335+ * @return void
336+ *
337+ * @throws OutOfBoundsException If upper bound excludes the key
338+ *
339+ * @since 1.0.0
340+ */
341+ private function assertHigherAllowed ($ key )
342+ {
343+ if ($ this ->toOption != self ::UNUSED && $ this ->compareKeys ($ key , $ this ->toKey ) >= 0 ) {
344+ throw new \OutOfBoundsException ('Higher element unexisting ' );
345+ }
346+ }
347+
348+ /**
349+ * Ensure lower() result respects an exclusive lower bound
350+ *
351+ * @param TreeNode $node The found node
352+ *
353+ * @return void
354+ *
355+ * @throws OutOfBoundsException If result is out of bounds
356+ *
357+ * @since 1.0.0
358+ */
359+ private function assertLowerResultInRange ($ node )
360+ {
361+ if ($ node === null ) {
362+ return ;
363+ }
364+
365+ if ($ this ->fromOption == self ::EXCLUSIVE && $ this ->compareKeys ($ node ->key , $ this ->fromKey ) <= 0 ) {
366+ throw new \OutOfBoundsException ('Lower element unexisting ' );
367+ }
368+ }
369+
370+ /**
371+ * Ensure higher() result respects an exclusive upper bound
372+ *
373+ * @param TreeNode $node The found node
374+ *
375+ * @return void
376+ *
377+ * @throws OutOfBoundsException If result is out of bounds
378+ *
379+ * @since 1.0.0
380+ */
381+ private function assertHigherResultInRange ($ node )
382+ {
383+ if ($ node === null ) {
384+ return ;
385+ }
386+
387+ if ($ this ->toOption == self ::EXCLUSIVE && $ this ->compareKeys ($ node ->key , $ this ->toKey ) >= 0 ) {
388+ throw new \OutOfBoundsException ('Higher element unexisting ' );
389+ }
390+ }
391+
392+ /**
393+ * Clamp a lower-like result against the upper bound
394+ *
395+ * @param TreeNode $node The found node
396+ *
397+ * @return TreeNode The clamped node
398+ *
399+ * @since 1.0.0
400+ */
401+ private function clampLowerToUpperBound ($ node )
402+ {
403+ if (
404+ ($ this ->toOption == self ::INCLUSIVE && $ this ->compareKeys ($ node ->key , $ this ->toKey ) > 0 )
405+ || ($ this ->toOption == self ::EXCLUSIVE && $ this ->compareKeys ($ node ->key , $ this ->toKey ) >= 0 )
406+ ) {
407+ return $ this ->last ();
408+ }
409+
410+ return $ node ;
411+ }
412+
413+ /**
414+ * Clamp a higher-like result against the lower bound
415+ *
416+ * @param TreeNode $node The found node
417+ *
418+ * @return TreeNode The clamped node
419+ *
420+ * @since 1.0.0
421+ */
422+ private function clampHigherToLowerBound ($ node )
423+ {
424+ if (
425+ ($ this ->fromOption == self ::INCLUSIVE && $ this ->compareKeys ($ node ->key , $ this ->fromKey ) < 0 )
426+ || ($ this ->fromOption == self ::EXCLUSIVE && $ this ->compareKeys ($ node ->key , $ this ->fromKey ) <= 0 )
427+ ) {
428+ return $ this ->first ();
429+ }
430+
431+ return $ node ;
432+ }
433+
297434 /**
298435 * Create
299436 *
@@ -519,39 +656,13 @@ public function lower($key)
519656 throw new \OutOfBoundsException ('Lower element unexisting ' );
520657 }
521658
522- switch ($ this ->fromOption ) {
523- case self ::UNUSED :
524- $ lower = $ this ->map ->lower ($ key );
525- break ;
526- default :
527- if (call_user_func ($ this ->map ->comparator (), $ key , $ this ->fromKey ) <= 0 ) {
528- throw new \OutOfBoundsException ('Lower element unexisting ' );
529- } else {
530- $ lower = $ this ->map ->lower ($ key );
659+ $ this ->assertLowerAllowed ($ key );
531660
532- if (
533- $ this ->fromOption == self ::EXCLUSIVE
534- && call_user_func ($ this ->map ->comparator (), $ lower ->key , $ this ->fromKey ) <= 0
535- ) {
536- throw new \OutOfBoundsException ('Lower element unexisting ' );
537- }
538- }
539- break ;
540- }
661+ $ lower = $ this ->mapInternal ->lower ($ key );
662+ $ this ->assertLowerResultInRange ($ lower );
541663
542664 if ($ lower ) {
543- switch ($ this ->toOption ) {
544- case self ::INCLUSIVE :
545- if (call_user_func ($ this ->map ->comparator (), $ lower ->key , $ this ->toKey ) > 0 ) {
546- $ lower = $ this ->last ();
547- }
548- break ;
549- case self ::EXCLUSIVE :
550- if (call_user_func ($ this ->map ->comparator (), $ lower ->key , $ this ->toKey ) >= 0 ) {
551- $ lower = $ this ->last ();
552- }
553- break ;
554- }
665+ $ lower = $ this ->clampLowerToUpperBound ($ lower );
555666 }
556667
557668 return $ lower ;
@@ -726,39 +837,13 @@ public function higher($key)
726837 throw new \OutOfBoundsException ('Higher element unexisting ' );
727838 }
728839
729- switch ($ this ->toOption ) {
730- case self ::UNUSED :
731- $ higher = $ this ->map ->higher ($ key );
732- break ;
733- default :
734- if (call_user_func ($ this ->map ->comparator (), $ key , $ this ->toKey ) >= 0 ) {
735- throw new \OutOfBoundsException ('Higher element unexisting ' );
736- } else {
737- $ higher = $ this ->map ->higher ($ key );
840+ $ this ->assertHigherAllowed ($ key );
738841
739- if (
740- $ this ->toOption == self ::EXCLUSIVE
741- && call_user_func ($ this ->map ->comparator (), $ higher ->key , $ this ->toKey ) >= 0
742- ) {
743- throw new \OutOfBoundsException ('Higher element unexisting ' );
744- }
745- }
746- break ;
747- }
842+ $ higher = $ this ->mapInternal ->higher ($ key );
843+ $ this ->assertHigherResultInRange ($ higher );
748844
749845 if ($ higher ) {
750- switch ($ this ->fromOption ) {
751- case self ::INCLUSIVE :
752- if (call_user_func ($ this ->map ->comparator (), $ higher ->key , $ this ->fromKey ) < 0 ) {
753- $ higher = $ this ->first ();
754- }
755- break ;
756- case self ::EXCLUSIVE :
757- if (call_user_func ($ this ->map ->comparator (), $ higher ->key , $ this ->fromKey ) <= 0 ) {
758- $ higher = $ this ->first ();
759- }
760- break ;
761- }
846+ $ higher = $ this ->clampHigherToLowerBound ($ higher );
762847 }
763848
764849 return $ higher ;
0 commit comments