comparison src/vbuf.c @ 43:f6db1f060a95

start on outlook 2003 64 bit format
author carl
date Sun, 06 Jan 2008 14:47:06 -0800
parents
children b12f4e50e2e8
comparison
equal deleted inserted replaced
42:7a97f50c39c5 43:f6db1f060a95
1 // {{{ includes
2
3 #include <ctype.h>
4 //#include "defines.h"
5 #include <errno.h>
6 #include <iconv.h>
7 #include <malloc.h>
8 #include <signal.h>
9 #include <stdarg.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include "vbuf.h"
14 #include "generic.h"
15
16 #ifdef WITH_DMALLOC
17 #include <dmalloc.h>
18 #endif
19
20 // }}}
21
22 int skip_nl( char *s ) // {{{ returns the width of the newline at s[0]
23 {
24 if( s[0] == '\n' ) return 1;
25 if( s[0] == '\r' && s[1] == '\n' ) return 2;
26 if( s[0] == '\0' ) return 0;
27 return -1;
28 } // }}}
29 int find_nl( vstr *vs ) // {{{ find newline of type type in b
30 {
31 char *nextr, *nextn;
32
33 nextr = memchr( vs->b, '\r', vs->dlen );
34 nextn = memchr( vs->b, '\n', vs->dlen );
35
36 //case 1: UNIX, we find \n first
37 if( nextn && (nextr == NULL || nextr > nextn ) ) {
38 return nextn - vs->b;
39 }
40
41 //case 2: DOS, we find \r\n
42 if( NULL != nextr && NULL != nextn && 1 == (char*)nextn - (char*)nextr ) {
43 return nextr - vs->b;
44 }
45
46 //case 3: we find nothing
47
48 return -1;
49 } // }}}
50
51 // {{{ UTF8 <-> UTF16 <-> ISO8859 Character set conversion functions and (ack) their globals
52
53 //TODO: the following should not be
54 char *wwbuf=NULL;
55 size_t nwwbuf=0;
56 static int unicode_up=0;
57 iconv_t i16to8, i8to16, i8859_1to8, i8toi8859_1;
58
59 void unicode_init() // {{{
60 {
61 char *wipe = "";
62 char dump[4];
63
64 if( unicode_up ) unicode_close();
65
66 if( (iconv_t)-1 == (i16to8 = iconv_open( "UTF-8", "UTF-16" ) ) ) {
67 fprintf(stderr, "doexport(): Couldn't open iconv descriptor for UTF-16 to UTF-8.\n");
68 exit( 1 );
69 }
70
71 if( (iconv_t)-1 == (i8to16 = iconv_open( "UTF-16", "UTF-8" ) ) ) {
72 fprintf(stderr, "doexport(): Couldn't open iconv descriptor for UTF-8 to UTF-16.\n");
73 exit( 2 );
74 }
75
76 //iconv will prefix output with an FF FE (utf-16 start seq), the following dumps that.
77 memset( dump, 'x', 4 );
78 ASSERT( 0 == utf8to16( wipe, 1, dump, 4 ), "unicode_init(): attempt to dump FF FE failed." );
79
80 if( (iconv_t)-1 == (i8859_1to8 = iconv_open( "UTF-8", "ISO_8859-1" ) ) ) {
81 fprintf(stderr, "doexport(): Couldn't open iconv descriptor for ASCII to UTF-8.\n");
82 exit( 1 );
83 }
84
85
86 if( (iconv_t)-1 == (i8toi8859_1 = iconv_open( "ISO_8859-1", "UTF-8" ) ) ) {
87 fprintf(stderr, "doexport(): Couldn't open iconv descriptor for UTF-8 to ASCII.\n");
88 exit( 1 );
89 }
90
91 unicode_up = 1;
92 }
93 // }}}
94 void unicode_close() // {{{
95 {
96 unicode_up = 0;
97 iconv_close( i8to16 );
98 iconv_close( i16to8 );
99 iconv_close( i8859_1to8 );
100 iconv_close( i8toi8859_1 );
101 }
102 // }}}
103
104 //int utf16_write( FILE* stream, const void *buf, size_t count ) // {{{ write utf-8 or iso_8869-1 to stream after converting it to utf-16
105 //{
106 //
107 // //TODO: if anything big comes through here we are sunk, should do it
108 // //bit-by-bit, not one-big-gulp
109 //
110 // size_t inbytesleft, outbytesleft;
111 // char *inbuf, *outbuf;
112 // size_t icresult;
113 // size_t rl;
114 //
115 // //do we have enough buffer space?
116 // if( !wwbuf || nwwbuf < (count * 2 + 2) ) {
117 // wwbuf = F_REALLOC( wwbuf, count * 2 +2 );
118 //
119 // nwwbuf = count * 2 + 2;
120 // }
121 //
122 // inbytesleft = count; outbytesleft = nwwbuf;
123 // inbuf = (char*)buf; outbuf = wwbuf;
124 //
125 //// fprintf(stderr, "X%s, %dX", (char*)buf, strlen( buf ));
126 //// fflush(stderr);
127 //
128 // if( (rl = strlen( buf ) + 1) != count ) {
129 // fprintf(stderr, "utf16_write(): reported buffer size (%d) does not match string length (%d)\n",
130 // count,
131 // rl);
132 //
133 // //hexdump( (char*)buf, 0, count, 1 );
134 //
135 // raise( SIGSEGV );
136 // inbytesleft = rl;
137 // }
138 //
139 //// fprintf(stderr, " attempting to convert:\n");
140 //// hexdump( (char*)inbuf, 0, count, 1 );
141 //
142 // icresult = iconv( i8to16, &inbuf, &inbytesleft, &outbuf, &outbytesleft );
143 //
144 //// fprintf(stderr, " converted:\n");
145 //// hexdump( (char*)buf, 0, count, 1 );
146 //
147 //// fprintf(stderr, " to:\n");
148 //// hexdump( (char*)wwbuf, 0, nwwbuf, 1 );
149 //
150 // if( (size_t)-1 == icresult ) {
151 // fprintf(stderr, "utf16_write(): iconv failure(%d): %s\n", errno, strerror( errno ) );
152 // fprintf(stderr, " attempted to convert:\n");
153 // hexdump( (char*)inbuf, 0, count, 1 );
154 //
155 // fprintf(stderr, " result:\n");
156 // hexdump( (char*)outbuf, 0, count, 1 );
157 //
158 // fprintf(stderr, "I'm going to segfault now.\n");
159 // raise( SIGSEGV );
160 // exit(1);
161 // }
162 //
163 // if( inbytesleft > 0 ) {
164 // fprintf(stderr, "utf16_write(): iconv returned a short count.\n");
165 // exit(1);
166 // }
167 //
168 // return fwrite( wwbuf, nwwbuf - outbytesleft - 2, 1, stream );
169 //}
170 // }}}
171
172 //char *utf16buf = NULL;
173 //int utf16buf_len = 0;
174 //
175 //int utf16_fprintf( FILE* stream, const char *fmt, ... ) // {{{
176 //{
177 // int result=0;
178 // va_list ap;
179 //
180 // if( utf16buf == NULL ) {
181 // utf16buf = (char*)F_MALLOC( SZ_MAX + 1 );
182 //
183 // utf16buf_len = SZ_MAX + 1;
184 // }
185 //
186 // va_start( ap, fmt );
187 //
188 // result = vsnprintf( utf16buf, utf16buf_len, fmt, ap );
189 //
190 // if( result + 1 > utf16buf_len ) { //didn't have space, realloc() and try again
191 // fprintf(stderr, "utf16_fprintf(): buffer too small (%d), F_MALLOC(%d)\n", utf16buf_len, result);
192 // free( utf16buf );
193 // utf16buf_len = result + 1;
194 // utf16buf = (char*)F_MALLOC( utf16buf_len );
195 //
196 // result = vsnprintf( utf16buf, utf16buf_len, fmt, ap );
197 // }
198 //
199 //
200 // //didn't have space...again...something weird is going on...
201 // ASSERT( result + 1 <= utf16buf_len, "utf16_fprintf(): Unpossible error!\n");
202 //
203 // if( 1 != utf16_write( stream, utf16buf, result + 1 ) )
204 // DIE( "Write error? -> %s or %s\n", strerror( errno ), uerr_str( uerr_get() ) );
205 //
206 // return result;
207 //}
208 //// }}}
209 //int utf16to8( char *inbuf_o, char *outbuf_o, int length ) // {{{
210 //{
211 // int inbytesleft = length;
212 // int outbytesleft = length;
213 // char *inbuf = inbuf_o;
214 // char *outbuf = outbuf_o;
215 // int rlen = -1, tlen;
216 // int icresult = -1;
217 //
218 // int i, strlen=-1;
219 //
220 // DEBUG(
221 // fprintf(stderr, " utf16to8(): attempting to convert:\n");
222 // //hexdump( (char*)inbuf_o, 0, length, 1 );
223 // fflush(stderr);
224 // );
225 //
226 // for( i=0; i<length ; i+=2 ) {
227 // if( inbuf_o[i] == 0 && inbuf_o[i + 1] == 0 ) {
228 // //fprintf(stderr, "End of string found at: %d\n", i );
229 // strlen = i;
230 // }
231 // }
232 //
233 // //hexdump( (char*)inbuf_o, 0, strlen, 1 );
234 //
235 // if( -1 == strlen ) WARN("String is not zero-terminated.");
236 //
237 // //iconv does not like it when the inbytesleft > actual string length
238 // //enum: zero terminated, length valid
239 // // zero terminated, length short //we won't go beyond length ever, so this is same as NZT case
240 // // zero terminated, length long
241 // // not zero terminated
242 // // TODO: MEMORY BUG HERE!
243 // for( tlen = 0; tlen <= inbytesleft - 2; tlen+=2 ) {
244 // if( inbuf_o[tlen] == 0 && inbuf_o[tlen+1] == 0 ){
245 // rlen = tlen + 2;
246 // tlen = rlen;
247 // break;
248 // }
249 // if( tlen == inbytesleft )fprintf(stderr, "Space allocated for string > actual string length. Go windows!\n");
250 // }
251 //
252 // if( rlen >= 0 )
253 // icresult = iconv( i16to8, &inbuf, &rlen, &outbuf, &outbytesleft );
254 //
255 // if( icresult == (size_t)-1 ) {
256 // fprintf(stderr, "utf16to8(): iconv failure(%d): %s\n", errno, strerror( errno ) );
257 // fprintf(stderr, " attempted to convert:\n");
258 // hexdump( (char*)inbuf_o, 0, length, 1 );
259 // fprintf(stderr, " result:\n");
260 // hexdump( (char*)outbuf_o, 0, length, 1 );
261 // fprintf(stderr, " MyDirtyOut:\n");
262 // for( i=0; i<length; i++) {
263 // if( inbuf_o[i] != '\0' ) fprintf(stderr, "%c", inbuf_o[i] );
264 // }
265 //
266 // fprintf( stderr, "\n" );
267 // raise( SIGSEGV );
268 // exit(1);
269 // }
270 //
271 // DEBUG(
272 // fprintf(stderr, " result:\n");
273 // hexdump( (char*)outbuf_o, 0, length, 1 );
274 // )
275 //
276 // //fprintf(stderr, "utf16to8() returning %s\n", outbuf );
277 //
278 // return icresult;
279 //}
280 //// }}}
281 int utf16_is_terminated( char *str, int length ) // {{{
282 {
283 VSTR_STATIC( errbuf, 100 );
284 int len = -1;
285 int i;
286 for( i=0; i<length ; i+=2 ) {
287 if( str[i] == 0 && str[i + 1] == 0 ) {
288 //fprintf(stderr, "End of string found at: %d\n", i );
289 len = i;
290 }
291 }
292
293 //hexdump( (char*)inbuf_o, 0, len, 1 );
294
295 if( -1 == len ) {
296 vshexdump( errbuf, str, 0, length, 1 );
297 WARN("String is not zero terminated (probably broken data from registry) %s.", errbuf->b);
298 }
299
300 return (-1 == len )?0:1;
301 } // }}}
302 int vb_utf16to8( vbuf *dest, char *buf, int len ) // {{{
303 {
304 int inbytesleft = len;
305 char *inbuf = buf;
306 //int rlen = -1, tlen;
307 int icresult = -1;
308 VBUF_STATIC( dumpster, 100 );
309
310 //int i; //, strlen=-1;
311 int outbytesleft;
312 char *outbuf;
313
314 ASSERT( unicode_up, "vb_utf16to8() called before unicode started." );
315
316 if( 2 > dest->blen ) vbresize( dest, 2 );
317 dest->dlen = 0;
318
319 //Bad Things can happen if a non-zero-terminated utf16 string comes through here
320 if( !utf16_is_terminated( buf, len ) ) return -1;
321
322 do {
323 outbytesleft = dest->blen - dest->dlen;
324 outbuf = dest->b + dest->dlen;
325 icresult = iconv( i16to8, &inbuf, &inbytesleft, &outbuf, &outbytesleft );
326 dest->dlen = outbuf - dest->b;
327 vbgrow( dest, inbytesleft);
328 } while( (size_t)-1 == icresult && E2BIG == errno );
329
330 if( 0 != vb_utf8to16T( dumpster, dest->b, dest->dlen ) )
331 DIE("Reverse conversion failed.");
332
333 if( icresult == (size_t)-1 ) {
334 //TODO: error
335 //ERR_UNIX( errno, "vb_utf16to8():iconv failure: %s", strerror( errno ) );
336 unicode_init();
337 return -1;
338 /*
339 fprintf(stderr, " attempted to convert:\n");
340 hexdump( (char*)cin, 0, inlen, 1 );
341 fprintf(stderr, " result:\n");
342 hexdump( (char*)bout->b, 0, bout->dlen, 1 );
343 fprintf(stderr, " MyDirtyOut:\n");
344 for( i=0; i<inlen; i++) {
345 if( inbuf[i] != '\0' ) fprintf(stderr, "%c", inbuf[i] );
346 }
347
348 fprintf( stderr, "\n" );
349 raise( SIGSEGV );
350 exit(1);
351 */
352 }
353
354 if( icresult ) {
355 //ERR_UNIX( EILSEQ, "Uhhhh...vb_utf16to8() returning icresult == %d", icresult );
356 return -1;
357 }
358 return icresult;
359 }
360 // }}}
361
362 int utf8to16( char *inbuf_o, int iblen, char *outbuf_o, int oblen) // {{{ iblen, oblen: bytes including \0
363 {
364 //TODO: this is *only* used to dump the utf16 preamble now...
365 //TODO: This (and 8to16) are the most horrible things I have ever seen...
366 int inbytesleft;
367 int outbytesleft = oblen;
368 char *inbuf = inbuf_o;
369 char *outbuf = outbuf_o;
370 //int rlen = -1, tlen;
371 int icresult = -1;
372
373 char *stend;
374
375 //int i; //, strlen=-1;
376
377 DEBUG(
378 fprintf(stderr, " utf8to16(): attempting to convert:\n");
379 //hexdump( (char*)inbuf_o, 0, length, 1 );
380 fflush(stderr);
381 );
382
383 stend = memchr( inbuf_o, '\0', iblen );
384 ASSERT( NULL != stend, "utf8to16(): in string not zero terminated." );
385
386 inbytesleft = ( stend - inbuf_o + 1 < iblen )? stend - inbuf_o + 1: iblen;
387
388 //iconv does not like it when the inbytesleft > actual string length
389 //enum: zero terminated, length valid
390 // zero terminated, length short //we won't go beyond length ever, so this is same as NZT case
391 // zero terminated, length long
392 // not zero terminated
393 // TODO: MEMORY BUG HERE!
394 //
395 /*
396 for( tlen = 0; tlen <= inbytesleft - 2; tlen+=2 ) {
397 if( inbuf_o[tlen] == 0 && inbuf_o[tlen+1] == 0 ){
398 rlen = tlen + 2;
399 tlen = rlen;
400 break;
401 }
402 if( tlen == inbytesleft )fprintf(stderr, "Space allocated for string > actual string length. Go windows!\n");
403 }
404 */
405
406 //if( rlen >= 0 )
407 icresult = iconv( i8to16, &inbuf, &inbytesleft, &outbuf, &outbytesleft );
408
409 if( icresult == (size_t)-1 ) {
410 DIE("iconv failure(%d): %s\n", errno, strerror( errno ) );
411 //fprintf(stderr, " attempted to convert:\n");
412 //hexdump( (char*)inbuf_o, 0, iblen, 1 );
413 //fprintf(stderr, " result:\n");
414 //hexdump( (char*)outbuf_o, 0, oblen, 1 );
415 //fprintf(stderr, " MyDirtyOut:\n");
416 // for( i=0; i<iblen; i++) {
417 // if( inbuf_o[i] != '\0' ) fprintf(stderr, "%c", inbuf_o[i] );
418 // }
419 //
420 // fprintf( stderr, "\n" );
421 // raise( SIGSEGV );
422 // exit(1);
423 }
424
425 // DEBUG(
426 // fprintf(stderr, " result:\n");
427 // hexdump( (char*)outbuf_o, 0, oblen, 1 );
428 // )
429
430 //fprintf(stderr, "utf8to16() returning %s\n", outbuf );
431
432 //TODO: error
433 if( icresult ) printf("Uhhhh...utf8to16() returning icresult == %d\n", icresult );
434 return icresult;
435 }
436 // }}}
437
438 int vb_utf8to16T( vbuf *bout, char *cin, int inlen ) // {{{
439 {
440 //TODO: This (and 8to16) are the most horrible things I have ever seen...
441 int inbytesleft = inlen;
442 char *inbuf = cin;
443 //int rlen = -1, tlen;
444 int icresult = -1;
445
446 //int i; //, strlen=-1;
447
448 //if( rlen >= 0 )
449 int outbytesleft;
450 char *outbuf;
451 if( 2 > bout->blen ) vbresize( bout, 2 );
452 bout->dlen = 0;
453
454 do {
455 outbytesleft = bout->blen - bout->dlen;
456 outbuf = bout->b + bout->dlen;
457 icresult = iconv( i8to16, &inbuf, &inbytesleft, &outbuf, &outbytesleft );
458 bout->dlen = outbuf - bout->b;
459 vbgrow( bout, 20 );
460 } while( (size_t)-1 == icresult && E2BIG == errno );
461
462 if( icresult == (size_t)-1 ) {
463 WARN("iconv failure: %s", strerror( errno ) );
464 //ERR_UNIX( errno, "vb_utf8to16():iconv failure: %s", strerror( errno ) );
465 unicode_init();
466 return -1;
467 /*
468 fprintf(stderr, "vb_utf8to16(): iconv failure(%d == %d?): %s\n", errno, E2BIG, strerror( errno ) );
469 fprintf(stderr, " attempted to convert:\n");
470 hexdump( (char*)cin, 0, inlen, 1 );
471 fprintf(stderr, " result:\n");
472 hexdump( (char*)bout->b, 0, bout->dlen, 1 );
473 fprintf(stderr, " MyDirtyOut:\n");
474 for( i=0; i<inlen; i++) {
475 if( inbuf[i] != '\0' ) fprintf(stderr, "%c", inbuf[i] );
476 }
477
478 fprintf( stderr, "\n" );
479 raise( SIGSEGV );
480 exit(1);
481 */
482 }
483
484 //TODO: error
485 if( icresult ) printf("Uhhhh...vb_utf8to16() returning icresult == %d\n", icresult );
486 return icresult;
487 }
488 // }}}
489 #if 1
490 void cheap_uni2ascii(char *src, char *dest, int l) /* {{{ Quick and dirty UNICODE to std. ascii */
491 {
492
493 for (; l > 0; l -=2) {
494 *dest = *src;
495 dest++; src +=2;
496 }
497 *dest = 0;
498 }
499 // }}}
500 #endif
501
502 void cheap_ascii2uni(char *src, char *dest, int l) /* {{{ Quick and dirty ascii to unicode */
503 {
504 for (; l > 0; l--) {
505 *dest++ = *src++;
506 *dest++ = 0;
507
508 }
509 }
510 // }}}
511
512 // }}}
513 // {{{ VARBUF Functions
514 vbuf *vballoc( size_t len ) // {{{
515 {
516 struct varbuf *result;
517
518 result = F_MALLOC( sizeof( struct varbuf ) );
519
520 result->dlen = 0;
521 result->blen = 0;
522 result->buf = NULL;
523
524 vbresize( result, len );
525
526 return result;
527
528 } // }}}
529 void vbcheck( vbuf *vb ) // {{{
530 {
531 ASSERT( vb->b - vb->buf <= vb->blen, "vbcheck(): vb->b outside of buffer range.");
532 ASSERT( vb->dlen <= vb->blen, "vbcheck(): data length > buffer length.");
533
534 ASSERT( vb->blen < 1024*1024, "vbcheck(): blen is a bit large...hmmm.");
535 } // }}}
536 void vbfree( vbuf *vb ) // {{{
537 {
538 free( vb->buf );
539 free( vb );
540 } // }}}
541 void vbclear( struct varbuf *vb ) // {{{ditch the data, keep the buffer
542 {
543 vbresize( vb, 0 );
544 } // }}}
545 void vbresize( struct varbuf *vb, size_t len ) // {{{ DESTRUCTIVELY grow or shrink buffer
546 {
547 vb->dlen = 0;
548
549 if( vb->blen >= len ) {
550 vb->b = vb->buf;
551 return;
552 }
553
554 vb->buf = F_REALLOC( vb->buf, len );
555 vb->b = vb->buf;
556 vb->blen = len;
557 } // }}}
558 int vbavail( vbuf *vb ) // {{{
559 {
560 return vb->blen - ((char*)vb->b - (char*)vb->buf + vb->dlen);
561 } // }}}
562 //void vbdump( vbuf *vb ) // {{{ TODO: to stdout? Yuck
563 //{
564 // printf("vb dump-------------\n");
565 // printf("dlen: %d\n", vb->dlen );
566 // printf("blen: %d\n", vb->blen );
567 // printf("b - buf: %d\n", vb->b - vb->buf );
568 // printf("buf:\n");
569 // hexdump( vb->buf, 0, vb->blen, 1 );
570 // printf("b:\n");
571 // hexdump( vb->b, 0, vb->dlen, 1 );
572 // printf("^^^^^^^^^^^^^^^^^^^^\n");
573 //} // }}}
574 void vbgrow( struct varbuf *vb, size_t len ) // {{{ out: vbavail(vb) >= len, data are preserved
575 {
576 if( 0 == len ) return;
577
578 if( 0 == vb->blen ) {
579 vbresize( vb, len );
580 return;
581 }
582
583 if( vb->dlen + len > vb->blen ) {
584 if( vb->dlen + len < vb->blen * 1.5 ) len = vb->blen * 1.5;
585 char *nb = F_MALLOC( vb->blen + len );
586 //printf("vbgrow() got %p back from malloc(%d)\n", nb, vb->blen + len);
587 vb->blen = vb->blen + len;
588 memcpy( nb, vb->b, vb->dlen );
589
590 //printf("vbgrow() I am going to free %p\n", vb->buf );
591 free( vb->buf );
592 vb->buf = nb;
593 vb->b = vb->buf;
594 } else {
595 if( vb->b != vb->buf )
596 memcpy( vb->buf, vb->b, vb->dlen );
597 }
598
599 vb->b = vb->buf;
600
601 ASSERT( vbavail( vb ) >= len, "vbgrow(): I have failed in my mission." );
602 } // }}}
603 void vbset( vbuf *vb, void *b, size_t len ) // {{{ set vbuf b size=len, resize if necessary, relen = how much to over-allocate
604 {
605 vbresize( vb, len );
606
607 memcpy( vb->b, b, len );
608 vb->dlen = len;
609 } // }}}
610 void vsskipws( vstr *vs ) // {{{
611 {
612 char *p = vs->b;
613 while( p - vs->b < vs->dlen && isspace( p[0] ) ) p++;
614
615 vbskip( (vbuf*)vs, p - vs->b );
616 } // }}}
617 void vbappend( struct varbuf *vb, void *b, size_t len ) // {{{ append len bytes of b to vbuf, resize if necessary
618 {
619 if( 0 == vb->dlen ) {
620 vbset( vb, b, len );
621 return;
622 }
623
624 vbgrow( vb, len );
625
626 memcpy( vb->b + vb->dlen, b, len );
627 vb->dlen += len;
628
629 //printf("vbappend() end: >%s/%d<\n", vbuf->b, vbuf->dlen );
630 } // }}}
631 void vbskip( struct varbuf *vb, size_t skip ) // {{{ dumps the first skip bytes from vbuf
632 {
633 ASSERT( skip <= vb->dlen, "vbskip(): Attempt to seek past end of buffer." );
634 //memmove( vbuf->b, vbuf->b + skip, vbuf->dlen - skip );
635 vb->b += skip;
636 vb->dlen -= skip;
637 } // }}}
638 void vboverwrite( struct varbuf *vbdest, struct varbuf *vbsrc ) // {{{ overwrite vbdest with vbsrc
639 {
640 vbresize( vbdest, vbsrc->blen );
641 memcpy( vbdest->b, vbsrc->b, vbsrc->dlen );
642 vbdest->blen = vbsrc->blen;
643 vbdest->dlen = vbsrc->dlen;
644 } // }}}
645 // }}}
646 // {{{ VARSTR Functions
647 vstr *vsalloc( size_t len ) // {{{
648 {
649 vstr *result = (vstr*)vballoc( len + 1 );
650 vsset( result, "" );
651 return result;
652 } // }}}
653 char *vsstr( vstr *vs ) // {{{
654 {
655 return vs->b;
656 } // }}}
657 size_t vslen( vstr *vs ) // {{{
658 {
659 return strlen( vsstr( vs ));
660 } // }}}
661 void vsfree( vstr *vs ) // {{{
662 {
663 vbfree( (vbuf*)vs );
664 } // }}}
665 void vscharcat( vstr *vb, int ch ) // {{{
666 {
667 vbgrow( (vbuf*)vb, 1);
668 vb->b[vb->dlen-1] = ch;
669 vb->b[vb->dlen] = '\0';
670 vb->dlen++;
671 } // }}}
672 void vsnprepend( vstr *vb, char *str, size_t len ) // {{{ prependappend string str to vbuf, vbuf must already contain a valid string
673 {
674 ASSERT( vb->b[vb->dlen-1] == '\0', "vsncat(): attempt to append string to non-string.");
675 int sl = strlen( str );
676 int n = (sl<len)?sl:len;
677 //string append
678 vbgrow( (vbuf*)vb, n + 1 );
679 memmove( vb->b + n, vb->b, vb->dlen - 1 );
680 memcpy( vb->b, str, n );
681 //strncat( vb->b, str, n );
682
683 vb->dlen += n;
684 vb->b[ vb->dlen - 1 ] = '\0';
685 } // }}}
686 void vsskip( vstr *vs, size_t len ) // {{{ len < dlen-1 -> skip len chars, else DIE
687 {
688 ASSERT( len < vs->dlen - 1, "Attempt to skip past end of string" );
689 vbskip( (vbuf*)vs, len );
690 } // }}}
691 int vsskipline( vstr *vs ) // {{{ in: vb->b == "stuff\nmore_stuff"; out: vb->b == "more_stuff"
692 {
693 int nloff = find_nl( vs );
694 int nll = skip_nl( vs->b + nloff );
695
696 if( nloff < 0 ) {
697 //TODO: error
698 printf("vb_skipline(): there seems to be no newline here.\n");
699 return -1;
700 }
701 if( skip_nl < 0 ) {
702 //TODO: error
703 printf("vb_skipline(): there seems to be no newline here...except there should be. :P\n");
704 return -1;
705 }
706
707 memmove( vs->b, vs->b + nloff + nll, vs->dlen - nloff - nll );
708
709 vs->dlen -= nloff + nll;
710
711 return 0;
712 } // }}}
713 int vscatprintf( vstr *vs, char *fmt, ... ) // {{{
714 {
715 int size;
716 va_list ap;
717
718 /* Guess we need no more than 100 bytes. */
719 //vsresize( vb, 100 );
720 if(!vs->b || vs->dlen == 0) {
721 vsset( vs, "" );
722 }
723
724 while (1) {
725 /* Try to print in the allocated space. */
726 va_start(ap, fmt);
727 size = vsnprintf (vs->b + vs->dlen - 1, vs->blen - vs->dlen, fmt, ap);
728 va_end(ap);
729
730 /* If that worked, return the string. */
731 if (size > -1 && size < vs->blen - vs->dlen ) {
732 vs->dlen += size;
733 return size;
734 }
735 /* Else try again with more space. */
736 if ( size >= 0 ) /* glibc 2.1 */
737 vbgrow( (vbuf*)vs, size+1 ); /* precisely what is needed */
738 else /* glibc 2.0 */
739 vbgrow( (vbuf*)vs, vs->blen);
740 }
741 } // }}}
742 int vslast( vstr *vs ) // {{{ returns the last character stored in a vstr
743 {
744 if( vs->dlen < 1 ) return -1;
745 if( vs->b[vs->dlen-1] != '\0' ) return -1;
746 if( vs->dlen == 1 ) return '\0';
747 return vs->b[vs->dlen-2];
748 } // }}}
749 void vs_printf( vstr *vs, char *fmt, ... ) // {{{ print over vb
750 {
751 int size;
752 va_list ap;
753
754 /* Guess we need no more than 100 bytes. */
755 vbresize( (vbuf*)vs, 100 );
756
757 while (1) {
758 /* Try to print in the allocated space. */
759 va_start(ap, fmt);
760 size = vsnprintf (vs->b, vs->blen, fmt, ap);
761 va_end(ap);
762
763 /* If that worked, return the string. */
764 if (size > -1 && size < vs->blen) {
765 vs->dlen = size + 1;
766 return;
767 }
768 /* Else try again with more space. */
769 if ( size >= 0 ) /* glibc 2.1 */
770 vbresize( (vbuf*)vs, size+1 ); /* precisely what is needed */
771 else /* glibc 2.0 */
772 vbresize( (vbuf*)vs, vs->blen*2);
773 }
774 } // }}}
775 void vs_printfa( vstr *vs, char *fmt, ... ) // {{{ printf append to vs
776 {
777 int size;
778 va_list ap;
779
780 if( vs->blen - vs->dlen < 50 )
781 vbgrow( (vbuf*)vs, 100 );
782
783 while (1) {
784 /* Try to print in the allocated space. */
785 va_start(ap, fmt);
786 size = vsnprintf (vs->b + vs->dlen - 1, vs->blen - vs->dlen + 1, fmt, ap);
787 va_end(ap);
788
789 /* If that worked, return the string. */
790 if (size > -1 && size < vs->blen) {
791 vs->dlen += size;
792 return;
793 }
794 /* Else try again with more space. */
795 if ( size >= 0 ) /* glibc 2.1 */
796 vbgrow( (vbuf*)vs, size+1 - vs->dlen ); /* precisely what is needed */
797 else /* glibc 2.0 */
798 vbgrow( (vbuf*)vs, size );
799 }
800 } // }}}
801 void vshexdump( vstr *vs, char *b, size_t start, size_t stop, int ascii ) // {{{
802 {
803 char c;
804 int diff,i;
805
806 while (start < stop ) {
807 diff = stop - start;
808 if (diff > 16) diff = 16;
809
810 vs_printfa(vs, ":%08X ",start);
811
812 for (i = 0; i < diff; i++) {
813 if( 8 == i ) vs_printfa( vs, " " );
814 vs_printfa(vs, "%02X ",(unsigned char)*(b+start+i));
815 }
816 if (ascii) {
817 for (i = diff; i < 16; i++) vs_printfa(vs, " ");
818 for (i = 0; i < diff; i++) {
819 c = *(b+start+i);
820 vs_printfa(vs, "%c", isprint(c) ? c : '.');
821 }
822 }
823 vs_printfa(vs, "\n");
824 start += 16;
825 }
826 } // }}}
827 void vsset( vstr *vs, char *s ) // {{{ Store string s in vs
828 {
829 vsnset( vs, s, strlen( s ) );
830 } // }}}
831 void vsnset( vstr *vs, char *s, size_t n ) // {{{ Store string s in vs
832 {
833 vbresize( (vbuf*)vs, n + 1 );
834 memcpy( vs->b, s, n);
835 vs->b[n] = '\0';
836 vs->dlen = n+1;
837 } // }}}
838 void vsgrow( vstr *vs, size_t len ) // {{{ grow buffer by len bytes, data are preserved
839 {
840 vbgrow( (vbuf*)vs, len );
841 } // }}}
842 size_t vsavail( vstr *vs ) // {{{
843 {
844 return vbavail( (vbuf*)vs );
845 } // }}}
846 void vsnset16( vstr *vs, char *s, size_t len ) // {{{ Like vbstrnset, but for UTF16
847 {
848 vbresize( (vbuf*)vs, len+1 );
849 memcpy( vs->b, s, len );
850
851 vs->b[len] = '\0';
852 vs->dlen = len+1;
853 vs->b[len] = '\0';
854 } // }}}
855 void vscat( vstr *vs, char *str ) // {{{
856 {
857 vsncat( vs, str, strlen(str ) );
858 } // }}}
859 int vscmp( vstr *vs, char *str ) // {{{
860 {
861 return strcmp( vs->b, str );
862 } // }}}
863 void vsncat( vstr *vs, char *str, size_t len ) // {{{ append string str to vstr, vstr must already contain a valid string
864 {
865 ASSERT( vs->b[vs->dlen-1] == '\0', "vsncat(): attempt to append string to non-string.");
866 int sl = strlen( str );
867 int n = (sl<len)?sl:len;
868 //string append
869 vbgrow( (vbuf*)vs, n + 1 );
870 memcpy( vs->b + vs->dlen - 1, str, n );
871 //strncat( vs->b, str, n );
872
873 vs->dlen += n;
874 vs->b[ vs->dlen - 1 ] = '\0';
875 } // }}}
876 void vstrunc( vstr *v, int off ) // {{{ Drop chars [off..dlen]
877 {
878 if( off >= v->dlen - 1 ) return; //nothing to do
879 v->b[off] = '\0';
880 v->dlen = off + 1;
881 }
882 // }}}
883 // }}}
884 // {{{ User input
885 // TODO: not sure how useful this stuff is here
886 int fmyinput(char *prmpt, char *ibuf, int maxlen) /* {{{ get user input */
887 {
888 printf("%s",prmpt);
889
890 fgets(ibuf,maxlen+1,stdin);
891
892 ibuf[strlen(ibuf)-1] = 0;
893
894 return(strlen(ibuf));
895 }
896 // }}}
897 //}}}
898 //
899 //
900 //{{{ String formatting and output to FILE *stream or just stdout, etc
901 // TODO: a lot of old, unused stuff in here
902 void vswinhex8(vstr *vs, unsigned char *hbuf, int start, int stop, int loff ) // {{{ Produce regedit-style hex output */
903 {
904 int i;
905 int lineflag=0;
906
907 for( i=start; i<stop; i++)
908 {
909 loff += vscatprintf( vs, "%02x", hbuf[i] );
910 if( i < stop - 1 ) {
911 loff+=vscatprintf( vs, "," );
912 switch( lineflag ) {
913 case 0:
914 if( loff >= 77) {
915 lineflag=1;
916 loff=0;
917 vscatprintf( vs, "\\%s ", STUPID_CR );
918 }
919 break;
920 case 1:
921 if( loff >= 75 ) {
922 loff=0;
923 vscatprintf( vs, "\\%s ", STUPID_CR );
924 }
925 break;
926 }
927 // if( 24 < i || 0 == (i - 17) % 25 ) fprintf( stream, "\\\n " );
928 }
929 }
930
931 // fprintf( stream, "\n" );
932 } // }}}