Passed
Push — 6.0 ( 310980...0f5702 )
by Olivier
01:36
created

DateFormatPattern   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 72
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 33
c 1
b 0
f 0
dl 0
loc 72
rs 10
wmc 11

2 Methods

Rating   Name   Duplication   Size   Complexity  
A tokenize() 0 5 1
B do_tokenize() 0 47 10
1
<?php
2
3
namespace ICanBoogie\CLDR;
4
5
/**
6
 * @link https://www.unicode.org/reports/tr35/tr35-72/tr35-dates.html#Date_Format_Patterns
7
 */
8
final class DateFormatPattern
9
{
10
    private const QUOTE = "'";
11
12
    /**
13
     * @param string $pattern
14
     *     A date format pattern; for example, "yyyy.MM.dd G 'at' HH:mm:ss zzz".
15
     *
16
     * @return array<string|array{ string, int }>
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<string|array{ at position 6 could not be parsed: the token is null at position 6.
Loading history...
17
     *     Where _value_ is either a literal or an array where `0` is a pattern character and `1` its length.
18
     */
19
    public static function tokenize(string $pattern): array
20
    {
21
        static $cache = [];
22
23
        return $cache[$pattern] ??= self::do_tokenize($pattern);
24
    }
25
26
    /**
27
     * @param string $pattern
28
     *     A date format pattern; for example, "yyyy.MM.dd G 'at' HH:mm:ss zzz".
29
     *
30
     * @return array<string|array{ string, int }>
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<string|array{ at position 6 could not be parsed: the token is null at position 6.
Loading history...
31
     *     Where _value_ is either a literal or an array where `0` is a pattern character and `1` its length.
32
     */
33
    private static function do_tokenize(string $pattern): array
34
    {
35
        $tokens = [];
36
        $is_literal = false;
37
        $literal = '';
38
        $z = mb_strlen($pattern);
39
40
        for ($i = 0; $i < $z; ++$i) {
41
            $c = mb_substr($pattern, $i, 1);
42
43
            if ($c === self::QUOTE) {
44
                // Two adjacent single vertical quotes (''), which represent a literal single quote,
45
                // either inside or outside a quoted text.
46
                if (mb_substr($pattern, $i + 1, 1) === self::QUOTE) {
47
                    $i++;
48
                    $literal .= self::QUOTE;
49
                } else {
50
                    // Toggle literal
51
                    $is_literal = !$is_literal;
0 ignored issues
show
introduced by
The condition $is_literal is always false.
Loading history...
52
                }
53
            } elseif ($is_literal) {
54
                $literal .= $c;
55
            } elseif (ctype_alpha($c)) {
56
                if ($literal) {
57
                    $tokens[] = $literal;
58
                    $literal = '';
59
                }
60
61
                for ($j = $i + 1; $j < $z; ++$j) {
62
                    $nc = mb_substr($pattern, $j, 1);
63
                    if ($nc !== $c) {
64
                        break;
65
                    }
66
                }
67
                $tokens[] = [ $c, $j - $i ];
68
                $i = $j - 1; // because +1 from the for loop
69
            } else {
70
                $literal .= $c;
71
            }
72
        }
73
74
        // If the pattern ends with literal (could also be a malformed quote)
75
        if ($literal) {
76
            $tokens[] = $literal;
77
        }
78
79
        return $tokens;
80
    }
81
}
82