• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

chdemko / php-sorted-collections / 12390158994

18 Dec 2024 09:33AM UTC coverage: 100.0%. Remained the same
12390158994

push

github

chdemko
Fix style in benchmarks

754 of 754 relevant lines covered (100.0%)

113.21 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

100.0
/src/SortedCollection/SubMap.php
1
<?php
2

3
/**
4
 * chdemko\SortedCollection\SubMap class
5
 *
6
 * @author    Christophe Demko <chdemko@gmail.com>
7
 * @copyright Copyright (C) 2012-2024 Christophe Demko. All rights reserved.
8
 *
9
 * @license BSD 3-Clause License
10
 *
11
 * This file is part of the php-sorted-collections package https://github.com/chdemko/php-sorted-collections
12
 */
13

14
// Declare chdemko\SortedCollection namespace
15
namespace chdemko\SortedCollection;
16

17
/**
18
 * Sub map
19
 *
20
 * @package    SortedCollection
21
 * @subpackage Map
22
 *
23
 * @since 1.0.0
24
 *
25
 * @property-read callable   $comparator     The key comparison function
26
 * @property-read TreeNode   $first          The first element of the map
27
 * @property-read mixed      $firstKey       The first key of the map
28
 * @property-read mixed      $firstValue     The first value of the map
29
 * @property-read TreeNode   $last           The last element of the map
30
 * @property-read mixed      $lastKey        The last key of the map
31
 * @property-read mixed      $lastValue      The last value of the map
32
 * @property-read Iterator   $keys           The keys iterator
33
 * @property-read Iterator   $values         The values iterator
34
 * @property-read integer    $count          The number of elements in the map
35
 * @property      mixed      $fromKey        The from key
36
 * @property      boolean    $fromInclusive  The from inclusive flag
37
 * @property      mixed      $toKey          The to key
38
 * @property      boolean    $toInclusive    The to inclusive flag
39
 * @property-read SortedMap  $map            The underlying map
40
 */
41
class SubMap extends AbstractMap
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':
34✔
121
                if ($this->fromOption == self::UNUSED) {
14✔
122
                     throw new \RuntimeException('Undefined property');
3✔
123
                } else {
124
                    return $this->fromKey;
11✔
125
                }
126

127
            case 'toKey':
31✔
128
                if ($this->toOption == self::UNUSED) {
14✔
129
                    throw new \RuntimeException('Undefined property');
3✔
130
                } else {
131
                    return $this->toKey;
11✔
132
                }
133

134
            case 'fromInclusive':
28✔
135
                if ($this->fromOption == self::UNUSED) {
12✔
136
                    throw new \RuntimeException('Undefined property');
1✔
137
                } else {
138
                    return $this->fromOption == self::INCLUSIVE;
11✔
139
                }
140

141
            case 'toInclusive':
25✔
142
                if ($this->toOption == self::UNUSED) {
12✔
143
                    throw new \RuntimeException('Undefined property');
1✔
144
                } else {
145
                    return $this->toOption == self::INCLUSIVE;
11✔
146
                }
147

148
            case 'map':
15✔
149
                return $this->map;
4✔
150
            default:
151
                return parent::__get($property);
11✔
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':
7✔
171
                $this->fromKey = $value;
2✔
172

173
                if ($this->fromOption == self::UNUSED) {
2✔
174
                     $this->fromOption = self::INCLUSIVE;
1✔
175
                }
176
                break;
2✔
177
            case 'toKey':
6✔
178
                $this->toKey = $value;
2✔
179

180
                if ($this->toOption == self::UNUSED) {
2✔
181
                    $this->toOption = self::EXCLUSIVE;
1✔
182
                }
183
                break;
2✔
184
            case 'fromInclusive':
5✔
185
                if ($this->fromOption == self::UNUSED) {
3✔
186
                    throw new \RuntimeException('Undefined property');
1✔
187
                } else {
188
                    $this->fromOption = $value ? self::INCLUSIVE : self::EXCLUSIVE;
2✔
189
                }
190
                break;
2✔
191
            case 'toInclusive':
4✔
192
                if ($this->toOption == self::UNUSED) {
3✔
193
                    throw new \RuntimeException('Undefined property');
1✔
194
                } else {
195
                    $this->toOption = $value ? self::INCLUSIVE : self::EXCLUSIVE;
2✔
196
                }
197
                break;
2✔
198
            default:
199
                throw new \RuntimeException('Undefined property');
1✔
200
        }
201

202
        $this->setEmpty();
4✔
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':
8✔
220
            case 'fromInclusive':
