Mercurial > libpst
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 } // }}} |