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