First implementation of yaz_stemmer API. Can compile.
[yaz-moved-to-github.git] / src / stemmer.c
1
2
3 #if HAVE_CONFIG_H
4 #include "config.h"
5 #endif
6
7 #if YAZ_HAVE_ICU
8
9 #include <yaz/yconfig.h>
10
11 #include <yaz/stemmer.h>
12
13 #include <yaz/xmalloc.h>
14
15 #include <libstemmer.h>
16
17 #include <unicode/ustring.h>  /* some more string fcns*/
18 #include <unicode/uchar.h>    /* char names           */
19
20 enum stemmer_implementation {
21     yaz_snowball
22 };
23 struct yaz_stemmer_t
24 {
25     int implementation;
26     // Required for cloning.
27     const char *locale;
28     const char *rule;
29     union {
30         struct sb_stemmer *sb_stemmer;
31     };
32 };
33
34 const char* yaz_stemmer_lookup_charenc(const char *charenc) {
35     return charenc;
36 }
37
38 const char* yaz_stemmer_lookup_algorithm(const char *locale, const char *rule) {
39     return rule;
40 }
41
42 yaz_stemmer_p yaz_stemmer_snowball_create(const char *locale, const char *rule, UErrorCode *status) {
43     const char *charenc = yaz_stemmer_lookup_charenc(locale);
44     const char *algorithm = yaz_stemmer_lookup_algorithm(locale,rule);
45     struct sb_stemmer *stemmer = sb_stemmer_new(algorithm, charenc);
46     yaz_stemmer_p yaz_stemmer;
47     if (stemmer == 0) {
48         *status = U_ARGUMENT_TYPE_MISMATCH;
49         return 0;
50     }
51     yaz_stemmer = xmalloc(sizeof(*yaz_stemmer));
52     yaz_stemmer->implementation = yaz_snowball;
53     yaz_stemmer->locale = xstrdup(locale);
54     yaz_stemmer->rule = xstrdup(rule);
55     yaz_stemmer->sb_stemmer = stemmer;
56
57     return yaz_stemmer;
58 }
59
60 yaz_stemmer_p yaz_stemmer_create(const char *locale, const char *rule, UErrorCode *status) {
61     *status = U_ZERO_ERROR;
62     // dispatch logic required if more algorithms is implemented.
63     return yaz_stemmer_snowball_create(locale, rule, status);
64 }
65
66 yaz_stemmer_p yaz_stemmer_clone(yaz_stemmer_p stemmer) {
67     UErrorCode error = U_ZERO_ERROR;
68     return yaz_stemmer_create(stemmer->locale, stemmer->rule, &error);
69 }
70
71 void yaz_stemmer_stem(yaz_stemmer_p stemmer, struct icu_buf_utf16 *dst, struct icu_buf_utf16* src, UErrorCode *status)
72 {
73     switch(stemmer->implementation) {
74     case yaz_snowball: {
75         int length;
76         struct icu_buf_utf8 *utf8_buf = icu_buf_utf8_create(0);
77         icu_utf16_to_utf8(utf8_buf, src, status);
78         if (*status == U_ZERO_ERROR) {
79             const char *sb_symbol = sb_stemmer_stem(stemmer->sb_stemmer, icu_buf_utf8_to_cstr(utf8_buf), length);
80             if (sb_symbol == 0) {
81                 icu_buf_utf16_copy(dst, src);
82             }
83             else {
84                 icu_utf16_from_utf8_cstr(dst, sb_symbol, status);
85             }
86         }
87         return ;
88         break;
89     }
90     }
91 }
92
93 void yaz_stemmer_destroy(yaz_stemmer_p stemmer) {
94     switch (stemmer->implementation) {
95     case yaz_snowball:
96         sb_stemmer_delete(stemmer->sb_stemmer);
97         break;
98     }
99     free(stemmer->locale);
100     free(stemmer->rule);
101     free(stemmer);
102 }
103
104 #endif /* YAZ_HAVE_ICU */