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

str.c

00001 /* 
00002  * Copyright (c) 2005-2007 by KoanLogic s.r.l. - All rights reserved.  
00003  */
00004 
00005 static const char rcsid[] =
00006     "$Id: str.c,v 1.3 2007/02/14 20:38:53 tat 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 
00249 
00250 /* internal */
00251 int u_string_do_printf(u_string_t *s, int clear, const char *fmt, ...)
00252 {
00253     va_list ap;
00254     size_t sz, avail;
00255 
00256     dbg_return_if(s == NULL, ~0);
00257     dbg_return_if(fmt == NULL, ~0);
00258 
00259     if(clear)
00260         u_string_clear(s);
00261 
00262 again:
00263     va_start(ap, fmt); 
00264 
00265     avail = s->data_sz - s->data_len; /* avail may be zero */
00266 
00267     /* write to the internal buffer of the string */
00268     dbg_err_if(( sz = vsnprintf(s->data + s->data_len, avail, fmt, ap)) <= 0);
00269 
00270     if(sz >= avail)
00271     {
00272         /* enlarge the buffer (make it at least 128 bytes bigger) */
00273         dbg_err_if(u_string_reserve(s, s->data_sz + s->data_len + 2*sz + 1));
00274 
00275         /* zero-term the buffer (vsnprintf has removed the last \0!) */
00276         s->data[s->data_len] = 0;
00277 
00278         va_end(ap);
00279 
00280         /* try again with a bigger buffer */
00281         goto again;
00282     }
00283 
00284     /* update string length */
00285     s->data_len += sz; 
00286     s->data[s->data_len] = 0;
00287 
00288     va_end(ap);
00289 
00290     return 0;
00291 err:
00292     va_end(ap);
00293     return ~0; /* error */
00294 }
00295 
00307 int u_string_append(u_string_t *s, const char *buf, size_t len)
00308 {
00309     size_t nsz, min;
00310 
00311     if(!len)
00312         return 0; /* nothing to do */
00313 
00314     /* if there's not enough space on s->data alloc a bigger buffer */
00315     if(s->data_len + len + 1 > s->data_sz)
00316     {
00317         min = s->data_len + len + 1; /* min required buffer length */
00318         nsz = s->data_sz;
00319         while(nsz <= min)
00320             nsz += (BLOCK_SIZE << s->shift_cnt++);
00321 
00322         dbg_err_if(u_string_reserve(s, nsz));
00323     }
00324 
00325     /* append this chunk to the data buffer */
00326     strncpy(s->data + s->data_len, buf, len);
00327     s->data_len += len;
00328     s->data[s->data_len] = 0;
00329     
00330     return 0;
00331 err:
00332     return ~0;
00333 }
00334 
00335 /* defines documentation */
00336 

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