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