Mercurial > libpst
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/vbuf.c Sun Jan 06 14:47:06 2008 -0800 @@ -0,0 +1,932 @@ +// {{{ includes + +#include <ctype.h> +//#include "defines.h" +#include <errno.h> +#include <iconv.h> +#include <malloc.h> +#include <signal.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "vbuf.h" +#include "generic.h" + +#ifdef WITH_DMALLOC +#include <dmalloc.h> +#endif + +// }}} + +int skip_nl( char *s ) // {{{ returns the width of the newline at s[0] +{ + if( s[0] == '\n' ) return 1; + if( s[0] == '\r' && s[1] == '\n' ) return 2; + if( s[0] == '\0' ) return 0; + return -1; +} // }}} +int find_nl( vstr *vs ) // {{{ find newline of type type in b +{ + char *nextr, *nextn; + + nextr = memchr( vs->b, '\r', vs->dlen ); + nextn = memchr( vs->b, '\n', vs->dlen ); + + //case 1: UNIX, we find \n first + if( nextn && (nextr == NULL || nextr > nextn ) ) { + return nextn - vs->b; + } + + //case 2: DOS, we find \r\n + if( NULL != nextr && NULL != nextn && 1 == (char*)nextn - (char*)nextr ) { + return nextr - vs->b; + } + + //case 3: we find nothing + + return -1; +} // }}} + +// {{{ UTF8 <-> UTF16 <-> ISO8859 Character set conversion functions and (ack) their globals + +//TODO: the following should not be +char *wwbuf=NULL; +size_t nwwbuf=0; +static int unicode_up=0; +iconv_t i16to8, i8to16, i8859_1to8, i8toi8859_1; + +void unicode_init() // {{{ +{ + char *wipe = ""; + char dump[4]; + + if( unicode_up ) unicode_close(); + + if( (iconv_t)-1 == (i16to8 = iconv_open( "UTF-8", "UTF-16" ) ) ) { + fprintf(stderr, "doexport(): Couldn't open iconv descriptor for UTF-16 to UTF-8.\n"); + exit( 1 ); + } + + if( (iconv_t)-1 == (i8to16 = iconv_open( "UTF-16", "UTF-8" ) ) ) { + fprintf(stderr, "doexport(): Couldn't open iconv descriptor for UTF-8 to UTF-16.\n"); + exit( 2 ); + } + + //iconv will prefix output with an FF FE (utf-16 start seq), the following dumps that. + memset( dump, 'x', 4 ); + ASSERT( 0 == utf8to16( wipe, 1, dump, 4 ), "unicode_init(): attempt to dump FF FE failed." ); + + if( (iconv_t)-1 == (i8859_1to8 = iconv_open( "UTF-8", "ISO_8859-1" ) ) ) { + fprintf(stderr, "doexport(): Couldn't open iconv descriptor for ASCII to UTF-8.\n"); + exit( 1 ); + } + + + if( (iconv_t)-1 == (i8toi8859_1 = iconv_open( "ISO_8859-1", "UTF-8" ) ) ) { + fprintf(stderr, "doexport(): Couldn't open iconv descriptor for UTF-8 to ASCII.\n"); + exit( 1 ); + } + + unicode_up = 1; +} +// }}} +void unicode_close() // {{{ +{ + unicode_up = 0; + iconv_close( i8to16 ); + iconv_close( i16to8 ); + iconv_close( i8859_1to8 ); + iconv_close( i8toi8859_1 ); +} +// }}} + +//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 +//{ +// +// //TODO: if anything big comes through here we are sunk, should do it +// //bit-by-bit, not one-big-gulp +// +// size_t inbytesleft, outbytesleft; +// char *inbuf, *outbuf; +// size_t icresult; +// size_t rl; +// +// //do we have enough buffer space? +// if( !wwbuf || nwwbuf < (count * 2 + 2) ) { +// wwbuf = F_REALLOC( wwbuf, count * 2 +2 ); +// +// nwwbuf = count * 2 + 2; +// } +// +// inbytesleft = count; outbytesleft = nwwbuf; +// inbuf = (char*)buf; outbuf = wwbuf; +// +//// fprintf(stderr, "X%s, %dX", (char*)buf, strlen( buf )); +//// fflush(stderr); +// +// if( (rl = strlen( buf ) + 1) != count ) { +// fprintf(stderr, "utf16_write(): reported buffer size (%d) does not match string length (%d)\n", +// count, +// rl); +// +// //hexdump( (char*)buf, 0, count, 1 ); +// +// raise( SIGSEGV ); +// inbytesleft = rl; +// } +// +//// fprintf(stderr, " attempting to convert:\n"); +//// hexdump( (char*)inbuf, 0, count, 1 ); +// +// icresult = iconv( i8to16, &inbuf, &inbytesleft, &outbuf, &outbytesleft ); +// +//// fprintf(stderr, " converted:\n"); +//// hexdump( (char*)buf, 0, count, 1 ); +// +//// fprintf(stderr, " to:\n"); +//// hexdump( (char*)wwbuf, 0, nwwbuf, 1 ); +// +// if( (size_t)-1 == icresult ) { +// fprintf(stderr, "utf16_write(): iconv failure(%d): %s\n", errno, strerror( errno ) ); +// fprintf(stderr, " attempted to convert:\n"); +// hexdump( (char*)inbuf, 0, count, 1 ); +// +// fprintf(stderr, " result:\n"); +// hexdump( (char*)outbuf, 0, count, 1 ); +// +// fprintf(stderr, "I'm going to segfault now.\n"); +// raise( SIGSEGV ); +// exit(1); +// } +// +// if( inbytesleft > 0 ) { +// fprintf(stderr, "utf16_write(): iconv returned a short count.\n"); +// exit(1); +// } +// +// return fwrite( wwbuf, nwwbuf - outbytesleft - 2, 1, stream ); +//} +// }}} + +//char *utf16buf = NULL; +//int utf16buf_len = 0; +// +//int utf16_fprintf( FILE* stream, const char *fmt, ... ) // {{{ +//{ +// int result=0; +// va_list ap; +// +// if( utf16buf == NULL ) { +// utf16buf = (char*)F_MALLOC( SZ_MAX + 1 ); +// +// utf16buf_len = SZ_MAX + 1; +// } +// +// va_start( ap, fmt ); +// +// result = vsnprintf( utf16buf, utf16buf_len, fmt, ap ); +// +// if( result + 1 > utf16buf_len ) { //didn't have space, realloc() and try again +// fprintf(stderr, "utf16_fprintf(): buffer too small (%d), F_MALLOC(%d)\n", utf16buf_len, result); +// free( utf16buf ); +// utf16buf_len = result + 1; +// utf16buf = (char*)F_MALLOC( utf16buf_len ); +// +// result = vsnprintf( utf16buf, utf16buf_len, fmt, ap ); +// } +// +// +// //didn't have space...again...something weird is going on... +// ASSERT( result + 1 <= utf16buf_len, "utf16_fprintf(): Unpossible error!\n"); +// +// if( 1 != utf16_write( stream, utf16buf, result + 1 ) ) +// DIE( "Write error? -> %s or %s\n", strerror( errno ), uerr_str( uerr_get() ) ); +// +// return result; +//} +//// }}} +//int utf16to8( char *inbuf_o, char *outbuf_o, int length ) // {{{ +//{ +// int inbytesleft = length; +// int outbytesleft = length; +// char *inbuf = inbuf_o; +// char *outbuf = outbuf_o; +// int rlen = -1, tlen; +// int icresult = -1; +// +// int i, strlen=-1; +// +// DEBUG( +// fprintf(stderr, " utf16to8(): attempting to convert:\n"); +// //hexdump( (char*)inbuf_o, 0, length, 1 ); +// fflush(stderr); +// ); +// +// for( i=0; i<length ; i+=2 ) { +// if( inbuf_o[i] == 0 && inbuf_o[i + 1] == 0 ) { +// //fprintf(stderr, "End of string found at: %d\n", i ); +// strlen = i; +// } +// } +// +// //hexdump( (char*)inbuf_o, 0, strlen, 1 ); +// +// if( -1 == strlen ) WARN("String is not zero-terminated."); +// +// //iconv does not like it when the inbytesleft > actual string length +// //enum: zero terminated, length valid +// // zero terminated, length short //we won't go beyond length ever, so this is same as NZT case +// // zero terminated, length long +// // not zero terminated +// // TODO: MEMORY BUG HERE! +// for( tlen = 0; tlen <= inbytesleft - 2; tlen+=2 ) { +// if( inbuf_o[tlen] == 0 && inbuf_o[tlen+1] == 0 ){ +// rlen = tlen + 2; +// tlen = rlen; +// break; +// } +// if( tlen == inbytesleft )fprintf(stderr, "Space allocated for string > actual string length. Go windows!\n"); +// } +// +// if( rlen >= 0 ) +// icresult = iconv( i16to8, &inbuf, &rlen, &outbuf, &outbytesleft ); +// +// if( icresult == (size_t)-1 ) { +// fprintf(stderr, "utf16to8(): iconv failure(%d): %s\n", errno, strerror( errno ) ); +// fprintf(stderr, " attempted to convert:\n"); +// hexdump( (char*)inbuf_o, 0, length, 1 ); +// fprintf(stderr, " result:\n"); +// hexdump( (char*)outbuf_o, 0, length, 1 ); +// fprintf(stderr, " MyDirtyOut:\n"); +// for( i=0; i<length; i++) { +// if( inbuf_o[i] != '\0' ) fprintf(stderr, "%c", inbuf_o[i] ); +// } +// +// fprintf( stderr, "\n" ); +// raise( SIGSEGV ); +// exit(1); +// } +// +// DEBUG( +// fprintf(stderr, " result:\n"); +// hexdump( (char*)outbuf_o, 0, length, 1 ); +// ) +// +// //fprintf(stderr, "utf16to8() returning %s\n", outbuf ); +// +// return icresult; +//} +//// }}} +int utf16_is_terminated( char *str, int length ) // {{{ +{ + VSTR_STATIC( errbuf, 100 ); + int len = -1; + int i; + for( i=0; i<length ; i+=2 ) { + if( str[i] == 0 && str[i + 1] == 0 ) { + //fprintf(stderr, "End of string found at: %d\n", i ); + len = i; + } + } + + //hexdump( (char*)inbuf_o, 0, len, 1 ); + + if( -1 == len ) { + vshexdump( errbuf, str, 0, length, 1 ); + WARN("String is not zero terminated (probably broken data from registry) %s.", errbuf->b); + } + + return (-1 == len )?0:1; +} // }}} +int vb_utf16to8( vbuf *dest, char *buf, int len ) // {{{ +{ + int inbytesleft = len; + char *inbuf = buf; + //int rlen = -1, tlen; + int icresult = -1; + VBUF_STATIC( dumpster, 100 ); + + //int i; //, strlen=-1; + int outbytesleft; + char *outbuf; + + ASSERT( unicode_up, "vb_utf16to8() called before unicode started." ); + + if( 2 > dest->blen ) vbresize( dest, 2 ); + dest->dlen = 0; + + //Bad Things can happen if a non-zero-terminated utf16 string comes through here + if( !utf16_is_terminated( buf, len ) ) return -1; + + do { + outbytesleft = dest->blen - dest->dlen; + outbuf = dest->b + dest->dlen; + icresult = iconv( i16to8, &inbuf, &inbytesleft, &outbuf, &outbytesleft ); + dest->dlen = outbuf - dest->b; + vbgrow( dest, inbytesleft); + } while( (size_t)-1 == icresult && E2BIG == errno ); + + if( 0 != vb_utf8to16T( dumpster, dest->b, dest->dlen ) ) + DIE("Reverse conversion failed."); + + if( icresult == (size_t)-1 ) { + //TODO: error + //ERR_UNIX( errno, "vb_utf16to8():iconv failure: %s", strerror( errno ) ); + unicode_init(); + return -1; + /* + fprintf(stderr, " attempted to convert:\n"); + hexdump( (char*)cin, 0, inlen, 1 ); + fprintf(stderr, " result:\n"); + hexdump( (char*)bout->b, 0, bout->dlen, 1 ); + fprintf(stderr, " MyDirtyOut:\n"); + for( i=0; i<inlen; i++) { + if( inbuf[i] != '\0' ) fprintf(stderr, "%c", inbuf[i] ); + } + + fprintf( stderr, "\n" ); + raise( SIGSEGV ); + exit(1); + */ + } + + if( icresult ) { + //ERR_UNIX( EILSEQ, "Uhhhh...vb_utf16to8() returning icresult == %d", icresult ); + return -1; + } + return icresult; +} +// }}} + +int utf8to16( char *inbuf_o, int iblen, char *outbuf_o, int oblen) // {{{ iblen, oblen: bytes including \0 +{ + //TODO: this is *only* used to dump the utf16 preamble now... + //TODO: This (and 8to16) are the most horrible things I have ever seen... + int inbytesleft; + int outbytesleft = oblen; + char *inbuf = inbuf_o; + char *outbuf = outbuf_o; + //int rlen = -1, tlen; + int icresult = -1; + + char *stend; + + //int i; //, strlen=-1; + + DEBUG( + fprintf(stderr, " utf8to16(): attempting to convert:\n"); + //hexdump( (char*)inbuf_o, 0, length, 1 ); + fflush(stderr); + ); + + stend = memchr( inbuf_o, '\0', iblen ); + ASSERT( NULL != stend, "utf8to16(): in string not zero terminated." ); + + inbytesleft = ( stend - inbuf_o + 1 < iblen )? stend - inbuf_o + 1: iblen; + + //iconv does not like it when the inbytesleft > actual string length + //enum: zero terminated, length valid + // zero terminated, length short //we won't go beyond length ever, so this is same as NZT case + // zero terminated, length long + // not zero terminated + // TODO: MEMORY BUG HERE! + // + /* + for( tlen = 0; tlen <= inbytesleft - 2; tlen+=2 ) { + if( inbuf_o[tlen] == 0 && inbuf_o[tlen+1] == 0 ){ + rlen = tlen + 2; + tlen = rlen; + break; + } + if( tlen == inbytesleft )fprintf(stderr, "Space allocated for string > actual string length. Go windows!\n"); + } + */ + + //if( rlen >= 0 ) + icresult = iconv( i8to16, &inbuf, &inbytesleft, &outbuf, &outbytesleft ); + + if( icresult == (size_t)-1 ) { + DIE("iconv failure(%d): %s\n", errno, strerror( errno ) ); + //fprintf(stderr, " attempted to convert:\n"); + //hexdump( (char*)inbuf_o, 0, iblen, 1 ); + //fprintf(stderr, " result:\n"); + //hexdump( (char*)outbuf_o, 0, oblen, 1 ); + //fprintf(stderr, " MyDirtyOut:\n"); +// for( i=0; i<iblen; i++) { +// if( inbuf_o[i] != '\0' ) fprintf(stderr, "%c", inbuf_o[i] ); +// } +// +// fprintf( stderr, "\n" ); +// raise( SIGSEGV ); +// exit(1); + } + +// DEBUG( +// fprintf(stderr, " result:\n"); +// hexdump( (char*)outbuf_o, 0, oblen, 1 ); +// ) + + //fprintf(stderr, "utf8to16() returning %s\n", outbuf ); + + //TODO: error + if( icresult ) printf("Uhhhh...utf8to16() returning icresult == %d\n", icresult ); + return icresult; +} +// }}} + +int vb_utf8to16T( vbuf *bout, char *cin, int inlen ) // {{{ +{ + //TODO: This (and 8to16) are the most horrible things I have ever seen... + int inbytesleft = inlen; + char *inbuf = cin; + //int rlen = -1, tlen; + int icresult = -1; + + //int i; //, strlen=-1; + + //if( rlen >= 0 ) + int outbytesleft; + char *outbuf; + if( 2 > bout->blen ) vbresize( bout, 2 ); + bout->dlen = 0; + + do { + outbytesleft = bout->blen - bout->dlen; + outbuf = bout->b + bout->dlen; + icresult = iconv( i8to16, &inbuf, &inbytesleft, &outbuf, &outbytesleft ); + bout->dlen = outbuf - bout->b; + vbgrow( bout, 20 ); + } while( (size_t)-1 == icresult && E2BIG == errno ); + + if( icresult == (size_t)-1 ) { + WARN("iconv failure: %s", strerror( errno ) ); + //ERR_UNIX( errno, "vb_utf8to16():iconv failure: %s", strerror( errno ) ); + unicode_init(); + return -1; + /* + fprintf(stderr, "vb_utf8to16(): iconv failure(%d == %d?): %s\n", errno, E2BIG, strerror( errno ) ); + fprintf(stderr, " attempted to convert:\n"); + hexdump( (char*)cin, 0, inlen, 1 ); + fprintf(stderr, " result:\n"); + hexdump( (char*)bout->b, 0, bout->dlen, 1 ); + fprintf(stderr, " MyDirtyOut:\n"); + for( i=0; i<inlen; i++) { + if( inbuf[i] != '\0' ) fprintf(stderr, "%c", inbuf[i] ); + } + + fprintf( stderr, "\n" ); + raise( SIGSEGV ); + exit(1); + */ + } + + //TODO: error + if( icresult ) printf("Uhhhh...vb_utf8to16() returning icresult == %d\n", icresult ); + return icresult; +} +// }}} +#if 1 +void cheap_uni2ascii(char *src, char *dest, int l) /* {{{ Quick and dirty UNICODE to std. ascii */ +{ + + for (; l > 0; l -=2) { + *dest = *src; + dest++; src +=2; + } + *dest = 0; +} +// }}} +#endif + +void cheap_ascii2uni(char *src, char *dest, int l) /* {{{ Quick and dirty ascii to unicode */ +{ + for (; l > 0; l--) { + *dest++ = *src++; + *dest++ = 0; + + } +} +// }}} + +// }}} +// {{{ VARBUF Functions +vbuf *vballoc( size_t len ) // {{{ +{ + struct varbuf *result; + + result = F_MALLOC( sizeof( struct varbuf ) ); + + result->dlen = 0; + result->blen = 0; + result->buf = NULL; + + vbresize( result, len ); + + return result; + +} // }}} +void vbcheck( vbuf *vb ) // {{{ +{ + ASSERT( vb->b - vb->buf <= vb->blen, "vbcheck(): vb->b outside of buffer range."); + ASSERT( vb->dlen <= vb->blen, "vbcheck(): data length > buffer length."); + + ASSERT( vb->blen < 1024*1024, "vbcheck(): blen is a bit large...hmmm."); +} // }}} +void vbfree( vbuf *vb ) // {{{ +{ + free( vb->buf ); + free( vb ); +} // }}} +void vbclear( struct varbuf *vb ) // {{{ditch the data, keep the buffer +{ + vbresize( vb, 0 ); +} // }}} +void vbresize( struct varbuf *vb, size_t len ) // {{{ DESTRUCTIVELY grow or shrink buffer +{ + vb->dlen = 0; + + if( vb->blen >= len ) { + vb->b = vb->buf; + return; + } + + vb->buf = F_REALLOC( vb->buf, len ); + vb->b = vb->buf; + vb->blen = len; +} // }}} +int vbavail( vbuf *vb ) // {{{ +{ + return vb->blen - ((char*)vb->b - (char*)vb->buf + vb->dlen); +} // }}} +//void vbdump( vbuf *vb ) // {{{ TODO: to stdout? Yuck +//{ +// printf("vb dump-------------\n"); +// printf("dlen: %d\n", vb->dlen ); +// printf("blen: %d\n", vb->blen ); +// printf("b - buf: %d\n", vb->b - vb->buf ); +// printf("buf:\n"); +// hexdump( vb->buf, 0, vb->blen, 1 ); +// printf("b:\n"); +// hexdump( vb->b, 0, vb->dlen, 1 ); +// printf("^^^^^^^^^^^^^^^^^^^^\n"); +//} // }}} +void vbgrow( struct varbuf *vb, size_t len ) // {{{ out: vbavail(vb) >= len, data are preserved +{ + if( 0 == len ) return; + + if( 0 == vb->blen ) { + vbresize( vb, len ); + return; + } + + if( vb->dlen + len > vb->blen ) { + if( vb->dlen + len < vb->blen * 1.5 ) len = vb->blen * 1.5; + char *nb = F_MALLOC( vb->blen + len ); + //printf("vbgrow() got %p back from malloc(%d)\n", nb, vb->blen + len); + vb->blen = vb->blen + len; + memcpy( nb, vb->b, vb->dlen ); + + //printf("vbgrow() I am going to free %p\n", vb->buf ); + free( vb->buf ); + vb->buf = nb; + vb->b = vb->buf; + } else { + if( vb->b != vb->buf ) + memcpy( vb->buf, vb->b, vb->dlen ); + } + + vb->b = vb->buf; + + ASSERT( vbavail( vb ) >= len, "vbgrow(): I have failed in my mission." ); +} // }}} +void vbset( vbuf *vb, void *b, size_t len ) // {{{ set vbuf b size=len, resize if necessary, relen = how much to over-allocate +{ + vbresize( vb, len ); + + memcpy( vb->b, b, len ); + vb->dlen = len; +} // }}} +void vsskipws( vstr *vs ) // {{{ +{ + char *p = vs->b; + while( p - vs->b < vs->dlen && isspace( p[0] ) ) p++; + + vbskip( (vbuf*)vs, p - vs->b ); +} // }}} +void vbappend( struct varbuf *vb, void *b, size_t len ) // {{{ append len bytes of b to vbuf, resize if necessary +{ + if( 0 == vb->dlen ) { + vbset( vb, b, len ); + return; + } + + vbgrow( vb, len ); + + memcpy( vb->b + vb->dlen, b, len ); + vb->dlen += len; + + //printf("vbappend() end: >%s/%d<\n", vbuf->b, vbuf->dlen ); +} // }}} +void vbskip( struct varbuf *vb, size_t skip ) // {{{ dumps the first skip bytes from vbuf +{ + ASSERT( skip <= vb->dlen, "vbskip(): Attempt to seek past end of buffer." ); + //memmove( vbuf->b, vbuf->b + skip, vbuf->dlen - skip ); + vb->b += skip; + vb->dlen -= skip; +} // }}} +void vboverwrite( struct varbuf *vbdest, struct varbuf *vbsrc ) // {{{ overwrite vbdest with vbsrc +{ + vbresize( vbdest, vbsrc->blen ); + memcpy( vbdest->b, vbsrc->b, vbsrc->dlen ); + vbdest->blen = vbsrc->blen; + vbdest->dlen = vbsrc->dlen; +} // }}} +// }}} +// {{{ VARSTR Functions +vstr *vsalloc( size_t len ) // {{{ +{ + vstr *result = (vstr*)vballoc( len + 1 ); + vsset( result, "" ); + return result; +} // }}} +char *vsstr( vstr *vs ) // {{{ +{ + return vs->b; +} // }}} +size_t vslen( vstr *vs ) // {{{ +{ + return strlen( vsstr( vs )); +} // }}} +void vsfree( vstr *vs ) // {{{ +{ + vbfree( (vbuf*)vs ); +} // }}} +void vscharcat( vstr *vb, int ch ) // {{{ +{ + vbgrow( (vbuf*)vb, 1); + vb->b[vb->dlen-1] = ch; + vb->b[vb->dlen] = '\0'; + vb->dlen++; +} // }}} +void vsnprepend( vstr *vb, char *str, size_t len ) // {{{ prependappend string str to vbuf, vbuf must already contain a valid string +{ + ASSERT( vb->b[vb->dlen-1] == '\0', "vsncat(): attempt to append string to non-string."); + int sl = strlen( str ); + int n = (sl<len)?sl:len; + //string append + vbgrow( (vbuf*)vb, n + 1 ); + memmove( vb->b + n, vb->b, vb->dlen - 1 ); + memcpy( vb->b, str, n ); + //strncat( vb->b, str, n ); + + vb->dlen += n; + vb->b[ vb->dlen - 1 ] = '\0'; +} // }}} +void vsskip( vstr *vs, size_t len ) // {{{ len < dlen-1 -> skip len chars, else DIE +{ + ASSERT( len < vs->dlen - 1, "Attempt to skip past end of string" ); + vbskip( (vbuf*)vs, len ); +} // }}} +int vsskipline( vstr *vs ) // {{{ in: vb->b == "stuff\nmore_stuff"; out: vb->b == "more_stuff" +{ + int nloff = find_nl( vs ); + int nll = skip_nl( vs->b + nloff ); + + if( nloff < 0 ) { + //TODO: error + printf("vb_skipline(): there seems to be no newline here.\n"); + return -1; + } + if( skip_nl < 0 ) { + //TODO: error + printf("vb_skipline(): there seems to be no newline here...except there should be. :P\n"); + return -1; + } + + memmove( vs->b, vs->b + nloff + nll, vs->dlen - nloff - nll ); + + vs->dlen -= nloff + nll; + + return 0; +} // }}} +int vscatprintf( vstr *vs, char *fmt, ... ) // {{{ +{ + int size; + va_list ap; + + /* Guess we need no more than 100 bytes. */ + //vsresize( vb, 100 ); + if(!vs->b || vs->dlen == 0) { + vsset( vs, "" ); + } + + while (1) { + /* Try to print in the allocated space. */ + va_start(ap, fmt); + size = vsnprintf (vs->b + vs->dlen - 1, vs->blen - vs->dlen, fmt, ap); + va_end(ap); + + /* If that worked, return the string. */ + if (size > -1 && size < vs->blen - vs->dlen ) { + vs->dlen += size; + return size; + } + /* Else try again with more space. */ + if ( size >= 0 ) /* glibc 2.1 */ + vbgrow( (vbuf*)vs, size+1 ); /* precisely what is needed */ + else /* glibc 2.0 */ + vbgrow( (vbuf*)vs, vs->blen); + } +} // }}} +int vslast( vstr *vs ) // {{{ returns the last character stored in a vstr +{ + if( vs->dlen < 1 ) return -1; + if( vs->b[vs->dlen-1] != '\0' ) return -1; + if( vs->dlen == 1 ) return '\0'; + return vs->b[vs->dlen-2]; +} // }}} +void vs_printf( vstr *vs, char *fmt, ... ) // {{{ print over vb +{ + int size; + va_list ap; + + /* Guess we need no more than 100 bytes. */ + vbresize( (vbuf*)vs, 100 ); + + while (1) { + /* Try to print in the allocated space. */ + va_start(ap, fmt); + size = vsnprintf (vs->b, vs->blen, fmt, ap); + va_end(ap); + + /* If that worked, return the string. */ + if (size > -1 && size < vs->blen) { + vs->dlen = size + 1; + return; + } + /* Else try again with more space. */ + if ( size >= 0 ) /* glibc 2.1 */ + vbresize( (vbuf*)vs, size+1 ); /* precisely what is needed */ + else /* glibc 2.0 */ + vbresize( (vbuf*)vs, vs->blen*2); + } +} // }}} +void vs_printfa( vstr *vs, char *fmt, ... ) // {{{ printf append to vs +{ + int size; + va_list ap; + + if( vs->blen - vs->dlen < 50 ) + vbgrow( (vbuf*)vs, 100 ); + + while (1) { + /* Try to print in the allocated space. */ + va_start(ap, fmt); + size = vsnprintf (vs->b + vs->dlen - 1, vs->blen - vs->dlen + 1, fmt, ap); + va_end(ap); + + /* If that worked, return the string. */ + if (size > -1 && size < vs->blen) { + vs->dlen += size; + return; + } + /* Else try again with more space. */ + if ( size >= 0 ) /* glibc 2.1 */ + vbgrow( (vbuf*)vs, size+1 - vs->dlen ); /* precisely what is needed */ + else /* glibc 2.0 */ + vbgrow( (vbuf*)vs, size ); + } +} // }}} +void vshexdump( vstr *vs, char *b, size_t start, size_t stop, int ascii ) // {{{ +{ + char c; + int diff,i; + + while (start < stop ) { + diff = stop - start; + if (diff > 16) diff = 16; + + vs_printfa(vs, ":%08X ",start); + + for (i = 0; i < diff; i++) { + if( 8 == i ) vs_printfa( vs, " " ); + vs_printfa(vs, "%02X ",(unsigned char)*(b+start+i)); + } + if (ascii) { + for (i = diff; i < 16; i++) vs_printfa(vs, " "); + for (i = 0; i < diff; i++) { + c = *(b+start+i); + vs_printfa(vs, "%c", isprint(c) ? c : '.'); + } + } + vs_printfa(vs, "\n"); + start += 16; + } +} // }}} +void vsset( vstr *vs, char *s ) // {{{ Store string s in vs +{ + vsnset( vs, s, strlen( s ) ); +} // }}} +void vsnset( vstr *vs, char *s, size_t n ) // {{{ Store string s in vs +{ + vbresize( (vbuf*)vs, n + 1 ); + memcpy( vs->b, s, n); + vs->b[n] = '\0'; + vs->dlen = n+1; +} // }}} +void vsgrow( vstr *vs, size_t len ) // {{{ grow buffer by len bytes, data are preserved +{ + vbgrow( (vbuf*)vs, len ); +} // }}} +size_t vsavail( vstr *vs ) // {{{ +{ + return vbavail( (vbuf*)vs ); +} // }}} +void vsnset16( vstr *vs, char *s, size_t len ) // {{{ Like vbstrnset, but for UTF16 +{ + vbresize( (vbuf*)vs, len+1 ); + memcpy( vs->b, s, len ); + + vs->b[len] = '\0'; + vs->dlen = len+1; + vs->b[len] = '\0'; +} // }}} +void vscat( vstr *vs, char *str ) // {{{ +{ + vsncat( vs, str, strlen(str ) ); +} // }}} +int vscmp( vstr *vs, char *str ) // {{{ +{ + return strcmp( vs->b, str ); +} // }}} +void vsncat( vstr *vs, char *str, size_t len ) // {{{ append string str to vstr, vstr must already contain a valid string +{ + ASSERT( vs->b[vs->dlen-1] == '\0', "vsncat(): attempt to append string to non-string."); + int sl = strlen( str ); + int n = (sl<len)?sl:len; + //string append + vbgrow( (vbuf*)vs, n + 1 ); + memcpy( vs->b + vs->dlen - 1, str, n ); + //strncat( vs->b, str, n ); + + vs->dlen += n; + vs->b[ vs->dlen - 1 ] = '\0'; +} // }}} +void vstrunc( vstr *v, int off ) // {{{ Drop chars [off..dlen] +{ + if( off >= v->dlen - 1 ) return; //nothing to do + v->b[off] = '\0'; + v->dlen = off + 1; +} +// }}} +// }}} +// {{{ User input +// TODO: not sure how useful this stuff is here +int fmyinput(char *prmpt, char *ibuf, int maxlen) /* {{{ get user input */ +{ + printf("%s",prmpt); + + fgets(ibuf,maxlen+1,stdin); + + ibuf[strlen(ibuf)-1] = 0; + + return(strlen(ibuf)); +} +// }}} +//}}} +// +// +//{{{ String formatting and output to FILE *stream or just stdout, etc +// TODO: a lot of old, unused stuff in here +void vswinhex8(vstr *vs, unsigned char *hbuf, int start, int stop, int loff ) // {{{ Produce regedit-style hex output */ +{ + int i; + int lineflag=0; + + for( i=start; i<stop; i++) + { + loff += vscatprintf( vs, "%02x", hbuf[i] ); + if( i < stop - 1 ) { + loff+=vscatprintf( vs, "," ); + switch( lineflag ) { + case 0: + if( loff >= 77) { + lineflag=1; + loff=0; + vscatprintf( vs, "\\%s ", STUPID_CR ); + } + break; + case 1: + if( loff >= 75 ) { + loff=0; + vscatprintf( vs, "\\%s ", STUPID_CR ); + } + break; + } + // if( 24 < i || 0 == (i - 17) % 25 ) fprintf( stream, "\\\n " ); + } + } + + // fprintf( stream, "\n" ); +} // }}}