1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 4 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2006 The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Author: hightman (hightman[AT]twomice.net) QQ = 16139558 |
16 +----------------------------------------------------------------------+
17 */
18
19 /* $Id$ */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "php.h"
26 #include "php_ini.h"
27 #include "ext/standard/info.h"
28 #include "php_scws.h"
29 #include <scws.h>
30
31 /// hightman.090716: for PHP5.3+
32 #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3) || (PHP_MAJOR_VERSION >= 6)
33 #undef ZVAL_REFCOUNT
34 #undef ZVAL_ADDREF
35 #undef ZVAL_DELREF
36 #define ZVAL_REFCOUNT Z_REFCOUNT_P
37 #define ZVAL_ADDREF Z_ADDREF_P
38 #define ZVAL_DELREF Z_DELREF_P
39 #endif
40
41 /// hightman.20150614: for PHP7+
42 #if PHP_MAJOR_VERSION >= 7
43 #undef FREE_ZVAL
44 #undef ZEND_REGISTER_RESOURCE
45 #undef RETVAL_RESOURCE
46 #undef MAKE_STD_ZVAL
47 #undef RETURN_STRING
48 #undef add_assoc_string
49 #undef add_assoc_stringl
50
51 #define FREE_ZVAL efree_rel
52 #define ZEND_REGISTER_RESOURCE(x,y,z) zend_register_resource(y,z)
53 #define RETVAL_RESOURCE RETVAL_RES
54 #define MAKE_STD_ZVAL(x) x = (zval *) emalloc(sizeof(zval))
55 #define RETURN_STRING(a,b) RETVAL_STRING(a); return
56 #define add_assoc_string(a,b,c,d) add_assoc_string_ex(a,b,strlen(b),c)
57 #define add_assoc_stringl(a,b,c,d,e) add_assoc_stringl_ex(a,b,strlen(b),(char*)c,d)
58 #define ZEND_LIST_DELETE zend_list_close
59
60 typedef size_t str_size_t;
61 #else
62 #define ZEND_LIST_DELETE zend_list_delete
63
64 typedef int str_size_t;
65 #endif
66
67 /// ZEND_DECLARE_MODULE_GLOBALS(scws)
68
69 static zend_class_entry *scws_class_entry_ptr;
70 static int le_scws;
71
72 #define PHP_SCWS_MODULE_VERSION "0.2.3"
73 #define PHP_SCWS_DEFAULT_CHARSET "gbk"
74 #define PHP_SCWS_OBJECT_TAG "scws handler"
75 #define DELREF_SCWS(x) { \
76 if (x != NULL) { \
77 ZVAL_DELREF(x); \
78 if (ZVAL_REFCOUNT(x) <= 0) { \
79 zval_dtor(x); \
80 FREE_ZVAL(x); \
81 } \
82 x = NULL; \
83 } \
84 }
85
86 #define CHECK_DR_SCWS() \
87 if (ps->s->r == NULL || ps->s->d == NULL) { \
88 char fpath[128], *folder, *ftoken; \
89 int plen; \
90 if (((folder = INI_STR("scws.default.fpath")) != NULL) \
91 && (plen = strlen(folder)) < 100) \
92 { \
93 strcpy(fpath, folder); \
94 ftoken = fpath + plen; \
95 if (plen > 0 && ftoken[-1] != DEFAULT_SLASH) \
96 *ftoken++ = DEFAULT_SLASH; \
97 if (ps->s->r == NULL) { \
98 if (ps->charset[0] \
99 && strcmp(ps->charset, PHP_SCWS_DEFAULT_CHARSET)) \
100 { \
101 zend_sprintf(ftoken, "rules.%s.ini", ps->charset); \
102 } \
103 else { \
104 strcpy(ftoken, "rules.ini"); \
105 } \
106 scws_set_rule(ps->s, fpath); \
107 } \
108 if (ps->s->d == NULL) { \
109 if (ps->charset[0] \
110 && strcmp(ps->charset, PHP_SCWS_DEFAULT_CHARSET)) \
111 { \
112 zend_sprintf(ftoken, "dict.%s.xdb", ps->charset); \
113 } \
114 else \
115 { \
116 strcpy(ftoken, "dict.xdb"); \
117 } \
118 scws_set_dict(ps->s, fpath, SCWS_XDICT_XDB); \
119 } \
120 } \
121 }
122
123 #if PHP_MAJOR_VERSION >= 7
124 #define SCWS_FETCH_PARAMETERS(ts, ...) \
125 do { \
126 zval *tmp = getThis(); \
127 if (tmp) { \
128 tmp = zend_hash_str_find(Z_OBJPROP_P(tmp), "handle", sizeof("handle") - 1); \
129 if (tmp == NULL) { \
130 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find the handle property"); \
131 RETURN_FALSE; \
132 } \
133 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ts, ##__VA_ARGS__) == FAILURE) { \
134 return; \
135 } \
136 } else { \
137 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r" ts, &tmp, ##__VA_ARGS__) == FAILURE) { \
138 return; \
139 } \
140 } \
141 ps = (struct php_scws *) zend_fetch_resource_ex(tmp, PHP_SCWS_OBJECT_TAG, le_scws); \
142 } while(0)
143 #else
144 #define SCWS_FETCH_PARAMETERS(ts, ...) \
145 do { \
146 zval **tmp; \
147 zval *object = getThis(); \
148 if (object) { \
149 if (zend_hash_find(Z_OBJPROP_P(object), "handle", sizeof("handle"), (void **)&tmp) == FAILURE) { \
150 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find the handle property"); \
151 RETURN_FALSE; \
152 } \
153 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ts, ##__VA_ARGS__) == FAILURE) { \
154 return; \
155 } \
156 } else { \
157 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r" ts, &object, ##__VA_ARGS__) == FAILURE) { \
158 return; \
159 } \
160 tmp = &object; \
161 } \
162 ZEND_FETCH_RESOURCE(ps, struct php_scws *, tmp, -1, PHP_SCWS_OBJECT_TAG, le_scws); \
163 } while(0)
164 #endif
165
166 struct php_scws
167 {
168 scws_t s;
169 zval *zt;
170 char charset[8];
171 #if PHP_MAJOR_VERSION >= 7
172 zend_resource *rsrc_id;
173 #else
174 int rsrc_id;
175 #endif
176 };
177
178 zend_function_entry scws_functions[] = {
179 PHP_FE(scws_open, NULL)
180 PHP_FE(scws_new, NULL)
181 PHP_FE(scws_close, NULL)
182 PHP_FE(scws_set_charset, NULL)
183 PHP_FE(scws_add_dict, NULL)
184 PHP_FE(scws_set_dict, NULL)
185 PHP_FE(scws_set_rule, NULL)
186 PHP_FE(scws_set_ignore, NULL)
187 PHP_FE(scws_set_multi, NULL)
188 PHP_FE(scws_set_duality, NULL)
189 PHP_FE(scws_send_text, NULL)
190 PHP_FE(scws_get_result, NULL)
191 PHP_FE(scws_get_tops, NULL)
192 PHP_FE(scws_has_word, NULL)
193 PHP_FE(scws_get_words, NULL)
194 PHP_FE(scws_version, NULL)
195 {NULL, NULL, NULL}
196 };
197
198 static zend_function_entry php_scws_class_functions[] = {
199 PHP_FALIAS(close, scws_close, NULL)
200 PHP_FALIAS(set_charset, scws_set_charset, NULL)
201 PHP_FALIAS(add_dict, scws_add_dict, NULL)
202 PHP_FALIAS(set_dict, scws_set_dict, NULL)
203 PHP_FALIAS(set_rule, scws_set_rule, NULL)
204 PHP_FALIAS(set_ignore, scws_set_ignore, NULL)
205 PHP_FALIAS(set_multi, scws_set_multi, NULL)
206 PHP_FALIAS(set_duality, scws_set_duality, NULL)
207 PHP_FALIAS(send_text, scws_send_text, NULL)
208 PHP_FALIAS(get_result, scws_get_result, NULL)
209 PHP_FALIAS(get_tops, scws_get_tops, NULL)
210 PHP_FALIAS(has_word, scws_has_word, NULL)
211 PHP_FALIAS(get_words, scws_get_words, NULL)
212 PHP_FALIAS(version, scws_version, NULL)
213 {NULL, NULL, NULL}
214 };
215
ZEND_RSRC_DTOR_FUNC(php_scws_dtor)216 static ZEND_RSRC_DTOR_FUNC(php_scws_dtor)
217 {
218 #if PHP_MAJOR_VERSION == 7
219 #define rsrc res
220 #endif
221 if (rsrc->ptr) {
222 struct php_scws *ps = (struct php_scws *) rsrc->ptr;
223 scws_free(ps->s);
224 #if PHP_MAJOR_VERSION < 7
225 DELREF_SCWS(ps->zt);
226 #endif
227 efree(ps);
228 rsrc->ptr = NULL;
229 }
230 #if PHP_MAJOR_VERSION == 7
231 #undef rsrc
232 #endif
233 }
234
235 zend_module_entry scws_module_entry = {
236 #if ZEND_MODULE_API_NO >= 20010901
237 STANDARD_MODULE_HEADER,
238 #endif
239 "scws",
240 scws_functions,
241 PHP_MINIT(scws),
242 PHP_MSHUTDOWN(scws),
243 NULL,
244 PHP_RSHUTDOWN(scws),
245 PHP_MINFO(scws),
246 #if ZEND_MODULE_API_NO >= 20010901
247 PHP_SCWS_MODULE_VERSION,
248 #endif
249 STANDARD_MODULE_PROPERTIES
250 };
251 /* }}} */
252
253 #ifdef COMPILE_DL_SCWS
254 ZEND_GET_MODULE(scws)
255 #endif
256
PHP_INI_BEGIN()257 PHP_INI_BEGIN()
258 PHP_INI_ENTRY("scws.default.charset", PHP_SCWS_DEFAULT_CHARSET, PHP_INI_ALL, NULL)
259 PHP_INI_ENTRY("scws.default.fpath", NULL, PHP_INI_ALL, NULL)
260 PHP_INI_END()
261
262 PHP_MINIT_FUNCTION(scws)
263 {
264 zend_class_entry scws_class_entry;
265
266 REGISTER_INI_ENTRIES();
267
268 le_scws = zend_register_list_destructors_ex(php_scws_dtor, NULL, PHP_SCWS_OBJECT_TAG, module_number);
269 INIT_CLASS_ENTRY(scws_class_entry, "SimpleCWS", php_scws_class_functions);
270 scws_class_entry_ptr = zend_register_internal_class(&scws_class_entry TSRMLS_CC);
271
272 REGISTER_LONG_CONSTANT("SCWS_XDICT_XDB", SCWS_XDICT_XDB, CONST_CS|CONST_PERSISTENT);
273 REGISTER_LONG_CONSTANT("SCWS_XDICT_MEM", SCWS_XDICT_MEM, CONST_CS|CONST_PERSISTENT);
274 REGISTER_LONG_CONSTANT("SCWS_XDICT_TXT", SCWS_XDICT_TXT, CONST_CS|CONST_PERSISTENT);
275
276 REGISTER_LONG_CONSTANT("SCWS_MULTI_NONE", SCWS_MULTI_NONE, CONST_CS|CONST_PERSISTENT);
277 REGISTER_LONG_CONSTANT("SCWS_MULTI_SHORT", (SCWS_MULTI_SHORT>>12), CONST_CS|CONST_PERSISTENT);
278 REGISTER_LONG_CONSTANT("SCWS_MULTI_DUALITY",(SCWS_MULTI_DUALITY>>12), CONST_CS|CONST_PERSISTENT);
279 REGISTER_LONG_CONSTANT("SCWS_MULTI_ZMAIN", (SCWS_MULTI_ZMAIN>>12), CONST_CS|CONST_PERSISTENT);
280 REGISTER_LONG_CONSTANT("SCWS_MULTI_ZALL", (SCWS_MULTI_ZALL>>12), CONST_CS|CONST_PERSISTENT);
281
282 return SUCCESS;
283 }
284
PHP_MSHUTDOWN_FUNCTION(scws)285 PHP_MSHUTDOWN_FUNCTION(scws)
286 {
287 UNREGISTER_INI_ENTRIES();
288 return SUCCESS;
289 }
290
PHP_RSHUTDOWN_FUNCTION(scws)291 PHP_RSHUTDOWN_FUNCTION(scws)
292 {
293 return SUCCESS;
294 }
295
PHP_MINFO_FUNCTION(scws)296 PHP_MINFO_FUNCTION(scws)
297 {
298 php_info_print_table_start();
299 php_info_print_table_header(2, "SCWS support", "Enabled");
300 php_info_print_table_row(2, "SCWS Description", "Simple Chinese Words Segmentation");
301 php_info_print_table_row(2, "PECL Module version", PHP_SCWS_MODULE_VERSION);
302 php_info_print_table_row(2, "SCWS Library", SCWS_VERSION);
303 php_info_print_table_row(2, "SCWS BugReport", SCWS_BUGREPORT);
304 php_info_print_table_end();
305 DISPLAY_INI_ENTRIES();
306 }
307
_php_create_scws(TSRMLS_D)308 static void *_php_create_scws(TSRMLS_D)
309 {
310 struct php_scws *ps;
311 char *ini_cs;
312 scws_t s;
313
314 s = scws_new();
315 if (s == NULL) {
316 return NULL;
317 }
318
319 ps = (struct php_scws *)emalloc(sizeof(struct php_scws));
320 ps->s = s;
321 ps->zt = NULL;
322 ps->charset[0] = '\0';
323 ps->rsrc_id = ZEND_REGISTER_RESOURCE(NULL, ps, le_scws);
324
325 ini_cs = INI_STR("scws.default.charset");
326 if (ini_cs != NULL && *ini_cs) {
327 memset(ps->charset, 0, sizeof(ps->charset));
328 strncpy(ps->charset, ini_cs, sizeof(ps->charset)-1);
329 scws_set_charset(s, ps->charset);
330 }
331
332 return ((void *)ps);
333 }
334
PHP_FUNCTION(scws_open)335 PHP_FUNCTION(scws_open)
336 {
337 struct php_scws *ps;
338
339 ps = (struct php_scws *)_php_create_scws(TSRMLS_C);
340 if (ps == NULL) {
341 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't create new scws handler");
342 RETURN_FALSE;
343 }
344
345 RETVAL_RESOURCE(ps->rsrc_id);
346 }
347
PHP_FUNCTION(scws_new)348 PHP_FUNCTION(scws_new)
349 {
350 struct php_scws *ps;
351
352 ps = (struct php_scws *)_php_create_scws(TSRMLS_C);
353 if (ps == NULL) {
354 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't create new scws object");
355 RETURN_FALSE;
356 }
357
358 object_init_ex(return_value, scws_class_entry_ptr);
359 add_property_resource(return_value, "handle", ps->rsrc_id);
360 }
361
PHP_FUNCTION(scws_close)362 PHP_FUNCTION(scws_close)
363 {
364 struct php_scws *ps;
365
366 SCWS_FETCH_PARAMETERS("");
367
368 ZEND_LIST_DELETE(ps->rsrc_id);
369 }
370
PHP_FUNCTION(scws_set_charset)371 PHP_FUNCTION(scws_set_charset)
372 {
373 char *cs;
374 str_size_t cs_len;
375 struct php_scws *ps;
376
377 SCWS_FETCH_PARAMETERS("s", &cs, &cs_len);
378
379 memset(ps->charset, 0, sizeof(ps->charset));
380 strncpy(ps->charset, cs, sizeof(ps->charset)-1);
381 scws_set_charset(ps->s, ps->charset);
382
383 RETURN_TRUE;
384 }
385
PHP_FUNCTION(scws_add_dict)386 PHP_FUNCTION(scws_add_dict)
387 {
388 long xmode = 0;
389 char *filepath, *fullpath = NULL;
390 str_size_t filepath_len;
391 struct php_scws *ps;
392
393 SCWS_FETCH_PARAMETERS("s|l", &filepath, &filepath_len, &xmode);
394
395 if (!(fullpath = expand_filepath(filepath, NULL TSRMLS_CC))) {
396 RETURN_FALSE;
397 }
398
399 #if PHP_API_VERSION < 20100412
400 if (PG(safe_mode) && (!php_checkuid(fullpath, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
401 efree(fullpath);
402 RETURN_FALSE;
403 }
404 #endif
405
406 if (php_check_open_basedir(fullpath TSRMLS_CC)) {
407 efree(fullpath);
408 RETURN_FALSE;
409 }
410
411 xmode = (int) scws_add_dict(ps->s, fullpath, xmode);
412 efree(fullpath);
413
414 if (xmode != 0) {
415 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to add the dict file");
416 RETURN_FALSE;
417 }
418
419 RETURN_TRUE;
420 }
421
PHP_FUNCTION(scws_set_dict)422 PHP_FUNCTION(scws_set_dict)
423 {
424 long xmode = 0;
425 char *filepath, *fullpath = NULL;
426 str_size_t filepath_len;
427 struct php_scws *ps;
428
429 SCWS_FETCH_PARAMETERS("s|l", &filepath, &filepath_len, &xmode);
430
431 if (!(fullpath = expand_filepath(filepath, NULL TSRMLS_CC))) {
432 RETURN_FALSE;
433 }
434
435 #if PHP_API_VERSION < 20100412
436 if (PG(safe_mode) && (!php_checkuid(fullpath, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
437 efree(fullpath);
438 RETURN_FALSE;
439 }
440 #endif
441
442 if (php_check_open_basedir(fullpath TSRMLS_CC)) {
443 efree(fullpath);
444 RETURN_FALSE;
445 }
446
447 xmode = (int) scws_set_dict(ps->s, fullpath, xmode);
448 efree(fullpath);
449
450 if (xmode != 0) {
451 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to set the dict file");
452 RETURN_FALSE;
453 }
454
455 RETURN_TRUE;
456 }
457
PHP_FUNCTION(scws_set_rule)458 PHP_FUNCTION(scws_set_rule)
459 {
460 char *filepath, *fullpath = NULL;
461 str_size_t filepath_len;
462 struct php_scws *ps;
463
464 SCWS_FETCH_PARAMETERS("s", &filepath, &filepath_len);
465
466 if (!(fullpath = expand_filepath(filepath, NULL TSRMLS_CC))) {
467 RETURN_FALSE;
468 }
469
470 #if PHP_API_VERSION < 20100412
471 if (PG(safe_mode) && (!php_checkuid(fullpath, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
472 efree(fullpath);
473 RETURN_FALSE;
474 }
475 #endif
476
477 if (php_check_open_basedir(fullpath TSRMLS_CC)) {
478 efree(fullpath);
479 RETURN_FALSE;
480 }
481
482 scws_set_rule(ps->s, fullpath);
483 efree(fullpath);
484
485 if (ps->s->r == NULL) {
486 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to load the ruleset file");
487 RETURN_FALSE;
488 }
489
490 RETURN_TRUE;
491 }
492
PHP_FUNCTION(scws_set_ignore)493 PHP_FUNCTION(scws_set_ignore)
494 {
495 zend_bool boolset = 1;
496 struct php_scws *ps;
497
498 SCWS_FETCH_PARAMETERS("b", &boolset);
499
500 scws_set_ignore(ps->s, boolset ? SCWS_YEA : SCWS_NA);
501 RETURN_TRUE;
502 }
503
PHP_FUNCTION(scws_set_multi)504 PHP_FUNCTION(scws_set_multi)
505 {
506 long multi = 0;
507 struct php_scws *ps;
508
509 SCWS_FETCH_PARAMETERS("l", &multi);
510
511 if (multi < 0 || (multi & 0x10)) {
512 RETURN_FALSE;
513 }
514
515 scws_set_multi(ps->s, (multi<<12));
516 RETURN_TRUE;
517 }
518
PHP_FUNCTION(scws_set_duality)519 PHP_FUNCTION(scws_set_duality)
520 {
521 zend_bool boolset = 1;
522 struct php_scws *ps;
523
524 SCWS_FETCH_PARAMETERS("b", &boolset);
525
526 scws_set_duality(ps->s, boolset ? SCWS_YEA : SCWS_NA);
527 RETURN_TRUE;
528 }
529
PHP_FUNCTION(scws_send_text)530 PHP_FUNCTION(scws_send_text)
531 {
532 zval *text;
533 struct php_scws *ps;
534
535 SCWS_FETCH_PARAMETERS("z", &text);
536
537 #if PHP_MAJOR_VERSION >= 7
538 convert_to_string_ex(text);
539 #else
540 convert_to_string_ex(&text);
541 #endif
542
543 #if PHP_MAJOR_VERSION < 7
544 DELREF_SCWS(ps->zt);
545 ZVAL_ADDREF(text);
546 #endif
547 ps->zt = text;
548
549 scws_send_text(ps->s, Z_STRVAL_P(ps->zt), Z_STRLEN_P(ps->zt));
550
551 CHECK_DR_SCWS();
552
553 RETURN_TRUE;
554 }
555
PHP_FUNCTION(scws_get_result)556 PHP_FUNCTION(scws_get_result)
557 {
558 zval *row;
559 scws_res_t res, cur;
560 struct php_scws *ps;
561
562 SCWS_FETCH_PARAMETERS("");
563
564 cur = res = scws_get_result(ps->s);
565 if (res == NULL) {
566 RETURN_FALSE;
567 }
568
569 array_init(return_value);
570 while (cur != NULL) {
571 MAKE_STD_ZVAL(row);
572 array_init(row);
573 add_assoc_stringl(row, "word", (char *) ps->s->txt + cur->off, cur->len, 1);
574 add_assoc_long(row, "off", cur->off);
575 add_assoc_long(row, "len", cur->len);
576 add_assoc_double(row, "idf", (double) cur->idf);
577 add_assoc_stringl(row, "attr", cur->attr, (cur->attr[1] == '\0' ? 1 : 2), 1);
578
579 cur = cur->next;
580 add_next_index_zval(return_value, row);
581 #if PHP_MAJOR_VERSION >= 7
582 efree(row);
583 #endif
584 }
585 scws_free_result(res);
586 }
587
588 // [, limit, [, exclude_attrs]]
PHP_FUNCTION(scws_get_tops)589 PHP_FUNCTION(scws_get_tops)
590 {
591 long limit = 0;
592 char *attr = NULL;
593 str_size_t attr_len;
594 scws_top_t top, cur;
595 zval *row;
596 struct php_scws *ps;
597
598 SCWS_FETCH_PARAMETERS("|ls", &limit, &attr, &attr_len);
599
600 if (limit <= 0) {
601 limit = 10;
602 }
603 cur = top = scws_get_tops(ps->s, limit, attr);
604 array_init(return_value);
605 while (cur != NULL) {
606 MAKE_STD_ZVAL(row);
607 array_init(row);
608
609 add_assoc_string(row, "word", cur->word, 1);
610 add_assoc_long(row, "times", cur->times);
611 add_assoc_double(row, "weight", (double) cur->weight);
612 add_assoc_stringl(row, "attr", cur->attr, (cur->attr[1] == '\0' ? 1 : 2), 1);
613
614 cur = cur->next;
615 add_next_index_zval(return_value, row);
616 #if PHP_MAJOR_VERSION >= 7
617 efree(row);
618 #endif
619 }
620 scws_free_tops(top);
621 }
622
623 // <attr>
PHP_FUNCTION(scws_has_word)624 PHP_FUNCTION(scws_has_word)
625 {
626 char *attr;
627 str_size_t attr_len;
628 struct php_scws *ps;
629
630 SCWS_FETCH_PARAMETERS("s", &attr, &attr_len);
631
632 if (scws_has_word(ps->s, attr) == 0) {
633 RETURN_FALSE;
634 }
635
636 RETURN_TRUE;
637 }
638
639 // <attr>
PHP_FUNCTION(scws_get_words)640 PHP_FUNCTION(scws_get_words)
641 {
642 char *attr;
643 str_size_t attr_len;
644 scws_top_t top, cur;
645 zval *row;
646 struct php_scws *ps;
647
648 SCWS_FETCH_PARAMETERS("s", &attr, &attr_len);
649
650 array_init(return_value);
651 cur = top = scws_get_words(ps->s, attr);
652 while (cur != NULL) {
653 MAKE_STD_ZVAL(row);
654 array_init(row);
655 add_assoc_string(row, "word", cur->word, 1);
656 add_assoc_long(row, "times", cur->times);
657 add_assoc_double(row, "weight", (double) cur->weight);
658 add_assoc_stringl(row, "attr", cur->attr, (cur->attr[1] == '\0' ? 1 : 2), 1);
659
660 cur = cur->next;
661 add_next_index_zval(return_value, row);
662 #if PHP_MAJOR_VERSION >= 7
663 efree(row);
664 #endif
665 }
666 scws_free_tops(top);
667 }
668
PHP_FUNCTION(scws_version)669 PHP_FUNCTION(scws_version)
670 {
671 char buf[128];
672
673 zend_sprintf(buf, "SCWS (Module version:%s, Library version:%s) - by hightman",
674 PHP_SCWS_MODULE_VERSION, SCWS_VERSION);
675 RETURN_STRING(buf, 1);
676 }
677
678 /// hightman.20150614: for PHP7+
679 #if PHP_MAJOR_VERSION >= 7
680 #undef RETURN_STRING
681 #undef add_assoc_string
682 #undef add_assoc_stringl
683 #endif
684
685 /*
686 * Local variables:
687 * tab-width: 4
688 * c-basic-offset: 4
689 * End:
690 * vim600: noet sw=4 ts=4 fdm=marker
691 * vim<600: noet sw=4 ts=4
692 */
693