6✔
221
                $this->fromOption = self::UNUSED;
4✔
222
                break;
4✔
223
            case 'toKey':
5✔
224
            case 'toInclusive':
3✔
225
                $this->toOption = self::UNUSED;
4✔
226
                break;
4✔
227
            default:
228
                throw new \RuntimeException('Undefined property');
1✔
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':
13✔
245
            case 'fromInclusive':
13✔
246
                return $this->fromOption != self::UNUSED;
11✔
247
            case 'toKey':
12✔
248
            case 'toInclusive':
3✔
249
                return $this->toOption != self::UNUSED;
11✔
250
            default:
251
                return false;
1✔
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;
229✔
269
        $this->fromKey = $fromKey;
229✔
270
        $this->fromOption = $fromOption;
229✔
271
        $this->toKey = $toKey;
229✔
272
        $this->toOption = $toOption;
229✔
273
        $this->setEmpty();
229✔
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) {
229✔
286
            $cmp = call_user_func($this->map->comparator(), $this->fromKey, $this->toKey);
178✔
287

288
            $this->empty = $cmp > 0
178✔
289
              || $cmp == 0 && ($this->fromOption == self::EXCLUSIVE || $this->toOption == self::EXCLUSIVE);
178✔
290
        } else {
291
            $this->empty = false;
53✔
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(
176✔
311
            $map,
176✔
312
            $fromKey,
176✔
313
            $fromInclusive ? self::INCLUSIVE : self::EXCLUSIVE,
176✔
314
            $toKey,
176✔
315
            $toInclusive ? self::INCLUSIVE : self::EXCLUSIVE
176✔
316
        );
176✔
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);
23✔
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);
26✔
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);
4✔
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();
1✔
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) {
38✔
389
            throw new \OutOfBoundsException('First element unexisting');
4✔
390
        }
391

392
        switch ($this->fromOption) {
34✔
393
            case self::INCLUSIVE:
394
                $first = $this->map->ceiling($this->fromKey);
13✔
395
                break;
13✔
396
            case self::EXCLUSIVE:
397
                $first = $this->map->higher($this->fromKey);
17✔
398
                break;
17✔
399
            default:
400
                $first = $this->map->first();
4✔
401
                break;
4✔
402
        }
403

404
        return $first;
34✔
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) {
17✔
419
            throw new \OutOfBoundsException('Last element unexisting');
2✔
420
        }
421

422
        switch ($this->toOption) {
15✔
423
            case self::INCLUSIVE:
424
                $last = $this->map->floor($this->toKey);
4✔
425
                break;
4✔
426
            case self::EXCLUSIVE:
427
                $last = $this->map->lower($this->toKey);
10✔
428
                break;
10✔
429
            default:
430
                $last = $this->map->last();
1✔
431
                break;
1✔
432
        }
433

434
        return $last;
15✔
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);
4✔
451

452
        if ($predecessor) {
4✔
453
            switch ($this->fromOption) {
4✔
454
                case self::INCLUSIVE:
455
                    if (call_user_func($this->map->comparator(), $predecessor->key, $this->fromKey) < 0) {
2✔
456
                        throw new \OutOfBoundsException('Predecessor element unexisting');
1✔
457
                    }
458
                    break;
1✔
459
                case self::EXCLUSIVE:
460
                    if (call_user_func($this->map->comparator(), $predecessor->key, $this->fromKey) <= 0) {
2✔
461
                        throw new \OutOfBoundsException('Predecessor element unexisting');
1✔
462
                    }
463
                    break;
1✔
464
            }
465
        }
466

467
        return $predecessor;
2✔
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);
21✔
484

485
        if ($successor) {
21✔
486
            switch ($this->toOption) {
21✔
487
                case self::INCLUSIVE:
488
                    if (call_user_func($this->map->comparator(), $successor->key, $this->toKey) > 0) {
9✔
489
                        throw new \OutOfBoundsException('Successor element unexisting');
8✔
490
                    }
491
                    break;
8✔
492
                case self::EXCLUSIVE:
493
                    if (call_user_func($this->map->comparator(), $successor->key, $this->toKey) >= 0) {
9✔
494
                        throw new \OutOfBoundsException('Successor element unexisting');
8✔
495
                    }
496
                    break;
8✔
497
            }
498
        }
499

500
        return $successor;
19✔
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) {
29✔
517
            throw new \OutOfBoundsException('Lower element unexisting');
2✔
518
        }
519

