Fixed 523: PQF parser does not properly diagnose @prox syntax errors.
[yaz-moved-to-github.git] / src / wrbuf.c
1 /*
2  * Copyright (C) 1995-2005, Index Data ApS
3  * See the file LICENSE for details.
4  *
5  * $Id: wrbuf.c,v 1.9 2005-09-27 17:52:46 adam Exp $
6  */
7
8 /**
9  * \file wrbuf.c
10  * \brief Implements WRBUF (growing buffer)
11  */
12
13 #if HAVE_CONFIG_H
14 #include <config.h>
15 #endif
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <stdarg.h>
21
22 #include <yaz/wrbuf.h>
23 #include <yaz/yaz-iconv.h>
24
25 WRBUF wrbuf_alloc(void)
26 {
27     WRBUF n;
28
29     if (!(n = (WRBUF)xmalloc(sizeof(*n))))
30         abort();
31     n->buf = 0;
32     n->size = 0;
33     n->pos = 0;
34     return n;
35 }
36
37 void wrbuf_free(WRBUF b, int free_buf)
38 {
39     if (free_buf && b->buf)
40         xfree(b->buf);
41     xfree(b);
42 }
43
44 void wrbuf_rewind(WRBUF b)
45 {
46     b->pos = 0;
47 }
48
49 int wrbuf_grow(WRBUF b, int minsize)
50 {
51     int togrow;
52
53     if (!b->size)
54         togrow = 1024;
55     else
56         togrow = b->size;
57     if (togrow < minsize)
58         togrow = minsize;
59     if (b->size && !(b->buf =(char *)xrealloc(b->buf, b->size += togrow)))
60         abort();
61     else if (!b->size && !(b->buf = (char *)xmalloc(b->size = togrow)))
62         abort();
63     return 0;
64 }
65
66 int wrbuf_write(WRBUF b, const char *buf, int size)
67 {
68     if (size <= 0)
69         return 0;
70     if (b->pos + size >= b->size)
71         wrbuf_grow(b, size);
72     memcpy(b->buf + b->pos, buf, size);
73     b->pos += size;
74     return 0;
75 }
76
77 int wrbuf_puts(WRBUF b, const char *buf)
78 {
79     wrbuf_write(b, buf, strlen(buf)+1);  /* '\0'-terminate as well */
80     (b->pos)--;                          /* don't include '\0' in count */
81     return 0;
82 }
83
84 void wrbuf_chop_right(WRBUF b)
85 {
86     while (b->pos && b->buf[b->pos-1] == ' ')
87     {
88         (b->pos)--;
89         b->buf[b->pos] = '\0';
90     }
91 }
92
93 int wrbuf_xmlputs(WRBUF b, const char *cp)
94 {
95     return wrbuf_xmlputs_n(b, cp, strlen(cp));
96 }
97
98 int wrbuf_xmlputs_n(WRBUF b, const char *cp, int size)
99 {
100     while (--size >= 0)
101     {
102         /* only TAB,CR,LF of ASCII CTRL are allowed in XML 1.0! */
103         if (*cp >= 0 && *cp <= 31)
104             if (*cp != 9 && *cp != 10 && *cp != 13)
105             {
106                 cp++;  /* we silently ignore (delete) these.. */
107                 continue;
108             }
109         switch(*cp)
110         {
111         case '<':
112             wrbuf_puts(b, "&lt;");
113             break;
114         case '>':
115             wrbuf_puts(b, "&gt;");
116             break;
117         case '&':
118             wrbuf_puts(b, "&amp;");
119             break;
120         case '"':
121             wrbuf_puts(b, "&quot;");
122             break;
123         case '\'':
124             wrbuf_puts(b, "&apos;");
125             break;
126         default:
127             wrbuf_putc(b, *cp);
128         }
129         cp++;
130     }
131     wrbuf_putc(b, 0);
132     (b->pos)--;
133     return 0;
134 }
135
136 void wrbuf_printf(WRBUF b, const char *fmt, ...)
137 {
138     va_list ap;
139     char buf[4096];
140
141     va_start(ap, fmt);
142 #ifdef WIN32
143     _vsnprintf(buf, sizeof(buf)-1, fmt, ap);
144 #else
145 /* !WIN32 */
146 #if HAVE_VSNPRINTF
147     vsnprintf(buf, sizeof(buf)-1, fmt, ap);
148 #else
149     vsprintf(buf, fmt, ap);
150 #endif
151 #endif
152     wrbuf_puts (b, buf);
153
154     va_end(ap);
155 }
156
157 static int wrbuf_iconv_write_x(WRBUF b, yaz_iconv_t cd, const char *buf,
158                                int size, int cdata)
159 {
160     if (cd)
161     {
162         char outbuf[12];
163         size_t inbytesleft = size;
164         const char *inp = buf;
165         while (inbytesleft)
166         {
167             size_t outbytesleft = sizeof(outbuf);
168             char *outp = outbuf;
169             size_t r = yaz_iconv(cd, (char**) &inp,  &inbytesleft,
170                                  &outp, &outbytesleft);
171             if (r == (size_t) (-1))
172             {
173                 int e = yaz_iconv_error(cd);
174                 if (e != YAZ_ICONV_E2BIG)
175                     break;
176             }
177             if (cdata)
178                 wrbuf_xmlputs_n(b, outbuf, outp - outbuf);
179             else
180                 wrbuf_write(b, outbuf, outp - outbuf);
181         }
182     }
183     else
184     {
185         if (cdata)
186             wrbuf_xmlputs_n(b, buf, size);
187         else
188             wrbuf_write(b, buf, size);
189     }
190     return wrbuf_len(b);
191 }
192
193 int wrbuf_iconv_write(WRBUF b, yaz_iconv_t cd, const char *buf, int size)
194 {
195     return wrbuf_iconv_write_x(b, cd, buf, size, 0);
196 }
197
198 int wrbuf_iconv_write_cdata(WRBUF b, yaz_iconv_t cd, const char *buf, int size)
199 {
200     return wrbuf_iconv_write_x(b, cd, buf, size, 1);
201 }
202
203 /*
204  * Local variables:
205  * c-basic-offset: 4
206  * indent-tabs-mode: nil
207  * End:
208  * vim: shiftwidth=4 tabstop=8 expandtab
209  */
210