root/libswish3/trunk/bindings/perl/3.xs

Revision 2151, 13.9 kB (checked in by karpet, 1 month ago)

update perl bindings to use new WordList? API

Line 
1 /* Copyright 2008 Peter Karman (perl@peknet.com)
2  * This program is free software; you can redistribute it and/or modify
3  * under the same terms as Perl itself.
4  */
5
6 /* all XS stuff is prefixed with 'sp_' for Swish Perl */
7
8 #include "xs_boiler.h"
9 #include "headers.h"
10 #include "macros.h"
11 #include "xs_helpers.c"
12
13
14 MODULE = SWISH::3       PACKAGE = SWISH::3
15
16 PROTOTYPES: enable
17
18 INCLUDE: XS/Constants.xs
19
20 swish_3*
21 init(CLASS)
22     char* CLASS;
23
24     PREINIT:
25         swish_3* s3;
26
27     CODE:
28         s3 = swish_init_swish3( &sp_handler, NULL );
29         s3->ref_cnt++;
30         s3->stash = sp_Stash_new();
31        
32         sp_Stash_set_char( s3->stash, DATA_CLASS_KEY,     DATA_CLASS );
33         sp_Stash_set_char( s3->stash, CONFIG_CLASS_KEY,   CONFIG_CLASS );
34         sp_Stash_set_char( s3->stash, ANALYZER_CLASS_KEY, ANALYZER_CLASS );
35         sp_Stash_set_char( s3->stash, PARSER_CLASS_KEY,   PARSER_CLASS );
36         sp_Stash_set_char( s3->stash, SELF_CLASS_KEY,     CLASS );
37        
38         //warn("new() stash refcnt = %d\n", SvREFCNT((SV*)SvRV((SV*)s3->stash)));
39         
40         //sp_describe_object( (SV*)s3->stash );
41         
42         // hardcode this till we can get ENV var or similar
43         s3->analyzer->tokenlist = 0;
44
45         if (s3->analyzer->tokenlist) {
46             s3->analyzer->tokenizer = (&sp_tokenize3);
47         }
48         else {
49             s3->analyzer->tokenizer = (&sp_tokenize);
50         }
51         s3->analyzer->stash  = sp_Stash_new();
52         sp_Stash_set_char( s3->analyzer->stash, SELF_CLASS_KEY, ANALYZER_CLASS );
53         s3->config->stash    = sp_Stash_new();
54         sp_Stash_set_char( s3->config->stash, SELF_CLASS_KEY, CONFIG_CLASS );
55                
56         RETVAL = s3;
57                
58     OUTPUT:
59         RETVAL
60
61
62
63 SV*
64 xml2_version(self)
65     SV* self;
66    
67     CODE:
68         RETVAL = newSVpvn( LIBXML_DOTTED_VERSION, strlen(LIBXML_DOTTED_VERSION) );
69        
70     OUTPUT:
71         RETVAL
72        
73              
74 SV*
75 version(self)
76     SV* self;
77    
78     CODE:
79         RETVAL = newSVpvn( SWISH_LIB_VERSION, strlen(SWISH_LIB_VERSION) );
80        
81     OUTPUT:
82         RETVAL   
83
84 SV*
85 slurp(self, filename)
86     swish_3*    self;
87     char*       filename;
88    
89     PREINIT:
90         xmlChar* buf;
91    
92     CODE:
93         buf     = swish_slurp_file((xmlChar*)filename);
94         RETVAL  = newSVpv( (const char*)buf, 0 );
95         swish_xfree(buf);
96        
97     OUTPUT:
98         RETVAL
99
100 int
101 parse_file(self, filename)
102     swish_3* self;
103         SV*          filename;
104    
105     PREINIT:
106         char* file;
107        
108     CODE:
109         file = SvPV(filename, PL_na);
110                
111 # need to swap return values to make it Perlish
112         RETVAL = swish_parse_file( self, (xmlChar*)file ) ? 0 : 1;
113                        
114     OUTPUT:
115         RETVAL
116        
117      
118 int
119 parse_buffer(self, buffer)
120     swish_3*    self;
121     SV*         buffer;
122    
123     PREINIT:
124         char* buf;
125        
126     CODE:
127         buf     = SvPV(buffer, PL_na);
128  
129 # need to swap return values to make it Perlish
130         RETVAL = swish_parse_buffer( self, (xmlChar*)buf ) ? 0 : 1;
131                
132     OUTPUT:
133         RETVAL
134
135 # TODO parse_fh
136
137
138
139 # accessors/mutators
140 void
141 _set_or_get(self, ...)
142     swish_3* self;
143 ALIAS:
144     set_config          = 1
145     get_config          = 2
146     set_analyzer        = 3
147     get_analyzer        = 4
148     set_parser          = 5
149     get_parser          = 6
150     set_handler         = 7
151     get_handler         = 8
152     set_data_class      = 9
153     get_data_class      = 10
154     set_parser_class    = 11
155     get_parser_class    = 12
156     set_config_class    = 13
157     get_config_class    = 14
158     set_analyzer_class  = 15
159     get_analyzer_class  = 16
160     set_regex           = 17
161     get_regex           = 18
162 PREINIT:
163     SV  *RETVAL;
164     char *class;
165 PPCODE:
166 {
167    
168     //warn("number of items %d for ix %d", items, ix);
169     
170     START_SET_OR_GET_SWITCH
171
172     // set_config
173     case 1if (!sv_derived_from(ST(1), CONFIG_CLASS)) {
174                 croak("usage: must be a %s object", CONFIG_CLASS);
175              }
176    
177              self->config->ref_cnt--;
178              //warn("set_config ref_cnt of old config = %d", self->config->ref_cnt);
179              if (self->config->ref_cnt < 1) {
180                 if (SWISH_DEBUG) {
181                     warn("freeing config on set_config");
182                 }
183                 sp_Stash_destroy(self->config->stash);
184                 if (self->config->stash != NULL) {
185                     //SWISH_WARN("set config stash to NULL");
186                     self->config->stash = NULL;
187                 }
188                 swish_free_config(self->config);
189              }
190              self->config = (swish_Config*)sp_extract_ptr(ST(1));
191              self->config->ref_cnt++;
192              //warn("set_config ref_cnt of new config = %d", self->config->ref_cnt);
193              break;
194              
195     // get_config   
196     case 2if (GIMME_V != G_VOID)
197                 self->config->ref_cnt++;
198              class = sp_Stash_get_char(self->stash, CONFIG_CLASS_KEY);
199              sp_Stash_set_char( self->config->stash, SELF_CLASS_KEY, class );
200              RETVAL = sp_bless_ptr(class, (IV)self->config);
201              break;
202
203     // set_analyzer
204     case 3if (!sv_derived_from(ST(1), ANALYZER_CLASS)) {
205                 croak("usage: must be a %s object", ANALYZER_CLASS);
206              }
207              
208              self->analyzer->ref_cnt--;
209              //warn("set_analyzer ref_cnt of old analyzer: %d", self->analyzer->ref_cnt);
210              if (self->analyzer->ref_cnt < 1) {
211                 if (SWISH_DEBUG) {
212                     warn("freeing analyzer on set_analyzer");
213                 }
214                 sp_Stash_destroy(self->analyzer->stash);
215                 swish_free_analyzer(self->analyzer);
216              }
217              self->analyzer = (swish_Analyzer*)sp_extract_ptr(ST(1));
218              self->analyzer->ref_cnt++;
219              //warn("set_analyzer ref_cnt of new analyzer: %d", self->analyzer->ref_cnt);
220              break;
221
222     // get_analyzer
223     case 4if (GIMME_V != G_VOID)
224                 self->analyzer->ref_cnt++;
225              class = sp_Stash_get_char(self->stash, ANALYZER_CLASS_KEY);
226              sp_Stash_set_char( self->analyzer->stash, SELF_CLASS_KEY, class );
227              RETVAL = sp_bless_ptr(class, (IV)self->analyzer);
228              break;
229
230     // set_parser
231     case 5if (!sv_derived_from(ST(1), PARSER_CLASS)) {
232                 croak("usage: must be a %s object", PARSER_CLASS);
233              }
234              
235              self->parser->ref_cnt--;
236              if (self->parser->ref_cnt < 1) {
237                 if (SWISH_DEBUG) {
238                     warn("freeing parser on set_parser");
239                 }
240                 swish_free_parser(self->parser);
241              }
242              self->parser = (swish_Parser*)sp_extract_ptr(ST(1));
243              self->parser->ref_cnt++;
244              break;
245            
246     // get_parser 
247     case 6if (GIMME_V != G_VOID)
248                 self->parser->ref_cnt++;
249              class = sp_Stash_get_char(self->stash, PARSER_CLASS_KEY);
250              RETVAL = sp_bless_ptr(class, (IV)self->parser);
251              break;
252
253     // set_handler
254     case 7:  sp_Stash_replace(self->stash, HANDLER_KEY, ST(1));
255              break;
256
257     // get_handler
258     case 8:  RETVAL = sp_Stash_get(self->stash, HANDLER_KEY);
259              break;
260    
261     // set_data_class
262     case 9:  sp_Stash_replace(self->stash, DATA_CLASS_KEY, ST(1));
263              break;
264              
265     // get_data_class
266     case 10: RETVAL = sp_Stash_get(self->stash, DATA_CLASS_KEY);
267              break;
268
269     // set_parser_class
270     case 11: sp_Stash_replace(self->stash, PARSER_CLASS_KEY, ST(1));
271              break;
272    
273     // get_parser_class
274     case 12: RETVAL = sp_Stash_get(self->stash, PARSER_CLASS_KEY);
275              break;
276    
277     // set_config_class
278     case 13: sp_Stash_replace(self->stash, CONFIG_CLASS_KEY, ST(1));
279              break;
280    
281     // get_config_class
282     case 14: RETVAL = sp_Stash_get(self->stash, CONFIG_CLASS_KEY);
283              break;
284
285     // set_analyzer_class
286     case 15: sp_Stash_replace(self->stash, ANALYZER_CLASS_KEY, ST(1));
287              break;
288    
289     // get_analyzer_class
290     case 16: RETVAL = sp_Stash_get(self->stash, ANALYZER_CLASS_KEY);
291              break;
292
293     // set_regex
294     case 17: sp_SV_is_qr( ST(1) );             
295              self->analyzer->regex = SvREFCNT_inc( ST(1) );
296              break;
297              
298     // get_regex
299     case 18: RETVAL  = self->analyzer->regex;
300              break;   
301        
302     END_SET_OR_GET_SWITCH
303 }
304
305 void
306 DESTROY(self)
307     SV *self;
308
309     PREINIT:
310         swish_3 *s3;
311        
312     CODE:
313         s3 = (swish_3*)sp_extract_ptr(self);
314         s3->ref_cnt--;
315
316         if ( SWISH_DEBUG ) {
317           warn("s3->stash refcnt = %d\n",
318             sp_Stash_inner_refcnt(s3->stash) );
319           warn("s3->config->stash refcnt = %d\n",
320             sp_Stash_inner_refcnt( s3->config->stash) );
321           warn("s3->analyzer->stash refcnt = %d\n",
322             sp_Stash_inner_refcnt( s3->analyzer->stash) );
323            
324         }           
325        
326         if (SWISH_DEBUG) {
327             warn("DESTROYing swish_3 object %s  [%d] [ref_cnt = %d]",
328                 SvPV(ST(0), PL_na), s3, s3->ref_cnt);
329         }
330        
331         if (s3->ref_cnt < 1) {
332             sp_Stash_destroy( s3->stash );
333             if ( s3->config->ref_cnt == 1 ) {
334                 sp_Stash_destroy( s3->config->stash );
335                 //SWISH_WARN("set config stash to NULL");
336                 s3->config->stash = NULL;
337             }
338             if ( s3->analyzer->ref_cnt == 1 ) {
339                 sp_Stash_destroy( s3->analyzer->stash );
340             }
341            
342             swish_free_swish3( s3 );
343         }
344        
345
346 int
347 refcount(obj)
348     SV* obj;
349        
350     CODE:
351         RETVAL = SvREFCNT((SV*)SvRV(obj));
352    
353     OUTPUT:
354         RETVAL
355
356
357 # utility methods
358
359 # tokenize() from Perl space uses same C func as tokenizer callback
360 swish_WordList *
361 tokenize(self, str, ...)
362     SV* self;
363     SV* str;
364    
365     PREINIT:
366         char* CLASS;
367         swish_WordList* list;
368         xmlChar* metaname;   
369         xmlChar* context;
370         unsigned int word_pos;
371         unsigned int offset;
372         xmlChar* buf;
373         int numtokens;
374        
375     CODE:
376         CLASS           = WORDLIST_CLASS;
377         list            = swish_init_wordlist();
378         list->ref_cnt++;
379         metaname        = (xmlChar*)SWISH_DEFAULT_METANAME;   
380         context         = (xmlChar*)SWISH_DEFAULT_METANAME;
381         word_pos        = 0;
382         offset          = 0;
383         buf             = (xmlChar*)SvPV(str, PL_na);
384        
385         // TODO reimplement as hashref arg
386                 
387         if (!SvUTF8(str))
388         {
389             if (swish_is_ascii(buf))
390                 SvUTF8_on(str);     /* flags original SV ?? */
391             else
392                 croak("%s is not flagged as a UTF-8 string and is not ASCII", buf);
393         }
394        
395         if ( items > 2 )
396         {
397             word_pos = (int)SvIV(ST(2));
398            
399             if ( items > 3 )
400                 offset = (int)SvIV(ST(3));
401                
402             if ( items > 4 )
403                 metaname = (xmlChar*)SvPV(ST(4), PL_na);
404                
405             if ( items > 5 )
406                 context = (xmlChar*)SvPV(ST(5), PL_na);
407                
408             //warn ("word_pos %d  offset %d  metaname %s  context %s\n", word_pos, offset, metaname, context );
409                 
410         }
411                        
412         numtokens = sp_tokenize(
413                         (swish_3*)sp_extract_ptr(self),
414                         buf,
415                         list,
416                         word_pos,
417                         offset,
418                         metaname,
419                         context
420                         );
421                
422         RETVAL = list;
423         /* TODO do we need to worry about free()ing metaname and context ?? */
424                        
425     OUTPUT:
426         RETVAL
427
428
429
430 # tokenize_isw() uses native libswish3 tokenizer
431 swish_WordList *
432 tokenize_isw(self, str, ...)
433     SV* self;
434     SV* str;
435
436     PREINIT:
437         char* CLASS;
438         swish_WordList* list;
439         xmlChar* metaname;   
440         xmlChar* context;
441         unsigned int word_pos;
442         unsigned int offset;
443         xmlChar* buf;
444         int numwords;
445        
446     CODE:
447         CLASS = WORDLIST_CLASS;
448         list = swish_init_wordlist();
449         list->ref_cnt++;
450         metaname = (xmlChar*)SWISH_DEFAULT_METANAME;   
451         context  = (xmlChar*)SWISH_DEFAULT_METANAME;
452         word_pos    = 0;
453         offset      = 0;
454         buf = (xmlChar*)SvPV(str, PL_na);
455        
456         if (!SvUTF8(str))
457         {
458             if (swish_is_ascii(buf))
459                 SvUTF8_on(str);     /* flags original SV ?? */
460             else
461                 croak("%s is not flagged as a UTF-8 string and is not ASCII", buf);
462         }
463        
464         if ( items > 2 )
465         {
466             word_pos = (int)SvIV(ST(2));
467            
468             if ( items > 3 )
469                 offset = (int)SvIV(ST(3));
470                
471             if ( items > 4 )
472                 metaname = (xmlChar*)SvPV(ST(4), PL_na);
473                
474             if ( items > 5 )
475                 context = (xmlChar*)SvPV(ST(5), PL_na);
476                
477         }
478                
479         swish_init_words(); /* in case it wasn't initialized elsewhere... */
480         numwords = swish_tokenize(
481                         (swish_3*)sp_extract_ptr(self),
482                         buf,
483                         list,
484                         word_pos,
485                         offset,
486                         metaname,
487                         context
488                         );
489        
490         RETVAL = list;
491        
492         /* TODO do we need to worry about free()ing metaname and context ?? */
493                        
494     OUTPUT:
495         RETVAL
496
497
498
499 # include the other .xs files
500 INCLUDE: XS/Config.xs
501 INCLUDE: XS/Analyzer.xs
502 INCLUDE: XS/WordList.xs
503 INCLUDE: XS/Word.xs
504 INCLUDE: XS/Doc.xs
505 INCLUDE: XS/Data.xs
506 INCLUDE: XS/Stash.xs
507 INCLUDE: XS/Property.xs
508 INCLUDE: XS/MetaName.xs
509 INCLUDE: XS/PropertyHash.xs
510 INCLUDE: XS/MetaNameHash.xs
511 INCLUDE: XS/xml2Hash.xs
512 INCLUDE: XS/Token.xs
513
Note: See TracBrowser for help on using the browser.