520
        switch ($this->fromOption) {
27✔
521
            case self::UNUSED:
522
                $lower = $this->map->lower($key);
4✔
523
                break;
3✔
524
            default:
525
                if (call_user_func($this->map->comparator(), $key, $this->fromKey) <= 0) {
23✔
526
                    throw new \OutOfBoundsException('Lower element unexisting');
6✔
527
                } else {
528
                    $lower = $this->map->lower($key);
17✔
529

530
                    if (
531
                        $this->fromOption == self::EXCLUSIVE
17✔
532
                          && call_user_func($this->map->comparator(), $lower->key, $this->fromKey) <= 0
17✔
533
                    ) {
534
                        throw new \OutOfBoundsException('Lower element unexisting');
2✔
535
                    }
536
                }
537
                break;
15✔
538
        }
539

540
        if ($lower) {
18✔
541
            switch ($this->toOption) {
18✔
542
                case self::INCLUSIVE:
543
                    if (call_user_func($this->map->comparator(), $lower->key, $this->toKey) > 0) {
8✔
544
                          $lower = $this->last();
1✔
545
                    }
546
                    break;
8✔
547
                case self::EXCLUSIVE:
548
                    if (call_user_func($this->map->comparator(), $lower->key, $this->toKey) >= 0) {
10✔
549
                        $lower = $this->last();
3✔
550
                    }
551
                    break;
10✔
552
            }
553
        }
554

555
        return $lower;
18✔
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) {
25✔
572
            throw new \OutOfBoundsException('Floor element unexisting');
2✔
573
        }
574

575
        switch ($this->fromOption) {
23✔
576
            case self::INCLUSIVE:
577
                if (call_user_func($this->map->comparator(), $key, $this->fromKey) < 0) {
8✔
578
                    throw new \OutOfBoundsException('Floor element unexisting');
2✔
579
                } else {
580
                    $floor = $this->map->floor($key);
6✔
581
                }
582
                break;
6✔
583
            case self::EXCLUSIVE:
584
                if (call_user_func($this->map->comparator(), $key, $this->fromKey) <= 0) {
12✔
585
                    throw new \OutOfBoundsException('Floor element unexisting');
4✔
586
                } else {
587
                    $floor = $this->map->floor($key);
8✔
588
                }
589
                break;
8✔
590
            default:
591
                $floor = $this->map->floor($key);
3✔
592
                break;
3✔
593
        }
594

595
        if ($floor) {
17✔
596
            switch ($this->toOption) {
17✔
597
                case self::INCLUSIVE:
598
                    if (call_user_func($this->map->comparator(), $floor->key, $this->toKey) > 0) {
7✔
599
                          $floor = $this->last();
2✔
600
                    }
601
                    break;
7✔
602
                case self::EXCLUSIVE:
603
                    if (call_user_func($this->map->comparator(), $floor->key, $this->toKey) >= 0) {
10✔
604
                        $floor = $this->last();
6✔
605
                    }
606
                    break;
10✔
607
            }
608
        }
609

610
        return $floor;
17✔
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) {
56✔
627
            case self::INCLUSIVE:
628
                if (call_user_func($this->map->comparator(), $key, $this->fromKey) < 0) {
26✔
629
                     throw new \OutOfBoundsException('Element unexisting');
8✔
630
                }
631
                break;
18✔
632
            case self::EXCLUSIVE:
633
                if (call_user_func($this->map->comparator(), $key, $this->fromKey) <= 0) {
30✔
634
                    throw new \OutOfBoundsException('Element unexisting');
8✔
635
                }
636
                break;
22✔
637
        }
638

639
        switch ($this->toOption) {
40✔
640
            case self::INCLUSIVE:
641
                if (call_user_func($this->map->comparator(), $key, $this->toKey) > 0) {
18✔
642
                    throw new \OutOfBoundsException('Element unexisting');
4✔
643
                }
644
                break;
14✔
645
            case self::EXCLUSIVE:
646
                if (call_user_func($this->map->comparator(), $key, $this->toKey) >= 0) {
22✔
647
                    throw new \OutOfBoundsException('Element unexisting');
8✔
648
                }
649
                break;
14✔
650
        }
651

652
        return $this->map->find($key);
28✔
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) {
23✔
669
            throw new \OutOfBoundsException('Ceiling element unexisting');
2✔
670
        }
671

