1 <?php
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
22
23 24 25
26 class phpMorphy_Fsa_Tree_Mem extends phpMorphy_Fsa {
27 function walk($trans, $word, $readAnnot = true) {
28 $__mem = $this->resource; $fsa_start = $this->fsa_start;
29
30 for($i = 0, $c = $GLOBALS['__phpmorphy_strlen']($word); $i < $c; $i++) {
31 $prev_trans = $trans;
32 $char = ord($word[$i]);
33
34
35
36
37 $result = true;
38 $start_offset = $fsa_start + ((($trans >> 11) & 0x1FFFFF) << 2);
39
40
41
42 list(, $trans) = unpack('V', $GLOBALS['__phpmorphy_substr']($__mem, $start_offset, 4));
43
44
45 if(($trans & 0x0100)) {
46
47 if(($trans & 0x0200) && ($trans & 0x0400)) {
48 $result = false;
49 } else {
50 $start_offset += 4;
51
52 list(, $trans) = unpack('V', $GLOBALS['__phpmorphy_substr']($__mem, $start_offset, 4));
53 }
54 }
55
56
57 if($result) {
58
59 for($idx = 1, $j = 0; ; $j++) {
60 $attr = ($trans & 0xFF);
61
62 if($attr == $char) {
63 $result = true;
64 break;
65 } else if($attr > $char) {
66 if(($trans & 0x0200)) {
67 $result = false;
68 break;
69 }
70
71 $idx = $idx << 1;
72 } else {
73 if(($trans & 0x0400)) {
74 $result = false;
75 break;
76 }
77
78 $idx = ($idx << 1) + 1;
79 }
80
81 if($j > 255) {
82 throw new phpMorphy_Exception('Infinite recursion possible');
83 }
84
85
86
87
88 list(, $trans) = unpack('V', $GLOBALS['__phpmorphy_substr']($__mem, $start_offset + (($idx - 1) << 2), 4));
89 }
90 }
91
92
93
94
95 if(!$result) {
96 $trans = $prev_trans;
97 break;
98 }
99 }
100
101 $annot = null;
102 $result = false;
103 $prev_trans = $trans;
104
105 if($i >= $c) {
106
107 $result = true;
108
109 if($readAnnot) {
110
111
112 list(, $trans) = unpack('V', $GLOBALS['__phpmorphy_substr']($__mem, $fsa_start + ((($trans >> 11) & 0x1FFFFF) << 2), 4));
113
114 if(0 == ($trans & 0x0100)) {
115 $result = false;
116 } else {
117 $annot = $this->getAnnot($trans);
118 }
119 }
120 }
121
122 return array(
123 'result' => $result,
124 'last_trans' => $trans,
125 'word_trans' => $prev_trans,
126 'walked' => $i,
127 'annot' => $annot
128 );
129 }
130
131 function collect($startNode, $callback, $readAnnot = true, $path = '') {
132 $total = 0;
133
134 $stack = array();
135 $stack_idx = array();
136 $start_idx = 0;
137 array_push($stack, null);
138 array_push($stack_idx, null);
139
140 $state = $this->readState((($startNode) >> 11) & 0x1FFFFF);
141
142 do {
143 for($i = $start_idx, $c = count($state); $i < $c; $i++) {
144 $trans = $state[$i];
145
146 if(($trans & 0x0100)) {
147 $total++;
148
149 if($readAnnot) {
150 $annot = $this->getAnnot($trans);
151 } else {
152 $annot = $trans;
153 }
154
155 if(!call_user_func($callback, $path, $annot)) {
156 return $total;
157 }
158 } else {
159 $path .= chr(($trans & 0xFF));
160 array_push($stack, $state);
161 array_push($stack_idx, $i + 1);
162 $state = $this->readState((($trans) >> 11) & 0x1FFFFF);
163 $start_idx = 0;
164
165 break;
166 }
167 }
168
169 if($i >= $c) {
170 $state = array_pop($stack);
171 $start_idx = array_pop($stack_idx);
172 $path = $GLOBALS['__phpmorphy_substr']($path, 0, -1);
173 }
174 } while(!empty($stack));
175
176 return $total;
177 }
178
179 function readState($index) {
180 $__mem = $this->resource; $fsa_start = $this->fsa_start;
181
182 $result = array();
183
184 $offset = $fsa_start + (($index) << 2);
185
186
187
188 list(, $trans) = unpack('V', $GLOBALS['__phpmorphy_substr']($__mem, $offset, 4));
189
190
191 if(($trans & 0x0100) && !(($trans & 0x0200) || ($trans & 0x0400))) {
192 $result[] = $trans;
193
194 list(, $trans) = unpack('V', $GLOBALS['__phpmorphy_substr']($__mem, $offset, 4));
195 $offset += 4;
196 }
197
198
199 for($expect = 1; $expect; $expect--) {
200 if(!($trans & 0x0200)) $expect++;
201 if(!($trans & 0x0400)) $expect++;
202
203 $result[] = $trans;
204
205 if($expect > 1) {
206 list(, $trans) = unpack('V', $GLOBALS['__phpmorphy_substr']($__mem, $offset, 4));
207 $offset += 4;
208 }
209 }
210
211 return $result;
212 }
213
214 function unpackTranses($rawTranses) {
215 settype($rawTranses, 'array');
216 $result = array();
217
218 foreach($rawTranses as $rawTrans) {
219 $result[] = array(
220 'term' => ($rawTrans & 0x0100) ? true : false,
221 'llast' => ($rawTrans & 0x0200) ? true : false,
222 'rlast' => ($rawTrans & 0x0400) ? true : false,
223 'attr' => ($rawTrans & 0xFF),
224 'dest' => (($rawTrans) >> 11) & 0x1FFFFF,
225 );
226 }
227
228 return $result;
229 }
230
231 protected function readRootTrans() {
232 $__mem = $this->resource; $fsa_start = $this->fsa_start;
233
234
235 list(, $trans) = unpack('V', $GLOBALS['__phpmorphy_substr']($__mem, $fsa_start + 0, 4));
236
237 return $trans;
238 }
239
240 protected function readAlphabet() {
241 $__mem = $this->resource; $fsa_start = $this->fsa_start;
242
243
244 return $GLOBALS['__phpmorphy_substr']($__mem, $this->header['alphabet_offset'], $this->header['alphabet_size']);
245 }
246
247 function getAnnot($trans) {
248 if(!($trans & 0x0100)) {
249 return null;
250 }
251
252 $__mem = $this->resource; $fsa_start = $this->fsa_start;
253
254 $offset =
255 $this->header['annot_offset'] +
256 ((($trans & 0xFF) << 21) | (($trans >> 11) & 0x1FFFFF));
257
258
259 $len = ord($GLOBALS['__phpmorphy_substr']($__mem, $offset, 1));
260
261 if($len) {
262 $annot = $GLOBALS['__phpmorphy_substr']($__mem, $offset + 1, $len);
263 } else {
264 $annot = null;
265 }
266
267 return $annot;
268 }
269
270
271 }
272
[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the
Silverstripe Forums to ask development related questions.
-