1
+ <?php declare (strict_types=1 );
2
+
3
+ namespace Toolkit \Extlib \Text ;
4
+
5
+ use Iterator ;
6
+ use Toolkit \Stdlib \Helper \Assert ;
7
+ use function strtok ;
8
+
9
+ /**
10
+ * @author inhere
11
+ */
12
+ class TextScanner implements Iterator
13
+ {
14
+ /** @var string source content */
15
+ private string $ source ;
16
+
17
+ /**
18
+ * @var string split token
19
+ */
20
+ private string $ splitToken = "\n" ;
21
+
22
+ private int $ index = 0 ;
23
+ private bool $ start = false ;
24
+ private bool $ done = false ;
25
+
26
+ /**
27
+ * @var string current token text
28
+ */
29
+ private string $ tokText = '' ;
30
+
31
+ /**
32
+ * @param string $source
33
+ *
34
+ * @return static
35
+ */
36
+ public static function new (string $ source = '' ): static
37
+ {
38
+ return new static ($ source );
39
+ }
40
+
41
+ public function __construct (string $ source = '' )
42
+ {
43
+ $ this ->source = $ source ;
44
+ }
45
+
46
+ /**
47
+ * scan text token
48
+ *
49
+ * Usage:
50
+ *
51
+ * ```php
52
+ * $s = Scanner::new($source);
53
+ * while ($s->scan()) {
54
+ * $txt = $s->getText();
55
+ * // do something
56
+ * }
57
+ * ```
58
+ *
59
+ * @return bool
60
+ */
61
+ public function scan (): bool
62
+ {
63
+ if ($ this ->done ) {
64
+ return false ;
65
+ }
66
+
67
+ if ($ this ->start ) {
68
+ $ txt = strtok ($ this ->splitToken );
69
+ } else {
70
+ $ this ->start = true ;
71
+ Assert::notEmpty ($ this ->source , 'The source can not be empty ' );
72
+ $ txt = strtok ($ this ->source , $ this ->splitToken );
73
+ }
74
+
75
+ // end
76
+ if ($ txt === false ) {
77
+ $ this ->tokText = '' ;
78
+ // reset
79
+ strtok ('' , '' );
80
+ $ this ->done = true ;
81
+ return false ;
82
+ }
83
+
84
+ $ this ->index ++;
85
+ $ this ->tokText = $ txt ;
86
+ return true ;
87
+ }
88
+
89
+ /**
90
+ * @return array = [bool, string]
91
+ */
92
+ public function nextText (): array
93
+ {
94
+ $ ok = $ this ->scan ();
95
+ return [$ ok , $ this ->tokText ];
96
+ }
97
+
98
+ /**
99
+ * find next token text from given token
100
+ *
101
+ * @return array = [bool, string]
102
+ */
103
+ public function nextToken (string $ tok ): array
104
+ {
105
+ $ txt = strtok ($ tok );
106
+ if ($ txt !== false ) {
107
+ return [true , $ txt ];
108
+ }
109
+ return [false , '' ];
110
+ }
111
+
112
+ /**
113
+ * @return string get current token text
114
+ */
115
+ public function getText (): string
116
+ {
117
+ return $ this ->tokText ;
118
+ }
119
+
120
+ public function getIndex (): int
121
+ {
122
+ return $ this ->index ;
123
+ }
124
+
125
+ public function getSource (): string
126
+ {
127
+ return $ this ->source ;
128
+ }
129
+
130
+ public function setSource (string $ source ): void
131
+ {
132
+ $ this ->source = $ source ;
133
+ }
134
+
135
+ public function setSplitToken (string $ splitToken ): void
136
+ {
137
+ $ this ->splitToken = $ splitToken ;
138
+ }
139
+
140
+ public function current (): string
141
+ {
142
+ return $ this ->tokText ;
143
+ }
144
+
145
+ public function next (): void
146
+ {
147
+ $ this ->scan ();
148
+ }
149
+
150
+ public function key (): int
151
+ {
152
+ return $ this ->index ;
153
+ }
154
+
155
+ public function valid (): bool
156
+ {
157
+ return !$ this ->done ;
158
+ }
159
+
160
+ public function rewind (): void
161
+ {
162
+ $ this ->source = '' ;
163
+ $ this ->tokText = '' ;
164
+
165
+ $ this ->index = 0 ;
166
+ $ this ->start = $ this ->done = false ;
167
+ }
168
+
169
+ }
0 commit comments