00001
00002 #include "define.h"
00003
00004
00005 #define ASSERT(x,...) { if( !(x) ) DIE(( __VA_ARGS__)); }
00006
00007
00008 int skip_nl(char *s)
00009 {
00010 if (s[0] == '\n')
00011 return 1;
00012 if (s[0] == '\r' && s[1] == '\n')
00013 return 2;
00014 if (s[0] == '\0')
00015 return 0;
00016 return -1;
00017 }
00018
00019
00020 int find_nl(vstr * vs)
00021 {
00022 char *nextr, *nextn;
00023
00024 nextr = memchr(vs->b, '\r', vs->dlen);
00025 nextn = memchr(vs->b, '\n', vs->dlen);
00026
00027
00028 if (nextn && (!nextr || (nextr > nextn))) {
00029 return nextn - vs->b;
00030 }
00031
00032 if (nextr && nextn && (nextn-nextr == 1)) {
00033 return nextr - vs->b;
00034 }
00035
00036
00037 return -1;
00038 }
00039
00040
00041
00042
00043 static int unicode_up = 0;
00044 static iconv_t i16to8;
00045 static const char *target_charset = NULL;
00046 static int target_open_from = 0;
00047 static int target_open_to = 0;
00048 static iconv_t i8totarget = (iconv_t)-1;
00049 static iconv_t target2i8 = (iconv_t)-1;
00050
00051
00052 void unicode_init()
00053 {
00054 if (unicode_up) unicode_close();
00055 i16to8 = iconv_open("utf-8", "utf-16le");
00056 if (i16to8 == (iconv_t)-1) {
00057 WARN(("Couldn't open iconv descriptor for utf-16le to utf-8.\n"));
00058 exit(1);
00059 }
00060 unicode_up = 1;
00061 }
00062
00063
00064 void unicode_close()
00065 {
00066 iconv_close(i16to8);
00067 if (target_open_from) iconv_close(i8totarget);
00068 if (target_open_to) iconv_close(target2i8);
00069 if (target_charset) free((char *)target_charset);
00070 target_charset = NULL;
00071 target_open_from = 0;
00072 target_open_to = 0;
00073 unicode_up = 0;
00074 }
00075
00076
00077 int utf16_is_terminated(const char *str, int length)
00078 {
00079 VSTR_STATIC(errbuf, 100);
00080 int len = -1;
00081 int i;
00082 for (i = 0; i < length; i += 2) {
00083 if (str[i] == 0 && str[i + 1] == 0) {
00084 len = i;
00085 }
00086 }
00087
00088 if (-1 == len) {
00089 vshexdump(errbuf, str, 0, length, 1);
00090 DEBUG_WARN(("String is not zero terminated (probably broken data from registry) %s.\n", errbuf->b));
00091 }
00092
00093 return (-1 == len) ? 0 : 1;
00094 }
00095
00096
00097 size_t vb_utf16to8(vbuf *dest, const char *inbuf, int iblen)
00098 {
00099 size_t inbytesleft = iblen;
00100 size_t icresult = (size_t)-1;
00101 size_t outbytesleft = 0;
00102 char *outbuf = NULL;
00103 int myerrno;
00104
00105 ASSERT(unicode_up, "vb_utf16to8() called before unicode started.");
00106 vbresize(dest, iblen);
00107
00108
00109 if (!utf16_is_terminated(inbuf, iblen))
00110 return (size_t)-1;
00111
00112 do {
00113 outbytesleft = dest->blen - dest->dlen;
00114 outbuf = dest->b + dest->dlen;
00115 icresult = iconv(i16to8, (ICONV_CONST char**)&inbuf, &inbytesleft, &outbuf, &outbytesleft);
00116 myerrno = errno;
00117 dest->dlen = outbuf - dest->b;
00118 if (inbytesleft) vbgrow(dest, inbytesleft);
00119 } while ((size_t)-1 == icresult && E2BIG == myerrno);
00120
00121 if (icresult == (size_t)-1) {
00122 DEBUG_WARN(("iconv failure: %s\n", strerror(myerrno)));
00123 unicode_init();
00124 return (size_t)-1;
00125 }
00126 return (icresult) ? (size_t)-1 : 0;
00127 }
00128
00129
00130 static void open_targets(const char* charset);
00131 static void open_targets(const char* charset)
00132 {
00133 if (!target_charset || strcasecmp(target_charset, charset)) {
00134 if (target_open_from) iconv_close(i8totarget);
00135 if (target_open_to) iconv_close(target2i8);
00136 if (target_charset) free((char *)target_charset);
00137 target_charset = strdup(charset);
00138 target_open_from = 1;
00139 target_open_to = 1;
00140 i8totarget = iconv_open(target_charset, "utf-8");
00141 if (i8totarget == (iconv_t)-1) {
00142 target_open_from = 0;
00143 WARN(("Couldn't open iconv descriptor for utf-8 to %s.\n", target_charset));
00144 }
00145 target2i8 = iconv_open("utf-8", target_charset);
00146 if (target2i8 == (iconv_t)-1) {
00147 target_open_to = 0;
00148 WARN(("Couldn't open iconv descriptor for %s to utf-8.\n", target_charset));
00149 }
00150 }
00151 }
00152
00153
00154 static size_t sbcs_conversion(vbuf *dest, const char *inbuf, int iblen, iconv_t conversion);
00155 static size_t sbcs_conversion(vbuf *dest, const char *inbuf, int iblen, iconv_t conversion)
00156 {
00157 size_t inbytesleft = iblen;
00158 size_t icresult = (size_t)-1;
00159 size_t outbytesleft = 0;
00160 char *outbuf = NULL;
00161 int myerrno;
00162
00163 vbresize(dest, 2*iblen);
00164
00165 do {
00166 outbytesleft = dest->blen - dest->dlen;
00167 outbuf = dest->b + dest->dlen;
00168 icresult = iconv(conversion, (ICONV_CONST char**)&inbuf, &inbytesleft, &outbuf, &outbytesleft);
00169 myerrno = errno;
00170 dest->dlen = outbuf - dest->b;
00171 if (inbytesleft) vbgrow(dest, 2*inbytesleft);
00172 } while ((size_t)-1 == icresult && E2BIG == myerrno);
00173
00174 if (icresult == (size_t)-1) {
00175 DEBUG_WARN(("iconv failure: %s\n", strerror(myerrno)));
00176 unicode_init();
00177 return (size_t)-1;
00178 }
00179 return (icresult) ? (size_t)-1 : 0;
00180 }
00181
00182
00183 size_t vb_utf8to8bit(vbuf *dest, const char *inbuf, int iblen, const char* charset)
00184 {
00185 open_targets(charset);
00186 if (!target_open_from) return (size_t)-1;
00187 return sbcs_conversion(dest, inbuf, iblen, i8totarget);
00188 }
00189
00190
00191 size_t vb_8bit2utf8(vbuf *dest, const char *inbuf, int iblen, const char* charset)
00192 {
00193 open_targets(charset);
00194 if (!target_open_to) return (size_t)-1;
00195 return sbcs_conversion(dest, inbuf, iblen, target2i8);
00196 }
00197
00198
00199 vbuf *vballoc(size_t len)
00200 {
00201 struct varbuf *result = malloc(sizeof(struct varbuf));
00202 if (result) {
00203 result->dlen = 0;
00204 result->blen = 0;
00205 result->buf = NULL;
00206 vbresize(result, len);
00207 }
00208 else DIE(("malloc() failure"));
00209 return result;
00210 }
00211
00212
00213 void vbcheck(vbuf * vb)
00214 {
00215 ASSERT(vb->b >= vb->buf, "vbcheck(): data not inside buffer");
00216 ASSERT((size_t)(vb->b - vb->buf) <= vb->blen, "vbcheck(): vb->b outside of buffer range.");
00217 ASSERT(vb->dlen <= vb->blen, "vbcheck(): data length > buffer length.");
00218 ASSERT(vb->blen < 1024 * 1024, "vbcheck(): blen is a bit large...hmmm.");
00219 }
00220
00221
00222 void vbfree(vbuf * vb)
00223 {
00224 free(vb->buf);
00225 free(vb);
00226 }
00227
00228
00229 void vbclear(struct varbuf *vb)
00230 {
00231 vbresize(vb, 0);
00232 }
00233
00234
00235 void vbresize(struct varbuf *vb, size_t len)
00236 {
00237 vb->dlen = 0;
00238
00239 if (vb->blen >= len) {
00240 vb->b = vb->buf;
00241 return;
00242 }
00243
00244 vb->buf = realloc(vb->buf, len);
00245 vb->b = vb->buf;
00246 vb->blen = len;
00247 }
00248
00249
00250 size_t vbavail(vbuf * vb)
00251 {
00252 return vb->blen - vb->dlen - (size_t)(vb->b - vb->buf);
00253 }
00254
00255
00256 void vbgrow(struct varbuf *vb, size_t len)
00257 {
00258 if (0 == len)
00259 return;
00260
00261 if (0 == vb->blen) {
00262 vbresize(vb, len);
00263 return;
00264 }
00265
00266 if (vb->dlen + len > vb->blen) {
00267 if (vb->dlen + len < vb->blen * 1.5)
00268 len = vb->blen * 1.5;
00269 char *nb = malloc(vb->blen + len);
00270 if (!nb) DIE(("malloc() failure"));
00271 vb->blen = vb->blen + len;
00272 memcpy(nb, vb->b, vb->dlen);
00273
00274 free(vb->buf);
00275 vb->buf = nb;
00276 vb->b = vb->buf;
00277 } else {
00278 if (vb->b != vb->buf)
00279 memcpy(vb->buf, vb->b, vb->dlen);
00280 }
00281
00282 vb->b = vb->buf;
00283
00284 ASSERT(vbavail(vb) >= len, "vbgrow(): I have failed in my mission.");
00285 }
00286
00287
00288 void vbset(vbuf * vb, void *b, size_t len)
00289 {
00290 vbresize(vb, len);
00291 memcpy(vb->b, b, len);
00292 vb->dlen = len;
00293 }
00294
00295
00296 void vsskipws(vstr * vs)
00297 {
00298 char *p = vs->b;
00299 while ((size_t)(p - vs->b) < vs->dlen && isspace(p[0]))
00300 p++;
00301
00302 vbskip((vbuf *) vs, p - vs->b);
00303 }
00304
00305
00306
00307 void vbappend(struct varbuf *vb, void *b, size_t len)
00308 {
00309 if (0 == vb->dlen) {
00310 vbset(vb, b, len);
00311 return;
00312 }
00313 vbgrow(vb, len);
00314 memcpy(vb->b + vb->dlen, b, len);
00315 vb->dlen += len;
00316 }
00317
00318
00319
00320 void vbskip(struct varbuf *vb, size_t skip)
00321 {
00322 ASSERT(skip <= vb->dlen, "vbskip(): Attempt to seek past end of buffer.");
00323 vb->b += skip;
00324 vb->dlen -= skip;
00325 }
00326
00327
00328
00329 void vboverwrite(struct varbuf *vbdest, struct varbuf *vbsrc)
00330 {
00331 vbresize(vbdest, vbsrc->blen);
00332 memcpy(vbdest->b, vbsrc->b, vbsrc->dlen);
00333 vbdest->blen = vbsrc->blen;
00334 vbdest->dlen = vbsrc->dlen;
00335 }
00336
00337
00338 vstr *vsalloc(size_t len)
00339 {
00340 vstr *result = (vstr *) vballoc(len + 1);
00341 vsset(result, "");
00342 return result;
00343 }
00344
00345
00346 char *vsstr(vstr * vs)
00347 {
00348 return vs->b;
00349 }
00350
00351
00352 size_t vslen(vstr * vs)
00353 {
00354 return strlen(vsstr(vs));
00355 }
00356
00357
00358 void vsfree(vstr * vs)
00359 {
00360 vbfree((vbuf *) vs);
00361 }
00362
00363
00364 void vscharcat(vstr * vb, int ch)
00365 {
00366 vbgrow((vbuf *) vb, 1);
00367 vb->b[vb->dlen - 1] = ch;
00368 vb->b[vb->dlen] = '\0';
00369 vb->dlen++;
00370 }
00371
00372
00373
00374 void vsnprepend(vstr * vb, char *str, size_t len)
00375 {
00376 ASSERT(vb->b[vb->dlen - 1] == '\0', "vsncat(): attempt to append string to non-string.");
00377 size_t sl = strlen(str);
00378 size_t n = (sl < len) ? sl : len;
00379 vbgrow((vbuf *) vb, n + 1);
00380 memmove(vb->b + n, vb->b, vb->dlen - 1);
00381 memcpy(vb->b, str, n);
00382 vb->dlen += n;
00383 vb->b[vb->dlen - 1] = '\0';
00384 }
00385
00386
00387
00388 void vsskip(vstr * vs, size_t len)
00389 {
00390 ASSERT(len < vs->dlen - 1, "Attempt to skip past end of string");
00391 vbskip((vbuf *) vs, len);
00392 }
00393
00394
00395
00396 int vsskipline(vstr * vs)
00397 {
00398 int nloff = find_nl(vs);
00399 int nll = skip_nl(vs->b + nloff);
00400
00401 if (nloff < 0) {
00402
00403 printf("vb_skipline(): there seems to be no newline here.\n");
00404 return -1;
00405 }
00406 if (nll < 0) {
00407
00408 printf("vb_skipline(): there seems to be no newline here...except there should be. :P\n");
00409 return -1;
00410 }
00411
00412 memmove(vs->b, vs->b + nloff + nll, vs->dlen - nloff - nll);
00413
00414 vs->dlen -= nloff + nll;
00415
00416 return 0;
00417 }
00418
00419
00420 int vscatprintf(vstr * vs, char *fmt, ...)
00421 {
00422 int size;
00423 va_list ap;
00424
00425
00426
00427 if (!vs->b || vs->dlen == 0) {
00428 vsset(vs, "");
00429 }
00430
00431 while (1) {
00432
00433 va_start(ap, fmt);
00434 size = vsnprintf(vs->b + vs->dlen - 1, vs->blen - vs->dlen, fmt, ap);
00435 va_end(ap);
00436
00437
00438 if ((size > -1) && ((size_t)size < vs->blen - vs->dlen)) {
00439 vs->dlen += size;
00440 return size;
00441 }
00442
00443 if (size >= 0)
00444 vbgrow((vbuf *) vs, size + 1);
00445 else
00446 vbgrow((vbuf *) vs, vs->blen);
00447 }
00448 }
00449
00450
00451
00452 int vslast(vstr * vs)
00453 {
00454 if (vs->dlen < 1)
00455 return -1;
00456 if (vs->b[vs->dlen - 1] != '\0')
00457 return -1;
00458 if (vs->dlen == 1)
00459 return '\0';
00460 return vs->b[vs->dlen - 2];
00461 }
00462
00463
00464
00465 void vs_printf(vstr * vs, char *fmt, ...)
00466 {
00467 int size;
00468 va_list ap;
00469
00470
00471 vbresize((vbuf *) vs, 100);
00472
00473 while (1) {
00474
00475 va_start(ap, fmt);
00476 size = vsnprintf(vs->b, vs->blen, fmt, ap);
00477 va_end(ap);
00478
00479
00480 if ((size > -1) && ((size_t)size < vs->blen)) {
00481 vs->dlen = size + 1;
00482 return;
00483 }
00484
00485 if (size >= 0)
00486 vbresize((vbuf *) vs, size + 1);
00487 else
00488 vbresize((vbuf *) vs, vs->blen * 2);
00489 }
00490 }
00491
00492
00493
00494 void vs_printfa(vstr * vs, char *fmt, ...)
00495 {
00496 int size;
00497 va_list ap;
00498
00499 if (vs->blen - vs->dlen < 50)
00500 vbgrow((vbuf *) vs, 100);
00501
00502 while (1) {
00503
00504 va_start(ap, fmt);
00505 size = vsnprintf(vs->b + vs->dlen - 1, vs->blen - vs->dlen + 1, fmt, ap);
00506 va_end(ap);
00507
00508
00509 if ((size > -1) && ((size_t)size < vs->blen)) {
00510 vs->dlen += size;
00511 return;
00512 }
00513
00514 if (size >= 0)
00515 vbgrow((vbuf *) vs, size + 1 - vs->dlen);
00516 else
00517 vbgrow((vbuf *) vs, size);
00518 }
00519 }
00520
00521
00522 void vshexdump(vstr * vs, const char *b, size_t start, size_t stop, int ascii)
00523 {
00524 char c;
00525 int diff, i;
00526
00527 while (start < stop) {
00528 diff = stop - start;
00529 if (diff > 16)
00530 diff = 16;
00531
00532 vs_printfa(vs, ":%08X ", start);
00533
00534 for (i = 0; i < diff; i++) {
00535 if (8 == i)
00536 vs_printfa(vs, " ");
00537 vs_printfa(vs, "%02X ", (unsigned char) *(b + start + i));
00538 }
00539 if (ascii) {
00540 for (i = diff; i < 16; i++)
00541 vs_printfa(vs, " ");
00542 for (i = 0; i < diff; i++) {
00543 c = *(b + start + i);
00544 vs_printfa(vs, "%c", isprint(c) ? c : '.');
00545 }
00546 }
00547 vs_printfa(vs, "\n");
00548 start += 16;
00549 }
00550 }
00551
00552
00553 void vsset(vstr * vs, char *s)
00554 {
00555 vsnset(vs, s, strlen(s));
00556 }
00557
00558
00559 void vsnset(vstr * vs, char *s, size_t n)
00560 {
00561 vbresize((vbuf *) vs, n + 1);
00562 memcpy(vs->b, s, n);
00563 vs->b[n] = '\0';
00564 vs->dlen = n + 1;
00565 }
00566
00567
00568 void vsgrow(vstr * vs, size_t len)
00569 {
00570 vbgrow((vbuf *) vs, len);
00571 }
00572
00573
00574 size_t vsavail(vstr * vs)
00575 {
00576 return vbavail((vbuf *) vs);
00577 }
00578
00579
00580 void vsnset16(vstr * vs, char *s, size_t len)
00581 {
00582 vbresize((vbuf *) vs, len + 1);
00583 memcpy(vs->b, s, len);
00584
00585 vs->b[len] = '\0';
00586 vs->dlen = len + 1;
00587 vs->b[len] = '\0';
00588 }
00589
00590
00591 void vscat(vstr * vs, char *str)
00592 {
00593 vsncat(vs, str, strlen(str));
00594 }
00595
00596
00597 int vscmp(vstr * vs, char *str)
00598 {
00599 return strcmp(vs->b, str);
00600 }
00601
00602
00603 void vsncat(vstr * vs, char *str, size_t len)
00604 {
00605 ASSERT(vs->b[vs->dlen - 1] == '\0', "vsncat(): attempt to append string to non-string.");
00606 size_t sl = strlen(str);
00607 size_t n = (sl < len) ? sl : len;
00608
00609 vbgrow((vbuf *) vs, n + 1);
00610 memcpy(vs->b + vs->dlen - 1, str, n);
00611 vs->dlen += n;
00612 vs->b[vs->dlen - 1] = '\0';
00613 }
00614
00615
00616 void vstrunc(vstr * v, size_t off)
00617 {
00618 if (off >= v->dlen - 1)
00619 return;
00620 v->b[off] = '\0';
00621 v->dlen = off + 1;
00622 }
00623
00624