43
|
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 } // }}}
|