672
        switch ($this->toOption) {
21✔
673
            case self::INCLUSIVE:
674
                if (call_user_func($this->map->comparator(), $key, $this->toKey) > 0) {
9✔
675
                    throw new \OutOfBoundsException('Ceiling element unexisting');
2✔
676
                } else {
677
                    $ceiling = $this->map->ceiling($key);
7✔
678
                }
679
                break;
7✔
680
            case self::EXCLUSIVE:
681
                if (call_user_func($this->map->comparator(), $key, $this->toKey) >= 0) {
6✔
682
                    throw new \OutOfBoundsException('Ceiling element unexisting');
2✔
683
                } else {
684
                    $ceiling = $this->map->ceiling($key);
4✔
685
                }
686
                break;
4✔
687
            default:
688
                $ceiling = $this->map->ceiling($key);
6✔
689
                break;
5✔
690
        }
691

692
        if ($ceiling) {
16✔
693
            switch ($this->fromOption) {
16✔
694
                case self::INCLUSIVE:
695
                    if (call_user_func($this->map->comparator(), $ceiling->key, $this->fromKey) < 0) {
8✔
696
                          $ceiling = $this->first();
3✔
697
                    }
698
                    break;
8✔
699
                case self::EXCLUSIVE:
700
                    if (call_user_func($this->map->comparator(), $ceiling->key, $this->fromKey) <= 0) {
8✔
701
                        $ceiling = $this->first();
6✔
702
                    }
703
                    break;
8✔
704
            }
705
        }
706

707
        return $ceiling;
16✔
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) {
26✔
724
            throw new \OutOfBoundsException('Higher element unexisting');
2✔
725
        }
726

727
        switch ($this->toOption) {
24✔
728
            case self::UNUSED:
729
                $higher = $this->map->higher($key);
7✔
730
                break;
5✔
731
            default:
732
                if (call_user_func($this->map->comparator(), $key, $this->toKey) >= 0) {
17✔
733
                    throw new \OutOfBoundsException('Higher element unexisting');
5✔
734
                } else {
735
                    $higher = $this->map->higher($key);
12✔
736

737
                    if (
738
                        $this->toOption == self::EXCLUSIVE
12✔
739
                          && call_user_func($this->map->comparator(), $higher->key, $this->toKey) >= 0
12✔
740
                    ) {
741
                        throw new \OutOfBoundsException('Higher element unexisting');
1✔
742
                    }
743
                }
744
                break;
11✔
745
        }
746

747
        if ($higher) {
16✔
748
            switch ($this->fromOption) {
16✔
749
                case self::INCLUSIVE:
750
                    if (call_user_func($this->map->comparator(), $higher->key, $this->fromKey) < 0) {
8✔
751
                          $higher = $this->first();
1✔
752
                    }
753
                    break;
8✔
754
                case self::EXCLUSIVE:
755
                    if (call_user_func($this->map->comparator(), $higher->key, $this->fromKey) <= 0) {
8✔
756
                        $higher = $this->first();
3✔
757
                    }
758
                    break;
8✔
759
            }
760
        }
761

762
        return $higher;
16✔
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(): array
773
    {
774
        if ($this->fromOption == self::UNUSED) {
8✔
775
            if ($this->toOption == self::UNUSED) {
2✔
776
                return array(
1✔
777
                    'ViewMap' => array(
1✔
778
                        'map' => $this->map->jsonSerialize(),
1✔
779
                     )
1✔
780
                );
1✔
781
            } else {
782
                return array(
1✔
783
                    'HeadMap' => array(
1✔
784
                        'map' => $this->map->jsonSerialize(),
1✔
785
                        'toKey' => $this->toKey,
1✔
786
                        'toInclusive' => $this->toOption == self::INCLUSIVE,
1✔
787
                    )
1✔
788
                );
1✔
789
            }
790
        } else {
791
            if ($this->toOption == self::UNUSED) {
6✔
792
                return array(
1✔
793
                    'TailMap' => array(
1✔
794
                        'map' => $this->map->jsonSerialize(),
1✔
795
                        'fromKey' => $this->fromKey,
1✔
796
                        'fromInclusive' => $this->fromOption == self::INCLUSIVE,
1✔
797
                    )
1✔
798
                );
1✔
799
            } else {
800
                return array(
5✔
801
                    'SubMap' => array(
5✔
802
                        'map' => $this->map->jsonSerialize(),
5✔
803
                        'fromKey' => $this->fromKey,
5✔
804
                        'fromInclusive' => $this->fromOption == self::INCLUSIVE,
5✔
805
                        'toKey' => $this->toKey,
5✔
806
                        'toInclusive' => $this->toOption == self::INCLUSIVE,
5✔
807
                    )
5✔
808
                );
5✔
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(): int
821
    {
822
        $count = 0;
5✔
823

824
        foreach ($this as $value) {
5✔
825
            $count++;
4✔
826
        }
827

828
        return $count;
5✔
829
    }
830
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc