Ignore zoomst10
[yaz-moved-to-github.git] / test / nfatest1.c
1 /*  Copyright (C) 2006, Index Data ApS
2  *  See the file LICENSE for details.
3  *
4  *  $Id: nfatest1.c,v 1.6 2006-05-10 13:58:47 heikki Exp $
5  *
6  */
7
8
9 #include <stdio.h>
10 #include <string.h>
11 #include <yaz/nfa.h>
12 #include <yaz/nmem.h>
13 #include <yaz/test.h>
14
15
16 char *printfunc(void *result) {
17     static char buf[200];
18     sprintf(buf, "\"%s\"", (char*) result);
19     return buf;
20 }
21
22 char *printfunc2(void *result) {
23     static char buf[200];
24     sprintf(buf,"(%p)",  result);
25     return buf;
26 }
27
28 void test_match(yaz_nfa *n, 
29         yaz_nfa_char *buf, size_t buflen, 
30         int expcode, char *expstr) {
31     yaz_nfa_char *c = buf;
32     yaz_nfa_char *cp1, *cp2;
33     void *resptr = 0;
34     int i, bi;
35     size_t buflen2 = buflen;
36     i = yaz_nfa_match(n,&c, &buflen2,&resptr);
37     if (yaz_test_get_verbosity()>3)
38         printf("\n'%s' returned %d. Moved c by %d, and resulted in '%s'\n",
39             expstr, i, (c-buf),(char*)resptr);
40     YAZ_CHECK_EQ(buflen-buflen2, c-buf);
41     YAZ_CHECK_EQ(i, expcode);
42     if (i==0)
43         YAZ_CHECK_EQ(strcmp(expstr,(char*)resptr), 0);
44     i = 0;
45     bi = 0;
46     while((bi!=2) && (yaz_test_get_verbosity()>3)){
47         bi = yaz_nfa_get_backref(n, i,&cp1,&cp2);
48         if (bi==0 && ( cp1 || cp2 ) ) {
49             printf("  got backref %d of %d chars (%p to %p): '",
50                     i, cp2-cp1+1, cp1, cp2);
51             while (cp2-cp1 >= 0 )
52                 printf("%c", *cp1++);
53             printf("'\n");
54         }
55         i++;
56     }
57 }
58
59 void construction_test() {
60     yaz_nfa* n= yaz_nfa_init();
61     yaz_nfa_char *cp, *cp1, *cp2;
62     yaz_nfa_state *s, *s0, *s1, *s2, *s3, *s4, *s5;
63     int i;
64     yaz_nfa_char seq1[]={'p', 'r', 'e', 'f', 'i', 'x', 0};
65     yaz_nfa_char seq2[]={'p', 'r', 'e', 'l', 'i', 'm', 0};
66     yaz_nfa_char tst1[]={'c', 0};
67     yaz_nfa_char tst2[]={'c', 'k', 0};
68     yaz_nfa_char tst3[]={'c', 'x', 0};
69     yaz_nfa_char tst4[]={'z', 'k', 0};
70     yaz_nfa_char tst5[]={'y', 'k', 'l', 'k', 'k', 'l', 'k', 'd', 0};
71     yaz_nfa_char tst6[]={'x', 'z', 'k', 'a', 'b', 0};
72     void *p;
73     size_t sz;
74
75     YAZ_CHECK(n);
76
77     s = yaz_nfa_get_first(n);
78     YAZ_CHECK(!s);
79
80     s0 = yaz_nfa_add_state(n);
81
82     s = yaz_nfa_get_first(n);
83     YAZ_CHECK(s);
84     s = yaz_nfa_get_next(n, s);
85     YAZ_CHECK(!s);
86
87     s1 = yaz_nfa_add_state(n);
88     i = yaz_nfa_set_result(n, s1, "first");
89     YAZ_CHECK_EQ(i, 0);
90
91     i = yaz_nfa_set_result(n, s1, "DUPLICATE");
92     YAZ_CHECK_EQ(i, YAZ_NFA_ALREADY);
93
94     p = yaz_nfa_get_result(n, s1);
95     YAZ_CHECK(p);
96     YAZ_CHECK( strcmp((char*)p, "first")==0 );
97
98     i = yaz_nfa_set_result(n, s1, 0);
99     YAZ_CHECK_EQ(i, 0);
100     p = yaz_nfa_get_result(n, s1);
101     YAZ_CHECK(!p);
102     i = yaz_nfa_set_result(n, s1, "first");
103     YAZ_CHECK_EQ(i, 0);
104     
105     s2 = yaz_nfa_add_state(n);
106     s3 = yaz_nfa_add_state(n);
107     yaz_nfa_set_result(n, s3, "a-k, x-z");
108
109     s = yaz_nfa_get_first(n);
110     YAZ_CHECK(s);
111     s = yaz_nfa_get_next(n, s);
112     YAZ_CHECK(s);
113
114     
115     yaz_nfa_add_transition(n, s0, s1, 'a', 'k');
116     yaz_nfa_add_transition(n, s1, s1, 'k', 'k');
117     yaz_nfa_add_transition(n, s0, s2, 'p', 'p');
118     yaz_nfa_add_transition(n, s1, s3, 'x', 'z');
119
120     s = yaz_nfa_add_range(n, 0, 'k', 's' );
121     yaz_nfa_set_result(n, s, "K-S");
122
123     s4 = yaz_nfa_add_range(n, s2, 'l', 'r' );
124     s5 = yaz_nfa_add_range(n, s2, 'l', 'r' );
125     YAZ_CHECK((s4==s5));
126     s = yaz_nfa_add_range(n, 0, 'c', 'c' );
127
128     s = yaz_nfa_add_range(n, 0, 'z', 'z' );
129     yaz_nfa_add_empty_transition(n, s, s);
130     yaz_nfa_set_result(n, s, "loop");
131
132     s = yaz_nfa_add_range(n, 0, 'y', 'y' );
133     yaz_nfa_set_backref_point(n, s, 1, 1);
134     s1 = yaz_nfa_add_state(n);
135     yaz_nfa_add_empty_transition(n, s, s1);
136     s = s1;
137     yaz_nfa_add_transition(n, s, s, 'k', 'l');
138     s = yaz_nfa_add_range(n, s, 'd', 'd' );
139     yaz_nfa_set_result(n, s, "y k+ d");
140     yaz_nfa_set_backref_point(n, s, 1, 0);
141
142     s = yaz_nfa_add_sequence(n, 0, seq1,6 ); 
143     yaz_nfa_set_result(n, s, "PREFIX");
144     s = yaz_nfa_add_sequence(n, 0, seq2,6 ); 
145     yaz_nfa_set_result(n, s, "PRELIM");
146
147     s = yaz_nfa_add_range(n, 0, 'x', 'x' );
148     i=yaz_nfa_set_backref_point(n, s, 2, 0);
149     YAZ_CHECK_EQ(i,YAZ_NFA_NOSTART);
150     i=yaz_nfa_set_backref_point(n, s, 2, 1);
151     YAZ_CHECK_EQ(i,YAZ_NFA_SUCCESS);
152     i=yaz_nfa_set_backref_point(n, s, 2, 1);
153     YAZ_CHECK_EQ(i,YAZ_NFA_ALREADY);
154     s1 = yaz_nfa_add_sequence(n, s, tst4,2);
155     yaz_nfa_set_backref_point(n, s1, 2, 0);
156     yaz_nfa_set_result(n, s1, "xzk");
157
158     /* check return codes before doing any matches */
159     i = yaz_nfa_get_backref(n, 0, &cp1, &cp2 );
160     YAZ_CHECK_EQ(i, YAZ_NFA_NOMATCH);
161     i = yaz_nfa_get_backref(n, 3, &cp1, &cp2 );
162     YAZ_CHECK_EQ(i, YAZ_NFA_NOSUCHBACKREF );
163     i = yaz_nfa_get_backref(n, 1, &cp1, &cp2 );
164     YAZ_CHECK_EQ(i, YAZ_NFA_NOMATCH );
165
166     
167     if (yaz_test_get_verbosity()>3)
168         yaz_nfa_dump(0, n, printfunc);
169
170     test_match(n, seq2, 3, YAZ_NFA_OVERRUN, "K-S");
171     test_match(n, seq2, 6, YAZ_NFA_SUCCESS, "PRELIM");
172     test_match(n, tst1, 3, YAZ_NFA_SUCCESS, "first");
173     test_match(n, tst2, 3, YAZ_NFA_SUCCESS, "first");
174     test_match(n, tst3, 3, YAZ_NFA_SUCCESS, "a-k, x-z");
175     test_match(n, tst4, 9, YAZ_NFA_LOOP, "loop");
176     test_match(n, tst5, 9, YAZ_NFA_SUCCESS, "y k+ d");
177
178     cp = tst6;  /* xzkab */
179     sz = 8;
180     i = yaz_nfa_match(n, &cp, &sz, &p);
181     YAZ_CHECK_EQ(i, YAZ_NFA_SUCCESS); 
182     i = yaz_nfa_get_backref(n, 2, &cp1, &cp2 );
183     YAZ_CHECK_EQ(i, 0);
184     YAZ_CHECK_EQ(cp2-cp1+1,2); 
185     YAZ_CHECK_EQ(*cp1, 'z' );
186     YAZ_CHECK_EQ(*cp2, 'k' );
187     if (yaz_test_get_verbosity()>3)
188         printf("backref from %p '%c' to %p '%c' is %d long. sz is now %d\n",
189             cp1, *cp1,  cp2, *cp2,  cp2-cp1+1, sz );
190
191     yaz_nfa_destroy(n);
192 }
193
194 void converter_test() {
195     yaz_nfa* n= yaz_nfa_init();
196     yaz_nfa_converter *c1, *c2, *c3;
197     yaz_nfa_char str1[]={'a','b','c'};
198     yaz_nfa_char seq1[]={'A','B','C'};
199     yaz_nfa_char seq2[]={'k','m','n','m','x','P','Q','X',0};
200     yaz_nfa_char outbuf[1024];
201     yaz_nfa_char *outp, *cp, *cp1, *cp2;
202     yaz_nfa_state *s, *s2;
203     void *vp;
204     int i;
205     size_t sz;
206
207     c1=yaz_nfa_create_string_converter(n,str1,3);
208
209     for(i=0;i<1024;i++)
210         outbuf[i]=10000+i;
211     outp=outbuf;
212     sz=1;
213     i=yaz_nfa_run_converters(n, c1, &outp, &sz);
214     YAZ_CHECK_EQ(i,4); /* overrun */
215     YAZ_CHECK_EQ(outbuf[0],'a');
216     YAZ_CHECK_EQ(outbuf[1],10000+1);
217
218     for(i=0;i<1024;i++)
219         outbuf[i]=10000+i;
220     outp=outbuf;
221     sz=3;
222     i=yaz_nfa_run_converters(n, c1, &outp, &sz);
223     YAZ_CHECK_EQ(i,0); 
224     YAZ_CHECK_EQ(outbuf[0],'a');
225     YAZ_CHECK_EQ(outbuf[1],'b');
226     YAZ_CHECK_EQ(outbuf[2],'c');
227     YAZ_CHECK_EQ(outbuf[3],10000+3);
228     YAZ_CHECK_EQ(sz,0);
229     
230     c2=yaz_nfa_create_string_converter(n,str1,2);
231     yaz_nfa_append_converter(n,c1,c2);
232
233     for(i=0;i<1024;i++)
234         outbuf[i]=10000+i;
235     outp=outbuf;
236     sz=10;
237     i=yaz_nfa_run_converters(n, c1, &outp, &sz);
238     YAZ_CHECK_EQ(i,0); 
239     YAZ_CHECK_EQ(outbuf[0],'a');
240     YAZ_CHECK_EQ(outbuf[1],'b');
241     YAZ_CHECK_EQ(outbuf[2],'c');
242     YAZ_CHECK_EQ(outbuf[3],'a');
243     YAZ_CHECK_EQ(outbuf[4],'b');
244     YAZ_CHECK_EQ(outbuf[5],10000+5);
245     YAZ_CHECK_EQ(sz,5);
246     
247     /* ABC -> abcab */
248     (void) yaz_nfa_add_state(n);/* start state */
249     s=yaz_nfa_add_state(n);
250     yaz_nfa_add_empty_transition(n,0,s);
251     yaz_nfa_set_backref_point(n,s,1,1);
252     s=yaz_nfa_add_sequence(n, s, seq1,3 ); 
253     yaz_nfa_set_result(n,s,c1);
254     yaz_nfa_set_backref_point(n,s,1,0);
255
256     /* ([k-o][m-n]*)x -> \1 */
257     s=yaz_nfa_add_state(n);
258     yaz_nfa_add_empty_transition(n,0,s);
259     yaz_nfa_set_backref_point(n,s,2,1);
260     s2=yaz_nfa_add_state(n);
261     yaz_nfa_add_transition(n,s,s2,'k','o');
262     yaz_nfa_add_transition(n,s2,s2,'m','n');
263     s=yaz_nfa_add_state(n);
264     yaz_nfa_add_transition(n,s2,s,'x','x');
265     yaz_nfa_set_backref_point(n,s,2,0);
266
267     c1=yaz_nfa_create_backref_converter(n,2);
268     yaz_nfa_set_result(n,s,c1);
269
270     if (yaz_test_get_verbosity()>3)
271         yaz_nfa_dump(0,n, printfunc2);
272
273     cp=seq2;
274     sz=18;
275     i=yaz_nfa_match(n,&cp,&sz,&vp);
276     c2=vp;
277     YAZ_CHECK_EQ(i,YAZ_NFA_SUCCESS); 
278     i=yaz_nfa_get_backref(n, 2, &cp1, &cp2 );
279     if (yaz_test_get_verbosity()>3)
280         printf("backref from %p '%c' to %p '%c' is %d long. sz is now %d\n",
281             cp1, *cp1,  cp2, *cp2,  cp2-cp1+1, sz );
282     YAZ_CHECK_EQ(i,0);
283     YAZ_CHECK_EQ((int)c1,(int)c2);  /* got our pointer back from nfa */
284     for(i=0;i<1024;i++)
285         outbuf[i]=10000+i;
286     outp=outbuf;
287     sz=11;
288     i=yaz_nfa_run_converters(n, c2, &outp, &sz);
289     YAZ_CHECK_EQ(i,0); 
290     YAZ_CHECK_EQ(outbuf[0],'k');
291     YAZ_CHECK_EQ(outbuf[1],'m');
292     YAZ_CHECK_EQ(outbuf[2],'n');
293     YAZ_CHECK_EQ(outbuf[3],'m');
294     YAZ_CHECK_EQ(outbuf[4],'x');
295     YAZ_CHECK_EQ(outbuf[5],10000+5);
296     YAZ_CHECK_EQ(sz,11-5);
297
298     c3=yaz_nfa_create_range_converter(n,2, 'a', 'A' );
299     for(i=0;i<1024;i++)
300         outbuf[i]=10000+i;
301     outp=outbuf;
302     sz=11;
303     i=yaz_nfa_run_converters(n, c3, &outp, &sz);
304     YAZ_CHECK_EQ(i,0); 
305     YAZ_CHECK_EQ(outbuf[0],'K');
306     YAZ_CHECK_EQ(outbuf[1],'M');
307     YAZ_CHECK_EQ(outbuf[2],'N');
308     YAZ_CHECK_EQ(outbuf[3],'M');
309     YAZ_CHECK_EQ(outbuf[4],'X');
310     YAZ_CHECK_EQ(outbuf[5],10000+5);
311     YAZ_CHECK_EQ(sz,11-5);
312
313     yaz_nfa_destroy(n);
314 }
315
316 yaz_nfa_char *makebuff(NMEM nmem, char *in) {
317     yaz_nfa_char *buff = nmem_malloc(nmem, strlen(in)*sizeof(yaz_nfa_char));
318     yaz_nfa_char *op=buff;
319     while ( (*op++ = *in++) )
320         ;
321     return buff;
322 }
323
324 void dumpbuff(char *msg, yaz_nfa_char *start, yaz_nfa_char *end) {
325     if (yaz_test_get_verbosity()>3) {
326         printf("%s\"",msg);
327         while (start!=end)
328             printf("%c",*start++);
329         printf("\"\n");
330     }
331 }
332
333 void chkbuff( yaz_nfa_char *start, yaz_nfa_char *end, char *exp) {
334     char *orig_exp=exp;
335     while (start!=end)
336         if ( *start++ != *exp++ ) {
337             if (yaz_test_get_verbosity()>3) {
338                 start--;
339                 exp--;
340                 printf ("chkbuff: unexpected conversion '%c' != '%c' \n"
341                         "\"%s\"\n", *start, *exp, orig_exp );
342             }
343             YAZ_CHECK(!"conversion differs! ");
344             return;
345         }
346
347 }
348
349 void high_level_test() {
350     NMEM nmem=nmem_create();
351     yaz_nfa_char from1[] = {'f','o','o','b','a','r'};
352     yaz_nfa_char to1[] = {'f','u','b','a','r'};
353     yaz_nfa_char tospace[] = {' '};
354     yaz_nfa_char todot[] = {'.'};
355     char *fromtext =
356             "It was a Dark and Rainy Night, when alpha and beta "
357             "fixme - FIND better names ?? !! ##  - "
358             "went out to fix the foobar "
359             "that was all foo.";
360     char *expected = 
361             "IT WAS A DARK AND RAINY NIGHT. WHEN ALPHA AND b "
362             "to-be-fixed-later . FIND BETTER NAMES .. .. ..  . "
363             "WENT OUT TO (fix) THE fubar "
364             "THAT WAS ALL FOO.";
365     yaz_nfa_char *from3 = makebuff(nmem,fromtext);
366     yaz_nfa_char *to3 = nmem_malloc(nmem, 1024*sizeof(yaz_nfa_char));
367     yaz_nfa_char *fromp=from3;
368     yaz_nfa_char *top=to3;
369     size_t insize=strlen(fromtext);
370     size_t outsize=1024;
371     size_t prev_insize=0;
372
373     yaz_nfa *n = yaz_nfa_init();
374     int i;
375     i = yaz_nfa_add_string_rule(n, from1, 6, to1, 5);
376     YAZ_CHECK_EQ(i,0);
377     i = yaz_nfa_add_string_rule(n, from1, 6, to1, 5);
378     YAZ_CHECK_EQ(i,YAZ_NFA_ALREADY);
379     i = yaz_nfa_add_ascii_string_rule(n,"beta","b");
380     YAZ_CHECK_EQ(i,0);
381     i = yaz_nfa_add_ascii_string_rule(n,"fixme","to-be-fixed-later");
382     YAZ_CHECK_EQ(i,0);
383     i = yaz_nfa_add_ascii_string_rule(n,"fix","(fix)");
384     YAZ_CHECK_EQ(i,0);
385     i = yaz_nfa_add_char_range_rule(n, 'a','z','A');
386     YAZ_CHECK_EQ(i,0);
387     i = yaz_nfa_add_char_string_rule(n, 0,' ', tospace,1);
388     YAZ_CHECK_EQ(i,0);
389     i = yaz_nfa_add_char_string_rule(n, '!','/', todot,1);
390     YAZ_CHECK_EQ(i,0);
391     i = yaz_nfa_add_char_string_rule(n, ':','?', todot,1);
392     YAZ_CHECK_EQ(i,0);
393     if (yaz_test_get_verbosity()>3)
394         yaz_nfa_dump(0,n, printfunc2);
395
396     YAZ_CHECK_EQ( *from3, 'I' ); /* just to be sure my copy func works */
397     for (i=0;i<100;i++)
398         to3[i]=10000+i;
399     i=yaz_nfa_convert_slice(n, &fromp, &insize, &top, &outsize);
400     YAZ_CHECK_EQ(i,YAZ_NFA_SUCCESS);
401     YAZ_CHECK_EQ(*to3,'I');
402     YAZ_CHECK_EQ(insize, strlen(fromtext)-1);
403     YAZ_CHECK_EQ(outsize, 1024-1);
404
405     while ( (i==YAZ_NFA_SUCCESS) && (insize > 0) && (prev_insize!=insize) ) {
406         prev_insize=insize; /* detect dead loops if something goes wrong */
407         i=yaz_nfa_convert_slice(n, &fromp, &insize, &top, &outsize);
408     }
409     YAZ_CHECK_EQ(i,YAZ_NFA_SUCCESS);
410     YAZ_CHECK_EQ(insize,0);
411     YAZ_CHECK(prev_insize != insize); /* the loop would have been endless */
412
413     dumpbuff("Original text: ",from3, fromp);
414     dumpbuff("Converted text: ",to3, top);
415
416     chkbuff(to3, top, expected);
417
418     yaz_nfa_destroy(n);
419     nmem_destroy(nmem);
420 }
421
422 int main(int argc, char **argv)
423 {
424     YAZ_CHECK_INIT(argc, argv);
425     nmem_init ();
426     construction_test(); 
427     converter_test();
428     high_level_test();
429     nmem_exit ();
430     YAZ_CHECK_TERM;
431 }
432
433
434 /* 
435  * Local variables:
436  * c-basic-offset: 4
437  * indent-tabs-mode: nil
438  * End:
439  * vim: shiftwidth=4 tabstop=8 expandtab
440  */