Fix left/right switch of truncation flag
[yaz-moved-to-github.git] / src / tokenizer.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2011 Index Data
3  * See the file LICENSE for details.
4  */
5 /**
6  * \file tokenizer.c
7  * \brief Simple tokenizer system.
8  */
9 #if HAVE_CONFIG_H
10 #include <config.h>
11 #endif
12
13 #include <assert.h>
14 #include <stdio.h>
15 #include <string.h>
16 #include <ctype.h>
17 #include <yaz/log.h>
18 #include <yaz/wrbuf.h>
19 #include <yaz/tokenizer.h>
20
21 struct yaz_tok_parse {
22     int unget_byte;
23     WRBUF wr_string;
24     int look;
25     
26     yaz_tok_cfg_t cfg;
27     yaz_tok_get_byte_t get_byte_func;
28     void *get_byte_data;
29 };
30
31 struct yaz_tok_cfg {
32     int ref_count;
33     char *comment;
34     char *white_space;
35     char *single_tokens;
36     char *quote_tokens_begin;
37     char *quote_tokens_end;
38 };
39
40 void yaz_tok_cfg_single_tokens(yaz_tok_cfg_t t, const char *simple)
41 {
42     xfree(t->single_tokens);
43     t->single_tokens = xstrdup(simple);
44 }
45
46 yaz_tok_cfg_t yaz_tok_cfg_create(void)
47 {
48     yaz_tok_cfg_t t = (yaz_tok_cfg_t) xmalloc(sizeof(*t));
49     t->white_space = xstrdup(" \t\r\n");
50     t->single_tokens = xstrdup("");
51     t->quote_tokens_begin = xstrdup("\"");
52     t->quote_tokens_end = xstrdup("\"");
53     t->comment = xstrdup("#");
54     t->ref_count = 1;
55     return t;
56 }
57
58 void yaz_tok_cfg_destroy(yaz_tok_cfg_t t)
59 {
60     t->ref_count--;
61     if (t->ref_count == 0)
62     {
63         xfree(t->white_space);
64         xfree(t->single_tokens);
65         xfree(t->quote_tokens_begin);
66         xfree(t->quote_tokens_end);
67         xfree(t->comment);
68         xfree(t);
69     }
70 }
71
72 static int read_buf(void **vp)
73 {
74     const char *cp = *(const char **) vp;
75     int ch = *cp;
76     if (ch)
77     {
78         cp++;
79         *(const char **)vp = cp;
80     }
81     return ch;
82 }
83
84 yaz_tok_parse_t yaz_tok_parse_buf(yaz_tok_cfg_t t, const char *buf)
85 {
86     return yaz_tok_parse_create(t, read_buf, (void *) buf);
87 }
88
89 static int get_byte(yaz_tok_parse_t tp)
90 {
91     int ch = tp->unget_byte;
92     assert(tp->get_byte_func);
93     if (ch)
94         tp->unget_byte = 0;
95     else
96         ch = tp->get_byte_func(&tp->get_byte_data);
97     return ch;
98 }
99
100 static void unget_byte(yaz_tok_parse_t tp, int ch)
101 {
102     tp->unget_byte = ch;
103 }
104
105 yaz_tok_parse_t yaz_tok_parse_create(yaz_tok_cfg_t t,
106                                      yaz_tok_get_byte_t h,
107                                      void *vp)
108 {
109     yaz_tok_parse_t tp = (yaz_tok_parse_t) xmalloc(sizeof(*tp));
110
111     tp->cfg = t;
112     tp->cfg->ref_count++;
113     tp->get_byte_func = h;
114     tp->get_byte_data = vp;
115
116     tp->look = YAZ_TOK_ERROR;
117     tp->unget_byte = 0;
118
119     tp->wr_string = wrbuf_alloc();
120     return tp;
121 }
122                                            
123
124 void yaz_tok_parse_destroy(yaz_tok_parse_t tp)
125 {
126     yaz_tok_cfg_destroy(tp->cfg);
127     wrbuf_destroy(tp->wr_string);
128     xfree(tp);
129 }
130
131 int yaz_tok_move(yaz_tok_parse_t tp)
132 {
133     yaz_tok_cfg_t t = tp->cfg;
134     const char *cp;
135     int ch = get_byte(tp);
136
137     /* skip white space */
138     while (ch && strchr(t->white_space, ch))
139         ch = get_byte(tp);
140     if (!ch) 
141         ch = YAZ_TOK_EOF;
142     else if (strchr(t->comment, ch))
143         ch = YAZ_TOK_EOF;
144     else if ((cp = strchr(t->single_tokens, ch)))
145         ch = *cp;  /* single token match */
146     else if ((cp = strchr(t->quote_tokens_begin, ch)))
147     {   /* quoted string */
148         int end_ch = t->quote_tokens_end[cp - t->quote_tokens_begin];
149         ch = get_byte(tp);
150         wrbuf_rewind(tp->wr_string);
151         while (ch && ch != end_ch)
152             wrbuf_putc(tp->wr_string, ch);
153         if (!ch)
154             ch = YAZ_TOK_ERROR;
155         else
156             ch = YAZ_TOK_QSTRING;
157     }
158     else
159     {  /* unquoted string */
160         wrbuf_rewind(tp->wr_string);
161         while (ch && !strchr(t->white_space, ch)
162                && !strchr(t->single_tokens, ch)
163                && !strchr(t->comment, ch))
164         {
165             wrbuf_putc(tp->wr_string, ch);
166             ch = get_byte(tp);
167         }
168         unget_byte(tp, ch);
169         ch = YAZ_TOK_STRING;
170     }
171     tp->look = ch;
172     return ch;
173 }
174
175 const char *yaz_tok_parse_string(yaz_tok_parse_t tp)
176 {
177     return wrbuf_cstr(tp->wr_string);
178 }
179
180 /*
181  * Local variables:
182  * c-basic-offset: 4
183  * c-file-style: "Stroustrup"
184  * indent-tabs-mode: nil
185  * End:
186  * vim: shiftwidth=4 tabstop=8 expandtab
187  */
188