00001
00002
00003
00004
00005 #include <stdlib.h>
00006 #include <errno.h>
00007 #include <toolbox/str.h>
00008 #include <toolbox/misc.h>
00009 #include <toolbox/carpal.h>
00010 #include <toolbox/memory.h>
00011
00012 enum { BLOCK_SIZE = 64 };
00013
00014
00015 static char null_cstr[1] = { 0 };
00016 static char *null = null_cstr;
00017
00018
00019 struct u_string_s
00020 {
00021 char *data;
00022 size_t data_sz;
00023 size_t data_len;
00024 size_t shift_cnt;
00025 };
00026
00027 static int u_string_do_vprintf (u_string_t *, int, const char *, va_list);
00028
00083 char *u_string_detach_cstr (u_string_t *s)
00084 {
00085 char *tmp;
00086
00087 dbg_return_if (s == NULL, NULL);
00088
00089 tmp = s->data;
00090
00091 u_free(s);
00092
00093 return tmp;
00094 }
00095
00106 int u_string_trim (u_string_t *s)
00107 {
00108 dbg_return_if (s == NULL, ~0);
00109
00110 if (s->data_len > 0)
00111 {
00112 u_trim(s->data);
00113 s->data_len = strlen(s->data);
00114 }
00115
00116 return 0;
00117 }
00118
00130 int u_string_set_length (u_string_t *s, size_t len)
00131 {
00132 dbg_return_if (s == NULL, ~0);
00133 dbg_return_if (len > s->data_len, ~0);
00134
00135 if (len < s->data_len)
00136 {
00137 s->data_len = len;
00138 s->data[len] = '\0';
00139 }
00140
00141
00142
00143 return 0;
00144 }
00145
00155 inline size_t u_string_len (u_string_t *s)
00156 {
00157 dbg_return_if (s == NULL, 0);
00158
00159 return s->data_len;
00160 }
00161
00172 inline const char *u_string_c (u_string_t *s)
00173 {
00174 dbg_return_if (s == NULL, NULL);
00175
00176 return s->data;
00177 }
00178
00191 inline int u_string_copy (u_string_t *dst, u_string_t *src)
00192 {
00193 dbg_return_if (dst == NULL, ~0);
00194 dbg_return_if (src == NULL, ~0);
00195
00196 (void) u_string_clear(dst);
00197
00198 return u_string_append(dst, src->data, src->data_len);
00199 }
00200
00211 int u_string_clear (u_string_t *s)
00212 {
00213 dbg_return_if (s == NULL, ~0);
00214
00215
00216 if (s->data_sz)
00217 {
00218 s->data[0] = '\0';
00219 s->data_len = 0;
00220 }
00221
00222 return 0;
00223 }
00224
00240 int u_string_create (const char *buf, size_t len, u_string_t **ps)
00241 {
00242 u_string_t *s = NULL;
00243
00244 dbg_return_if (ps == NULL, ~0);
00245
00246 dbg_err_sif ((s = u_malloc(sizeof(u_string_t))) == NULL);
00247
00248 s->data_sz = 0;
00249 s->data_len = 0;
00250 s->shift_cnt = 0;
00251 s->data = null;
00252
00253 if (buf)
00254 dbg_err_if (u_string_append(s, buf, len));
00255
00256 *ps = s;
00257
00258 return 0;
00259 err:
00260 if (s)
00261 u_string_free(s);
00262 return ~0;
00263 }
00264
00274 int u_string_free (u_string_t *s)
00275 {
00276 if (s)
00277 {
00278 if (s->data_sz)
00279 U_FREE(s->data);
00280 u_free(s);
00281 }
00282
00283 return 0;
00284 }
00285
00298 int u_string_set (u_string_t *s, const char *buf, size_t len)
00299 {
00300 dbg_return_if (s == NULL, ~0);
00301
00302 (void) u_string_clear(s);
00303
00304 return u_string_append(s, buf, len);
00305 }
00306
00319 int u_string_reserve (u_string_t *s, size_t size)
00320 {
00321 char *nbuf = NULL;
00322
00323 dbg_return_if (s == NULL, ~0);
00324 nop_return_if (size <= s->data_sz, 0);
00325
00326
00327 nbuf = u_realloc(((s->data == null) ? NULL : s->data), size + 1);
00328 dbg_err_sif (nbuf == NULL);
00329
00330
00331 nbuf[size] = '\0';
00332
00333 s->data = (void *) nbuf;
00334 s->data_sz = size;
00335
00336 return 0;
00337 err:
00338 return ~0;
00339 }
00340
00355 int u_string_do_printf (u_string_t *s, int clear, const char *fmt, ...)
00356 {
00357 int rc;
00358 va_list ap;
00359
00360 va_start(ap, fmt);
00361 rc = u_string_do_vprintf(s, clear, fmt, ap);
00362 va_end(ap);
00363
00364 return rc;
00365 }
00366
00379 int u_string_append (u_string_t *s, const char *buf, size_t len)
00380 {
00381 size_t nsz, min;
00382
00383 dbg_return_if (s == NULL, ~0);
00384 dbg_return_if (buf == NULL, ~0);
00385 nop_return_if (len == 0, 0);
00386
00387
00388 if (s->data_len + len + 1 > s->data_sz)
00389 {
00390 min = s->data_len + len + 1;
00391 nsz = s->data_sz;
00392 while (nsz <= min)
00393 nsz += (BLOCK_SIZE << s->shift_cnt++);
00394
00395 dbg_err_if (u_string_reserve(s, nsz));
00396 }
00397
00398
00399 strncpy(s->data + s->data_len, buf, len);
00400 s->data_len += len;
00401 s->data[s->data_len] = '\0';
00402
00403 return 0;
00404 err:
00405 return ~0;
00406 }
00407
00420 int u_string_sprintf (u_string_t *s, const char *fmt, ...)
00421 {
00422 int rc;
00423 va_list ap;
00424
00425 va_start(ap, fmt);
00426 rc = u_string_do_vprintf(s, 1, fmt, ap);
00427 va_end(ap);
00428
00429 return rc;
00430 }
00431
00444 int u_string_aprintf (u_string_t *s, const char *fmt, ...)
00445 {
00446 int rc;
00447 va_list ap;
00448
00449 va_start(ap, fmt);
00450 rc = u_string_do_vprintf(s, 0, fmt, ap);
00451 va_end(ap);
00452
00453 return rc;
00454 }
00455
00460 static int u_string_do_vprintf (u_string_t *s, int clear, const char *fmt,
00461 va_list ap)
00462 {
00463 size_t sz, avail;
00464 va_list apcpy;
00465
00466 dbg_return_if (s == NULL, ~0);
00467 dbg_return_if (fmt == NULL, ~0);
00468
00469 if (clear)
00470 (void) u_string_clear(s);
00471
00472 again:
00473 avail = s->data_sz - s->data_len;
00474
00475
00476 u_va_copy(apcpy, ap);
00477
00478
00479
00480
00481
00482 sz = vsnprintf(s->data + s->data_len, avail, fmt, apcpy);
00483
00484 va_end(apcpy);
00485
00486 if (sz >= avail)
00487 {
00488 dbg_err_if (u_string_reserve(s, s->data_sz + s->data_len + 2 * sz + 1));
00489
00490
00491 s->data[s->data_len] = '\0';
00492
00493 goto again;
00494 }
00495
00496
00497 s->data_len += sz;
00498
00499 return 0;
00500 err:
00501 return ~0;
00502 }