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_Sparse_Shm extends phpMorphy_Fsa {
27 function walk($trans, $word, $readAnnot = true) {
28 $__shm = $this->resource['shm_id']; $__offset = $this->resource['offset']; $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
39 list(, $trans) = unpack('V', shmop_read($__shm, $__offset + ($fsa_start + (((($trans >> 10) & 0x3FFFFF) + $char + 1) << 2)), 4));
40
41 if(($trans & 0x0200) || ($trans & 0xFF) != $char) {
42 $result = false;
43 }
44
45
46
47 if(!$result) {
48 $trans = $prev_trans;
49 break;
50 }
51 }
52
53 $annot = null;
54 $result = false;
55 $prev_trans = $trans;
56
57 if($i >= $c) {
58
59 $result = true;
60
61 if($readAnnot) {
62
63
64 list(, $trans) = unpack('V', shmop_read($__shm, $__offset + ($fsa_start + ((($trans >> 10) & 0x3FFFFF) << 2)), 4));
65
66 if(0 == ($trans & 0x0100)) {
67 $result = false;
68 } else {
69 $annot = $this->getAnnot($trans);
70 }
71 }
72 }
73
74 return array(
75 'result' => $result,
76 'last_trans' => $trans,
77 'word_trans' => $prev_trans,
78 'walked' => $i,
79 'annot' => $annot
80 );
81 }
82
83 function collect($startNode, $callback, $readAnnot = true, $path = '') {
84 $total = 0;
85
86 $stack = array();
87 $stack_idx = array();
88 $start_idx = 0;
89 array_push($stack, null);
90 array_push($stack_idx, null);
91
92 $state = $this->readState((($startNode) >> 10) & 0x3FFFFF);
93
94 do {
95 for($i = $start_idx, $c = count($state); $i < $c; $i++) {
96 $trans = $state[$i];
97
98 if(($trans & 0x0100)) {
99 $total++;
100
101 if($readAnnot) {
102 $annot = $this->getAnnot($trans);
103 } else {
104 $annot = $trans;
105 }
106
107 if(!call_user_func($callback, $path, $annot)) {
108 return $total;
109 }
110 } else {
111 $path .= chr(($trans & 0xFF));
112 array_push($stack, $state);
113 array_push($stack_idx, $i + 1);
114 $state = $this->readState((($trans) >> 10) & 0x3FFFFF);
115 $start_idx = 0;
116
117 break;
118 }
119 }
120
121 if($i >= $c) {
122 $state = array_pop($stack);
123 $start_idx = array_pop($stack_idx);
124 $path = $GLOBALS['__phpmorphy_substr']($path, 0, -1);
125 }
126 } while(!empty($stack));
127
128 return $total;
129 }
130
131 function readState($index) {
132 $__shm = $this->resource['shm_id']; $__offset = $this->resource['offset']; $fsa_start = $this->fsa_start;
133
134 $result = array();
135
136 $start_offset = $fsa_start + (($index) << 2);
137
138
139
140 list(, $trans) = unpack('V', shmop_read($__shm, $__offset + ($start_offset), 4));
141
142 if(($trans & 0x0100)) {
143 $result[] = $trans;
144 }
145
146
147 $start_offset += 4;
148 foreach($this->getAlphabetNum() as $char) {
149
150 list(, $trans) = unpack('V', shmop_read($__shm, $__offset + ($start_offset + (($char) << 2)), 4));
151
152
153
154 if(!(($trans & 0x0200) || ($trans & 0x0100)) && ($trans & 0xFF) == $char) {
155
156 $result[] = $trans;
157 }
158 }
159
160 return $result;
161 }
162
163 function unpackTranses($rawTranses) {
164 settype($rawTranses, 'array');
165 $result = array();
166
167 foreach($rawTranses as $rawTrans) {
168 $result[] = array(
169 'term' => ($rawTrans & 0x0100) ? true : false,
170 'empty' => ($rawTrans & 0x0200) ? true : false,
171 'attr' => ($rawTrans & 0xFF),
172 'dest' => (($rawTrans) >> 10) & 0x3FFFFF,
173 );
174 }
175
176 return $result;
177 }
178
179 protected function readRootTrans() {
180 $__shm = $this->resource['shm_id']; $__offset = $this->resource['offset']; $fsa_start = $this->fsa_start;
181
182
183 list(, $trans) = unpack('V', shmop_read($__shm, $__offset + ($fsa_start + 4), 4));
184
185 return $trans;
186 }
187
188 protected function readAlphabet() {
189 $__shm = $this->resource['shm_id']; $__offset = $this->resource['offset']; $fsa_start = $this->fsa_start;
190
191
192 return shmop_read($__shm, $__offset + ($this->header['alphabet_offset']), $this->header['alphabet_size']);
193 }
194
195 function getAnnot($trans) {
196 if(!($trans & 0x0100)) {
197 return null;
198 }
199
200 $__shm = $this->resource['shm_id']; $__offset = $this->resource['offset']; $fsa_start = $this->fsa_start;
201
202 $offset =
203 $this->header['annot_offset'] +
204 ((($trans & 0xFF) << 22) | (($trans >> 10) & 0x3FFFFF));
205
206
207 $len = ord(shmop_read($__shm, $__offset + ($offset), 1));
208
209 if($len) {
210 $annot = shmop_read($__shm, $__offset + ($offset + 1), $len);
211 } else {
212 $annot = null;
213 }
214
215 return $annot;
216 }
217
218 function getAlphabetNum() {
219 if(!isset($this->alphabet_num)) {
220 $this->alphabet_num = array_map('ord', $this->getAlphabet());
221 }
222
223 return $this->alphabet_num;
224 }
225 protected $alphabet_num;
226 }
227
[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.
-