Main Page | Modules | Data Structures | File List | Data Fields

str.c

00001 /* 
00002  * Copyright (c) 2005, 2006 by KoanLogic s.r.l. - All rights reserved.  
00003  */
00004 
00005 static const char rcsid[] =
00006     "$Id: str.c,v 1.1 2006/11/20 13:38:01 tho Exp $";
00007 
00008 #include <stdlib.h>
00009 #include <errno.h>
00010 
00011 #include <toolbox/str.h>
00012 #include <toolbox/misc.h>
00013 #include <toolbox/carpal.h>
00014 #include <toolbox/memory.h>
00015 
00021 /* null strings will be bound to the null char* */
00022 static char null_cstr[1] = { 0 };
00023 static char* null = null_cstr;
00024 
00025 /* internal string struct */
00026 struct u_string_s
00027 {
00028     char *data;
00029     size_t data_sz, data_len, shift_cnt;
00030 };
00031 
00041 int u_string_trim(u_string_t *s)
00042 {
00043     if(s->data_len)
00044     {
00045         u_trim(s->data);
00046 
00047         s->data_len = strlen(s->data);
00048     }
00049 
00050     return 0;
00051 }
00052 
00062 int u_string_set_length(u_string_t *s, size_t len)
00063 {
00064     dbg_err_if(len > s->data_len);
00065 
00066     if(len < s->data_len)
00067     {
00068         s->data_len = len;
00069         s->data[len] = 0;
00070     }
00071 
00072     return 0;
00073 err:
00074     return ~0;
00075 }
00076 
00086 inline size_t u_string_len(u_string_t *s)
00087 {
00088     return s->data_len;
00089 }
00090 
00101 inline const char *u_string_c(u_string_t *s)
00102 {
00103     return s->data;
00104 }
00105 
00116 inline int u_string_copy(u_string_t *dst, u_string_t *src)
00117 {
00118     u_string_clear(dst);
00119     return u_string_append(dst, src->data, src->data_len);
00120 }
00121 
00131 int u_string_clear(u_string_t *s)
00132 {
00133     /* clear the string but not deallocate the buffer */
00134     if(s->data_sz)
00135     {
00136         s->data[0] = 0;
00137         s->data_len = 0;
00138     }
00139 
00140     return 0;
00141 }
00142 
00157 int u_string_create(const char *buf, size_t len, u_string_t **ps)
00158 {
00159     u_string_t *s = NULL;
00160 
00161     s = u_zalloc(sizeof(u_string_t));
00162     dbg_err_sif(s == NULL);
00163 
00164     s->data = null;
00165 
00166     if(buf)
00167         dbg_err_if(u_string_append(s, buf, len));
00168 
00169     *ps = s;
00170 
00171     return 0;
00172 err:
00173     return ~0;
00174 }
00175 
00176 
00186 int u_string_free(u_string_t *s)
00187 {
00188     if(s)
00189     {
00190         if(s->data_sz)
00191             U_FREE(s->data);
00192         U_FREE(s);
00193     }
00194     return 0;
00195 }
00196 
00197 
00209 int u_string_set(u_string_t *s, const char *buf, size_t len)
00210 {
00211     u_string_clear(s);
00212     return u_string_append(s, buf, len);
00213 }
00214 
00225 int u_string_reserve(u_string_t *s, size_t size)
00226 {
00227     char *nbuf;
00228 
00229     dbg_err_if(s == NULL);
00230 
00231     if(size <= s->data_sz)
00232         return 0; /* nothing to do */
00233    
00234     /* size plus 1 char to store a '\0' */
00235     nbuf = u_realloc( ((s->data == null) ? NULL : s->data), size+1);
00236     dbg_err_if(nbuf == NULL);
00237 
00238     /* zero terminate it */
00239     nbuf[size] = 0;
00240 
00241     s->data = (void*)nbuf;
00242     s->data_sz = size;
00243 
00244     return 0;
00245 err:
00246     return ~0;
00247 }
00248 
00260 int u_string_append(u_string_t *s, const char *buf, size_t len)
00261 {
00262     size_t nsz, min;
00263 
00264     if(!len)
00265         return 0; /* nothing to do */
00266 
00267     /* if there's not enough space on s->data alloc a bigger buffer */
00268     if(s->data_len + len + 1 > s->data_sz)
00269     {
00270         min = s->data_len + len + 1; /* min required buffer length */
00271         nsz = s->data_sz;
00272         while(nsz <= min)
00273             nsz += (BLOCK_SIZE << s->shift_cnt++);
00274 
00275         dbg_err_if(u_string_reserve(s, nsz));
00276     }
00277 
00278     /* append this chunk to the data buffer */
00279     strncpy(s->data + s->data_len, buf, len);
00280     s->data_len += len;
00281     s->data[s->data_len] = 0;
00282     
00283     return 0;
00284 err:
00285     return ~0;
00286 }
00287 
00299 int u_string_sprintf(u_string_t *s, const char *fmt, ...)
00300 {
00301     va_list ap;
00302     size_t sz, avail;
00303 
00304     dbg_return_if(s == NULL, ~0);
00305     dbg_return_if(fmt == NULL, ~0);
00306 
00307     u_string_clear(s);
00308 
00309 again:
00310     va_start(ap, fmt); 
00311 
00312     avail = s->data_sz - s->data_len; /* avail may be zero */
00313 
00314     /* write to the internal buffer of the string */
00315     dbg_err_if(( sz = vsnprintf(s->data + s->data_len, avail, fmt, ap)) <= 0);
00316 
00317     if(sz >= avail)
00318     {
00319         /* enlarge the buffer (make it at least 128 bytes bigger) */
00320         dbg_err_if(u_string_reserve(s, s->data_sz + s->data_len + 2*sz + 1));
00321 
00322         /* zero-term the buffer (vsnprintf has removed the last \0!) */
00323         s->data[s->data_len] = 0;
00324 
00325         va_end(ap);
00326 
00327         /* try again with a bigger buffer */
00328         goto again;
00329     }
00330 
00331     /* update string length */
00332     s->data_len += sz; 
00333     s->data[s->data_len] = 0;
00334 
00335     va_end(ap);
00336 
00337     return 0;
00338 err:
00339     va_end(ap);
00340     return ~0; /* error */
00341 }
00342 

←Products
© 2005-2006 - KoanLogic S.r.l. - All rights reserved