comparison src/vbuf.c @ 182:b65e8d0a088a

more cleanup on external names in the shared object file
author Carl Byington <carl@five-ten-sg.com>
date Mon, 13 Apr 2009 11:39:33 -0700
parents ac6e22c8a9cf
children 320cfcba8058
comparison
equal deleted inserted replaced
181:3b04745ff76d 182:b65e8d0a088a
1 1
2 #include "define.h" 2 #include "define.h"
3
4 static int pst_skip_nl(char *s); // returns the width of the newline at s[0]
5 static int pst_find_nl(vstr *vs); // find newline of type type in b
6
7 // vbuf functions
8 static void pst_vbfree(vbuf *vb);
9 static void pst_vbclear(vbuf *vb); // ditch the data, keep the buffer
10 static void pst_vbresize(vbuf *vb, size_t len);
11 static size_t pst_vbavail(vbuf *vb);
12 static void pst_vbdump(vbuf *vb);
13 static void pst_vbskipws(vbuf *vb);
14 static void pst_vbskip(vbuf *vb, size_t skip);
15 static void pst_vboverwrite(vbuf *vbdest, vbuf *vbsrc);
16
17 // vstr functions
18 static vstr *pst_vsalloc(size_t len);
19 static char *pst_vsb(vstr *vs);
20 static size_t pst_vslen(vstr *vs); //strlen
21 static void pst_vsfree(vstr *vs);
22 static void pst_vsset(vstr *vs, char *s); // Store string s in vb
23 static void pst_vsnset(vstr *vs, char *s, size_t n); // Store string s in vb
24 static void pst_vsgrow(vstr *vs, size_t len); // grow buffer by len bytes, data are preserved
25 static size_t pst_vsavail(vstr *vs);
26 static void pst_vscat(vstr *vs, char *str);
27 static void pst_vsncat(vstr *vs, char *str, size_t len);
28 static void pst_vsnprepend(vstr *vs, char *str, size_t len) ;
29 static void pst_vsskip(vstr *vs, size_t len);
30 static int pst_vscmp(vstr *vs, char *str);
31 static void pst_vsskipws(vstr *vs);
32 static void pst_vs_printf(vstr *vs, char *fmt, ...);
33 static void pst_vs_printfa(vstr *vs, char *fmt, ...);
34 static void pst_vshexdump(vstr *vs, const char *b, size_t start, size_t stop, int ascii);
35 static int pst_vscatprintf(vstr *vs, char *fmt, ...);
36 static void pst_vsvprintf(vstr *vs, char *fmt, va_list ap);
37 static void pst_vstrunc(vstr *vs, size_t off); // Drop chars [off..dlen]
38 static int pst_vslast(vstr *vs); // returns the last character stored in a vstr string
39 static void pst_vscharcat(vstr *vs, int ch);
40
41 static void pst_unicode_close();
42
43 static int pst_vb_skipline(vbuf *vb); // in: vb->b == "stuff\nmore_stuff"; out: vb->b == "more_stuff"
44
45
46
47
48 #define ASSERT(x,...) { if( !(x) ) DIE(( __VA_ARGS__)); }
49
50
51 static int pst_skip_nl(char *s)
52 {
53 if (s[0] == '\n')
54 return 1;
55 if (s[0] == '\r' && s[1] == '\n')
56 return 2;
57 if (s[0] == '\0')
58 return 0;
59 return -1;
60 }
61
62
63 static int pst_find_nl(vstr * vs)
64 {
65 char *nextr, *nextn;
66
67 nextr = memchr(vs->b, '\r', vs->dlen);
68 nextn = memchr(vs->b, '\n', vs->dlen);
69
70 //case 1: UNIX, we find \n first
71 if (nextn && (!nextr || (nextr > nextn))) {
72 return nextn - vs->b;
73 }
74 //case 2: DOS, we find \r\n
75 if (nextr && nextn && (nextn-nextr == 1)) {
76 return nextr - vs->b;
77 }
78 //case 3: we find nothing
79
80 return -1;
81 }
82
83
84 // UTF8 <-> UTF16 <-> ISO8859 Character set conversion functions and (ack) their globals
85 3
86 static int unicode_up = 0; 4 static int unicode_up = 0;
87 static iconv_t i16to8; 5 static iconv_t i16to8;
88 static const char *target_charset = NULL; 6 static const char *target_charset = NULL;
89 static int target_open_from = 0; 7 static int target_open_from = 0;
90 static int target_open_to = 0; 8 static int target_open_to = 0;
91 static iconv_t i8totarget = (iconv_t)-1; 9 static iconv_t i8totarget = (iconv_t)-1;
92 static iconv_t target2i8 = (iconv_t)-1; 10 static iconv_t target2i8 = (iconv_t)-1;
93 11
94 12
95 void pst_unicode_init() 13 #define ASSERT(x,...) { if( !(x) ) DIE(( __VA_ARGS__)); }
96 { 14
97 if (unicode_up) pst_unicode_close(); 15
98 i16to8 = iconv_open("utf-8", "utf-16le"); 16 /** DESTRUCTIVELY grow or shrink buffer
99 if (i16to8 == (iconv_t)-1) { 17 */
100 WARN(("Couldn't open iconv descriptor for utf-16le to utf-8.\n")); 18 static void pst_vbresize(pst_vbuf *vb, size_t len);
101 exit(1); 19 static void pst_vbresize(pst_vbuf *vb, size_t len)
102 } 20 {
103 unicode_up = 1; 21 vb->dlen = 0;
104 } 22
105 23 if (vb->blen >= len) {
106 24 vb->b = vb->buf;
107 static void pst_unicode_close() 25 return;
108 { 26 }
109 iconv_close(i16to8); 27
110 if (target_open_from) iconv_close(i8totarget); 28 vb->buf = realloc(vb->buf, len);
111 if (target_open_to) iconv_close(target2i8); 29 vb->b = vb->buf;
112 if (target_charset) free((char *)target_charset); 30 vb->blen = len;
113 target_charset = NULL; 31 }
114 target_open_from = 0; 32
115 target_open_to = 0; 33
116 unicode_up = 0; 34 static size_t pst_vbavail(pst_vbuf * vb);
117 } 35 static size_t pst_vbavail(pst_vbuf * vb)
118 36 {
119 37 return vb->blen - vb->dlen - (size_t)(vb->b - vb->buf);
120 static int utf16_is_terminated(const char *str, int length);
121 static int utf16_is_terminated(const char *str, int length)
122 {
123 VSTR_STATIC(errbuf, 100);
124 int len = -1;
125 int i;
126 for (i = 0; i < length; i += 2) {
127 if (str[i] == 0 && str[i + 1] == 0) {
128 len = i;
129 }
130 }
131
132 if (-1 == len) {
133 pst_vshexdump(errbuf, str, 0, length, 1);
134 DEBUG_WARN(("String is not zero terminated (probably broken data from registry) %s.\n", errbuf->b));
135 }
136
137 return (-1 == len) ? 0 : 1;
138 }
139
140
141 size_t pst_vb_utf16to8(vbuf *dest, const char *inbuf, int iblen)
142 {
143 size_t inbytesleft = iblen;
144 size_t icresult = (size_t)-1;
145 size_t outbytesleft = 0;
146 char *outbuf = NULL;
147 int myerrno;
148
149 ASSERT(unicode_up, "vb_utf16to8() called before unicode started.");
150 pst_vbresize(dest, iblen);
151
152 //Bad Things can happen if a non-zero-terminated utf16 string comes through here
153 if (!utf16_is_terminated(inbuf, iblen))
154 return (size_t)-1;
155
156 do {
157 outbytesleft = dest->blen - dest->dlen;
158 outbuf = dest->b + dest->dlen;
159 icresult = iconv(i16to8, (ICONV_CONST char**)&inbuf, &inbytesleft, &outbuf, &outbytesleft);
160 myerrno = errno;
161 dest->dlen = outbuf - dest->b;
162 if (inbytesleft) pst_vbgrow(dest, inbytesleft);
163 } while ((size_t)-1 == icresult && E2BIG == myerrno);
164
165 if (icresult == (size_t)-1) {
166 DEBUG_WARN(("iconv failure: %s\n", strerror(myerrno)));
167 pst_unicode_init();
168 return (size_t)-1;
169 }
170 return (icresult) ? (size_t)-1 : 0;
171 } 38 }
172 39
173 40
174 static void open_targets(const char* charset); 41 static void open_targets(const char* charset);
175 static void open_targets(const char* charset) 42 static void open_targets(const char* charset)
193 } 60 }
194 } 61 }
195 } 62 }
196 63
197 64
198 static size_t sbcs_conversion(vbuf *dest, const char *inbuf, int iblen, iconv_t conversion); 65 static size_t sbcs_conversion(pst_vbuf *dest, const char *inbuf, int iblen, iconv_t conversion);
199 static size_t sbcs_conversion(vbuf *dest, const char *inbuf, int iblen, iconv_t conversion) 66 static size_t sbcs_conversion(pst_vbuf *dest, const char *inbuf, int iblen, iconv_t conversion)
200 { 67 {
201 size_t inbytesleft = iblen; 68 size_t inbytesleft = iblen;
202 size_t icresult = (size_t)-1; 69 size_t icresult = (size_t)-1;
203 size_t outbytesleft = 0; 70 size_t outbytesleft = 0;
204 char *outbuf = NULL; 71 char *outbuf = NULL;
222 } 89 }
223 return (icresult) ? (size_t)-1 : 0; 90 return (icresult) ? (size_t)-1 : 0;
224 } 91 }
225 92
226 93
227 size_t pst_vb_utf8to8bit(vbuf *dest, const char *inbuf, int iblen, const char* charset) 94 static void pst_unicode_close();
228 { 95 static void pst_unicode_close()
229 open_targets(charset); 96 {
230 if (!target_open_from) return (size_t)-1; // failure to open the target 97 iconv_close(i16to8);
231 return sbcs_conversion(dest, inbuf, iblen, i8totarget); 98 if (target_open_from) iconv_close(i8totarget);
232 } 99 if (target_open_to) iconv_close(target2i8);
233 100 if (target_charset) free((char *)target_charset);
234 101 target_charset = NULL;
235 size_t pst_vb_8bit2utf8(vbuf *dest, const char *inbuf, int iblen, const char* charset) 102 target_open_from = 0;
236 { 103 target_open_to = 0;
237 open_targets(charset); 104 unicode_up = 0;
238 if (!target_open_to) return (size_t)-1; // failure to open the target 105 }
239 return sbcs_conversion(dest, inbuf, iblen, target2i8); 106
240 } 107
241 108 static int utf16_is_terminated(const char *str, int length);
242 109 static int utf16_is_terminated(const char *str, int length)
243 vbuf *pst_vballoc(size_t len) 110 {
244 { 111 int len = -1;
245 vbuf *result = malloc(sizeof(vbuf)); 112 int i;
113 for (i = 0; i < length; i += 2) {
114 if (str[i] == 0 && str[i + 1] == 0) {
115 len = i;
116 }
117 }
118
119 if (len == -1) {
120 DEBUG_WARN(("utf16 string is not zero terminated\n"));
121 }
122
123 return (len == -1) ? 0 : 1;
124 }
125
126
127 pst_vbuf *pst_vballoc(size_t len)
128 {
129 pst_vbuf *result = pst_malloc(sizeof(pst_vbuf));
246 if (result) { 130 if (result) {
247 result->dlen = 0; 131 result->dlen = 0;
248 result->blen = 0; 132 result->blen = 0;
249 result->buf = NULL; 133 result->buf = NULL;
250 pst_vbresize(result, len); 134 pst_vbresize(result, len);
252 else DIE(("malloc() failure")); 136 else DIE(("malloc() failure"));
253 return result; 137 return result;
254 } 138 }
255 139
256 140
257 static void pst_vbcheck(vbuf * vb) 141 /** out: vbavail(vb) >= len, data are preserved
258 { 142 */
259 ASSERT(vb->b >= vb->buf, "vbcheck(): data not inside buffer"); 143 void pst_vbgrow(pst_vbuf *vb, size_t len)
260 ASSERT((size_t)(vb->b - vb->buf) <= vb->blen, "vbcheck(): vb->b outside of buffer range.");
261 ASSERT(vb->dlen <= vb->blen, "vbcheck(): data length > buffer length.");
262 ASSERT(vb->blen < 1024 * 1024, "vbcheck(): blen is a bit large...hmmm.");
263 }
264
265
266 static void pst_vbfree(vbuf * vb)
267 {
268 free(vb->buf);
269 free(vb);
270 }
271
272
273 static void pst_vbclear(vbuf *vb) // ditch the data, keep the buffer
274 {
275 pst_vbresize(vb, 0);
276 }
277
278
279 static void pst_vbresize(vbuf *vb, size_t len) // DESTRUCTIVELY grow or shrink buffer
280 {
281 vb->dlen = 0;
282
283 if (vb->blen >= len) {
284 vb->b = vb->buf;
285 return;
286 }
287
288 vb->buf = realloc(vb->buf, len);
289 vb->b = vb->buf;
290 vb->blen = len;
291 }
292
293
294 static size_t pst_vbavail(vbuf * vb)
295 {
296 return vb->blen - vb->dlen - (size_t)(vb->b - vb->buf);
297 }
298
299
300 void pst_vbgrow(vbuf *vb, size_t len) // out: vbavail(vb) >= len, data are preserved
301 { 144 {
302 if (0 == len) 145 if (0 == len)
303 return; 146 return;
304 147
305 if (0 == vb->blen) { 148 if (0 == vb->blen) {
327 170
328 ASSERT(pst_vbavail(vb) >= len, "vbgrow(): I have failed in my mission."); 171 ASSERT(pst_vbavail(vb) >= len, "vbgrow(): I have failed in my mission.");
329 } 172 }
330 173
331 174
332 void pst_vbset(vbuf * vb, void *b, size_t len) // set vbuf b size=len, resize if necessary, relen = how much to over-allocate 175 /** set vbuf b size=len, resize if necessary, relen = how much to over-allocate
176 */
177 void pst_vbset(pst_vbuf * vb, void *b, size_t len)
333 { 178 {
334 pst_vbresize(vb, len); 179 pst_vbresize(vb, len);
335 memcpy(vb->b, b, len); 180 memcpy(vb->b, b, len);
336 vb->dlen = len; 181 vb->dlen = len;
337 } 182 }
338 183
339 184
340 static void pst_vsskipws(vstr * vs) 185 /** append len bytes of b to vb, resize if necessary
341 { 186 */
342 char *p = vs->b; 187 void pst_vbappend(pst_vbuf *vb, void *b, size_t len)
343 while ((size_t)(p - vs->b) < vs->dlen && isspace(p[0]))
344 p++;
345
346 pst_vbskip((vbuf *) vs, p - vs->b);
347 }
348
349
350 // append len bytes of b to vbuf, resize if necessary
351 void pst_vbappend(vbuf *vb, void *b, size_t len)
352 { 188 {
353 if (0 == vb->dlen) { 189 if (0 == vb->dlen) {
354 pst_vbset(vb, b, len); 190 pst_vbset(vb, b, len);
355 return; 191 return;
356 } 192 }
358 memcpy(vb->b + vb->dlen, b, len); 194 memcpy(vb->b + vb->dlen, b, len);
359 vb->dlen += len; 195 vb->dlen += len;
360 } 196 }
361 197
362 198
363 // dumps the first skip bytes from vbuf 199 void pst_unicode_init()
364 static void pst_vbskip(vbuf *vb, size_t skip) 200 {
365 { 201 if (unicode_up) pst_unicode_close();
366 ASSERT(skip <= vb->dlen, "vbskip(): Attempt to seek past end of buffer."); 202 i16to8 = iconv_open("utf-8", "utf-16le");
367 vb->b += skip; 203 if (i16to8 == (iconv_t)-1) {
368 vb->dlen -= skip; 204 WARN(("Couldn't open iconv descriptor for utf-16le to utf-8.\n"));
369 } 205 exit(1);
370 206 }
371 207 unicode_up = 1;
372 // overwrite vbdest with vbsrc 208 }
373 static void pst_vboverwrite(vbuf *vbdest, vbuf *vbsrc) 209
374 { 210
375 pst_vbresize(vbdest, vbsrc->blen); 211 size_t pst_vb_utf16to8(pst_vbuf *dest, const char *inbuf, int iblen)
376 memcpy(vbdest->b, vbsrc->b, vbsrc->dlen); 212 {
377 vbdest->blen = vbsrc->blen; 213 size_t inbytesleft = iblen;
378 vbdest->dlen = vbsrc->dlen; 214 size_t icresult = (size_t)-1;
379 } 215 size_t outbytesleft = 0;
380 216 char *outbuf = NULL;
381 217 int myerrno;
382 static vstr *pst_vsalloc(size_t len) 218
383 { 219 ASSERT(unicode_up, "vb_utf16to8() called before unicode started.");
384 vstr *result = (vstr *) pst_vballoc(len + 1); 220 pst_vbresize(dest, iblen);
385 pst_vsset(result, ""); 221
386 return result; 222 //Bad Things can happen if a non-zero-terminated utf16 string comes through here
387 } 223 if (!utf16_is_terminated(inbuf, iblen))
388 224 return (size_t)-1;
389 225
390 static char *pst_vsstr(vstr * vs); 226 do {
391 static char *pst_vsstr(vstr * vs) 227 outbytesleft = dest->blen - dest->dlen;
392 { 228 outbuf = dest->b + dest->dlen;
393 return vs->b; 229 icresult = iconv(i16to8, (ICONV_CONST char**)&inbuf, &inbytesleft, &outbuf, &outbytesleft);
394 } 230 myerrno = errno;
395 231 dest->dlen = outbuf - dest->b;
396 232 if (inbytesleft) pst_vbgrow(dest, inbytesleft);
397 static size_t pst_vslen(vstr * vs) 233 } while ((size_t)-1 == icresult && E2BIG == myerrno);
398 { 234
399 return strlen(pst_vsstr(vs)); 235 if (icresult == (size_t)-1) {
400 } 236 DEBUG_WARN(("iconv failure: %s\n", strerror(myerrno)));
401 237 pst_unicode_init();
402 238 return (size_t)-1;
403 static void pst_vsfree(vstr * vs) 239 }
404 { 240 return (icresult) ? (size_t)-1 : 0;
405 pst_vbfree((vbuf *) vs); 241 }
406 } 242
407 243
408 244 size_t pst_vb_utf8to8bit(pst_vbuf *dest, const char *inbuf, int iblen, const char* charset)
409 static void pst_vscharcat(vstr * vb, int ch) 245 {
410 { 246 open_targets(charset);
411 pst_vbgrow((vbuf *) vb, 1); 247 if (!target_open_from) return (size_t)-1; // failure to open the target
412 vb->b[vb->dlen - 1] = ch; 248 return sbcs_conversion(dest, inbuf, iblen, i8totarget);
413 vb->b[vb->dlen] = '\0'; 249 }
414 vb->dlen++; 250
415 } 251
416 252 size_t pst_vb_8bit2utf8(pst_vbuf *dest, const char *inbuf, int iblen, const char* charset)
417 253 {
418 // prependappend string str to vbuf, vbuf must already contain a valid string 254 open_targets(charset);
419 static void pst_vsnprepend(vstr * vb, char *str, size_t len) 255 if (!target_open_to) return (size_t)-1; // failure to open the target
420 { 256 return sbcs_conversion(dest, inbuf, iblen, target2i8);
421 ASSERT(vb->b[vb->dlen - 1] == '\0', "vsncat(): attempt to append string to non-string."); 257 }
422 size_t sl = strlen(str); 258
423 size_t n = (sl < len) ? sl : len;
424 pst_vbgrow((vbuf *) vb, n + 1);
425 memmove(vb->b + n, vb->b, vb->dlen - 1);
426 memcpy(vb->b, str, n);
427 vb->dlen += n;
428 vb->b[vb->dlen - 1] = '\0';
429 }
430
431
432 // len < dlen-1 -> skip len chars, else DIE
433 static void pst_vsskip(vstr * vs, size_t len)
434 {
435 ASSERT(len < vs->dlen - 1, "Attempt to skip past end of string");
436 pst_vbskip((vbuf *) vs, len);
437 }
438
439
440 // in: vb->b == "stuff\nmore_stuff"; out: vb->b == "more_stuff"
441 static int pst_vsskipline(vstr * vs)
442 {
443 int nloff = pst_find_nl(vs);
444 int nll = pst_skip_nl(vs->b + nloff);
445
446 if (nloff < 0) {
447 //TODO: error
448 printf("vb_skipline(): there seems to be no newline here.\n");
449 return -1;
450 }
451 if (nll < 0) {
452 //TODO: error
453 printf("vb_skipline(): there seems to be no newline here...except there should be. :P\n");
454 return -1;
455 }
456
457 memmove(vs->b, vs->b + nloff + nll, vs->dlen - nloff - nll);
458
459 vs->dlen -= nloff + nll;
460
461 return 0;
462 }
463
464
465 static int pst_vscatprintf(vstr * vs, char *fmt, ...)
466 {
467 int size;
468 va_list ap;
469
470 /* Guess we need no more than 100 bytes. */
471 //vsresize( vb, 100 );
472 if (!vs->b || vs->dlen == 0) {
473 pst_vsset(vs, "");
474 }
475
476 while (1) {
477 /* Try to print in the allocated space. */
478 va_start(ap, fmt);
479 size = vsnprintf(vs->b + vs->dlen - 1, vs->blen - vs->dlen, fmt, ap);
480 va_end(ap);
481
482 /* If that worked, return the string. */
483 if ((size > -1) && ((size_t)size < vs->blen - vs->dlen)) {
484 vs->dlen += size;
485 return size;
486 }
487 /* Else try again with more space. */
488 if (size >= 0) /* glibc 2.1 */
489 pst_vbgrow((vbuf *) vs, size + 1); /* precisely what is needed */
490 else /* glibc 2.0 */
491 pst_vbgrow((vbuf *) vs, vs->blen);
492 }
493 }
494
495
496 // returns the last character stored in a vstr
497 static int pst_vslast(vstr * vs)
498 {
499 if (vs->dlen < 1)
500 return -1;
501 if (vs->b[vs->dlen - 1] != '\0')
502 return -1;
503 if (vs->dlen == 1)
504 return '\0';
505 return vs->b[vs->dlen - 2];
506 }
507
508
509 // print over vb
510 static void pst_vs_printf(vstr * vs, char *fmt, ...)
511 {
512 int size;
513 va_list ap;
514
515 /* Guess we need no more than 100 bytes. */
516 pst_vbresize((vbuf *) vs, 100);
517
518 while (1) {
519 /* Try to print in the allocated space. */
520 va_start(ap, fmt);
521 size = vsnprintf(vs->b, vs->blen, fmt, ap);
522 va_end(ap);
523
524 /* If that worked, return the string. */
525 if ((size > -1) && ((size_t)size < vs->blen)) {
526 vs->dlen = size + 1;
527 return;
528 }
529 /* Else try again with more space. */
530 if (size >= 0) /* glibc 2.1 */
531 pst_vbresize((vbuf *) vs, size + 1); /* precisely what is needed */
532 else /* glibc 2.0 */
533 pst_vbresize((vbuf *) vs, vs->blen * 2);
534 }
535 }
536
537
538 // printf append to vs
539 static void pst_vs_printfa(vstr * vs, char *fmt, ...)
540 {
541 int size;
542 va_list ap;
543
544 if (vs->blen - vs->dlen < 50)
545 pst_vbgrow((vbuf *) vs, 100);
546
547 while (1) {
548 /* Try to print in the allocated space. */
549 va_start(ap, fmt);
550 size = vsnprintf(vs->b + vs->dlen - 1, vs->blen - vs->dlen + 1, fmt, ap);
551 va_end(ap);
552
553 /* If that worked, return the string. */
554 if ((size > -1) && ((size_t)size < vs->blen)) {
555 vs->dlen += size;
556 return;
557 }
558 /* Else try again with more space. */
559 if (size >= 0) /* glibc 2.1 */
560 pst_vbgrow((vbuf *) vs, size + 1 - vs->dlen); /* precisely what is needed */
561 else /* glibc 2.0 */
562 pst_vbgrow((vbuf *) vs, size);
563 }
564 }
565
566
567 static void pst_vshexdump(vstr * vs, const char *b, size_t start, size_t stop, int ascii)
568 {
569 char c;
570 int diff, i;
571
572 while (start < stop) {
573 diff = stop - start;
574 if (diff > 16)
575 diff = 16;
576
577 pst_vs_printfa(vs, ":%08X ", start);
578
579 for (i = 0; i < diff; i++) {
580 if (8 == i)
581 pst_vs_printfa(vs, " ");
582 pst_vs_printfa(vs, "%02X ", (unsigned char) *(b + start + i));
583 }
584 if (ascii) {
585 for (i = diff; i < 16; i++)
586 pst_vs_printfa(vs, " ");
587 for (i = 0; i < diff; i++) {
588 c = *(b + start + i);
589 pst_vs_printfa(vs, "%c", isprint(c) ? c : '.');
590 }
591 }
592 pst_vs_printfa(vs, "\n");
593 start += 16;
594 }
595 }
596
597
598 static void pst_vsset(vstr * vs, char *s) // Store string s in vs
599 {
600 pst_vsnset(vs, s, strlen(s));
601 }
602
603
604 static void pst_vsnset(vstr * vs, char *s, size_t n) // Store string s in vs
605 {
606 pst_vbresize((vbuf *) vs, n + 1);
607 memcpy(vs->b, s, n);
608 vs->b[n] = '\0';
609 vs->dlen = n + 1;
610 }
611
612
613 static void pst_vsgrow(vstr * vs, size_t len) // grow buffer by len bytes, data are preserved
614 {
615 pst_vbgrow((vbuf *) vs, len);
616 }
617
618
619 static size_t pst_vsavail(vstr * vs)
620 {
621 return pst_vbavail((vbuf *) vs);
622 }
623
624
625 static void pst_vsnset16(vstr * vs, char *s, size_t len) // Like vbstrnset, but for UTF16
626 {
627 pst_vbresize((vbuf *) vs, len + 1);
628 memcpy(vs->b, s, len);
629
630 vs->b[len] = '\0';
631 vs->dlen = len + 1;
632 vs->b[len] = '\0';
633 }
634
635
636 static void pst_vscat(vstr * vs, char *str)
637 {
638 pst_vsncat(vs, str, strlen(str));
639 }
640
641
642 static int pst_vscmp(vstr * vs, char *str)
643 {
644 return strcmp(vs->b, str);
645 }
646
647
648 static void pst_vsncat(vstr * vs, char *str, size_t len) // append string str to vstr, vstr must already contain a valid string
649 {
650 ASSERT(vs->b[vs->dlen - 1] == '\0', "vsncat(): attempt to append string to non-string.");
651 size_t sl = strlen(str);
652 size_t n = (sl < len) ? sl : len;
653 //string append
654 pst_vbgrow((vbuf *) vs, n + 1);
655 memcpy(vs->b + vs->dlen - 1, str, n);
656 vs->dlen += n;
657 vs->b[vs->dlen - 1] = '\0';
658 }
659
660
661 static void pst_vstrunc(vstr * v, size_t off) // Drop chars [off..dlen]
662 {
663 if (off >= v->dlen - 1)
664 return; //nothing to do
665 v->b[off] = '\0';
666 v->dlen = off + 1;
667 }
668
669