1 <?php
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
22
23 interface phpMorphy_GramInfo_Interace {
24 25 26 27
28 function getLocale();
29
30 31 32 33
34 function getEncoding();
35
36 37 38 39
40 function getCharSize();
41
42 43 44 45
46 function getEnds();
47
48 49 50 51 52 53
54 function ($offset);
55
56 57 58
59 function ();
60
61 62 63 64 65 66
67 function readAncodes($info);
68
69 70 71 72 73 74
75 function readFlexiaData($info);
76
77 78 79 80
81 function readAllGramInfoOffsets();
82
83 function ();
84 function readAllPartOfSpeech();
85 function readAllGrammems();
86 function readAllAncodes();
87 }
88
89 abstract class phpMorphy_GramInfo implements phpMorphy_GramInfo_Interace {
90 const = 128;
91
92 protected
93 $resource,
94 $header,
95 $ends,
96 $ends_size;
97
98 protected function phpMorphy_GramInfo($resource, $header) {
99 $this->resource = $resource;
100 $this->header = $header;
101
102 $this->ends = str_repeat("\0", $header['char_size'] + 1);
103 $this->ends_size = $GLOBALS['__phpmorphy_strlen']($this->ends);
104 }
105
106 static function create(phpMorphy_Storage $storage, $lazy) {
107 if($lazy) {
108 return new phpMorphy_GramInfo_Proxy($storage);
109 }
110
111 $header = phpMorphy_GramInfo::readHeader(
112 $storage->read(0, self::HEADER_SIZE)
113 );
114
115 if(!phpMorphy_GramInfo::validateHeader($header)) {
116 throw new phpMorphy_Exception('Invalid graminfo format');
117 }
118
119 $storage_type = $storage->getTypeAsString();
120 $file_path = dirname(__FILE__) . "/access/graminfo_{$storage_type}.php";
121 $clazz = 'phpMorphy_GramInfo_' . ucfirst($storage_type);
122
123 require_once($file_path);
124 return new $clazz($storage->getResource(), $header);
125 }
126
127 function getLocale() {
128 return $this->header['lang'];
129 }
130
131 function getEncoding() {
132 return $this->header['encoding'];
133 }
134
135 function getCharSize() {
136 return $this->header['char_size'];
137 }
138
139 function getEnds() {
140 return $this->ends;
141 }
142
143 function () {
144 return $this->header;
145 }
146
147 static protected function ($headerRaw) {
148 $header = unpack(
149 'Vver/Vis_be/Vflex_count_old/' .
150 'Vflex_offset/Vflex_size/Vflex_count/Vflex_index_offset/Vflex_index_size/' .
151 'Vposes_offset/Vposes_size/Vposes_count/Vposes_index_offset/Vposes_index_size/' .
152 'Vgrammems_offset/Vgrammems_size/Vgrammems_count/Vgrammems_index_offset/Vgrammems_index_size/' .
153 'Vancodes_offset/Vancodes_size/Vancodes_count/Vancodes_index_offset/Vancodes_index_size/' .
154 'Vchar_size/',
155 $headerRaw
156 );
157
158 $offset = 24 * 4;
159 $len = ord($GLOBALS['__phpmorphy_substr']($headerRaw, $offset++, 1));
160 $header['lang'] = rtrim($GLOBALS['__phpmorphy_substr']($headerRaw, $offset, $len));
161
162 $offset += $len;
163
164 $len = ord($GLOBALS['__phpmorphy_substr']($headerRaw, $offset++, 1));
165 $header['encoding'] = rtrim($GLOBALS['__phpmorphy_substr']($headerRaw, $offset, $len));
166
167 return $header;
168 }
169
170 static protected function ($header) {
171 if(
172 3 != $header['ver'] ||
173 1 == $header['is_be']
174 ) {
175 return false;
176 }
177
178 return true;
179 }
180
181 protected function cleanupCString($string) {
182 if(false !== ($pos = $GLOBALS['__phpmorphy_strpos']($string, $this->ends))) {
183 $string = $GLOBALS['__phpmorphy_substr']($string, 0, $pos);
184 }
185
186 return $string;
187 }
188
189 abstract protected function readSectionIndex($offset, $count);
190
191 protected function readSectionIndexAsSize($offset, $count, $total_size) {
192 if(!$count) {
193 return array();
194 }
195
196 $index = $this->readSectionIndex($offset, $count);
197 $index[$count] = $index[0] + $total_size;
198
199 for($i = 0; $i < $count; $i++) {
200 $index[$i] = $index[$i + 1] - $index[$i];
201 }
202
203 unset($index[$count]);
204
205 return $index;
206 }
207 };
208
209 class phpMorphy_GramInfo_Decorator implements phpMorphy_GramInfo_Interace {
210 protected $info;
211
212 function phpMorphy_GramInfo_Decorator(phpMorphy_GramInfo_Interace $info) {
213 $this->info = $info;
214 }
215
216 function ($offset) { return $this->info->readGramInfoHeader($offset); }
217 function () { return $this->info->getGramInfoHeaderSize($offset); }
218 function readAncodes($info) { return $this->info->readAncodes($info); }
219 function readFlexiaData($info) { return $this->info->readFlexiaData($info); }
220 function readAllGramInfoOffsets() { return $this->info->readAllGramInfoOffsets(); }
221 function readAllPartOfSpeech() { return $this->info->readAllPartOfSpeech(); }
222 function readAllGrammems() { return $this->info->readAllGrammems(); }
223 function readAllAncodes() { return $this->info->readAllAncodes(); }
224
225 function getLocale() { return $this->info->getLocale(); }
226 function getEncoding() { return $this->info->getEncoding(); }
227 function getCharSize() { return $this->info->getCharSize(); }
228 function getEnds() { return $this->info->getEnds(); }
229 function () { return $this->info->getHeader(); }
230 }
231
232 class phpMorphy_GramInfo_Proxy extends phpMorphy_GramInfo_Decorator {
233 protected $storage;
234
235 function __construct(phpMorphy_Storage $storage) {
236 $this->storage = $storage;
237 unset($this->info);
238 }
239
240 function __get($propName) {
241 if($propName == 'info') {
242 $this->info = phpMorphy_GramInfo::create($this->storage, false);
243 unset($this->storage);
244 return $this->info;
245 }
246
247 throw new phpMorphy_Exception("Unknown prop name '$propName'");
248 }
249 }
250
251 class extends phpMorphy_GramInfo_Proxy {
252 protected
253 $cache,
254 $ends;
255
256 function __construct(phpMorphy_Storage $storage, $cacheFile) {
257 parent::__construct($storage);
258
259 $this->cache = $this->readCache($cacheFile);
260 $this->ends = str_repeat("\0", $this->getCharSize() + 1);
261 }
262
263 protected function readCache($fileName) {
264 if(!is_array($result = include($fileName))) {
265 throw new phpMorphy_Exception("Can`t get header cache from '$fileName' file'");
266 }
267
268 return $result;
269 }
270
271 function getLocale() {
272 return $this->cache['lang'];
273 }
274
275 function getEncoding() {
276 return $this->cache['encoding'];
277 }
278
279 function getCharSize() {
280 return $this->cache['char_size'];
281 }
282
283 function getEnds() {
284 return $this->ends;
285 }
286
287 function () {
288 return $this->cache;
289 }
290 }
291
292 class phpMorphy_GramInfo_RuntimeCaching extends phpMorphy_GramInfo_Decorator {
293 protected
294 $flexia = array(),
295 $ancodes = array();
296
297 function readFlexiaData($info) {
298 $offset = $info['offset'];
299
300 if(!isset($this->flexia_all[$offset])) {
301 $this->flexia_all[$offset] = $this->info->readFlexiaData($info);
302 }
303
304 return $this->flexia_all[$offset];
305 }
306 }
307
308 class phpMorphy_GramInfo_AncodeCache extends phpMorphy_GramInfo_Decorator {
309 public
310 $hits = 0,
311 $miss = 0;
312
313 protected
314 $cache;
315
316 function __construct(phpMorphy_GramInfo_Interace $inner, $resource) {
317 parent::__construct($inner);
318
319 if(false === ($this->cache = unserialize($resource->read(0, $resource->getFileSize())))) {
320 throw new phpMorphy_Exception("Can`t read ancodes cache");
321 }
322 }
323
324 function readAncodes($info) {
325 $offset = $info['offset'];
326
327 if(isset($this->cache[$offset])) {
328 $this->hits++;
329
330 return $this->cache[$offset];
331 } else {
332
333 $this->miss++;
334
335 return parent::readAncodes($info);
336 }
337 }
338 }
[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.
-