buf.c

00001 /* 
00002  * Copyright (c) 2005-2012 by KoanLogic s.r.l. - All rights reserved.  
00003  */
00004 
00005 #include <sys/types.h>
00006 #include <sys/stat.h>
00007 #include <unistd.h>
00008 #include <stdio.h>
00009 #include <stdarg.h>
00010 #include <u/libu.h>
00011 #include <toolbox/buf.h>
00012 
00013 struct u_buf_s
00014 {
00015     char *data;     /* the memory buffer */
00016     size_t size;    /* bytes malloc'd for .data */
00017     size_t len;     /* bytes actually in use (always <= .size) */
00018 };
00019 
00041 int u_buf_reserve (u_buf_t *ubuf, size_t size)
00042 {
00043     char *nbuf;
00044 
00045     dbg_err_if (ubuf == NULL);
00046 
00047     nop_return_if (size <= ubuf->size, 0);  /* nothing to do */
00048    
00049     /* size plus 1 char to store a '\0' */
00050     dbg_err_sif ((nbuf = u_realloc(ubuf->data, size + 1)) == NULL);
00051 
00052     /* buffer data will always be zero-terminated (but the len field will not
00053      * count the last '\0') */
00054     nbuf[size] = '\0';
00055 
00056     ubuf->data = nbuf;
00057     ubuf->size = size;
00058 
00059     return 0;
00060 err:
00061     return ~0;
00062 }
00063 
00077 int u_buf_append (u_buf_t *ubuf, const void *data, size_t size)
00078 {
00079     dbg_return_if (ubuf == NULL, ~0);
00080     dbg_return_if (data == NULL, ~0);
00081     dbg_return_if (size == 0, ~0);
00082 
00083     if (ubuf->size - ubuf->len < size)
00084     {
00085         /* buffer too small, resize generously */
00086         dbg_err_if (u_buf_reserve(ubuf, ubuf->size + ubuf->len + 2 * size));
00087     }
00088  
00089     memcpy(ubuf->data + ubuf->len, data, size);
00090     ubuf->len += size;
00091 
00092     /* zero term the buffer so it can be used (when applicable) as a string */
00093     ubuf->data[ubuf->len] = '\0';
00094 
00095     return 0;
00096 err:
00097     return ~0;
00098 }
00099 
00111 int u_buf_load (u_buf_t *ubuf, const char *filename)
00112 {
00113     struct stat st;
00114     FILE *fp = NULL;
00115 
00116     dbg_return_if (ubuf == NULL, ~0);
00117     dbg_return_if (filename == NULL, ~0);
00118 
00119     dbg_err_sif (stat(filename, &st) == -1);
00120 
00121     /* clear the current data */
00122     dbg_err_if (u_buf_clear(ubuf));
00123 
00124     /* be sure to have a big enough buffer */
00125     dbg_err_if (u_buf_reserve(ubuf, st.st_size));
00126 
00127     dbg_err_sifm ((fp = fopen(filename, "r")) == NULL, "%s", filename);
00128 
00129     /* fill the buffer with the whole file content */
00130     dbg_err_if (fread(ubuf->data, st.st_size, 1, fp) != 1);
00131     ubuf->len = st.st_size;
00132 
00133     (void) fclose(fp);
00134 
00135     return 0;
00136 err:
00137     U_FCLOSE(fp);
00138     return ~0;
00139 }
00140 
00152 int u_buf_save (u_buf_t *ubuf, const char *filename)
00153 {
00154     dbg_return_if (ubuf == NULL, ~0);
00155     dbg_return_if (filename == NULL, ~0);
00156 
00157     return u_data_dump(u_buf_ptr(ubuf), u_buf_len(ubuf), filename);
00158 }
00159 
00174 int u_buf_detach (u_buf_t *ubuf)
00175 {
00176     dbg_return_if (ubuf == NULL, ~0);
00177 
00178     ubuf->data = NULL;
00179     ubuf->size = 0;
00180     ubuf->len = 0;
00181 
00182     return 0;
00183 }
00184 
00197 ssize_t u_buf_size (u_buf_t *ubuf)
00198 {
00199     dbg_return_if (ubuf == NULL, -1);
00200 
00201     return ubuf->size;
00202 }
00203 
00215 ssize_t u_buf_len (u_buf_t *ubuf)
00216 {
00217     dbg_return_if (ubuf == NULL, -1);
00218 
00219     return ubuf->len;
00220 }
00221 
00233 int u_buf_clear (u_buf_t *ubuf)
00234 {
00235     dbg_return_if (ubuf == NULL, ~0);
00236     
00237     ubuf->len = 0;
00238 
00239     return 0;
00240 }
00241 
00257 int u_buf_set (u_buf_t *ubuf, const void *data, size_t size)
00258 {
00259     dbg_return_if (ubuf == NULL, ~0);
00260     dbg_return_if (data == NULL, ~0);
00261     dbg_return_if (size == 0, ~0);
00262 
00263     dbg_err_if (u_buf_clear(ubuf));
00264     dbg_err_if (u_buf_append(ubuf, data, size));
00265 
00266     return 0;
00267 err:
00268     return ~0;
00269 }
00270 
00282 void *u_buf_ptr (u_buf_t *ubuf)
00283 {
00284     dbg_return_if (ubuf == NULL, NULL);
00285     
00286     return ubuf->data;
00287 }
00288 
00302 int u_buf_shrink(u_buf_t *ubuf, size_t newlen)
00303 {
00304     dbg_err_if (ubuf == NULL);
00305     dbg_err_if (newlen > ubuf->len);
00306 
00307     ubuf->len = newlen;
00308 
00309     return 0;
00310 err:
00311     return ~0;
00312 }
00313 
00324 int u_buf_free (u_buf_t *ubuf)
00325 {
00326     dbg_return_if (ubuf == NULL, ~0);
00327 
00328     U_FREE(ubuf->data);
00329     u_free(ubuf);
00330 
00331     return 0;
00332 }
00333 
00349 int u_buf_printf (u_buf_t *ubuf, const char *fmt, ...)
00350 {
00351     va_list ap;
00352     size_t sz, avail;
00353 
00354     dbg_return_if (ubuf == NULL, ~0);
00355     dbg_return_if (fmt == NULL, ~0);
00356 
00357 again:
00358     va_start(ap, fmt); 
00359 
00360     avail = ubuf->size - ubuf->len; /* avail may be zero */
00361 
00362     /* write to the internal buffer of ubuf */
00363     dbg_err_if ((sz = vsnprintf(ubuf->data + ubuf->len, avail, fmt, ap)) <= 0);
00364 
00365     if (sz >= avail)
00366     {
00367         /* enlarge the buffer (make it at least 128 bytes bigger) */
00368         dbg_err_if (u_buf_reserve(ubuf, ubuf->len + U_MIN(128, sz + 1)));
00369 
00370         /* zero-term the buffer (vsnprintf has removed the last \0!) */
00371         ubuf->data[ubuf->len] = '\0';
00372 
00373         va_end(ap);
00374 
00375         /* try again with a bigger buffer */
00376         goto again;
00377     }
00378 
00379     /* update data length (don't include the '\0' in the size count) */
00380     ubuf->len += sz; 
00381 
00382     va_end(ap);
00383 
00384     return 0;
00385 err:
00386     va_end(ap);
00387     return ~0;
00388 }
00389 
00390 
00402 int u_buf_create (u_buf_t **pubuf)
00403 {
00404     u_buf_t *ubuf = NULL;
00405 
00406     dbg_return_if (pubuf == NULL, ~0);
00407 
00408     dbg_err_sif ((ubuf = u_zalloc(sizeof(u_buf_t))) == NULL);
00409 
00410     ubuf->len = 0;
00411     ubuf->size = 0;
00412     ubuf->data = NULL;
00413 
00414     *pubuf = ubuf;
00415 
00416     return 0;
00417 err:
00418     return ~0;
00419 }
00420 

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