1 #ifdef __cplusplus
2 extern "C" {
3 #endif
4 #include "EXTERN.h"
5 #include "perl.h"
6 #include "XSUB.h"
7 #include "patchlevel.h"
8 #ifdef __cplusplus
9 }
10 #endif
11 
12 #include "apse.h"
13 
14 #if PATCHLEVEL < 5
15 # define PL_na na
16 #endif
17 
18 MODULE = String::Approx         PACKAGE = String::Approx
19 
20 PROTOTYPES: DISABLE
21 
22 apse_t*
23 new(CLASS, pattern, ...)
24         char*           CLASS
25         SV*             pattern
26     CODE:
27         apse_t*         ap;
28         apse_size_t     edit_distance;
29         IV pattern_size = sv_len(pattern);
30         if (items == 2)
31                 edit_distance = ((pattern_size-1)/10)+1;
32         else if (items == 3)
33                 edit_distance = (apse_size_t)SvIV(ST(2));
34         else {
35                 warn("Usage: new(pattern[, edit_distance])\n");
36                 XSRETURN_UNDEF;
37         }
38         ap = apse_create((unsigned char *)SvPV(pattern, PL_na),
39                          pattern_size, edit_distance);
40         if (ap) {
41                 RETVAL = ap;
42         } else {
43                 warn("unable to allocate");
44                 XSRETURN_UNDEF;
45         }
46     OUTPUT:
47         RETVAL
48 
49 void
50 DESTROY(ap)
51         apse_t*         ap
52     CODE:
53         apse_destroy(ap);
54 
55 apse_bool_t
56 match(ap, text)
57         apse_t*         ap
58         SV*             text
59     CODE:
60         RETVAL = apse_match(ap,
61                             (unsigned char *)SvPV(text, PL_na),
62                             sv_len(text));
63     OUTPUT:
64         RETVAL
65 
66 apse_bool_t
67 match_next(ap, text)
68         apse_t*         ap
69         SV*             text
70     CODE:
71         RETVAL = apse_match_next(ap,
72                                  (unsigned char *)SvPV(text, PL_na),
73                                  sv_len(text));
74     OUTPUT:
75         RETVAL
76 
77 apse_ssize_t
78 index(ap, text)
79         apse_t*         ap
80         SV*             text
81     CODE:
82         RETVAL = apse_index(ap,
83                             (unsigned char *)SvPV(text, PL_na),
84                             sv_len(text));
85     OUTPUT:
86         RETVAL
87 
88 void
slice(ap,text)89 slice(ap, text)
90         apse_t*         ap
91         SV*             text
92     PREINIT:
93         apse_size_t     match_begin;
94         apse_size_t     match_size;
95     PPCODE:
96 	if (ap->use_minimal_distance) {
97 	  apse_slice(ap,
98 		     (unsigned char *)SvPV(text, PL_na),
99 		     (apse_size_t)sv_len(text),
100 		     &match_begin,
101 		     &match_size);
102 	  EXTEND(sp, 3);
103 	  PUSHs(sv_2mortal(newSViv(match_begin)));
104 	  PUSHs(sv_2mortal(newSViv(match_size)));
105 	  PUSHs(sv_2mortal(newSViv(ap->edit_distance)));
106 	} else if (apse_slice(ap,
107 			      (unsigned char *)SvPV(text, PL_na),
108 			      (apse_size_t)sv_len(text),
109 			      &match_begin,
110 			      &match_size)) {
111 	  EXTEND(sp, 2);
112 	  PUSHs(sv_2mortal(newSViv(match_begin)));
113 	  PUSHs(sv_2mortal(newSViv(match_size)));
114         }
115 
116 void
slice_next(ap,text)117 slice_next(ap, text)
118         apse_t*         ap
119         SV*             text
120     PREINIT:
121         apse_size_t     match_begin;
122         apse_size_t     match_size;
123     PPCODE:
124         if (apse_slice_next(ap,
125                             (unsigned char *)SvPV(text, PL_na),
126                             sv_len(text),
127                             &match_begin,
128                             &match_size)) {
129                 EXTEND(sp, 2);
130                 PUSHs(sv_2mortal(newSViv(match_begin)));
131                 PUSHs(sv_2mortal(newSViv(match_size)));
132 		if (ap->use_minimal_distance) {
133 		    EXTEND(sp, 1);
134 		    PUSHs(sv_2mortal(newSViv(ap->edit_distance)));
135 		}
136         }
137 
138 void
139 set_greedy(ap)
140         apse_t*         ap
141     CODE:
142         apse_set_greedy(ap, 1);
143 
144 apse_bool_t
145 set_caseignore_slice(ap, ...)
146         apse_t* ap
147     PREINIT:
148         apse_size_t     offset;
149         apse_size_t     size;
150         apse_bool_t     ignore;
151     CODE:
152         offset = items < 2 ? 0 : (apse_size_t)SvIV(ST(1));
153         size   = items < 3 ? ap->pattern_size : (apse_size_t)SvIV(ST(2));
154         ignore = items < 4 ? 1 : (apse_bool_t)SvIV(ST(3));
155         RETVAL = apse_set_caseignore_slice(ap, offset, size, ignore);
156     OUTPUT:
157         RETVAL
158 
159 apse_bool_t
160 set_insertions(ap, insertions)
161         apse_t*         ap
162         apse_size_t     insertions = SvUV($arg);
163     CODE:
164         RETVAL = apse_set_insertions(ap, insertions);
165     OUTPUT:
166         RETVAL
167 
168 apse_bool_t
169 set_deletions(ap, deletions)
170         apse_t*         ap
171         apse_size_t     deletions = SvUV($arg);
172     CODE:
173         RETVAL = apse_set_deletions(ap, deletions);
174     OUTPUT:
175         RETVAL
176 
177 apse_bool_t
178 set_substitutions(ap, substitutions)
179         apse_t*         ap
180         apse_size_t     substitutions = SvUV($arg);
181     CODE:
182         RETVAL = apse_set_substitutions(ap, substitutions);
183     OUTPUT:
184         RETVAL
185 
186 apse_bool_t
187 set_edit_distance(ap, edit_distance)
188         apse_t*         ap
189         apse_size_t     edit_distance = SvUV($arg);
190     CODE:
191         RETVAL = apse_set_edit_distance(ap, edit_distance);
192     OUTPUT:
193         RETVAL
194 
195 apse_size_t
196 get_edit_distance(ap)
197         apse_t*         ap
198     CODE:
199         ST(0) = sv_newmortal();
200         sv_setiv(ST(0), apse_get_edit_distance(ap));
201 
202 apse_bool_t
203 set_text_initial_position(ap, text_initial_position)
204         apse_t*         ap
205         apse_size_t     text_initial_position = SvUV($arg);
206     CODE:
207         RETVAL = apse_set_text_initial_position(ap, text_initial_position);
208     OUTPUT:
209         RETVAL
210 
211 apse_bool_t
212 set_text_final_position(ap, text_final_position)
213         apse_t*         ap
214         apse_size_t     text_final_position = SvUV($arg);
215     CODE:
216         RETVAL = apse_set_text_final_position(ap, text_final_position);
217     OUTPUT:
218         RETVAL
219 
220 apse_bool_t
221 set_text_position_range(ap, text_position_range)
222         apse_t*         ap
223         apse_size_t     text_position_range = SvUV($arg);
224     CODE:
225         RETVAL = apse_set_text_position_range(ap, text_position_range);
226     OUTPUT:
227         RETVAL
228 
229 void
230 set_minimal_distance(ap, b)
231         apse_t*         ap
232 	apse_bool_t	b
233     CODE:
234         apse_set_minimal_distance(ap, b);
235