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