1 /**
2 * The MeCab PHP extension
3 *
4 * Copyright (c) 2006-2015 Ryusuke SEKIYAMA. All rights reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 * @package php-mecab
25 * @author Ryusuke SEKIYAMA <rsky0711@gmail.com>
26 * @copyright 2006-2015 Ryusuke SEKIYAMA
27 * @license http://www.opensource.org/licenses/mit-license.php MIT License
28 * @version $Id$
29 */
30
31 #include "php_mecab.h"
32 #include "php_mecab_compat7.h"
33
34 #define PATHBUFSIZE (MAXPATHLEN + 3)
35
36 /* {{{ globals */
37
38 static ZEND_DECLARE_MODULE_GLOBALS(mecab)
39
40 /* }}} */
41
42 /* {{{ class entries */
43
44 static zend_class_entry *ext_ce_Iterator;
45 static zend_class_entry *ext_ce_IteratorAggregate;
46 static zend_class_entry *ext_ce_BadMethodCallException;
47 static zend_class_entry *ext_ce_InvalidArgumentException;
48 static zend_class_entry *ext_ce_OutOfRangeException;
49
50 static zend_class_entry *ce_MeCab_Tagger = NULL;
51 static zend_class_entry *ce_MeCab_Node = NULL;
52 static zend_class_entry *ce_MeCab_NodeIterator = NULL;
53 static zend_class_entry *ce_MeCab_Path = NULL;
54
55 static zend_object_handlers php_mecab_object_handlers;
56 static zend_object_handlers php_mecab_node_object_handlers;
57 static zend_object_handlers php_mecab_path_object_handlers;
58
59 /* }}} */
60
61 /* {{{ module function prototypes */
62
63 static PHP_MINIT_FUNCTION(mecab);
64 static PHP_MSHUTDOWN_FUNCTION(mecab);
65 static PHP_MINFO_FUNCTION(mecab);
66 static PHP_GINIT_FUNCTION(mecab);
67
68 /* }}} */
69
70 /* {{{ PHP function prototypes */
71
72 /* Get MeCab library version */
73 static PHP_FUNCTION(version);
74 /* Wakati-Gaki function */
75 static PHP_FUNCTION(split);
76 /* MeCab API wrappers */
77 static PHP_FUNCTION(mecab_new);
78 static PHP_FUNCTION(mecab_get_partial);
79 static PHP_FUNCTION(mecab_set_partial);
80 static PHP_FUNCTION(mecab_get_theta);
81 static PHP_FUNCTION(mecab_set_theta);
82 static PHP_FUNCTION(mecab_get_lattice_level);
83 static PHP_FUNCTION(mecab_set_lattice_level);
84 static PHP_FUNCTION(mecab_get_all_morphs);
85 static PHP_FUNCTION(mecab_set_all_morphs);
86 static PHP_FUNCTION(mecab_sparse_tostr);
87 static PHP_FUNCTION(mecab_sparse_tonode);
88 static PHP_FUNCTION(mecab_nbest_sparse_tostr);
89 static PHP_FUNCTION(mecab_nbest_init);
90 static PHP_FUNCTION(mecab_nbest_next_tostr);
91 static PHP_FUNCTION(mecab_nbest_next_tonode);
92 static PHP_FUNCTION(mecab_format_node);
93 static PHP_FUNCTION(mecab_dictionary_info);
94 /* Dumper for mecab_node */
95 static PHP_FUNCTION(mecab_node_toarray);
96 static PHP_FUNCTION(mecab_node_tostring);
97 /* Getters for mecab_node */
98 static PHP_FUNCTION(mecab_node_prev);
99 static PHP_FUNCTION(mecab_node_next);
100 static PHP_FUNCTION(mecab_node_enext);
101 static PHP_FUNCTION(mecab_node_bnext);
102 static PHP_FUNCTION(mecab_node_rpath);
103 static PHP_FUNCTION(mecab_node_lpath);
104 static PHP_FUNCTION(mecab_node_surface);
105 static PHP_FUNCTION(mecab_node_feature);
106 static PHP_FUNCTION(mecab_node_id);
107 static PHP_FUNCTION(mecab_node_length);
108 static PHP_FUNCTION(mecab_node_rlength);
109 static PHP_FUNCTION(mecab_node_rcattr);
110 static PHP_FUNCTION(mecab_node_lcattr);
111 static PHP_FUNCTION(mecab_node_posid);
112 static PHP_FUNCTION(mecab_node_char_type);
113 static PHP_FUNCTION(mecab_node_stat);
114 static PHP_FUNCTION(mecab_node_isbest);
115 static PHP_FUNCTION(mecab_node_alpha);
116 static PHP_FUNCTION(mecab_node_beta);
117 static PHP_FUNCTION(mecab_node_prob);
118 static PHP_FUNCTION(mecab_node_wcost);
119 static PHP_FUNCTION(mecab_node_cost);
120 /* Getters for mecab_path */
121 static PHP_FUNCTION(mecab_path_rnext);
122 static PHP_FUNCTION(mecab_path_lnext);
123 static PHP_FUNCTION(mecab_path_rnode);
124 static PHP_FUNCTION(mecab_path_lnode);
125 static PHP_FUNCTION(mecab_path_prob);
126 static PHP_FUNCTION(mecab_path_cost);
127
128 /* }}} */
129
130 /* {{{ PHP method prototypes */
131
132 static PHP_METHOD(MeCab_Node, __construct);
133 static PHP_METHOD(MeCab_Path, __construct);
134 /* Overloading implementations for mecab_node */
135 static PHP_METHOD(MeCab_Node, __get);
136 static PHP_METHOD(MeCab_Node, __isset);
137 /* IteratorAggregate implementations for mecab_node */
138 static PHP_METHOD(MeCab_Node, getIterator);
139 static PHP_METHOD(MeCab_Node, setTraverse);
140 /* Iterator implementations for mecab_node */
141 static PHP_METHOD(MeCab_NodeIterator, __construct);
142 static PHP_METHOD(MeCab_NodeIterator, current);
143 static PHP_METHOD(MeCab_NodeIterator, key);
144 static PHP_METHOD(MeCab_NodeIterator, valid);
145 static PHP_METHOD(MeCab_NodeIterator, rewind);
146 static PHP_METHOD(MeCab_NodeIterator, next);
147 /* Overloading implementations for mecab_path */
148 static PHP_METHOD(MeCab_Path, __get);
149 static PHP_METHOD(MeCab_Path, __isset);
150
151 /* }}} */
152
153 /* {{{ internal function prototypes */
154
155 /* allocate for mecab */
156 static php_mecab *
157 php_mecab_ctor(TSRMLS_D);
158
159 /* free the mecab */
160 static void
161 php_mecab_dtor(php_mecab *mecab TSRMLS_DC);
162
163 /* set string to the mecab */
164 static void
165 php_mecab_set_string(php_mecab *mecab, zend_string *str TSRMLS_DC);
166
167 /* allocate for mecab_node */
168 static php_mecab_node *
169 php_mecab_node_ctor(TSRMLS_D);
170
171 /* free the mecab_node */
172 static void
173 php_mecab_node_dtor(php_mecab_node *node TSRMLS_DC);
174
175 /* set mecab to the mecab_node */
176 static void
177 php_mecab_node_set_tagger(php_mecab_node *node, php_mecab *mecab TSRMLS_DC);
178
179 /* allocate for mecab_path */
180 static php_mecab_path *
181 php_mecab_path_ctor(TSRMLS_D);
182
183 /* free the mecab_path */
184 static void
185 php_mecab_path_dtor(php_mecab_path *path TSRMLS_DC);
186
187 /* set mecab_node to the mecab_path */
188 static void
189 php_mecab_path_set_tagger(php_mecab_path *path, php_mecab *mecab TSRMLS_DC);
190
191 /* get sibling node from mecab_node */
192 static zval *
193 php_mecab_node_get_sibling(zval *zv, zval *object, php_mecab_node *xnode, php_mecab_node_rel rel TSRMLS_DC);
194
195 /* get related path from mecab_node */
196 static zval *
197 php_mecab_node_get_path(zval *zv, zval *object, php_mecab_node *xnode, php_mecab_node_rel rel TSRMLS_DC);
198
199 /* get sibling path from mecab_path */
200 static zval *
201 php_mecab_path_get_sibling(zval *zv, zval *object, php_mecab_path *xpath, php_mecab_path_rel rel TSRMLS_DC);
202
203 /* get related node from mecab_path */
204 static zval *
205 php_mecab_path_get_node(zval *zv, zval *object, php_mecab_path *xpath, php_mecab_path_rel rel TSRMLS_DC);
206
207 /* wrappers */
208 static void
209 php_mecab_node_get_sibling_wrapper(INTERNAL_FUNCTION_PARAMETERS, php_mecab_node_rel rel),
210 php_mecab_node_get_path_wrapper(INTERNAL_FUNCTION_PARAMETERS, php_mecab_node_rel rel),
211 php_mecab_path_get_sibling_wrapper(INTERNAL_FUNCTION_PARAMETERS, php_mecab_path_rel rel),
212 php_mecab_path_get_node_wrapper(INTERNAL_FUNCTION_PARAMETERS, php_mecab_path_rel rel);
213
214 /* allocate for mecab object */
215 zend_object *
216 php_mecab_object_new(zend_class_entry *ce TSRMLS_DC);
217
218 /* free the mecab object */
219 static void
220 php_mecab_free_object_storage(zend_object *object TSRMLS_DC);
221
222 /* fetch the mecab object */
php_mecab_object_fetch_object(zend_object * obj)223 static inline php_mecab_object * php_mecab_object_fetch_object(zend_object *obj) {
224 return (php_mecab_object *)((char *)obj - XtOffsetOf(php_mecab_object, std));
225 }
226 #define PHP_MECAB_OBJECT_P(zv) php_mecab_object_fetch_object(Z_OBJ_P(zv))
227
228 /* allocate for mecab_node object */
229 zend_object *
230 php_mecab_node_object_new(zend_class_entry *ce TSRMLS_DC);
231
232 /* free the mecab_node object */
233 static void
234 php_mecab_node_free_object_storage(zend_object *object TSRMLS_DC);
235
236 /* fetch the mecab_node object */
php_mecab_node_object_fetch_object(zend_object * obj)237 static inline php_mecab_node_object * php_mecab_node_object_fetch_object(zend_object *obj) {
238 return (php_mecab_node_object *)((char *)obj - XtOffsetOf(php_mecab_node_object, std));
239 }
240 #define PHP_MECAB_NODE_OBJECT_P(zv) php_mecab_node_object_fetch_object(Z_OBJ_P(zv))
241
242 /* allocate for mecab_path object */
243 zend_object *
244 php_mecab_path_object_new(zend_class_entry *ce TSRMLS_DC);
245
246 /* free the mecab_path object */
247 static void
248 php_mecab_path_free_object_storage(zend_object *object TSRMLS_DC);
249
250 /* fetch the mecab_path object */
php_mecab_path_object_fetch_object(zend_object * obj)251 static inline php_mecab_path_object * php_mecab_path_object_fetch_object(zend_object *obj) {
252 return (php_mecab_path_object *)((char *)obj - XtOffsetOf(php_mecab_path_object, std));
253 }
254 #define PHP_MECAB_PATH_OBJECT_P(zv) php_mecab_path_object_fetch_object(Z_OBJ_P(zv))
255
256 /* get the class entry */
257 static zend_class_entry *
258 php_mecab_get_class_entry(const char *lcname TSRMLS_DC);
259
260 /* }}} */
261
262 /* check file/dicectory accessibility */
263 static zend_bool
264 php_mecab_check_path(const char *path, size_t length, char *real_path TSRMLS_DC);
265
266 /* }}} */
267
268 /* {{{ argument informations */
269
270 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_split, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
271 ZEND_ARG_INFO(0, str)
272 ZEND_ARG_INFO(0, dicdir)
273 ZEND_ARG_INFO(0, userdic)
274 ZEND_END_ARG_INFO()
275
276 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_new, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0)
277 ZEND_ARG_ARRAY_INFO(0, arg, 1)
278 ZEND_END_ARG_INFO()
279
280 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_set_partial_m, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0)
281 ZEND_ARG_INFO(0, partial)
282 ZEND_END_ARG_INFO()
283
284 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_set_theta_m, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0)
285 ZEND_ARG_INFO(0, theta)
286 ZEND_END_ARG_INFO()
287
288 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_set_lattice_level_m, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0)
289 ZEND_ARG_INFO(0, level)
290 ZEND_END_ARG_INFO()
291
292 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_set_all_morphs_m, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0)
293 ZEND_ARG_INFO(0, all_morphs)
294 ZEND_END_ARG_INFO()
295
296 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_sparse_tostr_m, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
297 ZEND_ARG_INFO(0, str)
298 ZEND_ARG_INFO(0, len)
299 ZEND_ARG_INFO(0, olen)
300 ZEND_END_ARG_INFO()
301
302 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_sparse_tonode_m, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
303 ZEND_ARG_INFO(0, str)
304 ZEND_ARG_INFO(0, len)
305 ZEND_END_ARG_INFO()
306
307 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_nbest_sparse_tostr_m, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 2)
308 ZEND_ARG_INFO(0, n)
309 ZEND_ARG_INFO(0, str)
310 ZEND_ARG_INFO(0, len)
311 ZEND_ARG_INFO(0, olen)
312 ZEND_END_ARG_INFO()
313
314 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_nbest_init_m, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
315 ZEND_ARG_INFO(0, str)
316 ZEND_ARG_INFO(0, len)
317 ZEND_END_ARG_INFO()
318
319 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_nbest_next_tostr_m, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0)
320 ZEND_ARG_INFO(0, olen)
321 ZEND_END_ARG_INFO()
322
323 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_format_node_m, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
324 ZEND_ARG_OBJ_INFO(0, node, MeCab\\Node, 0)
325 ZEND_END_ARG_INFO()
326
327 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_node_toarray_m, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 0)
328 ZEND_ARG_INFO(0, dump_all)
329 ZEND_END_ARG_INFO()
330
331 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab_node_settraverse, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
332 ZEND_ARG_INFO(0, traverse)
333 ZEND_END_ARG_INFO()
334
335 ZEND_BEGIN_ARG_INFO_EX(arginfo_mecab__magic_getter, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
336 ZEND_ARG_INFO(0, name)
337 ZEND_END_ARG_INFO()
338
339 /* }}} arginfo */
340
341 /* {{{ MeCab\Tagger methods[] */
342
343 #define PM_TAGGER_ME_MAPPING(methname, funcname) \
344 PHP_ME_MAPPING(methname, mecab_ ## funcname, NULL, ZEND_ACC_PUBLIC)
345 #define PM_TAGGER_ME_MAPPING_EX(methname, funcname) \
346 PHP_ME_MAPPING(methname, mecab_ ## funcname, arginfo_mecab_ ## funcname ## _m, ZEND_ACC_PUBLIC)
347
348 static zend_function_entry mecab_methods[] = {
349 /* MeCab API wrappers */
350 PHP_ME_MAPPING(__construct, mecab_new, arginfo_mecab_new, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
351 PM_TAGGER_ME_MAPPING(getPartial, get_partial)
352 PM_TAGGER_ME_MAPPING_EX(setPartial, set_partial)
353 PM_TAGGER_ME_MAPPING(getTheta, get_theta)
354 PM_TAGGER_ME_MAPPING_EX(setTheta, set_theta)
355 PM_TAGGER_ME_MAPPING(getLatticeLevel, get_lattice_level)
356 PM_TAGGER_ME_MAPPING_EX(setLatticeLevel, set_lattice_level)
357 PM_TAGGER_ME_MAPPING(getAllMorphs, get_all_morphs)
358 PM_TAGGER_ME_MAPPING_EX(setAllMorphs, set_all_morphs)
359 PM_TAGGER_ME_MAPPING_EX(parse, sparse_tostr)
360 PM_TAGGER_ME_MAPPING_EX(parseToString, sparse_tostr)
361 PM_TAGGER_ME_MAPPING_EX(parseToNode, sparse_tonode)
362 PM_TAGGER_ME_MAPPING_EX(parseNBest, nbest_sparse_tostr)
363 PM_TAGGER_ME_MAPPING_EX(parseNBestInit, nbest_init)
364 PM_TAGGER_ME_MAPPING_EX(next, nbest_next_tostr)
365 PM_TAGGER_ME_MAPPING(nextNode, nbest_next_tonode)
366 PM_TAGGER_ME_MAPPING_EX(formatNode, format_node)
367 PM_TAGGER_ME_MAPPING(dictionaryInfo, dictionary_info)
368 PHP_FE_END
369 };
370 /* }}} */
371
372 /* {{{ MeCab\Node methods[] */
373 #define PM_NODE_ME_MAPPING(methname, funcname) \
374 PHP_ME_MAPPING(methname, mecab_node_ ## funcname, NULL, ZEND_ACC_PUBLIC)
375
376 static zend_function_entry mecab_node_methods[] = {
377 /* Constructor */
378 PHP_ME(MeCab_Node, __construct, NULL, ZEND_ACC_PRIVATE | ZEND_ACC_CTOR)
379 /* Overloading implementations */
380 PHP_ME(MeCab_Node, __get, arginfo_mecab__magic_getter, ZEND_ACC_PUBLIC)
381 PHP_ME(MeCab_Node, __isset, arginfo_mecab__magic_getter, ZEND_ACC_PUBLIC)
382 /* IteratorAggregate implementations */
383 PHP_ME(MeCab_Node, getIterator, NULL, ZEND_ACC_PUBLIC)
384 PHP_ME(MeCab_Node, setTraverse, arginfo_mecab_node_settraverse, ZEND_ACC_PUBLIC)
385 /* Dumper */
386 PHP_ME_MAPPING(toArray, mecab_node_toarray, arginfo_mecab_node_toarray_m, ZEND_ACC_PUBLIC)
387 PM_NODE_ME_MAPPING(toString, tostring)
388 PM_NODE_ME_MAPPING(__toString, tostring)
389 /* Getters */
390 PM_NODE_ME_MAPPING(getPrev, prev)
391 PM_NODE_ME_MAPPING(getNext, next)
392 PM_NODE_ME_MAPPING(getENext, enext)
393 PM_NODE_ME_MAPPING(getBNext, bnext)
394 PM_NODE_ME_MAPPING(getRPath, rpath)
395 PM_NODE_ME_MAPPING(getLPath, lpath)
396 PM_NODE_ME_MAPPING(getSurface, surface)
397 PM_NODE_ME_MAPPING(getFeature, feature)
398 PM_NODE_ME_MAPPING(getId, id)
399 PM_NODE_ME_MAPPING(getLength, length)
400 PM_NODE_ME_MAPPING(getRLength, rlength)
401 PM_NODE_ME_MAPPING(getRcAttr, rcattr)
402 PM_NODE_ME_MAPPING(getLcAttr, lcattr)
403 PM_NODE_ME_MAPPING(getPosId, posid)
404 PM_NODE_ME_MAPPING(getCharType, char_type)
405 PM_NODE_ME_MAPPING(getStat, stat)
406 PM_NODE_ME_MAPPING(isBest, isbest)
407 PM_NODE_ME_MAPPING(getAlpha, alpha)
408 PM_NODE_ME_MAPPING(getBeta, beta)
409 PM_NODE_ME_MAPPING(getProb, prob)
410 PM_NODE_ME_MAPPING(getWCost, wcost)
411 PM_NODE_ME_MAPPING(getCost, cost)
412 PHP_FE_END
413 };
414 /* }}} */
415
416 /* {{{ MeCab_NodeIterator methods[] */
417 static zend_function_entry mecab_iterator_methods[] = {
418 /* Constructor */
419 PHP_ME(MeCab_NodeIterator, __construct, NULL, ZEND_ACC_PRIVATE | ZEND_ACC_CTOR)
420 /* Iterator implementations */
421 PHP_ME(MeCab_NodeIterator, current, NULL, ZEND_ACC_PUBLIC)
422 PHP_ME(MeCab_NodeIterator, key, NULL, ZEND_ACC_PUBLIC)
423 PHP_ME(MeCab_NodeIterator, next, NULL, ZEND_ACC_PUBLIC)
424 PHP_ME(MeCab_NodeIterator, rewind, NULL, ZEND_ACC_PUBLIC)
425 PHP_ME(MeCab_NodeIterator, valid, NULL, ZEND_ACC_PUBLIC)
426 PHP_FE_END
427 };
428 /* }}} */
429
430 /* {{{ MeCab\Path methods[] */
431 #define PM_PATH_ME_MAPPING(methname, funcname) \
432 PHP_ME_MAPPING(methname, mecab_path_ ## funcname, NULL, ZEND_ACC_PUBLIC)
433
434 static zend_function_entry mecab_path_methods[] = {
435 /* Constructor */
436 PHP_ME(MeCab_Path, __construct, NULL, ZEND_ACC_PRIVATE | ZEND_ACC_CTOR)
437 /* Overloading implementations */
438 PHP_ME(MeCab_Path, __get, arginfo_mecab__magic_getter, ZEND_ACC_PUBLIC)
439 PHP_ME(MeCab_Path, __isset, arginfo_mecab__magic_getter, ZEND_ACC_PUBLIC)
440 /* Getters */
441 PM_PATH_ME_MAPPING(getRNext, rnext)
442 PM_PATH_ME_MAPPING(getLNext, lnext)
443 PM_PATH_ME_MAPPING(getRNode, rnode)
444 PM_PATH_ME_MAPPING(getLNode, lnode)
445 PM_PATH_ME_MAPPING(getProb, prob)
446 PM_PATH_ME_MAPPING(getCost, cost)
447 PHP_FE_END
448 };
449 /* }}} methods */
450
451 /* }}} class definitions */
452
453 /* {{{ mecab_functions[] */
454
455 static zend_function_entry mecab_functions[] = {
456 ZEND_NS_FE("MeCab", version, NULL)
457 ZEND_NS_FE("MeCab", split, arginfo_mecab_split)
458 PHP_FE_END
459 };
460 /* }}} */
461
462 /* {{{ cross-extension dependencies */
463
464 static zend_module_dep mecab_deps[] = {
465 ZEND_MOD_REQUIRED("spl")
466 ZEND_MOD_END
467 };
468
469 /* }}} */
470
471 /* {{{ mecab_module_entry */
472 zend_module_entry mecab_module_entry = {
473 STANDARD_MODULE_HEADER_EX,
474 NULL,
475 mecab_deps,
476 "mecab",
477 mecab_functions,
478 PHP_MINIT(mecab),
479 PHP_MSHUTDOWN(mecab),
480 NULL,
481 NULL,
482 PHP_MINFO(mecab),
483 PHP_MECAB_MODULE_VERSION,
484 PHP_MODULE_GLOBALS(mecab),
485 PHP_GINIT(mecab),
486 NULL,
487 NULL,
488 STANDARD_MODULE_PROPERTIES_EX
489 };
490 /* }}} */
491
492 #ifdef COMPILE_DL_MECAB
493 ZEND_GET_MODULE(mecab)
494 #endif
495
496 /* {{{ ini entries */
497
PHP_INI_BEGIN()498 PHP_INI_BEGIN()
499 STD_PHP_INI_ENTRY("mecab.default_rcfile", "", PHP_INI_ALL,
500 OnUpdateString, default_rcfile, zend_mecab_globals, mecab_globals)
501 STD_PHP_INI_ENTRY("mecab.default_dicdir", "", PHP_INI_ALL,
502 OnUpdateString, default_dicdir, zend_mecab_globals, mecab_globals)
503 STD_PHP_INI_ENTRY("mecab.default_userdic", "", PHP_INI_ALL,
504 OnUpdateString, default_userdic, zend_mecab_globals, mecab_globals)
505 PHP_INI_END()
506
507 /* }}} */
508
509 /* {{{ PHP_MINIT_FUNCTION */
510 static PHP_MINIT_FUNCTION(mecab)
511 {
512 REGISTER_INI_ENTRIES();
513
514 REGISTER_NS_STRING_CONSTANT("MeCab", "VERSION", (char *)mecab_version(), CONST_PERSISTENT | CONST_CS);
515 PHP_MECAB_REGISTER_NS_CONSTANT(NOR_NODE);
516 PHP_MECAB_REGISTER_NS_CONSTANT(UNK_NODE);
517 PHP_MECAB_REGISTER_NS_CONSTANT(BOS_NODE);
518 PHP_MECAB_REGISTER_NS_CONSTANT(EOS_NODE);
519 PHP_MECAB_REGISTER_NS_CONSTANT(SYS_DIC);
520 PHP_MECAB_REGISTER_NS_CONSTANT(USR_DIC);
521 PHP_MECAB_REGISTER_NS_CONSTANT(UNK_DIC);
522
523 ext_ce_Iterator = php_mecab_get_class_entry("iterator" TSRMLS_CC);
524 ext_ce_IteratorAggregate = php_mecab_get_class_entry("iteratoraggregate" TSRMLS_CC);
525 ext_ce_BadMethodCallException = php_mecab_get_class_entry("badmethodcallexception" TSRMLS_CC);
526 ext_ce_InvalidArgumentException = php_mecab_get_class_entry("invalidargumentexception" TSRMLS_CC);
527 ext_ce_OutOfRangeException = php_mecab_get_class_entry("outofrangeexception" TSRMLS_CC);
528 if (ext_ce_Iterator == NULL ||
529 ext_ce_IteratorAggregate == NULL ||
530 ext_ce_BadMethodCallException == NULL ||
531 ext_ce_InvalidArgumentException == NULL ||
532 ext_ce_OutOfRangeException == NULL)
533 {
534 return FAILURE;
535 }
536 {
537 zend_class_entry ce1;
538
539 INIT_NS_CLASS_ENTRY(ce1, "MeCab", "Tagger", mecab_methods);
540 ce_MeCab_Tagger = zend_register_internal_class(&ce1);
541 if (!ce_MeCab_Tagger) {
542 return FAILURE;
543 }
544 ce_MeCab_Tagger->create_object = php_mecab_object_new;
545
546 memcpy(&php_mecab_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
547 php_mecab_object_handlers.clone_obj = NULL;
548 php_mecab_object_handlers.free_obj = php_mecab_free_object_storage;
549 php_mecab_object_handlers.offset = XtOffsetOf(php_mecab_object, std);
550 }
551 {
552 zend_class_entry ce2, ce2i;
553
554 INIT_NS_CLASS_ENTRY(ce2, "MeCab", "Node", mecab_node_methods);
555 ce_MeCab_Node = zend_register_internal_class(&ce2);
556 if (!ce_MeCab_Node) {
557 return FAILURE;
558 }
559 ce_MeCab_Node->create_object = php_mecab_node_object_new;
560
561 INIT_NS_CLASS_ENTRY(ce2i, "MeCab", "NodeIterator", mecab_iterator_methods);
562 ce_MeCab_NodeIterator = zend_register_internal_class(&ce2i);
563 if (!ce_MeCab_NodeIterator) {
564 return FAILURE;
565 }
566 ce_MeCab_NodeIterator->create_object = php_mecab_node_object_new;
567
568 memcpy(&php_mecab_node_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
569 php_mecab_node_object_handlers.clone_obj = NULL;
570 php_mecab_node_object_handlers.free_obj = php_mecab_node_free_object_storage;
571 php_mecab_node_object_handlers.offset = XtOffsetOf(php_mecab_node_object, std);
572
573 zend_class_implements(ce_MeCab_Node TSRMLS_CC, 1, ext_ce_IteratorAggregate);
574 zend_class_implements(ce_MeCab_NodeIterator TSRMLS_CC, 1, ext_ce_Iterator);
575
576 zend_declare_class_constant_long(ce_MeCab_Node, "NOR", 3, MECAB_NOR_NODE TSRMLS_CC);
577 zend_declare_class_constant_long(ce_MeCab_Node, "UNK", 3, MECAB_UNK_NODE TSRMLS_CC);
578 zend_declare_class_constant_long(ce_MeCab_Node, "BOS", 3, MECAB_BOS_NODE TSRMLS_CC);
579 zend_declare_class_constant_long(ce_MeCab_Node, "EOS", 3, MECAB_EOS_NODE TSRMLS_CC);
580
581 zend_declare_class_constant_long(ce_MeCab_Node, "TRAVERSE_NEXT", 13, (long)TRAVERSE_NEXT TSRMLS_CC);
582 zend_declare_class_constant_long(ce_MeCab_Node, "TRAVERSE_ENEXT", 14, (long)TRAVERSE_ENEXT TSRMLS_CC);
583 zend_declare_class_constant_long(ce_MeCab_Node, "TRAVERSE_BNEXT", 14, (long)TRAVERSE_BNEXT TSRMLS_CC);
584 }
585 {
586 zend_class_entry ce3;
587
588 INIT_NS_CLASS_ENTRY(ce3, "MeCab", "Path", mecab_path_methods);
589 ce_MeCab_Path = zend_register_internal_class(&ce3);
590 if (!ce_MeCab_Path) {
591 return FAILURE;
592 }
593 ce_MeCab_Path->create_object = php_mecab_path_object_new;
594
595 memcpy(&php_mecab_path_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
596 php_mecab_path_object_handlers.clone_obj = NULL;
597 php_mecab_path_object_handlers.free_obj = php_mecab_path_free_object_storage;
598 php_mecab_path_object_handlers.offset = XtOffsetOf(php_mecab_path_object, std);
599 }
600
601 return SUCCESS;
602 }
603 /* }}} */
604
605 /* {{{ PHP_MSHUTDOWN_FUNCTION */
PHP_MSHUTDOWN_FUNCTION(mecab)606 static PHP_MSHUTDOWN_FUNCTION(mecab)
607 {
608 UNREGISTER_INI_ENTRIES();
609 return SUCCESS;
610 }
611 /* }}} */
612
613 /* {{{ PHP_MINFO_FUNCTION */
PHP_MINFO_FUNCTION(mecab)614 static PHP_MINFO_FUNCTION(mecab)
615 {
616 php_info_print_table_start();
617 php_info_print_table_row(2, "MeCab Support", "enabled");
618 php_info_print_table_row(2, "Module Version", PHP_MECAB_MODULE_VERSION);
619 php_info_print_table_end();
620
621 php_info_print_table_start();
622 php_info_print_table_header(3, "Version Info", "Compiled", "Linked");
623 php_info_print_table_row(3, "MeCab Library", PHP_MECAB_VERSION_STRING, mecab_version());
624 php_info_print_table_end();
625
626 DISPLAY_INI_ENTRIES();
627 }
628 /* }}} */
629
630 /* {{{ PHP_GINIT_FUNCTION */
PHP_GINIT_FUNCTION(mecab)631 static PHP_GINIT_FUNCTION(mecab)
632 {
633 mecab_globals->default_rcfile = NULL;
634 mecab_globals->default_dicdir = NULL;
635 mecab_globals->default_userdic = NULL;
636 }
637 /* }}} */
638
639 /* {{{ internal function implementation for mecab_t */
640
641 /* {{{ php_mecab_ctor()
642 * allocate for mecab
643 */
644 static php_mecab *
php_mecab_ctor(TSRMLS_D)645 php_mecab_ctor(TSRMLS_D)
646 {
647 php_mecab *mecab = NULL;
648
649 mecab = (php_mecab *)ecalloc(1, sizeof(php_mecab));
650 if (mecab == NULL) {
651 return NULL;
652 }
653
654 mecab->ptr = NULL;
655 mecab->str = NULL;
656 mecab->ref = 1;
657
658 return mecab;
659 }
660 /* }}} */
661
662 /* {{{ php_mecab_dtor()
663 * free the mecab
664 */
665 static void
php_mecab_dtor(php_mecab * mecab TSRMLS_DC)666 php_mecab_dtor(php_mecab *mecab TSRMLS_DC)
667 {
668 mecab->ref--;
669 if (mecab->ref == 0) {
670 if (mecab->str != NULL) {
671 zend_string_release(mecab->str);
672 }
673 mecab_destroy(mecab->ptr);
674 efree(mecab);
675 }
676 }
677 /* }}} */
678
679 /* {{{ php_mecab_set_string()
680 * set string to the mecab
681 */
682 static void
php_mecab_set_string(php_mecab * mecab,zend_string * str TSRMLS_DC)683 php_mecab_set_string(php_mecab *mecab, zend_string *str TSRMLS_DC)
684 {
685 if (mecab->str != NULL) {
686 zend_string_release(mecab->str);
687 }
688 if (str == NULL) {
689 mecab->str = NULL;
690 } else {
691 mecab->str = zend_string_copy(str);
692 }
693 }
694 /* }}} */
695
696 /* {{{ php_mecab_object_new()
697 * allocate for mecab object
698 */
699 zend_object *
php_mecab_object_new(zend_class_entry * ce TSRMLS_DC)700 php_mecab_object_new(zend_class_entry *ce TSRMLS_DC)
701 {
702 php_mecab_object *intern;
703
704 intern = (php_mecab_object *)ecalloc(1, sizeof(php_mecab_object));
705 intern->ptr = php_mecab_ctor(TSRMLS_C);
706
707 zend_object_std_init(&intern->std, ce TSRMLS_CC);
708 object_properties_init(&intern->std, ce);
709
710 intern->std.handlers = &php_mecab_object_handlers;
711
712 return &intern->std;
713 }
714 /* }}} */
715
716 /* {{{ php_mecab_free_object_storage()
717 * free the mecab object
718 */
719 static void
php_mecab_free_object_storage(zend_object * object TSRMLS_DC)720 php_mecab_free_object_storage(zend_object *object TSRMLS_DC)
721 {
722 php_mecab_object *intern = php_mecab_object_fetch_object(object);
723 php_mecab_dtor(intern->ptr TSRMLS_CC);
724 zend_object_std_dtor(&intern->std TSRMLS_CC);
725 }
726 /* }}} */
727
728 /* }}} mecab_t */
729
730 /* {{{ internal function implementation for mecab_node_t */
731
732 /* {{{ php_mecab_node_ctor()
733 * allocate for mecab_node
734 */
735 static php_mecab_node *
php_mecab_node_ctor(TSRMLS_D)736 php_mecab_node_ctor(TSRMLS_D)
737 {
738 php_mecab_node *node = NULL;
739
740 node = (php_mecab_node *)ecalloc(1, sizeof(php_mecab_node));
741 if (node == NULL) {
742 return NULL;
743 }
744
745 node->tagger = NULL;
746 node->ptr = NULL;
747
748 return node;
749 }
750 /* }}} */
751
752 /* {{{ php_mecab_node_dtor()
753 * free the mecab_node
754 */
755 static void
php_mecab_node_dtor(php_mecab_node * node TSRMLS_DC)756 php_mecab_node_dtor(php_mecab_node *node TSRMLS_DC)
757 {
758 if (node->tagger != NULL) {
759 php_mecab_dtor(node->tagger TSRMLS_CC);
760 }
761 efree(node);
762 }
763 /* }}} */
764
765 /* {{{ php_mecab_node_set_tagger()
766 * set mecab to the mecab_node
767 */
768 static void
php_mecab_node_set_tagger(php_mecab_node * node,php_mecab * mecab TSRMLS_DC)769 php_mecab_node_set_tagger(php_mecab_node *node, php_mecab *mecab TSRMLS_DC)
770 {
771 if (node->tagger != NULL) {
772 php_mecab_dtor(node->tagger TSRMLS_CC);
773 }
774 if (mecab == NULL) {
775 node->tagger = NULL;
776 } else {
777 node->tagger = mecab;
778 node->tagger->ref++;
779 }
780 }
781 /* }}} */
782
783 /* {{{ php_mecab_node_object_new()
784 * allocate for mecab_node object
785 */
786 zend_object *
php_mecab_node_object_new(zend_class_entry * ce TSRMLS_DC)787 php_mecab_node_object_new(zend_class_entry *ce TSRMLS_DC)
788 {
789 php_mecab_node_object *intern;
790
791 intern = (php_mecab_node_object *)ecalloc(1, sizeof(php_mecab_node_object));
792 intern->ptr = php_mecab_node_ctor(TSRMLS_C);
793 intern->mode = TRAVERSE_NEXT;
794
795 zend_object_std_init(&intern->std, ce TSRMLS_CC);
796 object_properties_init(&intern->std, ce);
797 intern->std.handlers = &php_mecab_node_object_handlers;
798
799 return &intern->std;
800 }
801 /* }}} */
802
803 /* {{{ php_mecab_node_free_object_storage()
804 * free the mecab_node object
805 */
806 static void
php_mecab_node_free_object_storage(zend_object * object TSRMLS_DC)807 php_mecab_node_free_object_storage(zend_object *object TSRMLS_DC)
808 {
809 php_mecab_node_object *intern = php_mecab_node_object_fetch_object(object);
810 php_mecab_node_dtor(intern->ptr TSRMLS_CC);
811 zend_object_std_dtor(&intern->std TSRMLS_CC);
812 }
813 /* }}} */
814
815 /* }}} mecab_node_t */
816
817 /* {{{ php_mecab_path_ctor()
818 * allocate for mecab_path
819 */
820 static php_mecab_path *
php_mecab_path_ctor(TSRMLS_D)821 php_mecab_path_ctor(TSRMLS_D)
822 {
823 php_mecab_path *path = NULL;
824
825 path = (php_mecab_path *)ecalloc(1, sizeof(php_mecab_path));
826 if (path == NULL) {
827 return NULL;
828 }
829
830 path->tagger = NULL;
831 path->ptr = NULL;
832
833 return path;
834 }
835 /* }}} */
836
837 /* {{{ php_mecab_path_dtor()
838 * free the mecab_path
839 */
840 static void
php_mecab_path_dtor(php_mecab_path * path TSRMLS_DC)841 php_mecab_path_dtor(php_mecab_path *path TSRMLS_DC)
842 {
843 if (path->tagger != NULL) {
844 php_mecab_dtor(path->tagger TSRMLS_CC);
845 }
846 efree(path);
847 }
848 /* }}} */
849
850 /* {{{ php_mecab_path_set_tagger()
851 * set mecab_node to the mecab_path
852 */
853 static void
php_mecab_path_set_tagger(php_mecab_path * path,php_mecab * mecab TSRMLS_DC)854 php_mecab_path_set_tagger(php_mecab_path *path, php_mecab *mecab TSRMLS_DC)
855 {
856 if (path->tagger != NULL) {
857 php_mecab_dtor(path->tagger TSRMLS_CC);
858 }
859 if (mecab == NULL) {
860 path->tagger = NULL;
861 } else {
862 path->tagger = mecab;
863 path->tagger->ref++;
864 }
865 }
866 /* }}} */
867
868 /* {{{ php_mecab_path_object_new()
869 * allocate for mecab_path object
870 */
871 zend_object *
php_mecab_path_object_new(zend_class_entry * ce TSRMLS_DC)872 php_mecab_path_object_new(zend_class_entry *ce TSRMLS_DC)
873 {
874 php_mecab_path_object *intern;
875
876 intern = (php_mecab_path_object *)ecalloc(1, sizeof(php_mecab_path_object));
877 intern->ptr = php_mecab_path_ctor(TSRMLS_C);
878
879 zend_object_std_init(&intern->std, ce TSRMLS_CC);
880 object_properties_init(&intern->std, ce);
881 intern->std.handlers = &php_mecab_path_object_handlers;
882
883 return &intern->std;
884 }
885 /* }}} */
886
887 /* {{{ php_mecab_path_free_object_storage()
888 * free the mecab_path object
889 */
890 static void
php_mecab_path_free_object_storage(zend_object * object TSRMLS_DC)891 php_mecab_path_free_object_storage(zend_object *object TSRMLS_DC)
892 {
893 php_mecab_path_object *intern = php_mecab_path_object_fetch_object(object);
894 php_mecab_path_dtor(intern->ptr TSRMLS_CC);
895 zend_object_std_dtor(&intern->std TSRMLS_CC);
896 }
897 /* }}} */
898
899 /* }}} mecab_path_t */
900
901 /* {{{ php_mecab_node_get_sibling()
902 * get sibling node from mecab_node
903 */
904 static zval *
php_mecab_node_get_sibling(zval * zv,zval * object,php_mecab_node * xnode,php_mecab_node_rel rel TSRMLS_DC)905 php_mecab_node_get_sibling(zval *zv, zval *object, php_mecab_node *xnode, php_mecab_node_rel rel TSRMLS_DC)
906 {
907 const mecab_node_t *node = xnode->ptr;
908 php_mecab_node *xsbl = NULL;
909 const mecab_node_t *sbl = NULL;
910 zval *retval = NULL;
911
912 if (zv == NULL) {
913 retval = (zval *)emalloc(sizeof(zval));
914 } else {
915 zval_dtor(zv);
916 retval = zv;
917 }
918
919 /* scan */
920 if (rel == NODE_PREV) {
921 sbl = node->prev;
922 } else if (rel == NODE_NEXT) {
923 sbl = node->next;
924 } else if (rel == NODE_ENEXT) {
925 sbl = node->enext;
926 } else if (rel == NODE_BNEXT) {
927 sbl = node->bnext;
928 } else {
929 ZVAL_FALSE(retval);
930 return retval;
931 }
932
933 if (sbl == NULL) {
934 ZVAL_NULL(retval);
935 return retval;
936 }
937
938 /* set return value */
939 {
940 php_mecab_node_object *newobj;
941 object_init_ex(retval, ce_MeCab_Node);
942 newobj = PHP_MECAB_NODE_OBJECT_P(retval);
943 xsbl = newobj->ptr;
944 xsbl->ptr = sbl;
945 }
946 php_mecab_node_set_tagger(xsbl, xnode->tagger TSRMLS_CC);
947
948 return retval;
949 }
950 /* }}} */
951
952 /* {{{ php_mecab_node_get_path()
953 * get related path from mecab_node
954 */
955 static zval *
php_mecab_node_get_path(zval * zv,zval * object,php_mecab_node * xnode,php_mecab_node_rel rel TSRMLS_DC)956 php_mecab_node_get_path(zval *zv, zval *object, php_mecab_node *xnode, php_mecab_node_rel rel TSRMLS_DC)
957 {
958 const mecab_node_t *node = xnode->ptr;
959 php_mecab_path *xpath = NULL;
960 const mecab_path_t *path = NULL;
961 zval *retval = NULL;
962
963 if (zv == NULL) {
964 retval = (zval *)emalloc(sizeof(zval));
965 } else {
966 zval_dtor(zv);
967 retval = zv;
968 }
969
970 /* scan */
971 if (rel == NODE_RPATH) {
972 path = node->rpath;
973 } else if (rel == NODE_LPATH) {
974 path = node->lpath;
975 } else {
976 ZVAL_FALSE(retval);
977 return retval;
978 }
979
980 if (path == NULL) {
981 ZVAL_NULL(retval);
982 return retval;
983 }
984
985 /* set return value */
986 {
987 php_mecab_path_object *newobj;
988 object_init_ex(retval, ce_MeCab_Path);
989 newobj = PHP_MECAB_PATH_OBJECT_P(retval);
990 xpath = newobj->ptr;
991 xpath->ptr = path;
992 }
993 php_mecab_path_set_tagger(xpath, xnode->tagger TSRMLS_CC);
994
995 return retval;
996 }
997 /* }}} */
998
999 /* {{{ php_mecab_path_get_sibling()
1000 * get sibling path from mecab_path
1001 */
1002 static zval *
php_mecab_path_get_sibling(zval * zv,zval * object,php_mecab_path * xpath,php_mecab_path_rel rel TSRMLS_DC)1003 php_mecab_path_get_sibling(zval *zv, zval *object, php_mecab_path *xpath, php_mecab_path_rel rel TSRMLS_DC)
1004 {
1005 const mecab_path_t *path = xpath->ptr;
1006 php_mecab_path *xsbl = NULL;
1007 const mecab_path_t *sbl = NULL;
1008 zval *retval = NULL;
1009
1010 if (zv == NULL) {
1011 retval = (zval *)emalloc(sizeof(zval));
1012 } else {
1013 zval_dtor(zv);
1014 retval = zv;
1015 }
1016
1017 /* scan */
1018 if (rel == PATH_RNEXT) {
1019 sbl = path->rnext;
1020 } else if (rel == PATH_LNEXT) {
1021 sbl = path->lnext;
1022 } else {
1023 ZVAL_FALSE(retval);
1024 return retval;
1025 }
1026
1027 if (sbl == NULL) {
1028 ZVAL_NULL(retval);
1029 return retval;
1030 }
1031
1032 /* set return value */
1033 {
1034 php_mecab_path_object *newobj;
1035 object_init_ex(retval, ce_MeCab_Path);
1036 newobj = PHP_MECAB_PATH_OBJECT_P(retval);
1037 xsbl = newobj->ptr;
1038 xsbl->ptr = sbl;
1039 }
1040 php_mecab_path_set_tagger(xsbl, xpath->tagger TSRMLS_CC);
1041
1042 return retval;
1043 }
1044 /* }}} */
1045
1046 /* {{{ php_mecab_path_get_node()
1047 * get related node from mecab_path
1048 */
1049 static zval *
php_mecab_path_get_node(zval * zv,zval * object,php_mecab_path * xpath,php_mecab_path_rel rel TSRMLS_DC)1050 php_mecab_path_get_node(zval *zv, zval *object, php_mecab_path *xpath, php_mecab_path_rel rel TSRMLS_DC)
1051 {
1052 const mecab_path_t *path = xpath->ptr;
1053 php_mecab_node *xnode = NULL;
1054 const mecab_node_t *node = NULL;
1055 zval *retval = NULL;
1056
1057 if (zv == NULL) {
1058 retval = (zval *)emalloc(sizeof(zval));
1059 } else {
1060 zval_dtor(zv);
1061 retval = zv;
1062 }
1063
1064 /* scan */
1065 if (rel == PATH_RNODE) {
1066 node = path->rnode;
1067 } else if (rel == PATH_LNODE) {
1068 node = path->lnode;
1069 } else {
1070 ZVAL_FALSE(retval);
1071 return retval;
1072 }
1073
1074 if (node == NULL) {
1075 ZVAL_NULL(retval);
1076 return retval;
1077 }
1078
1079 /* set return value */
1080 {
1081 php_mecab_node_object *newobj;
1082 object_init_ex(retval, ce_MeCab_Node);
1083 newobj = PHP_MECAB_NODE_OBJECT_P(retval);
1084 xnode = newobj->ptr;
1085 xnode->ptr = node;
1086 }
1087 php_mecab_node_set_tagger(xnode, xpath->tagger TSRMLS_CC);
1088
1089 return retval;
1090 }
1091 /* }}} */
1092
1093 /* {{{ php_mecab_node_get_sibling_wrapper()
1094 * wraps php_mecab_node_get_sibling()
1095 */
1096 static void
php_mecab_node_get_sibling_wrapper(INTERNAL_FUNCTION_PARAMETERS,php_mecab_node_rel rel)1097 php_mecab_node_get_sibling_wrapper(INTERNAL_FUNCTION_PARAMETERS, php_mecab_node_rel rel)
1098 {
1099 /* declaration of the resources */
1100 php_mecab_node *xnode = NULL;
1101
1102 /* parse the arguments */
1103 PHP_MECAB_NODE_INTERNAL_FROM_PARAMETER();
1104
1105 php_mecab_node_get_sibling(return_value, getThis(), xnode, rel TSRMLS_CC);
1106 }
1107 /* }}} */
1108
1109 /* {{{ php_mecab_node_get_path_wrapper()
1110 * wraps php_mecab_node_get_path()
1111 */
1112 static void
php_mecab_node_get_path_wrapper(INTERNAL_FUNCTION_PARAMETERS,php_mecab_node_rel rel)1113 php_mecab_node_get_path_wrapper(INTERNAL_FUNCTION_PARAMETERS, php_mecab_node_rel rel)
1114 {
1115 /* declaration of the resources */
1116 php_mecab_node *xnode = NULL;
1117
1118 /* parse the arguments */
1119 PHP_MECAB_NODE_INTERNAL_FROM_PARAMETER();
1120
1121 php_mecab_node_get_path(return_value, getThis(), xnode, rel TSRMLS_CC);
1122 }
1123 /* }}} */
1124
1125 /* {{{ php_mecab_path_get_sibling_wrapper()
1126 * wraps php_mecab_path_get_sibling()
1127 */
1128 static void
php_mecab_path_get_sibling_wrapper(INTERNAL_FUNCTION_PARAMETERS,php_mecab_path_rel rel)1129 php_mecab_path_get_sibling_wrapper(INTERNAL_FUNCTION_PARAMETERS, php_mecab_path_rel rel)
1130 {
1131 /* declaration of the resources */
1132 php_mecab_path *xpath = NULL;
1133
1134 /* parse the arguments */
1135 PHP_MECAB_PATH_INTERNAL_FROM_PARAMETER();
1136
1137 php_mecab_path_get_sibling(return_value, getThis(), xpath, rel TSRMLS_CC);
1138 }
1139 /* }}} */
1140
1141 /* {{{ php_mecab_path_get_node_wrapper()
1142 * wraps php_mecab_path_get_path()
1143 */
1144 static void
php_mecab_path_get_node_wrapper(INTERNAL_FUNCTION_PARAMETERS,php_mecab_path_rel rel)1145 php_mecab_path_get_node_wrapper(INTERNAL_FUNCTION_PARAMETERS, php_mecab_path_rel rel)
1146 {
1147 /* declaration of the resources */
1148 php_mecab_path *xpath = NULL;
1149
1150 /* parse the arguments */
1151 PHP_MECAB_PATH_INTERNAL_FROM_PARAMETER();
1152
1153 php_mecab_path_get_node(return_value, getThis(), xpath, rel TSRMLS_CC);
1154 }
1155 /* }}} */
1156
1157 /* {{{ php_mecab_get_class_entry()
1158 * get the class entry
1159 */
1160 static zend_class_entry *
php_mecab_get_class_entry(const char * lcname TSRMLS_DC)1161 php_mecab_get_class_entry(const char *lcname TSRMLS_DC)
1162 {
1163 zval *entry = zend_hash_str_find(CG(class_table), lcname, strlen(lcname));
1164 if (entry && Z_TYPE_P(entry) == IS_PTR) {
1165 return Z_PTR_P(entry);
1166 } else {
1167 return NULL;
1168 }
1169 }
1170 /* }}} */
1171
1172 /* {{{ php_mecab_node_list_method()
1173 * check file/dicectory accessibility
1174 */
1175 static zend_bool
php_mecab_check_path(const char * path,size_t length,char * real_path TSRMLS_DC)1176 php_mecab_check_path(const char *path, size_t length, char *real_path TSRMLS_DC)
1177 {
1178 char *full_path;
1179
1180 if (strlen(path) != length ||
1181 (full_path = expand_filepath(path, real_path TSRMLS_CC)) == NULL)
1182 {
1183 return 0;
1184 }
1185
1186 if (VCWD_ACCESS(full_path, F_OK) != 0 ||
1187 VCWD_ACCESS(full_path, R_OK) != 0 ||
1188 php_check_open_basedir(full_path TSRMLS_CC))
1189 {
1190 if (real_path == NULL) {
1191 efree(full_path);
1192 }
1193 return 0;
1194 }
1195
1196 #if !defined(PHP_VERSION_ID) || PHP_VERSION_ID < 50400
1197 if (PG(safe_mode) && !php_checkuid(full_path, NULL, CHECKUID_CHECK_FILE_AND_DIR)) {
1198 if (real_path == NULL) {
1199 efree(full_path);
1200 }
1201 return 0;
1202 }
1203 #endif
1204
1205 if (real_path == NULL) {
1206 efree(full_path);
1207 }
1208 return 1;
1209 }
1210 /* }}} */
1211
1212 /* {{{ macro for checking constructor options */
1213
1214 /* check if default parameter is set */
1215 #define PHP_MECAB_CHECK_DEFAULT(name) \
1216 (MECAB_G(default_##name) != NULL && MECAB_G(default_##name)[0] != '\0')
1217
1218 #define PHP_MECAB_GETOPT_FAILURE -1
1219 #define PHP_MECAB_GETOPT_SUCCESS 0
1220 #define PHP_MECAB_GETOPT_FLAG_EXPECTED (1 << 0)
1221 #define PHP_MECAB_GETOPT_RCFILE_EXPECTED (1 << 2)
1222 #define PHP_MECAB_GETOPT_DICDIR_EXPECTED (1 << 3)
1223 #define PHP_MECAB_GETOPT_USERDIC_EXPECTED (1 << 4)
1224 #define PHP_MECAB_GETOPT_PATH_EXPECTED \
1225 (PHP_MECAB_GETOPT_RCFILE_EXPECTED | PHP_MECAB_GETOPT_DICDIR_EXPECTED | PHP_MECAB_GETOPT_USERDIC_EXPECTED)
1226
1227 /* check for option */
1228 static int
php_mecab_check_option(const char * option)1229 php_mecab_check_option(const char *option)
1230 {
1231 /* not an option */
1232 if (*option != '-') {
1233 return PHP_MECAB_GETOPT_FAILURE;
1234 }
1235
1236 /* resource file */
1237 if (!strcmp(option, "-r") || !strcmp(option, "--rcfile")) {
1238 return PHP_MECAB_GETOPT_RCFILE_EXPECTED;
1239 }
1240
1241 /* system dicdir */
1242 if (!strcmp(option, "-d") || !strcmp(option, "--dicdir")) {
1243 return PHP_MECAB_GETOPT_DICDIR_EXPECTED;
1244 }
1245
1246 /* user dictionary */
1247 if (!strcmp(option, "-u") || !strcmp(option, "--userdic")) {
1248 return PHP_MECAB_GETOPT_USERDIC_EXPECTED;
1249 }
1250
1251 /* options whose parameter is not filename */
1252 if (!strcmp(option, "-l") || !strcmp(option, "--lattice-level") ||
1253 !strcmp(option, "-O") || !strcmp(option, "--output-format-type") ||
1254 !strcmp(option, "-F") || !strcmp(option, "--node-format") ||
1255 !strcmp(option, "-U") || !strcmp(option, "--unk-format") ||
1256 !strcmp(option, "-B") || !strcmp(option, "--bos-format") ||
1257 !strcmp(option, "-E") || !strcmp(option, "--eos-format") ||
1258 !strcmp(option, "-x") || !strcmp(option, "--unk-feature") ||
1259 !strcmp(option, "-b") || !strcmp(option, "--input-buffer-size") ||
1260 !strcmp(option, "-N") || !strcmp(option, "--nbest") ||
1261 !strcmp(option, "-t") || !strcmp(option, "--theta"))
1262 {
1263 return PHP_MECAB_GETOPT_SUCCESS;
1264 }
1265
1266 /* options which does not have parameter */
1267 if (!strcmp(option, "-a") || !strcmp(option, "--all-morphs") ||
1268 !strcmp(option, "-p") || !strcmp(option, "--partial") ||
1269 !strcmp(option, "-C") || !strcmp(option, "--allocate-sentence"))
1270 {
1271 return (PHP_MECAB_GETOPT_SUCCESS | PHP_MECAB_GETOPT_FLAG_EXPECTED);
1272 }
1273
1274 /* invalid options */
1275 return PHP_MECAB_GETOPT_FAILURE;
1276 }
1277
1278 /* check for open_basedir and safe_mode */
1279 #define PHP_MECAB_CHECK_FILE(path, length) \
1280 { \
1281 if (!php_mecab_check_path((path), (length), resolved_path TSRMLS_CC)) { \
1282 efree(argv); \
1283 php_error_docref(NULL TSRMLS_CC, E_WARNING, "'%s' does not exist or is not readable", (path)); \
1284 RETURN_FALSE; \
1285 } \
1286 flag_expected = 1; \
1287 path_expected = 0; \
1288 }
1289
1290 /* }}} */
1291
1292 /* {{{ Functions */
1293
1294 /* {{{ proto string MeCab\version(void) */
1295 /**
1296 * Get the version number of MeCab.
1297 *
1298 * @return string The version of linked MeCab library.
1299 */
PHP_FUNCTION(version)1300 static PHP_FUNCTION(version)
1301 {
1302 if (ZEND_NUM_ARGS() != 0) {
1303 WRONG_PARAM_COUNT;
1304 }
1305 RETURN_STRING((char *)mecab_version());
1306 }
1307 /* }}} mecab_version */
1308
1309 /* {{{ proto array MeCab\split(string str[, string dicdir[, string userdic]]) */
1310 /**
1311 * Split string into an array of morphemes.
1312 *
1313 * @param string $str The target string.
1314 * @param string $dicdir The path for system dictionary.
1315 * @param string $userdic The path for user dictionary.
1316 * @return array
1317 */
PHP_FUNCTION(split)1318 static PHP_FUNCTION(split)
1319 {
1320 /* variables from argument */
1321 zend_string *str = NULL;
1322 zend_string *zdicdir = NULL;
1323 const char *dicdir = NULL;
1324 int dicdir_len = 0;
1325 zend_string *zuserdic = NULL;
1326 const char *userdic = NULL;
1327 int userdic_len = 0;
1328
1329 /* local variables */
1330 mecab_t *mecab = NULL;
1331 const mecab_node_t *node = NULL;
1332 int argc = 2;
1333 char *argv[5] = { "mecab", "-Owakati", NULL, NULL, NULL };
1334 char pathbuf[2][PATHBUFSIZE] = {{'\0'}};
1335 char *dicdir_buf = &(pathbuf[0][0]);
1336 char *userdic_buf = &(pathbuf[1][0]);
1337
1338 /* parse arguments */
1339 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "S|S!S!", &str, &zdicdir, &zuserdic) == FAILURE) {
1340 return;
1341 }
1342
1343 /* apply default options */
1344 if (zdicdir != NULL && ZSTR_LEN(zdicdir) > 0) {
1345 dicdir = ZSTR_VAL(zdicdir);
1346 dicdir_len = ZSTR_LEN(zdicdir);
1347 } else if (PHP_MECAB_CHECK_DEFAULT(dicdir)) {
1348 dicdir = MECAB_G(default_dicdir);
1349 dicdir_len = (int)strlen(MECAB_G(default_dicdir));
1350 }
1351 if (zuserdic != NULL && ZSTR_LEN(zuserdic) > 0) {
1352 userdic = ZSTR_VAL(zuserdic);
1353 userdic_len = ZSTR_LEN(zuserdic);
1354 } else if (PHP_MECAB_CHECK_DEFAULT(userdic)) {
1355 userdic = MECAB_G(default_userdic);
1356 userdic_len = (int)strlen(MECAB_G(default_userdic));
1357 }
1358
1359 /* check for dictionary */
1360 if (dicdir != NULL && dicdir_len > 0) {
1361 char *dicdir_ptr = dicdir_buf;
1362 *dicdir_ptr++ = '-';
1363 *dicdir_ptr++ = 'd';
1364 if (!php_mecab_check_path(dicdir, dicdir_len, dicdir_ptr TSRMLS_CC)) {
1365 php_error_docref(NULL TSRMLS_CC, E_WARNING,
1366 "'%s' does not exist or is not readable", dicdir);
1367 RETURN_FALSE;
1368 }
1369 argv[argc++] = dicdir_buf;
1370 }
1371 if (userdic != NULL && userdic_len > 0) {
1372 char *userdic_ptr = userdic_buf;
1373 *userdic_ptr++ = '-';
1374 *userdic_ptr++ = 'u';
1375 if (!php_mecab_check_path(userdic, userdic_len, userdic_ptr TSRMLS_CC)) {
1376 php_error_docref(NULL TSRMLS_CC, E_WARNING,
1377 "'%s' does not exist or is not readable", userdic);
1378 RETURN_FALSE;
1379 }
1380 argv[argc++] = userdic_buf;
1381 }
1382
1383 /* create mecab object */
1384 mecab = mecab_new(argc, argv);
1385
1386 /* on error */
1387 if (mecab == NULL) {
1388 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", mecab_strerror(NULL));
1389 RETURN_FALSE;
1390 }
1391
1392 /* parse the string */
1393 node = mecab_sparse_tonode(mecab, ZSTR_VAL(str));
1394 if (node == NULL) {
1395 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", mecab_strerror(mecab));
1396 mecab_destroy(mecab);
1397 RETURN_FALSE;
1398 }
1399
1400 /* initialize */
1401 array_init(return_value);
1402
1403 /* put surfaces of each node to return value */
1404 while (node != NULL) {
1405 if (node->length > 0) {
1406 add_next_index_stringl(return_value, (char *)node->surface, (int)node->length);
1407 }
1408 node = node->next;
1409 }
1410
1411 /* free mecab object */
1412 mecab_destroy(mecab);
1413 }
1414 /* }}} mecab_split */
1415
1416 /* {{{ proto resource mecab mecab_new([array options]) */
1417 /**
1418 * resource mecab mecab_new([array options])
1419 * object MeCab_Tagger MeCab_Tagger::__construct([array options])
1420 *
1421 * Create new tagger resource of MeCab.
1422 *
1423 * @param array $options The analysis/output options. (optional)
1424 * The values are same to command line options.
1425 * The detail is found in the web site and/or the manpage of MeCab.
1426 * @return resource mecab A tagger resource of MeCab.
1427 */
PHP_FUNCTION(mecab_new)1428 static PHP_FUNCTION(mecab_new)
1429 {
1430 /* declaration of the resources */
1431 php_mecab *xmecab = NULL;
1432 mecab_t *mecab = NULL;
1433
1434 /* declaration of the arguments */
1435 zval *zoptions = NULL;
1436 HashTable *options = NULL;
1437
1438 /* declaration of the local variables */
1439 size_t min_argc = 5; /* "mecab" + "-r" + "-d" + "-u" + NULL */
1440 int argc = 1;
1441 char **argv = NULL;
1442 int flag_expected = 1;
1443 int path_expected = 0;
1444 char pathbuf[3][PATHBUFSIZE] = {{'\0'}};
1445 char *rcfile_buf = &(pathbuf[0][0]);
1446 char *dicdir_buf = &(pathbuf[1][0]);
1447 char *userdic_buf = &(pathbuf[2][0]);
1448 char *resolved_path = NULL;
1449
1450 /* parse arguments */
1451 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!", &zoptions) == FAILURE) {
1452 return;
1453 }
1454
1455 /* parse options */
1456 if (zoptions != NULL) {
1457 int getopt_result = 0;
1458 zend_string *key;
1459 ulong num_key;
1460 zval *entry;
1461
1462 ALLOC_HASHTABLE(options);
1463
1464 zend_hash_init(options, zend_hash_num_elements(Z_ARRVAL_P(zoptions)), NULL, ZVAL_PTR_DTOR, 0);
1465 zend_hash_copy(options, Z_ARRVAL_P(zoptions), (copy_ctor_func_t)zval_add_ref);
1466
1467 argv = (char **)ecalloc(2 * zend_hash_num_elements(options) + min_argc, sizeof(char *));
1468
1469 ZEND_HASH_FOREACH_KEY_VAL(options, num_key, key, entry) {
1470 convert_to_string_ex(entry);
1471 if (key) {
1472 getopt_result = php_mecab_check_option(ZSTR_VAL(key));
1473 if (getopt_result == FAILURE) {
1474 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid option '%s' given", ZSTR_VAL(key));
1475 efree(argv);
1476 RETURN_FALSE;
1477 } else {
1478 flag_expected = getopt_result & PHP_MECAB_GETOPT_FLAG_EXPECTED;
1479 path_expected = getopt_result & PHP_MECAB_GETOPT_PATH_EXPECTED;
1480 if (getopt_result & PHP_MECAB_GETOPT_RCFILE_EXPECTED) {
1481 resolved_path = rcfile_buf;
1482 } else if (getopt_result & PHP_MECAB_GETOPT_DICDIR_EXPECTED) {
1483 resolved_path = dicdir_buf;
1484 } else if (getopt_result & PHP_MECAB_GETOPT_USERDIC_EXPECTED) {
1485 resolved_path = userdic_buf;
1486 }
1487 }
1488 argv[argc++] = ZSTR_VAL(key);
1489 if (path_expected) {
1490 PHP_MECAB_CHECK_FILE(Z_STRVAL_P(entry), Z_STRLEN_P(entry));
1491 argv[argc++] = resolved_path;
1492 } else {
1493 argv[argc++] = Z_STRVAL_P(entry);
1494 }
1495 flag_expected = 1;
1496 path_expected = 0;
1497 } else {
1498 if (flag_expected) {
1499 getopt_result = php_mecab_check_option(Z_STRVAL_P(entry));
1500 if (getopt_result == FAILURE) {
1501 php_error_docref(NULL TSRMLS_CC, E_WARNING,
1502 "Invalid option '%s' given", Z_STRVAL_P(entry));
1503 efree(argv);
1504 RETURN_FALSE;
1505 } else {
1506 flag_expected = getopt_result & PHP_MECAB_GETOPT_FLAG_EXPECTED;
1507 path_expected = getopt_result & PHP_MECAB_GETOPT_PATH_EXPECTED;
1508 if (getopt_result & PHP_MECAB_GETOPT_RCFILE_EXPECTED) {
1509 resolved_path = rcfile_buf;
1510 } else if (getopt_result & PHP_MECAB_GETOPT_DICDIR_EXPECTED) {
1511 resolved_path = dicdir_buf;
1512 } else if (getopt_result & PHP_MECAB_GETOPT_USERDIC_EXPECTED) {
1513 resolved_path = userdic_buf;
1514 }
1515 }
1516 argv[argc++] = Z_STRVAL_P(entry);
1517 } else if (path_expected) {
1518 PHP_MECAB_CHECK_FILE(Z_STRVAL_P(entry), Z_STRLEN_P(entry));
1519 argv[argc++] = resolved_path;
1520 } else {
1521 argv[argc++] = Z_STRVAL_P(entry);
1522 }
1523 }
1524 } ZEND_HASH_FOREACH_END();
1525 } else {
1526 argv = (char **)ecalloc(min_argc, sizeof(char *));
1527 }
1528
1529 /* apply default options */
1530 if (rcfile_buf[0] == '\0' && PHP_MECAB_CHECK_DEFAULT(rcfile)) {
1531 size_t rcfile_len = strlen(MECAB_G(default_rcfile));
1532 resolved_path = rcfile_buf;
1533 *resolved_path++ = '-';
1534 *resolved_path++ = 'r';
1535 PHP_MECAB_CHECK_FILE(MECAB_G(default_rcfile), rcfile_len);
1536 argv[argc++] = rcfile_buf;
1537 }
1538 if (dicdir_buf[0] == '\0' && PHP_MECAB_CHECK_DEFAULT(dicdir)) {
1539 size_t dicdir_len = strlen(MECAB_G(default_dicdir));
1540 resolved_path = dicdir_buf;
1541 *resolved_path++ = '-';
1542 *resolved_path++ = 'd';
1543 PHP_MECAB_CHECK_FILE(MECAB_G(default_dicdir), dicdir_len);
1544 argv[argc++] = dicdir_buf;
1545 }
1546 if (userdic_buf[0] == '\0' && PHP_MECAB_CHECK_DEFAULT(userdic)) {
1547 size_t userdic_len = strlen(MECAB_G(default_userdic));
1548 resolved_path = userdic_buf;
1549 *resolved_path++ = '-';
1550 *resolved_path++ = 'u';
1551 PHP_MECAB_CHECK_FILE(MECAB_G(default_userdic), userdic_len);
1552 argv[argc++] = userdic_buf;
1553 }
1554
1555 /* create mecab object */
1556 argv[0] = "mecab";
1557 argv[argc] = NULL;
1558 mecab = mecab_new(argc, argv);
1559
1560 efree(argv);
1561 if (options != NULL) {
1562 zend_hash_destroy(options);
1563 FREE_HASHTABLE(options);
1564 }
1565
1566 /* on error */
1567 if (mecab == NULL) {
1568 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", mecab_strerror(NULL));
1569 RETURN_FALSE;
1570 }
1571
1572 {
1573 const php_mecab_object *intern = PHP_MECAB_OBJECT_P(getThis());
1574 xmecab = intern->ptr;
1575 if (xmecab->ptr != NULL) {
1576 mecab_destroy(mecab);
1577 zend_throw_exception(ext_ce_BadMethodCallException,
1578 "MeCab already initialized", 0 TSRMLS_CC);
1579 return;
1580 }
1581 }
1582 xmecab->ptr = mecab;
1583 }
1584 /* }}} mecab_new */
1585
1586 /* {{{ proto bool mecab_get_partial(resource mecab mecab) */
1587 /**
1588 * bool mecab_get_partial(resource mecab mecab)
1589 * bool MeCab_Tagger::getPartial()
1590 *
1591 * Get partial parsing mode.
1592 *
1593 * @param resource mecab $mecab The tagger resource of MeCab.
1594 * @return bool
1595 */
PHP_FUNCTION(mecab_get_partial)1596 static PHP_FUNCTION(mecab_get_partial)
1597 {
1598 /* declaration of the resources */
1599 php_mecab *xmecab = NULL;
1600 mecab_t *mecab = NULL;
1601
1602 /* parse the arguments */
1603 PHP_MECAB_FROM_PARAMETER();
1604
1605 RETURN_BOOL(mecab_get_partial(mecab))
1606 }
1607 /* }}} */
1608
1609 /* {{{ proto void mecab_set_partial(resource mecab mecab, bool partial) */
1610 /**
1611 * void mecab_set_partial(resource mecab mecab, bool partial)
1612 * void MeCab_Tagger::setPartial(bool partial)
1613 *
1614 * Set partial parsing mode.
1615 *
1616 * @param resource mecab $mecab The tagger resource of MeCab.
1617 * @param bool $partial The partial parsing mode.
1618 * @return void
1619 */
PHP_FUNCTION(mecab_set_partial)1620 static PHP_FUNCTION(mecab_set_partial)
1621 {
1622 /* declaration of the resources */
1623 php_mecab *xmecab = NULL;
1624 mecab_t *mecab = NULL;
1625
1626 /* declaration of the arguments */
1627 zend_bool partial = 0;
1628
1629 /* parse the arguments */
1630 PHP_MECAB_PARSE_PARAMETERS("b", &partial);
1631
1632 mecab_set_partial(mecab, (int)partial);
1633 }
1634 /* }}} */
1635
1636 /* {{{ proto float mecab_get_theta(resource mecab mecab) */
1637 /**
1638 * float mecab_get_theta(resource mecab mecab)
1639 * float MeCab_Tagger::getTheta()
1640 *
1641 * Get temparature parameter theta.
1642 *
1643 * @param resource mecab $mecab The tagger resource of MeCab.
1644 * @return float
1645 */
PHP_FUNCTION(mecab_get_theta)1646 static PHP_FUNCTION(mecab_get_theta)
1647 {
1648 /* declaration of the resources */
1649 php_mecab *xmecab = NULL;
1650 mecab_t *mecab = NULL;
1651
1652 /* parse the arguments */
1653 PHP_MECAB_FROM_PARAMETER();
1654
1655 RETURN_DOUBLE((double)mecab_get_theta(mecab))
1656 }
1657 /* }}} */
1658
1659 /* {{{ proto void mecab_(resource mecab mecab, float theta) */
1660 /**
1661 * void mecab_set_theta(resource mecab mecab, float theta)
1662 * void MeCab_Tagger::setTheta(float theta)
1663 *
1664 * Set temparature parameter theta.
1665 *
1666 * @param resource mecab $mecab The tagger resource of MeCab.
1667 * @param float $theta The temparature parameter theta.
1668 * @return void
1669 */
PHP_FUNCTION(mecab_set_theta)1670 static PHP_FUNCTION(mecab_set_theta)
1671 {
1672 /* declaration of the resources */
1673 php_mecab *xmecab = NULL;
1674 mecab_t *mecab = NULL;
1675
1676 /* declaration of the arguments */
1677 double theta = 0;
1678
1679 /* parse the arguments */
1680 PHP_MECAB_PARSE_PARAMETERS("d", &theta);
1681
1682 mecab_set_theta(mecab, (float)theta);
1683 }
1684 /* }}} */
1685
1686 /* {{{ proto int mecab_get_lattice_level(resource mecab mecab) */
1687 /**
1688 * int mecab_get_lattice_level(resource mecab mecab)
1689 * int MeCab_Tagger::getLatticeLevel()
1690 *
1691 * Get lattice information level.
1692 *
1693 * @param resource mecab $mecab The tagger resource of MeCab.
1694 * @return int
1695 */
PHP_FUNCTION(mecab_get_lattice_level)1696 static PHP_FUNCTION(mecab_get_lattice_level)
1697 {
1698 /* declaration of the resources */
1699 php_mecab *xmecab = NULL;
1700 mecab_t *mecab = NULL;
1701
1702 /* parse the arguments */
1703 PHP_MECAB_FROM_PARAMETER();
1704
1705 RETURN_LONG((long)mecab_get_lattice_level(mecab))
1706 }
1707 /* }}} */
1708
1709 /* {{{ proto void mecab_set_lattice_level(resource mecab mecab, int level) */
1710 /**
1711 * void mecab_set_lattice_level(resource mecab mecab, int level)
1712 * void MeCab_Tagger::setLatticeLevel(int level)
1713 *
1714 * Set lattice information level.
1715 *
1716 * @param resource mecab $mecab The tagger resource of MeCab.
1717 * @param int $level The lattice information level.
1718 * @return void
1719 */
PHP_FUNCTION(mecab_set_lattice_level)1720 static PHP_FUNCTION(mecab_set_lattice_level)
1721 {
1722 /* declaration of the resources */
1723 php_mecab *xmecab = NULL;
1724 mecab_t *mecab = NULL;
1725
1726 /* declaration of the arguments */
1727 long level = 0L;
1728
1729 /* parse the arguments */
1730 PHP_MECAB_PARSE_PARAMETERS("l", &level);
1731
1732 mecab_set_lattice_level(mecab, (int)level);
1733 }
1734 /* }}} */
1735
1736 /* {{{ proto bool mecab_get_all_morphs(resource mecab mecab) */
1737 /**
1738 * bool mecab_get_all_morphs(resource mecab mecab)
1739 * bool MeCab_Tagger::getAllMorphs()
1740 *
1741 * Get all morphs mode.
1742 *
1743 * @param resource mecab $mecab The tagger resource of MeCab.
1744 * @return bool
1745 */
PHP_FUNCTION(mecab_get_all_morphs)1746 static PHP_FUNCTION(mecab_get_all_morphs)
1747 {
1748 /* declaration of the resources */
1749 php_mecab *xmecab = NULL;
1750 mecab_t *mecab = NULL;
1751
1752 /* parse the arguments */
1753 PHP_MECAB_FROM_PARAMETER();
1754
1755 RETURN_BOOL(mecab_get_all_morphs(mecab))
1756 }
1757 /* }}} */
1758
1759 /* {{{ proto void mecab_set_all_morphs(resource mecab mecab, int all_morphs) */
1760 /**
1761 * void mecab_set_all_morphs(resource mecab mecab, int all_morphs)
1762 * void MeCab_Tagger::setAllMorphs(int all_morphs)
1763 *
1764 * Set all morphs mode.
1765 *
1766 * @param resource mecab $mecab The tagger resource of MeCab.
1767 * @param bool $all_morphs The all morphs mode.
1768 * @return void
1769 */
PHP_FUNCTION(mecab_set_all_morphs)1770 static PHP_FUNCTION(mecab_set_all_morphs)
1771 {
1772 /* declaration of the resources */
1773 php_mecab *xmecab = NULL;
1774 mecab_t *mecab = NULL;
1775
1776 /* declaration of the arguments */
1777 zend_bool all_morphs = 0;
1778
1779 /* parse the arguments */
1780 PHP_MECAB_PARSE_PARAMETERS("b", &all_morphs);
1781
1782 mecab_set_all_morphs(mecab, (int)all_morphs);
1783 }
1784 /* }}} */
1785
1786 /* {{{ proto string mecab_sparse_tostr(resource mecab mecab, string str[, int len[, int olen]]) */
1787 /**
1788 * string mecab_sparse_tostr(resource mecab mecab, string str[, int len[, int olen]])
1789 * string MeCab_Tagger::parse(string str[, int len[, int olen]])
1790 * string MeCab_Tagger::parseToString(string str[, int len[, int olen]])
1791 *
1792 * Get the parse result as a string.
1793 *
1794 * @param resource mecab $mecab The tagger resource of MeCab.
1795 * @param string $str The parse target.
1796 * @param int $len The maximum length that can be analyzed. (optional)
1797 * @param int $olen The limit length of the output buffer. (optional)
1798 * @return string The parse result.
1799 * If output buffer has overflowed, returns false.
1800 */
PHP_FUNCTION(mecab_sparse_tostr)1801 static PHP_FUNCTION(mecab_sparse_tostr)
1802 {
1803 /* declaration of the resources */
1804 php_mecab *xmecab = NULL;
1805 mecab_t *mecab = NULL;
1806
1807 /* declaration of the arguments */
1808 zend_string *str = NULL;
1809 long len = 0;
1810 long olen = 0;
1811
1812 /* declaration of the local variables */
1813 size_t ilen = 0;
1814 char *ostr = NULL;
1815 zend_bool ostr_free = 0;
1816
1817 /* parse the arguments */
1818 PHP_MECAB_PARSE_PARAMETERS("S|ll", &str, &len, &olen);
1819
1820 /* call mecab_sparse_tostr() */
1821 php_mecab_set_string(xmecab, str TSRMLS_CC);
1822 ilen = (size_t)((len > 0) ? MIN(len, (long)ZSTR_LEN(str)) : ZSTR_LEN(str));
1823 if (olen == 0) {
1824 ostr = (char *)mecab_sparse_tostr2(mecab, ZSTR_VAL(xmecab->str), ilen);
1825 } else {
1826 ostr = (char *)emalloc((size_t)olen + 1);
1827 ostr = mecab_sparse_tostr3(mecab, ZSTR_VAL(xmecab->str), ilen, ostr, (size_t)olen);
1828 ostr_free = 1;
1829 }
1830
1831 /* set return value */
1832 if (ostr == NULL) {
1833 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", mecab_strerror(mecab));
1834 RETVAL_FALSE;
1835 } else {
1836 RETVAL_STRING(ostr);
1837 }
1838
1839 /* free */
1840 if (ostr_free) {
1841 efree(ostr);
1842 }
1843 }
1844 /* }}} mecab_sparse_tostr */
1845
1846 /* {{{ proto resource mecab_node mecab_sparse_tonode(resource mecab mecab, string str[, int len]) */
1847 /**
1848 * resource mecab_node mecab_sparse_tonode(resource mecab mecab, string str[, int len])
1849 * object MeCab_Node MeCab_Tagger::parseToNode(string str[, int len])
1850 *
1851 * Get the parse result as a node.
1852 *
1853 * @param resource mecab $mecab The tagger resource of MeCab.
1854 * @param string $str The parse target.
1855 * @param int $len The maximum length that can be analyzed. (optional)
1856 * @return resource mecab_node The result node of given string.
1857 */
PHP_FUNCTION(mecab_sparse_tonode)1858 static PHP_FUNCTION(mecab_sparse_tonode)
1859 {
1860 /* declaration of the resources */
1861 php_mecab *xmecab = NULL;
1862 mecab_t *mecab = NULL;
1863
1864 /* declaration of the arguments */
1865 zend_string *str = NULL;
1866 long len = 0;
1867
1868 /* declaration of the local variables */
1869 size_t ilen = 0;
1870 const mecab_node_t *node = NULL;
1871 php_mecab_node *xnode = NULL;
1872
1873 /* parse the arguments */
1874 PHP_MECAB_PARSE_PARAMETERS("S|l", &str, &len);
1875
1876 /* call mecab_sparse_tonode() */
1877 php_mecab_set_string(xmecab, str TSRMLS_CC);
1878 ilen = (size_t)((len > 0) ? MIN(len, (long)ZSTR_LEN(str)) : ZSTR_LEN(str));
1879 node = mecab_sparse_tonode2(mecab, ZSTR_VAL(xmecab->str), ilen);
1880 if (node == NULL) {
1881 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", mecab_strerror(mecab));
1882 RETURN_FALSE;
1883 }
1884
1885 /* set return value */
1886 {
1887 php_mecab_node_object *newobj;
1888 object_init_ex(return_value, ce_MeCab_Node);
1889 newobj = PHP_MECAB_NODE_OBJECT_P(return_value);
1890 xnode = newobj->ptr;
1891 }
1892 xnode->ptr = node;
1893 php_mecab_node_set_tagger(xnode, xmecab TSRMLS_CC);
1894 }
1895 /* }}} mecab_sparse_tonode */
1896
1897 /* {{{ proto string mecab_nbest_sparse_tostr(resource mecab mecab, int n, string str[, int len[, int olen]]) */
1898 /**
1899 * string mecab_nbest_sparse_tostr(resource mecab mecab, int n, string str[, int len[, int olen]])
1900 * string MeCab_Tagger::parseNBest(int n, string str[, int len[, int olen]])
1901 *
1902 * Get the N-Best list as a string.
1903 *
1904 * @param resource mecab $mecab The tagger resource of MeCab.
1905 * @param int $n The number of the result list.
1906 * @param string $str The parse target.
1907 * @param int $len The maximum length that can be analyzed. (optional)
1908 * @param int $olen The maximum length of the output. (optional)
1909 * @return string The N-Best list.
1910 * If output buffer has overflowed, returns false.
1911 */
PHP_FUNCTION(mecab_nbest_sparse_tostr)1912 static PHP_FUNCTION(mecab_nbest_sparse_tostr)
1913 {
1914 /* declaration of the resources */
1915 php_mecab *xmecab = NULL;
1916 mecab_t *mecab = NULL;
1917
1918 /* declaration of the arguments */
1919 long n = 0;
1920 zend_string *str = NULL;
1921 long len = 0;
1922 long olen = 0;
1923
1924 /* declaration of the local variables */
1925 size_t ilen = 0;
1926 char *ostr = NULL;
1927 zend_bool ostr_free = 1;
1928
1929 /* parse the arguments */
1930 PHP_MECAB_PARSE_PARAMETERS("lS|ll", &n, &str, &len, &olen);
1931
1932 /* call mecab_nbest_sparse_tostr() */
1933 php_mecab_set_string(xmecab, str TSRMLS_CC);
1934 ilen = (size_t)((len > 0) ? MIN(len, (long)ZSTR_LEN(str)) : ZSTR_LEN(str));
1935 if (olen == 0) {
1936 ostr = (char *)mecab_nbest_sparse_tostr2(mecab, n, ZSTR_VAL(xmecab->str), ilen);
1937 } else {
1938 ostr = (char *)emalloc(olen + 1);
1939 ostr = mecab_nbest_sparse_tostr3(mecab, n, ZSTR_VAL(xmecab->str), ilen, ostr, (size_t)olen);
1940 ostr_free = 1;
1941 }
1942
1943 /* set return value */
1944 if (ostr == NULL) {
1945 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", mecab_strerror(mecab));
1946 RETVAL_FALSE;
1947 } else {
1948 RETVAL_STRING(ostr);
1949 }
1950
1951 /* free */
1952 if (ostr_free) {
1953 efree(ostr);
1954 }
1955 }
1956 /* }}} mecab_nbest_sparse_tostr */
1957
1958 /* {{{ proto bool mecab_nbest_init(resource mecab mecab, string str[, int len]) */
1959 /**
1960 * bool mecab_nbest_init(resource mecab mecab, string str[, int len])
1961 * bool MeCab_Tagger::parseNBestInit(string str[, int len])
1962 *
1963 * Initialize the N-Best list.
1964 *
1965 * @param resource mecab $mecab The tagger resource of MeCab.
1966 * @param string $str The parse target.
1967 * @param int $len The maximum length that can be analyzed. (optional)
1968 * @return bool True if succeeded to initilalize, otherwise returns false.
1969 */
PHP_FUNCTION(mecab_nbest_init)1970 static PHP_FUNCTION(mecab_nbest_init)
1971 {
1972 /* declaration of the resources */
1973 php_mecab *xmecab = NULL;
1974 mecab_t *mecab = NULL;
1975
1976 /* declaration of the arguments */
1977 zend_string *str = NULL;
1978 long len = 0;
1979
1980 /* declaration of the local variables */
1981 size_t ilen = 0;
1982 int result = 0;
1983
1984 /* parse the arguments */
1985 PHP_MECAB_PARSE_PARAMETERS("S|l", &str, &len);
1986
1987 /* call mecab_nbest_init() */
1988 php_mecab_set_string(xmecab, str TSRMLS_CC);
1989 ilen = (size_t)((len > 0) ? MIN(len, (long)ZSTR_LEN(str)) : ZSTR_LEN(str));
1990 result = mecab_nbest_init2(mecab, ZSTR_VAL(xmecab->str), ilen);
1991 if (result == 0) {
1992 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", mecab_strerror(mecab));
1993 RETURN_FALSE;
1994 }
1995 RETURN_TRUE;
1996 }
1997 /* }}} mecab_nbest_init */
1998
1999 /* {{{ proto string mecab_nbest_next_tostr(resource mecab mecab[, int olen]) */
2000 /**
2001 * string mecab_nbest_next_tostr(resource mecab mecab[, int olen])
2002 * string MeCab_Tagger::next([int olen]])
2003 *
2004 * Get the next result of N-Best as a string.
2005 *
2006 * @param resource mecab $mecab The tagger resource of MeCab.
2007 * @param int $olen The maximum length of the output. (optional)
2008 * @return string The parse result of the next pointer.
2009 * If there are no more results, returns false.
2010 * Also returns false if output buffer has overflowed.
2011 */
PHP_FUNCTION(mecab_nbest_next_tostr)2012 static PHP_FUNCTION(mecab_nbest_next_tostr)
2013 {
2014 /* declaration of the resources */
2015 php_mecab *xmecab = NULL;
2016 mecab_t *mecab = NULL;
2017
2018 /* declaration of the arguments */
2019 long olen = 0;
2020
2021 /* declaration of the local variables */
2022 char *ostr = NULL;
2023 zend_bool ostr_free = 0;
2024 const char *what = NULL;
2025
2026 /* parse the arguments */
2027 PHP_MECAB_PARSE_PARAMETERS("|l", &olen);
2028
2029 /* call mecab_nbest_sparse_tostr() */
2030 if (olen == 0) {
2031 ostr = (char *)mecab_nbest_next_tostr(mecab);
2032 } else {
2033 ostr = (char *)emalloc(olen + 1);
2034 ostr = mecab_nbest_next_tostr2(mecab, ostr, (size_t)olen);
2035 ostr_free = 1;
2036 }
2037
2038 /* set return value */
2039 if (ostr == NULL) {
2040 if ((what = mecab_strerror(mecab)) != NULL &&
2041 strcmp((char *)what, "no more results"))
2042 {
2043 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", what);
2044 }
2045 RETVAL_FALSE;
2046 } else {
2047 RETVAL_STRING(ostr);
2048 }
2049
2050 /* free */
2051 if (ostr_free) {
2052 efree(ostr);
2053 }
2054 }
2055 /* }}} mecab_nbest_next_tostr */
2056
2057 /* {{{ proto resource mecab_node mecab_nbest_next_tonode(resource mecab mecab) */
2058 /**
2059 * resource mecab_node mecab_nbest_next_tonode(resource mecab mecab)
2060 * object MeCab_Node MeCab_Tagger::nextNode(void)
2061 *
2062 * Get the next result of N-Best as a node.
2063 *
2064 * @param resource mecab $mecab The tagger resource of MeCab.
2065 * @return resource mecab_node The result node of the next pointer.
2066 * If there are no more results, returns false.
2067 */
PHP_FUNCTION(mecab_nbest_next_tonode)2068 static PHP_FUNCTION(mecab_nbest_next_tonode)
2069 {
2070 /* declaration of the resources */
2071 php_mecab *xmecab = NULL;
2072 mecab_t *mecab = NULL;
2073
2074 /* declaration of the local variables */
2075 const mecab_node_t *node = NULL;
2076 php_mecab_node *xnode = NULL;
2077 const char *what = NULL;
2078
2079 /* parse the arguments */
2080 PHP_MECAB_FROM_PARAMETER();
2081
2082 /* call mecab_nbest_next_tonode() */
2083 node = mecab_nbest_next_tonode(mecab);
2084 if (node == NULL) {
2085 if ((what = mecab_strerror(mecab)) != NULL &&
2086 strcmp((char *)what, "no more results"))
2087 {
2088 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", what);
2089 }
2090 RETURN_FALSE;
2091 }
2092
2093 /* set return value */
2094 {
2095 php_mecab_node_object *newobj;
2096 object_init_ex(return_value, ce_MeCab_Node);
2097 newobj = PHP_MECAB_NODE_OBJECT_P(return_value);
2098 xnode = newobj->ptr;
2099 }
2100 xnode->ptr = node;
2101 php_mecab_node_set_tagger(xnode, xmecab TSRMLS_CC);
2102 }
2103 /* }}} mecab_nbest_next_tonode */
2104
2105 /* {{{ proto string mecab_format_node(resource mecab mecab, resource mecab_node node) */
2106 /**
2107 * string mecab_format_node(resource mecab mecab, resource mecab_node node)
2108 * string MeCab_Tagger::formatNode(object MeCab_Node node)
2109 *
2110 * Format a node to string.
2111 * The format is specified by "-O" option or --{node|unk|bos|eos}-format=STR.
2112 * The detail is found in the web site and/or the manpage of MeCab.
2113 * NOTICE: If the option was "wakati" or "dump", the return string will be empty.
2114 *
2115 * @param resource mecab $mecab The tagger resource of MeCab.
2116 * @param resource mecab_node $node The node of the source string.
2117 * @return string The formatted string.
2118 * @see mecab_node_tostring
2119 */
PHP_FUNCTION(mecab_format_node)2120 static PHP_FUNCTION(mecab_format_node)
2121 {
2122 /* declaration of the resources */
2123 zval *node_object = NULL;
2124 php_mecab *xmecab = NULL;
2125 php_mecab_node *xnode = NULL;
2126 mecab_t *mecab = NULL;
2127 const mecab_node_t *node = NULL;
2128
2129 /* declaration of the local variables */
2130 const char *fmt = NULL;
2131
2132 /* parse the arguments */
2133 {
2134 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &node_object, ce_MeCab_Node) == FAILURE) {
2135 return;
2136 } else {
2137 const php_mecab_object *intern = PHP_MECAB_OBJECT_P(getThis());
2138 const php_mecab_node_object *intern_node = PHP_MECAB_NODE_OBJECT_P(node_object);
2139 xmecab = intern->ptr;
2140 xnode = intern_node->ptr;
2141 }
2142 }
2143 mecab = xmecab->ptr;
2144 node = xnode->ptr;
2145
2146 /* call mecab_format_node() */
2147 fmt = mecab_format_node(mecab, node);
2148 if (fmt == NULL) {
2149 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", mecab_strerror(mecab));
2150 RETURN_FALSE;
2151 }
2152
2153 /* set return value */
2154 RETURN_STRING((char *)fmt);
2155 }
2156 /* }}} mecab_format_node */
2157
2158 /* {{{ proto array mecab_dictionary_info(resource mecab mecab) */
2159 /**
2160 * array mecab_dictionary_info(resource mecab mecab)
2161 * array MeCab_Tagger::dictionaryInfo(void)
2162 *
2163 * Get the information of using dictionary as an associative array.
2164 *
2165 * @return array The information of the dictionary.
2166 */
PHP_FUNCTION(mecab_dictionary_info)2167 static PHP_FUNCTION(mecab_dictionary_info)
2168 {
2169 /* declaration of the resources */
2170 php_mecab *xmecab = NULL;
2171 mecab_t *mecab = NULL;
2172
2173 /* declaration of the local variables */
2174 const mecab_dictionary_info_t *dicinfo = NULL;
2175
2176 /* parse the arguments */
2177 PHP_MECAB_FROM_PARAMETER();
2178 /* get dictionary information */
2179 dicinfo = mecab_dictionary_info(mecab);
2180 if (dicinfo == NULL) {
2181 RETURN_NULL();
2182 }
2183
2184 /* initialize */
2185 array_init(return_value);
2186
2187 /* get information for each dictionary */
2188 while (dicinfo != NULL) {
2189 zval tmp;
2190 array_init(&tmp);
2191
2192 add_assoc_string(&tmp, "filename", (char *)dicinfo->filename);
2193 add_assoc_string(&tmp, "charset", (char *)dicinfo->charset);
2194 add_assoc_long(&tmp, "size", (long)dicinfo->size);
2195 add_assoc_long(&tmp, "type", (long)dicinfo->type);
2196 add_assoc_long(&tmp, "lsize", (long)dicinfo->lsize);
2197 add_assoc_long(&tmp, "rsize", (long)dicinfo->rsize);
2198 add_assoc_long(&tmp, "version", (long)dicinfo->version);
2199
2200 add_next_index_zval(return_value, &tmp);
2201
2202 dicinfo = dicinfo->next;
2203 }
2204 }
2205 /* }}} mecab_dictionary_info */
2206
2207 /* {{{ proto array mecab_node_toarray(resource mecab_node node[, bool dump_all]) */
2208 /**
2209 * array mecab_node_toarray(resource mecab_node node[, bool dump_all])
2210 * array MeCab_Node::toArray([bool dump_all])
2211 *
2212 * Get all elements of the node as an associative array.
2213 *
2214 * @param resource mecab_node $node The node of the source string.
2215 * @param bool $dump_all Whether dump all related nodes and paths or not.
2216 * @return array All elements of the node.
2217 */
PHP_FUNCTION(mecab_node_toarray)2218 static PHP_FUNCTION(mecab_node_toarray)
2219 {
2220 /* declaration of the resources */
2221 zval *object = getThis();
2222 php_mecab_node *xnode = NULL;
2223 const mecab_node_t *node = NULL;
2224
2225 /* declaration of the arguments */
2226 zend_bool dump_all = 0;
2227
2228 /* parse the arguments */
2229 PHP_MECAB_NODE_PARSE_PARAMETERS("|b", &dump_all);
2230 node = xnode->ptr;
2231
2232 /* initialize */
2233 array_init(return_value);
2234
2235 /* assign siblings and paths */
2236 if (dump_all) {
2237 add_assoc_zval(return_value, "prev", php_mecab_node_get_sibling(NULL, object, xnode, NODE_PREV TSRMLS_CC));
2238 add_assoc_zval(return_value, "next", php_mecab_node_get_sibling(NULL, object, xnode, NODE_NEXT TSRMLS_CC));
2239 add_assoc_zval(return_value, "enext", php_mecab_node_get_sibling(NULL, object, xnode, NODE_ENEXT TSRMLS_CC));
2240 add_assoc_zval(return_value, "bnext", php_mecab_node_get_sibling(NULL, object, xnode, NODE_BNEXT TSRMLS_CC));
2241 add_assoc_zval(return_value, "rpath", php_mecab_node_get_path(NULL, object, xnode, NODE_RPATH TSRMLS_CC));
2242 add_assoc_zval(return_value, "lpath", php_mecab_node_get_path(NULL, object, xnode, NODE_LPATH TSRMLS_CC));
2243 }
2244
2245 /* assign node info */
2246 add_assoc_stringl(return_value, "surface", (char *)node->surface, (int)node->length);
2247 add_assoc_stringl(return_value, "feature", (char *)node->feature, (int)strlen(node->feature));
2248 add_assoc_long(return_value, "id", (long)node->id);
2249 add_assoc_long(return_value, "length", (long)node->length);
2250 add_assoc_long(return_value, "rlength", (long)node->rlength);
2251 add_assoc_long(return_value, "rcAttr", (long)node->rcAttr);
2252 add_assoc_long(return_value, "lcAttr", (long)node->lcAttr);
2253 add_assoc_long(return_value, "posid", (long)node->posid);
2254 add_assoc_long(return_value, "char_type", (long)node->char_type);
2255 add_assoc_long(return_value, "stat", (long)node->stat);
2256 add_assoc_bool(return_value, "isbest", (long)node->isbest);
2257 add_assoc_double(return_value, "alpha", (double)node->alpha);
2258 add_assoc_double(return_value, "beta", (double)node->beta);
2259 add_assoc_double(return_value, "prob", (double)node->prob);
2260 add_assoc_long(return_value, "wcost", (long)node->wcost);
2261 add_assoc_long(return_value, "cost", (long)node->cost);
2262 }
2263 /* }}} mecab_node_toarray */
2264
2265 /* {{{ proto string mecab_node_tostring(resource mecab_node node) */
2266 /**
2267 * string mecab_node_tostring(resource mecab_node node)
2268 * string MeCab_Node::toString(void)
2269 * string MeCab_Node::__toString(void)
2270 *
2271 * Get the formatted string of the node.
2272 *
2273 * @param resource mecab_node $node The node of the source string.
2274 * @return string The formatted string.
2275 * @see mecab_format_node
2276 */
PHP_FUNCTION(mecab_node_tostring)2277 static PHP_FUNCTION(mecab_node_tostring)
2278 {
2279 /* declaration of the resources */
2280 php_mecab_node *xnode = NULL;
2281 const mecab_node_t *node = NULL;
2282
2283 /* local variables */
2284 mecab_t *mecab = NULL;
2285 const char *fmt = NULL;
2286
2287 /* parse the arguments */
2288 PHP_MECAB_NODE_FROM_PARAMETER();
2289
2290 /* call mecab_format_node() */
2291 mecab = xnode->tagger->ptr;
2292 fmt = mecab_format_node(mecab, node);
2293 if (fmt == NULL) {
2294 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", mecab_strerror(mecab));
2295 RETURN_FALSE;
2296 }
2297
2298 /* set return value */
2299 RETURN_STRING((char *)fmt);
2300 }
2301 /* }}} mecab_node_tostring */
2302
2303 /* {{{ proto resource mecab_node mecab_node_prev(resource mecab_node node) */
2304 /**
2305 * resource mecab_node mecab_node_prev(resource mecab_node node)
2306 * object MeCab_Node MeCab_Node::getPrev(void)
2307 *
2308 * Get the previous node.
2309 *
2310 * @param resource mecab_node $node The node of the source string.
2311 * @return resource mecab_node The previous node.
2312 * If the given node is the first one, returns FALSE.
2313 */
PHP_FUNCTION(mecab_node_prev)2314 static PHP_FUNCTION(mecab_node_prev)
2315 {
2316 php_mecab_node_get_sibling_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, NODE_PREV);
2317 }
2318 /* }}} mecab_node_prev */
2319
2320 /* {{{ proto resource mecab_node mecab_node_next(resource mecab_node node) */
2321 /**
2322 * resource mecab_node mecab_node_next(resource mecab_node node)
2323 * object MeCab_Node MeCab_Node::getNext(void)
2324 *
2325 * Get the next node.
2326 *
2327 * @param resource mecab_node $node The node of the source string.
2328 * @return resource mecab_node The next node.
2329 * If the given node is the last one, returns FALSE.
2330 */
PHP_FUNCTION(mecab_node_next)2331 static PHP_FUNCTION(mecab_node_next)
2332 {
2333 php_mecab_node_get_sibling_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, NODE_NEXT);
2334 }
2335 /* }}} mecab_node_next */
2336
2337 /* {{{ proto resource mecab_node mecab_node_enext(resource mecab_node node) */
2338 /**
2339 * resource mecab_node mecab_node_enext(resource mecab_node node)
2340 * object MeCab_Node MeCab_Node::getENext(void)
2341 *
2342 * Get the enext node.
2343 *
2344 * @param resource mecab_node $node The node of the source string.
2345 * @return resource mecab_node The next node which has same end point as the given node.
2346 * If there is no `enext' node, returns false.
2347 */
PHP_FUNCTION(mecab_node_enext)2348 static PHP_FUNCTION(mecab_node_enext)
2349 {
2350 php_mecab_node_get_sibling_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, NODE_ENEXT);
2351 }
2352 /* }}} mecab_node_enext */
2353
2354 /* {{{ proto resource mecab_node mecab_node_bnext(resource mecab_node node) */
2355 /**
2356 * resource mecab_node mecab_node_bnext(resource mecab_node node)
2357 * object MeCab_Node MeCab_Node::getBNext(void)
2358 *
2359 * Get the bnext node.
2360 *
2361 * @param resource mecab_node $node The node of the source string.
2362 * @return resource mecab_node The next node which has same beggining point as the given one.
2363 * If there is no `bnext' node, returns false.
2364 */
PHP_FUNCTION(mecab_node_bnext)2365 static PHP_FUNCTION(mecab_node_bnext)
2366 {
2367 php_mecab_node_get_sibling_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, NODE_BNEXT);
2368 }
2369 /* }}} mecab_node_bnext */
2370
2371 /* {{{ proto resource mecab_path mecab_node_rpath(resource mecab_node node) */
2372 /**
2373 * resource mecab_path mecab_node_rpath(resource mecab_node node)
2374 * object MeCab_Path MeCab_Node::getRPath(void)
2375 *
2376 * Get the rpath.
2377 *
2378 * @param resource mecab_node $node The node of the source string.
2379 * @return resource mecab_path The next node which has same end point as the given node.
2380 * If there is no `rpath' node, returns false.
2381 */
PHP_FUNCTION(mecab_node_rpath)2382 static PHP_FUNCTION(mecab_node_rpath)
2383 {
2384 php_mecab_node_get_path_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, NODE_RPATH);
2385 }
2386 /* }}} mecab_node_rpath */
2387
2388 /* {{{ proto resource mecab_path mecab_node_lpath(resource mecab_node node) */
2389 /**
2390 * resource mecab_path mecab_node_lpath(resource mecab_node node)
2391 * object MeCab_Path MeCab_Node::getLPath(void)
2392 *
2393 * Get the lpath.
2394 *
2395 * @param resource mecab_node $node The node of the source string.
2396 * @return resource mecab_path The next node which has same beggining point as the given one.
2397 * If there is no `lpath' node, returns false.
2398 */
PHP_FUNCTION(mecab_node_lpath)2399 static PHP_FUNCTION(mecab_node_lpath)
2400 {
2401 php_mecab_node_get_path_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, NODE_LPATH);
2402 }
2403 /* }}} mecab_node_lpath */
2404
2405 /* {{{ proto string mecab_node_surface(resource mecab_node node) */
2406 /**
2407 * string mecab_node_surface(resource mecab_node node)
2408 * string MeCab_Node::getSurface(void)
2409 *
2410 * Get the surface.
2411 *
2412 * @param resource mecab_node $node The node of the source string.
2413 * @return string The surface of the node.
2414 */
PHP_FUNCTION(mecab_node_surface)2415 static PHP_FUNCTION(mecab_node_surface)
2416 {
2417 PHP_MECAB_NODE_RETURN_PROPERTY(STRINGL, (char *)node->surface, (int)node->length);
2418 }
2419 /* }}} mecab_node_surface */
2420
2421 /* {{{ proto string mecab_node_feature(resource mecab_node node) */
2422 /**
2423 * string mecab_node_feature(resource mecab_node node)
2424 * string MeCab_Node::getFeature(void)
2425 *
2426 * Get the feature.
2427 *
2428 * @param resource mecab_node $node The node of the source string.
2429 * @return string The feature of the node.
2430 */
PHP_FUNCTION(mecab_node_feature)2431 static PHP_FUNCTION(mecab_node_feature)
2432 {
2433 PHP_MECAB_NODE_RETURN_PROPERTY(STRING, (char *)node->feature);
2434 }
2435 /* }}} mecab_node_feature */
2436
2437 /* {{{ proto int mecab_node_id(resource mecab_node node) */
2438 /**
2439 * int mecab_node_id(resource mecab_node node)
2440 * int MeCab_Node::getId(void)
2441 *
2442 * Get the ID.
2443 *
2444 * @param resource mecab_node $node The node of the source string.
2445 * @return int The ID of the node.
2446 */
PHP_FUNCTION(mecab_node_id)2447 static PHP_FUNCTION(mecab_node_id)
2448 {
2449 PHP_MECAB_NODE_RETURN_PROPERTY(LONG, (long)node->id);
2450 }
2451 /* }}} mecab_node_id */
2452
2453 /* {{{ proto int mecab_node_length(resource mecab_node node) */
2454 /**
2455 * int mecab_node_length(resource mecab_node node)
2456 * int MeCab_Node::getLength(void)
2457 *
2458 * Get the length of the surface.
2459 *
2460 * @param resource mecab_node $node The node of the source string.
2461 * @return int The length of the surface of the node.
2462 */
PHP_FUNCTION(mecab_node_length)2463 static PHP_FUNCTION(mecab_node_length)
2464 {
2465 PHP_MECAB_NODE_RETURN_PROPERTY(LONG, (long)node->length);
2466 }
2467 /* }}} mecab_node_length */
2468
2469 /* {{{ proto int mecab_node_rlength(resource mecab_node node) */
2470 /**
2471 * int mecab_node_rlength(resource mecab_node node)
2472 * int MeCab_Node::getRLength(void)
2473 *
2474 * Get the length of the surface and its leading whitespace.
2475 *
2476 * @param resource mecab_node $node The node of the source string.
2477 * @return int The length of the surface and its leading whitespace of the node.
2478 */
PHP_FUNCTION(mecab_node_rlength)2479 static PHP_FUNCTION(mecab_node_rlength)
2480 {
2481 PHP_MECAB_NODE_RETURN_PROPERTY(LONG, (long)node->rlength);
2482 }
2483 /* }}} mecab_node_rlength */
2484
2485 /* {{{ proto int mecab_node_rcattr(resource mecab_node node) */
2486 /**
2487 * int mecab_node_rcattr(resource mecab_node node)
2488 * int MeCab_Node::getRcAttr(void)
2489 *
2490 * Get the ID of the right context.
2491 *
2492 * @param resource mecab_node $node The node of the source string.
2493 * @return int The ID of the right context.
2494 */
PHP_FUNCTION(mecab_node_rcattr)2495 static PHP_FUNCTION(mecab_node_rcattr)
2496 {
2497 PHP_MECAB_NODE_RETURN_PROPERTY(LONG, (long)node->rcAttr);
2498 }
2499 /* }}} mecab_node_rcattr */
2500
2501 /* {{{ proto int mecab_node_lcattr(resource mecab_node node) */
2502 /**
2503 * int mecab_node_lcattr(resource mecab_node node)
2504 * int MeCab_Node::getLcAttr(void)
2505 *
2506 * Get the ID of the left context.
2507 *
2508 * @param resource mecab_node $node The node of the source string.
2509 * @return int The ID of the left context.
2510 */
PHP_FUNCTION(mecab_node_lcattr)2511 static PHP_FUNCTION(mecab_node_lcattr)
2512 {
2513 PHP_MECAB_NODE_RETURN_PROPERTY(LONG, (long)node->lcAttr);
2514 }
2515 /* }}} mecab_node_lcattr */
2516
2517 /* {{{ proto int mecab_node_posid(resource mecab_node node) */
2518 /**
2519 * int mecab_node_posid(resource mecab_node node)
2520 * int MeCab_Node::getPosId(void)
2521 *
2522 * Get the ID of the Part-of-Speech.
2523 * (node->posid is not used in MeCab-0.90)
2524 *
2525 * @param resource mecab_node $node The node of the source string.
2526 * @return int The ID of the Part-of-Speech.
2527 * Currently, always returns 0.
2528 */
PHP_FUNCTION(mecab_node_posid)2529 static PHP_FUNCTION(mecab_node_posid)
2530 {
2531 PHP_MECAB_NODE_RETURN_PROPERTY(LONG, (long)node->posid);
2532 }
2533 /* }}} mecab_node_posid */
2534
2535 /* {{{ proto int mecab_node_char_type(resource mecab_node node) */
2536 /**
2537 * int mecab_node_char_type(resource mecab_node node)
2538 * int MeCab_Node::getCharType(void)
2539 *
2540 * Get the type of the character.
2541 *
2542 * @param resource mecab_node $node The node of the source string.
2543 * @return int The type of the character.
2544 */
PHP_FUNCTION(mecab_node_char_type)2545 static PHP_FUNCTION(mecab_node_char_type)
2546 {
2547 PHP_MECAB_NODE_RETURN_PROPERTY(LONG, (long)node->char_type);
2548 }
2549 /* }}} mecab_node_char_type */
2550
2551 /* {{{ proto int mecab_node_stat(resource mecab_node node) */
2552 /**
2553 * int mecab_node_stat(resource mecab_node node)
2554 * int MeCab_Node::getStat(void)
2555 *
2556 * Get the status.
2557 *
2558 * @param resource mecab_node $node The node of the source string.
2559 * @return int The status of the node.
2560 * The return value is one of the following:
2561 * MECAB_NOR_NODE (0:Normal)
2562 * MECAB_UNK_NODE (1:Unknown)
2563 * MECAB_BOS_NODE (2:Beginning-of-Sentence)
2564 * MECAB_EOS_NODE (3:End-of-Sentence)
2565 */
PHP_FUNCTION(mecab_node_stat)2566 static PHP_FUNCTION(mecab_node_stat)
2567 {
2568 PHP_MECAB_NODE_RETURN_PROPERTY(LONG, (long)node->stat);
2569 }
2570 /* }}} mecab_node_stat */
2571
2572 /* {{{ proto bool mecab_node_isbest(resource mecab_node node) */
2573 /**
2574 * bool mecab_node_isbest(resource mecab_node node)
2575 * bool MeCab_Node::isBest(void)
2576 *
2577 * Determine whether the node is the best solution.
2578 *
2579 * @param resource mecab_node $node The node of the source string.
2580 * @return bool True if the node is the best, otherwise returns false.
2581 */
PHP_FUNCTION(mecab_node_isbest)2582 static PHP_FUNCTION(mecab_node_isbest)
2583 {
2584 PHP_MECAB_NODE_RETURN_PROPERTY(BOOL, (node->isbest == 1));
2585 }
2586 /* }}} mecab_node_isbest */
2587
2588 /* {{{ proto double mecab_node_alpha(resource mecab_node node) */
2589 /**
2590 * double mecab_node_alpha(resource mecab_node node)
2591 * double MeCab_Node::getAlpha(void)
2592 *
2593 * Get the forward log probability.
2594 *
2595 * @param resource mecab_node $node The node of the source string.
2596 * @return double The forward log probability of the node.
2597 */
PHP_FUNCTION(mecab_node_alpha)2598 static PHP_FUNCTION(mecab_node_alpha)
2599 {
2600 PHP_MECAB_NODE_RETURN_PROPERTY(DOUBLE, (double)node->alpha);
2601 }
2602 /* }}} mecab_node_alpha */
2603
2604 /* {{{ proto double mecab_node_beta(resource mecab_node node) */
2605 /**
2606 * double mecab_node_beta(resource mecab_node node)
2607 * double MeCab_Node::getBeta(void)
2608 *
2609 * Get the backward log probability.
2610 *
2611 * @param resource mecab_node $node The node of the source string.
2612 * @return double The backward log probability of the node.
2613 */
PHP_FUNCTION(mecab_node_beta)2614 static PHP_FUNCTION(mecab_node_beta)
2615 {
2616 PHP_MECAB_NODE_RETURN_PROPERTY(DOUBLE, (double)node->beta);
2617 }
2618 /* }}} mecab_node_beta */
2619
2620 /* {{{ proto double mecab_node_prob(resource mecab_node node) */
2621 /**
2622 * double mecab_node_prob(resource mecab_node node)
2623 * double MeCab_Node::getProb(void)
2624 *
2625 * Get the marginal probability.
2626 *
2627 * @param resource mecab_node $node The node of the source string.
2628 * @return double The marginal probability of the node.
2629 */
PHP_FUNCTION(mecab_node_prob)2630 static PHP_FUNCTION(mecab_node_prob)
2631 {
2632 PHP_MECAB_NODE_RETURN_PROPERTY(DOUBLE, (double)node->prob);
2633 }
2634 /* }}} mecab_node_prob */
2635
2636 /* {{{ proto int mecab_node_wcost(resource mecab_node node) */
2637 /**
2638 * int mecab_node_wcost(resource mecab_node node)
2639 * int MeCab_Node::getWCost(void)
2640 *
2641 * Get the word arising cost.
2642 *
2643 * @param resource mecab_node $node The node of the source string.
2644 * @return int The word arising cost of the node.
2645 */
PHP_FUNCTION(mecab_node_wcost)2646 static PHP_FUNCTION(mecab_node_wcost)
2647 {
2648 PHP_MECAB_NODE_RETURN_PROPERTY(LONG, (long)node->wcost);
2649 }
2650 /* }}} mecab_node_wcost */
2651
2652 /* {{{ proto int mecab_node_cost(resource mecab_node node) */
2653 /**
2654 * int mecab_node_cost(resource mecab_node node)
2655 * int MeCab_Node::getCost(void)
2656 *
2657 * Get the cumulative cost.
2658 *
2659 * @param resource mecab_node $node The node of the source string.
2660 * @return int The cumulative cost of the node.
2661 */
PHP_FUNCTION(mecab_node_cost)2662 static PHP_FUNCTION(mecab_node_cost)
2663 {
2664 PHP_MECAB_NODE_RETURN_PROPERTY(LONG, (long)node->cost);
2665 }
2666 /* }}} mecab_node_cost */
2667
2668 /* {{{ proto resource mecab_path mecab_path_rnext(resource mecab_path path) */
2669 /**
2670 * resource mecab_path mecab_path_rnext(resource mecab_path path)
2671 * object MeCab_Path MeCab_Path::getRNext(void)
2672 *
2673 * Get the rnext path.
2674 *
2675 * @param resource mecab_path $path The path of the source string.
2676 * @return resource mecab_path The rnext path.
2677 * If the given path is the first one, returns FALSE.
2678 */
PHP_FUNCTION(mecab_path_rnext)2679 static PHP_FUNCTION(mecab_path_rnext)
2680 {
2681 php_mecab_path_get_sibling_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PATH_RNEXT);
2682 }
2683 /* }}} mecab_path_rnext */
2684
2685 /* {{{ proto resource mecab_path mecab_path_lnext(resource mecab_path path) */
2686 /**
2687 * resource mecab_path mecab_path_lnext(resource mecab_path path)
2688 * object MeCab_Path MeCab_Path::getLNext(void)
2689 *
2690 * Get the lnext path.
2691 *
2692 * @param resource mecab_path $path The path of the source string.
2693 * @return resource mecab_path The lnext path.
2694 * If the given path is the last one, returns FALSE.
2695 */
PHP_FUNCTION(mecab_path_lnext)2696 static PHP_FUNCTION(mecab_path_lnext)
2697 {
2698 php_mecab_path_get_sibling_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PATH_LNEXT);
2699 }
2700 /* }}} mecab_path_lnext */
2701
2702 /* {{{ proto resource mecab_node mecab_path_rnode(resource mecab_path path) */
2703 /**
2704 * resource mecab_node mecab_path_rnode(resource mecab_path path)
2705 * object MeCab_Node MeCab_Path::getRNode(void)
2706 *
2707 * Get the rnode.
2708 *
2709 * @param resource mecab_path $path The path of the source string.
2710 * @return resource mecab_node The next path which has same end point as the given path.
2711 * If there is no `rnode' path, returns false.
2712 */
PHP_FUNCTION(mecab_path_rnode)2713 static PHP_FUNCTION(mecab_path_rnode)
2714 {
2715 php_mecab_path_get_node_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PATH_RNODE);
2716 }
2717 /* }}} mecab_path_rnode */
2718
2719 /* {{{ proto resource mecab_node mecab_path_lnode(resource mecab_path path) */
2720 /**
2721 * resource mecab_node mecab_path_lnode(resource mecab_path path)
2722 * object MeCab_Node MeCab_Path::getLNode(void)
2723 *
2724 * Get the lnode.
2725 *
2726 * @param resource mecab_path $path The path of the source string.
2727 * @return resource mecab_node The next path which has same beggining point as the given one.
2728 * If there is no `lnode' path, returns false.
2729 */
PHP_FUNCTION(mecab_path_lnode)2730 static PHP_FUNCTION(mecab_path_lnode)
2731 {
2732 php_mecab_path_get_node_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, PATH_LNODE);
2733 }
2734 /* }}} mecab_path_lnode */
2735
2736 /* {{{ proto double mecab_path_prob(resource mecab_path path) */
2737 /**
2738 * double mecab_path_prob(resource mecab_path path)
2739 * double MeCab_Path::getProb(void)
2740 *
2741 * Get the marginal probability.
2742 *
2743 * @param resource mecab_path $path The path of the source string.
2744 * @return double The marginal probability of the path.
2745 */
PHP_FUNCTION(mecab_path_prob)2746 static PHP_FUNCTION(mecab_path_prob)
2747 {
2748 PHP_MECAB_PATH_RETURN_PROPERTY(DOUBLE, (double)(path->prob));
2749 }
2750 /* }}} mecab_path_prob */
2751
2752 /* {{{ proto int mecab_path_cost(resource mecab_path path) */
2753 /**
2754 * int mecab_path_cost(resource mecab_path path)
2755 * int MeCab_Path::getCost(void)
2756 *
2757 * Get the cumulative cost.
2758 *
2759 * @param resource mecab_path $path The path of the source string.
2760 * @return int The cumulative cost of the path.
2761 */
PHP_FUNCTION(mecab_path_cost)2762 static PHP_FUNCTION(mecab_path_cost)
2763 {
2764 PHP_MECAB_PATH_RETURN_PROPERTY(LONG, (long)(path->cost));
2765 }
2766 /* }}} mecab_node_cost */
2767
2768 /* }}} Functions */
2769
2770 /* {{{ methods */
2771
2772 /* {{{ methods of class MeCab_Node*/
2773
2774 /* {{{ proto object MeCab_Node __construct(void) */
2775 /**
2776 * object MeCab_Node MeCab_Node::__construct(void)
2777 *
2778 * Create MeCab_Node object.
2779 *
2780 * @access private
2781 * @igore
2782 */
PHP_METHOD(MeCab_Node,__construct)2783 static PHP_METHOD(MeCab_Node, __construct)
2784 {
2785 return;
2786 }
2787 /* }}} MeCab_Node::__construct */
2788
2789 /* {{{ proto mixed MeCab_Node::__get(string name) */
2790 /**
2791 * mixed MeCab_Node::__get(string name)
2792 *
2793 * [Overloading implementation]
2794 * A magick getter.
2795 *
2796 * @param string $name The name of property.
2797 * @return mixed The value of the property.
2798 * If there is not a named property, causes E_NOTICE error and returns false.
2799 * @access public
2800 * @ignore
2801 */
PHP_METHOD(MeCab_Node,__get)2802 static PHP_METHOD(MeCab_Node, __get)
2803 {
2804 /* declaration of the resources */
2805 zval *object = getThis();
2806 php_mecab_node *xnode = NULL;
2807 const mecab_node_t *node = NULL;
2808
2809 /* declaration of the arguments */
2810 zend_string *zname = NULL;
2811 const char *name = NULL;
2812
2813 /* parse the arguments */
2814 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "S", &zname) == FAILURE) {
2815 return;
2816 } else {
2817 const php_mecab_node_object *intern = PHP_MECAB_NODE_OBJECT_P(object);
2818 xnode = intern->ptr;
2819 node = xnode->ptr;
2820 name = ZSTR_VAL(zname);
2821 }
2822
2823 /* check for given property name */
2824 if (!strcmp(name, "prev")) {
2825 php_mecab_node_get_sibling(return_value, object, xnode, NODE_PREV TSRMLS_CC);
2826 return;
2827 }
2828 if (!strcmp(name, "next")) {
2829 php_mecab_node_get_sibling(return_value, object, xnode, NODE_NEXT TSRMLS_CC);
2830 return;
2831 }
2832 if (!strcmp(name, "enext")) {
2833 php_mecab_node_get_sibling(return_value, object, xnode, NODE_ENEXT TSRMLS_CC);
2834 return;
2835 }
2836 if (!strcmp(name, "bnext")) {
2837 php_mecab_node_get_sibling(return_value, object, xnode, NODE_BNEXT TSRMLS_CC);
2838 return;
2839 }
2840 if (!strcmp(name, "rpath")) {
2841 php_mecab_node_get_path(return_value, object, xnode, NODE_RPATH TSRMLS_CC);
2842 return;
2843 }
2844 if (!strcmp(name, "lpath")) {
2845 php_mecab_node_get_path(return_value, object, xnode, NODE_LPATH TSRMLS_CC);
2846 return;
2847 }
2848 if (!strcmp(name, "surface")) RETURN_STRINGL((char *)node->surface, (int)node->length);
2849 if (!strcmp(name, "feature")) RETURN_STRING((char *)node->feature);
2850 if (!strcmp(name, "id")) RETURN_LONG((long)node->id);
2851 if (!strcmp(name, "length")) RETURN_LONG((long)node->length);
2852 if (!strcmp(name, "rlength")) RETURN_LONG((long)node->rlength);
2853 if (!strcmp(name, "rcAttr")) RETURN_LONG((long)node->rcAttr);
2854 if (!strcmp(name, "lcAttr")) RETURN_LONG((long)node->lcAttr);
2855 if (!strcmp(name, "posid")) RETURN_LONG((long)node->posid);
2856 if (!strcmp(name, "char_type")) RETURN_LONG((long)node->char_type);
2857 if (!strcmp(name, "stat")) RETURN_LONG((long)node->stat);
2858 if (!strcmp(name, "isbest")) RETURN_BOOL((long)node->isbest);
2859 if (!strcmp(name, "alpha")) RETURN_DOUBLE((double)node->alpha);
2860 if (!strcmp(name, "beta")) RETURN_DOUBLE((double)node->beta);
2861 if (!strcmp(name, "prob")) RETURN_DOUBLE((double)node->prob);
2862 if (!strcmp(name, "wcost")) RETURN_LONG((long)node->wcost);
2863 if (!strcmp(name, "cost")) RETURN_LONG((long)node->cost);
2864
2865 /* when going to fetch undefined property */
2866 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Undefined property (%s)", name);
2867 RETURN_NULL();
2868 }
2869 /* }}} MeCab_Node::__get */
2870
2871 /* {{{ proto bool MeCab_Node::__isset(string name) */
2872 /**
2873 * bool MeCab_Node::__isset(string name)
2874 *
2875 * [Overloading implementation]
2876 * Determine whether there is a named property.
2877 *
2878 * @param string $name The name of property.
2879 * @return bool True if there is a named property, otherwise returns false.
2880 * @access public
2881 * @ignore
2882 */
PHP_METHOD(MeCab_Node,__isset)2883 static PHP_METHOD(MeCab_Node, __isset)
2884 {
2885 /* declaration of the resources */
2886 php_mecab_node *xnode = NULL;
2887 const mecab_node_t *node = NULL;
2888
2889 /* declaration of the arguments */
2890 zend_string *zname = NULL;
2891 const char *name = NULL;
2892
2893 /* parse the arguments */
2894 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "S", &zname) == FAILURE) {
2895 return;
2896 } else {
2897 const php_mecab_node_object *intern = PHP_MECAB_NODE_OBJECT_P(getThis());
2898 xnode = intern->ptr;
2899 node = xnode->ptr;
2900 name = ZSTR_VAL(zname);
2901 }
2902
2903 /* check for given property name */
2904 if ((!strcmp(name, "prev") && node->prev != NULL) ||
2905 (!strcmp(name, "next") && node->next != NULL) ||
2906 (!strcmp(name, "enext") && node->enext != NULL) ||
2907 (!strcmp(name, "bnext") && node->bnext != NULL) ||
2908 (!strcmp(name, "rpath") && node->rpath != NULL) ||
2909 (!strcmp(name, "lpath") && node->lpath != NULL) ||
2910 !strcmp(name, "surface") ||
2911 !strcmp(name, "feature") ||
2912 !strcmp(name, "id") ||
2913 !strcmp(name, "length") ||
2914 !strcmp(name, "rlength") ||
2915 !strcmp(name, "rcAttr") ||
2916 !strcmp(name, "lcAttr") ||
2917 !strcmp(name, "posid") ||
2918 !strcmp(name, "char_type") ||
2919 !strcmp(name, "stat") ||
2920 !strcmp(name, "isbest") ||
2921 !strcmp(name, "sentence_length") ||
2922 !strcmp(name, "alpha") ||
2923 !strcmp(name, "beta") ||
2924 !strcmp(name, "prob") ||
2925 !strcmp(name, "wcost") ||
2926 !strcmp(name, "cost"))
2927 {
2928 RETURN_TRUE;
2929 }
2930 RETURN_FALSE;
2931 }
2932 /* }}} MeCab_Node::__isset */
2933
2934 /* {{{ proto object MeCab_NodeIterator MeCab_Node::getIterator(void) */
2935 /**
2936 * object MeCab_NodeIterator MeCab_Node::getIterator(void)
2937 *
2938 * [IteratorAggregate implementation]
2939 * Return the iterator object.
2940 *
2941 * @return object MeCab_NodeIterator
2942 * @access public
2943 * @ignore
2944 */
PHP_METHOD(MeCab_Node,getIterator)2945 static PHP_METHOD(MeCab_Node, getIterator)
2946 {
2947 php_mecab_node_object *intern;
2948 php_mecab_node *xnode;
2949 const mecab_node_t *node;
2950 php_mecab_node_object *newobj;
2951 php_mecab_node *newnode;
2952
2953 intern = PHP_MECAB_NODE_OBJECT_P(getThis());
2954 xnode = intern->ptr;
2955 node = xnode->ptr;
2956
2957 if (node == NULL) {
2958 RETURN_NULL();
2959 }
2960
2961 object_init_ex(return_value, ce_MeCab_NodeIterator);
2962 newobj = PHP_MECAB_NODE_OBJECT_P(return_value);
2963 newobj->root = node;
2964 newobj->mode = intern->mode;
2965 newnode = newobj->ptr;
2966 newnode->ptr = node;
2967 php_mecab_node_set_tagger(newnode, xnode->tagger TSRMLS_CC);
2968 }
2969 /* }}} MeCab_Node::getIterator */
2970
2971 /* {{{ proto void MeCab_Node::setTraverse(int tranverse) */
2972 /**
2973 * void MeCab_Node::setTraverse(int tranverse)
2974 *
2975 * Set the traverse mode.
2976 *
2977 * @param int $traverse The traverse mode.
2978 * @return void
2979 * @throws InvalidArgumentException
2980 * @access public
2981 */
PHP_METHOD(MeCab_Node,setTraverse)2982 static PHP_METHOD(MeCab_Node, setTraverse)
2983 {
2984 php_mecab_node_object *intern;
2985 long traverse = 0;
2986
2987 #if PHP_VERSION_ID >= 50300
2988 zend_error_handling error_handling;
2989
2990 zend_replace_error_handling(EH_THROW, ext_ce_InvalidArgumentException, &error_handling TSRMLS_CC);
2991 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &traverse) == FAILURE) {
2992 zend_restore_error_handling(&error_handling TSRMLS_CC);
2993 return;
2994 }
2995 zend_restore_error_handling(&error_handling TSRMLS_CC);
2996 #else
2997 php_set_error_handling(EH_THROW, ext_ce_InvalidArgumentException TSRMLS_CC);
2998 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &traverse) == FAILURE) {
2999 php_std_error_handling();
3000 return;
3001 }
3002 php_std_error_handling();
3003 #endif
3004
3005 intern = PHP_MECAB_NODE_OBJECT_P(getThis());
3006
3007 if (traverse == (long)TRAVERSE_NEXT ||
3008 traverse == (long)TRAVERSE_ENEXT ||
3009 traverse == (long)TRAVERSE_BNEXT)
3010 {
3011 intern->mode = (php_mecab_traverse_mode)traverse;
3012 } else {
3013 zend_throw_exception(ext_ce_InvalidArgumentException,
3014 "Invalid traverse mdoe given", 0 TSRMLS_CC);
3015 }
3016 }
3017 /* }}} MeCab_Node::setTraverse */
3018
3019 /* }}} methods of class MeCab_Node */
3020
3021 /* {{{ methods of class MeCab_NodeIterator*/
3022
3023 /* {{{ proto object MeCab_NodeIterator __construct(void) */
3024 /**
3025 * object MeCab_Path MeCab_NodeIterator::__construct(void)
3026 *
3027 * Create MeCab_NodeIterator object.
3028 *
3029 * @access private
3030 * @igore
3031 */
PHP_METHOD(MeCab_NodeIterator,__construct)3032 static PHP_METHOD(MeCab_NodeIterator, __construct)
3033 {
3034 return;
3035 }
3036 /* }}} MeCab_NodeIterator::__construct */
3037
3038 /* {{{ object MeCab_Node MeCab_NodeIterator::current(void) */
3039 /**
3040 * object MeCab_Node MeCab_NodeIterator::current(void)
3041 *
3042 * [Iterator implementation]
3043 * Return the current element.
3044 *
3045 * @access public
3046 * @igore
3047 */
PHP_METHOD(MeCab_NodeIterator,current)3048 static PHP_METHOD(MeCab_NodeIterator, current)
3049 {
3050 php_mecab_node_object *intern;
3051 php_mecab_node *xnode;
3052 const mecab_node_t *node;
3053 php_mecab_node_object *newobj;
3054 php_mecab_node *newnode;
3055
3056 if (ZEND_NUM_ARGS() != 0) {
3057 WRONG_PARAM_COUNT;
3058 }
3059 intern = PHP_MECAB_NODE_OBJECT_P(getThis());
3060 xnode = intern->ptr;
3061 node = xnode->ptr;
3062
3063 if (node == NULL) {
3064 RETURN_NULL();
3065 }
3066
3067 object_init_ex(return_value, ce_MeCab_Node);
3068 newobj = PHP_MECAB_NODE_OBJECT_P(return_value);
3069 newobj->mode = intern->mode;
3070 newnode = newobj->ptr;
3071 newnode->ptr = node;
3072 php_mecab_node_set_tagger(newnode, xnode->tagger TSRMLS_CC);
3073 }
3074 /* }}} MeCab_NodeIterator::current */
3075
3076 /* {{{ proto int MeCab_NodeIterator::key(void) */
3077 /**
3078 * int MeCab_Node::key(void)
3079 *
3080 * [Iterator implementation]
3081 * Return the key of the current element.
3082 *
3083 * @return int The cumulative cost of the node.
3084 * @access public
3085 * @igore
3086 */
PHP_METHOD(MeCab_NodeIterator,key)3087 static PHP_METHOD(MeCab_NodeIterator, key)
3088 {
3089 php_mecab_node_object *intern;
3090 php_mecab_node *xnode;
3091 const mecab_node_t *node;
3092
3093 if (ZEND_NUM_ARGS() != 0) {
3094 WRONG_PARAM_COUNT;
3095 }
3096 intern = PHP_MECAB_NODE_OBJECT_P(getThis());
3097 xnode = intern->ptr;
3098 node = xnode->ptr;
3099
3100 if (node == NULL) {
3101 RETURN_NULL();
3102 }
3103
3104 RETURN_LONG((long)node->id);
3105 }
3106 /* }}} MeCab_NodeIterator::key */
3107
3108 /* {{{ proto void MeCab_NodeIterator::next(void) */
3109 /**
3110 * void MeCab_NodeIterator::next(void)
3111 *
3112 * [Iterator implementation]
3113 * Set the node pointer to the next.
3114 *
3115 * @return void
3116 * @access public
3117 * @igore
3118 */
PHP_METHOD(MeCab_NodeIterator,next)3119 static PHP_METHOD(MeCab_NodeIterator, next)
3120 {
3121 php_mecab_node_object *intern;
3122 php_mecab_node *xnode;
3123 const mecab_node_t *node;
3124
3125 if (ZEND_NUM_ARGS() != 0) {
3126 WRONG_PARAM_COUNT;
3127 }
3128 intern = PHP_MECAB_NODE_OBJECT_P(getThis());
3129 xnode = intern->ptr;
3130 node = xnode->ptr;
3131
3132 if (node == NULL) {
3133 return;
3134 }
3135
3136 switch (intern->mode) {
3137 case TRAVERSE_NEXT:
3138 xnode->ptr = node->next;
3139 break;
3140 case TRAVERSE_ENEXT:
3141 xnode->ptr = node->enext;
3142 break;
3143 case TRAVERSE_BNEXT:
3144 xnode->ptr = node->bnext;
3145 break;
3146 default:
3147 xnode->ptr = NULL;
3148 }
3149 }
3150 /* }}} MeCab_NodeIterator::next */
3151
3152 /* {{{ proto void MeCab_NodeIterator::rewind(void) */
3153 /**
3154 * void MeCab_NodeIterator::rewind(void)
3155 *
3156 * [Iterator implementation]
3157 * Set the node pointer to the beginning.
3158 *
3159 * @return void
3160 * @access public
3161 * @igore
3162 */
PHP_METHOD(MeCab_NodeIterator,rewind)3163 static PHP_METHOD(MeCab_NodeIterator, rewind)
3164 {
3165 php_mecab_node_object *intern;
3166 php_mecab_node *xnode;
3167
3168 if (ZEND_NUM_ARGS() != 0) {
3169 WRONG_PARAM_COUNT;
3170 }
3171 intern = PHP_MECAB_NODE_OBJECT_P(getThis());
3172 xnode = intern->ptr;
3173 xnode->ptr = intern->root;
3174 }
3175 /* }}} MeCab_NodeIterator::rewind */
3176
3177 /* {{{ proto bool MeCab_NodeIterator::valid(void) */
3178 /**
3179 * bool MeCab_NodeIterator::valid(void)
3180 *
3181 * [Iterator implementation]
3182 * Check if there is a current element after calls to rewind() or next().
3183 *
3184 * @return bool True if there is an element after the current element, otherwise returns false.
3185 * @access public
3186 * @igore
3187 */
PHP_METHOD(MeCab_NodeIterator,valid)3188 static PHP_METHOD(MeCab_NodeIterator, valid)
3189 {
3190 php_mecab_node_object *intern;
3191 php_mecab_node *xnode;
3192 const mecab_node_t *node;
3193
3194 if (ZEND_NUM_ARGS() != 0) {
3195 WRONG_PARAM_COUNT;
3196 }
3197 intern = PHP_MECAB_NODE_OBJECT_P(getThis());
3198 xnode = intern->ptr;
3199 node = xnode->ptr;
3200
3201 RETURN_BOOL(node != NULL);
3202 }
3203 /* }}} MeCab_NodeIterator::valid */
3204
3205 /* }}} methods of class MeCab_NodeIterator */
3206
3207 /* {{{ methods of class MeCab_Path*/
3208
3209 /* {{{ proto object MeCab_Path __construct(void) */
3210 /**
3211 * object MeCab_Path MeCab_Path::__construct(void)
3212 *
3213 * Create MeCab_Path object.
3214 *
3215 * @access private
3216 * @igore
3217 */
PHP_METHOD(MeCab_Path,__construct)3218 static PHP_METHOD(MeCab_Path, __construct)
3219 {
3220 return;
3221 }
3222 /* }}} MeCab_Path::__construct */
3223
3224 /* {{{ proto mixed MeCab_Path::__get(string name) */
3225 /**
3226 * mixed MeCab_Path::__get(string name)
3227 *
3228 * [Overloading implementation]
3229 * A magick getter.
3230 *
3231 * @param string $name The name of property.
3232 * @return mixed The value of the property.
3233 * If there is not a named property, causes E_NOTICE error and returns false.
3234 * @access public
3235 * @ignore
3236 */
PHP_METHOD(MeCab_Path,__get)3237 static PHP_METHOD(MeCab_Path, __get)
3238 {
3239 /* declaration of the resources */
3240 zval *object = getThis();
3241 php_mecab_path *xpath = NULL;
3242 const mecab_path_t *path = NULL;
3243
3244 /* declaration of the arguments */
3245 zend_string *zname = NULL;
3246 const char *name = NULL;
3247
3248 /* parse the arguments */
3249 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "S", &zname) == FAILURE) {
3250 return;
3251 } else {
3252 const php_mecab_path_object *intern = PHP_MECAB_PATH_OBJECT_P(object);
3253 xpath = intern->ptr;
3254 path = xpath->ptr;
3255 name = ZSTR_VAL(zname);
3256 }
3257
3258 /* check for given property name */
3259 if (!strcmp(name, "rnext")) {
3260 php_mecab_path_get_sibling(return_value, object, xpath, PATH_RNEXT TSRMLS_CC);
3261 return;
3262 }
3263 if (!strcmp(name, "lnext")) {
3264 php_mecab_path_get_sibling(return_value, object, xpath, PATH_LNEXT TSRMLS_CC);
3265 return;
3266 }
3267 if (!strcmp(name, "rnode")) {
3268 php_mecab_path_get_node(return_value, object, xpath, PATH_RNODE TSRMLS_CC);
3269 return;
3270 }
3271 if (!strcmp(name, "lnode")) {
3272 php_mecab_path_get_node(return_value, object, xpath, PATH_LNODE TSRMLS_CC);
3273 return;
3274 }
3275 if (!strcmp(name, "prob")) RETURN_DOUBLE((double)(path->prob));
3276 if (!strcmp(name, "cost")) RETURN_LONG((long)(path->cost));
3277
3278 /* when going to fetch undefined property */
3279 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Undefined property (%s)", name);
3280 RETURN_NULL();
3281 }
3282 /* }}} MeCab_Path::__get */
3283
3284 /* {{{ proto boolMeCab_Path:: __isset(string name) */
3285 /**
3286 * bool MeCab_Path::__isset(string name)
3287 *
3288 * [Overloading implementation]
3289 * Determine whether there is a named property.
3290 *
3291 * @param string $name The name of property.
3292 * @return bool True if there is a named property, otherwise returns false.
3293 * @access public
3294 * @ignore
3295 */
PHP_METHOD(MeCab_Path,__isset)3296 static PHP_METHOD(MeCab_Path, __isset)
3297 {
3298 /* declaration of the resources */
3299 php_mecab_path *xpath = NULL;
3300 const mecab_path_t *path = NULL;
3301
3302 /* declaration of the arguments */
3303 zend_string *zname = NULL;
3304 const char *name = NULL;
3305
3306 /* parse the arguments */
3307 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "S", &zname) == FAILURE) {
3308 return;
3309 } else {
3310 const php_mecab_path_object *intern = PHP_MECAB_PATH_OBJECT_P(getThis());
3311 xpath = intern->ptr;
3312 path = xpath->ptr;
3313 name = ZSTR_VAL(zname);
3314 }
3315
3316 /* check for given property name */
3317 if ((!strcmp(name, "rnext") && path->rnext != NULL) ||
3318 (!strcmp(name, "lnext") && path->lnext != NULL) ||
3319 (!strcmp(name, "rnode") && path->rnode != NULL) ||
3320 (!strcmp(name, "lnode") && path->lnode != NULL) ||
3321 !strcmp(name, "prob") ||
3322 !strcmp(name, "cost"))
3323 {
3324 RETURN_TRUE;
3325 }
3326 RETURN_FALSE;
3327 }
3328 /* }}} MeCab_Path::__isset */
3329
3330 /* }}} methods of class MeCab_Path */
3331
3332 /* }}} methods */
3333
3334 /*
3335 * Local variables:
3336 * tab-width: 4
3337 * c-basic-offset: 4
3338 * End:
3339 * vim600: noet sw=4 ts=4 fdm=marker
3340 * vim<600: noet sw=4 ts=4
3341 */
3342