00001
00002
00003
00004
00005
00011 #if HAVE_CONFIG_H
00012 #include <config.h>
00013 #endif
00014
00015 #include <stdio.h>
00016 #include <stdlib.h>
00017 #include <string.h>
00018 #include <stdarg.h>
00019
00020 #include <yaz/wrbuf.h>
00021 #include <yaz/snprintf.h>
00022 #include <yaz/yaz-iconv.h>
00023
00024 WRBUF wrbuf_alloc(void)
00025 {
00026 WRBUF n;
00027
00028 if (!(n = (WRBUF)xmalloc(sizeof(*n))))
00029 abort();
00030 n->buf = 0;
00031 n->size = 0;
00032 n->pos = 0;
00033 return n;
00034 }
00035
00036 void wrbuf_destroy(WRBUF b)
00037 {
00038 xfree(b->buf);
00039 xfree(b);
00040 }
00041
00042 void wrbuf_rewind(WRBUF b)
00043 {
00044 b->pos = 0;
00045 }
00046
00047 int wrbuf_grow(WRBUF b, int minsize)
00048 {
00049 int togrow;
00050
00051 if (!b->size)
00052 togrow = 1024;
00053 else
00054 togrow = b->size;
00055 if (togrow < minsize)
00056 togrow = minsize;
00057 if (b->size && !(b->buf =(char *)xrealloc(b->buf, b->size += togrow)))
00058 abort();
00059 else if (!b->size && !(b->buf = (char *)xmalloc(b->size = togrow)))
00060 abort();
00061 return 0;
00062 }
00063
00064 int wrbuf_write(WRBUF b, const char *buf, int size)
00065 {
00066 if (size <= 0)
00067 return 0;
00068 if (b->pos + size >= b->size)
00069 wrbuf_grow(b, size);
00070 memcpy(b->buf + b->pos, buf, size);
00071 b->pos += size;
00072 return 0;
00073 }
00074
00075 int wrbuf_puts(WRBUF b, const char *buf)
00076 {
00077 wrbuf_write(b, buf, strlen(buf));
00078 return 0;
00079 }
00080
00081 void wrbuf_vputs(const char *buf, void *client_data)
00082 {
00083 wrbuf_write((WRBUF) client_data, buf, strlen(buf));
00084 }
00085
00086 int wrbuf_puts_replace_char(WRBUF b, const char *buf,
00087 const char from, const char to)
00088 {
00089 while(*buf)
00090 {
00091 if (*buf == from)
00092 wrbuf_putc(b, to);
00093 else
00094 wrbuf_putc(b, *buf);
00095 buf++;
00096 }
00097 return 0;
00098 }
00099
00100 void wrbuf_chop_right(WRBUF b)
00101 {
00102 while (b->pos && b->buf[b->pos-1] == ' ')
00103 {
00104 (b->pos)--;
00105 }
00106 }
00107
00108 int wrbuf_xmlputs(WRBUF b, const char *cp)
00109 {
00110 return wrbuf_xmlputs_n(b, cp, strlen(cp));
00111 }
00112
00113 int wrbuf_xmlputs_n(WRBUF b, const char *cp, int size)
00114 {
00115 while (--size >= 0)
00116 {
00117
00118 if (*cp >= 0 && *cp <= 31)
00119 if (*cp != 9 && *cp != 10 && *cp != 13)
00120 {
00121 cp++;
00122 continue;
00123 }
00124 switch(*cp)
00125 {
00126 case '<':
00127 wrbuf_puts(b, "<");
00128 break;
00129 case '>':
00130 wrbuf_puts(b, ">");
00131 break;
00132 case '&':
00133 wrbuf_puts(b, "&");
00134 break;
00135 case '"':
00136 wrbuf_puts(b, """);
00137 break;
00138 case '\'':
00139 wrbuf_puts(b, "'");
00140 break;
00141 default:
00142 wrbuf_putc(b, *cp);
00143 }
00144 cp++;
00145 }
00146 return 0;
00147 }
00148
00149 void wrbuf_printf(WRBUF b, const char *fmt, ...)
00150 {
00151 va_list ap;
00152 char buf[4096];
00153
00154 va_start(ap, fmt);
00155 yaz_vsnprintf(buf, sizeof(buf)-1, fmt, ap);
00156 wrbuf_puts (b, buf);
00157
00158 va_end(ap);
00159 }
00160
00161 static int wrbuf_iconv_write_x(WRBUF b, yaz_iconv_t cd, const char *buf,
00162 int size, int cdata)
00163 {
00164 if (cd)
00165 {
00166 char outbuf[16];
00167 size_t inbytesleft = size;
00168 const char *inp = buf;
00169 while (inbytesleft)
00170 {
00171 size_t outbytesleft = sizeof(outbuf);
00172 char *outp = outbuf;
00173 size_t r = yaz_iconv(cd, (char**) &inp, &inbytesleft,
00174 &outp, &outbytesleft);
00175 if (r == (size_t) (-1))
00176 {
00177 int e = yaz_iconv_error(cd);
00178 if (e != YAZ_ICONV_E2BIG)
00179 break;
00180 }
00181 if (cdata)
00182 wrbuf_xmlputs_n(b, outbuf, outp - outbuf);
00183 else
00184 wrbuf_write(b, outbuf, outp - outbuf);
00185 }
00186 }
00187 else
00188 {
00189 if (cdata)
00190 wrbuf_xmlputs_n(b, buf, size);
00191 else
00192 wrbuf_write(b, buf, size);
00193 }
00194 return wrbuf_len(b);
00195 }
00196
00197 int wrbuf_iconv_write(WRBUF b, yaz_iconv_t cd, const char *buf, int size)
00198 {
00199 return wrbuf_iconv_write_x(b, cd, buf, size, 0);
00200 }
00201
00202 int wrbuf_iconv_puts(WRBUF b, yaz_iconv_t cd, const char *strz)
00203 {
00204 return wrbuf_iconv_write(b, cd, strz, strlen(strz));
00205 }
00206
00207 int wrbuf_iconv_putchar(WRBUF b, yaz_iconv_t cd, int ch)
00208 {
00209 char buf[1];
00210 buf[0] = ch;
00211 return wrbuf_iconv_write(b, cd, buf, 1);
00212 }
00213
00214 int wrbuf_iconv_write_cdata(WRBUF b, yaz_iconv_t cd, const char *buf, int size)
00215 {
00216 return wrbuf_iconv_write_x(b, cd, buf, size, 1);
00217 }
00218
00219 int wrbuf_iconv_puts_cdata(WRBUF b, yaz_iconv_t cd, const char *strz)
00220 {
00221 return wrbuf_iconv_write_x(b, cd, strz, strlen(strz), 1);
00222 }
00223
00224 void wrbuf_iconv_reset(WRBUF b, yaz_iconv_t cd)
00225 {
00226 if (cd)
00227 {
00228 char outbuf[16];
00229 size_t outbytesleft = sizeof(outbuf);
00230 char *outp = outbuf;
00231 size_t r = yaz_iconv(cd, 0, 0, &outp, &outbytesleft);
00232 if (r != (size_t) (-1))
00233 wrbuf_write(b, outbuf, outp - outbuf);
00234 }
00235 }
00236
00237 const char *wrbuf_cstr(WRBUF b)
00238 {
00239 wrbuf_putc(b, '\0');
00240 (b->pos)--;
00241 return b->buf;
00242 }
00243
00244 void wrbuf_cut_right(WRBUF b, size_t no_to_remove)
00245 {
00246 if (no_to_remove > b->pos)
00247 no_to_remove = b->pos;
00248 b->pos = b->pos - no_to_remove;
00249 }
00250
00251 void wrbuf_puts_escaped(WRBUF b, const char *str)
00252 {
00253 wrbuf_write_escaped(b, str, strlen(str));
00254 }
00255
00256 void wrbuf_write_escaped(WRBUF b, const char *str, size_t len)
00257 {
00258 size_t i;
00259 for (i = 0; i < len; i++)
00260 if (str[i] < ' ' || str[i] > 126)
00261 wrbuf_printf(b, "\\x%02X", str[i] & 0xff);
00262 else
00263 wrbuf_putc(b, str[i]);
00264 }
00265
00266
00267
00268
00269
00270
00271
00272
00273