ccn_charbuf.c

Go to the documentation of this file.
00001 /**
00002  * @file ccn_charbuf.c
00003  * @brief Support expandable buffer for counted sequences of arbitrary bytes.
00004  * 
00005  * Part of the CCNx C Library.
00006  *
00007  * Copyright (C) 2008, 2009 Palo Alto Research Center, Inc.
00008  *
00009  * This library is free software; you can redistribute it and/or modify it
00010  * under the terms of the GNU Lesser General Public License version 2.1
00011  * as published by the Free Software Foundation.
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00015  * Lesser General Public License for more details. You should have received
00016  * a copy of the GNU Lesser General Public License along with this library;
00017  * if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
00018  * Fifth Floor, Boston, MA 02110-1301 USA.
00019  */
00020 #include <stdarg.h>
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <sys/time.h>
00025 #include <ccn/charbuf.h>
00026 
00027 struct ccn_charbuf *
00028 ccn_charbuf_create(void)
00029 {
00030     struct ccn_charbuf *c;
00031     c = calloc(1, sizeof(*c));
00032     return(c);
00033 }
00034 
00035 struct ccn_charbuf *
00036 ccn_charbuf_create_n(size_t n)
00037 {
00038     struct ccn_charbuf *c;
00039     c = malloc(sizeof(*c));
00040     if (c == NULL) return (NULL);
00041     c->length = 0;
00042     c->limit = n;
00043     if (n == 0) {
00044         c->buf = NULL;
00045         return(c);
00046     }
00047     c->buf = malloc(n);
00048     if (c->buf == NULL) {
00049         free(c);
00050         c = NULL;
00051     }
00052     return(c);
00053 }
00054 
00055 void
00056 ccn_charbuf_destroy(struct ccn_charbuf **cbp)
00057 {
00058     struct ccn_charbuf *c = *cbp;
00059     if (c != NULL) {
00060         if (c->buf != NULL)
00061             free(c->buf);
00062         free(c);
00063         *cbp = NULL;
00064     }
00065 }
00066 
00067 /*
00068  * ccn_charbuf_reserve: expand buffer as necessary to hold n more chars
00069  */
00070 unsigned char *
00071 ccn_charbuf_reserve(struct ccn_charbuf *c, size_t n)
00072 {
00073     size_t newsz = n + c->length;
00074     unsigned char *buf = c->buf;
00075     if (newsz < n)
00076         return(NULL);
00077     if (newsz > c->limit) {
00078         if (2 * c->limit > newsz)
00079             newsz = 2 * c->limit;
00080 #ifdef CCN_NOREALLOC
00081         buf = malloc(newsz);
00082         if (buf == NULL)
00083             return(NULL);
00084         memcpy(buf, c->buf, c->limit);
00085         free(c->buf);
00086 #else
00087         buf = realloc(c->buf, newsz);
00088         if (buf == NULL)
00089             return(NULL);
00090 #endif
00091         memset(buf + c->limit, 0, newsz - c->limit);
00092         c->buf = buf;
00093         c->limit = newsz;
00094     }
00095     buf += c->length;
00096     return(buf);
00097 }
00098 
00099 void ccn_charbuf_reset(struct ccn_charbuf *c)
00100 {
00101     if (c == NULL) {
00102       return;
00103     } 
00104     c->length = 0;
00105 }
00106 
00107 int
00108 ccn_charbuf_append(struct ccn_charbuf *c, const void *p, size_t n)
00109 {
00110     unsigned char *dst = ccn_charbuf_reserve(c, n);
00111     if (dst == NULL)
00112         return(-1);
00113     memcpy(dst, p, n);
00114     c->length += n;
00115     return(0);
00116 }
00117 
00118 int
00119 ccn_charbuf_append_value(struct ccn_charbuf *c, unsigned val, unsigned n)
00120 {
00121     unsigned char *dst;
00122     unsigned i;
00123     if (n > sizeof(val))
00124         return(-1);
00125     dst = ccn_charbuf_reserve(c, n);
00126     if (dst == NULL)
00127         return(-1);
00128     for (i = 0; i < n; i++)
00129         dst[i] = (unsigned char)(val >> (8 * (n-1-i)));
00130     c->length += n;
00131     return(0);
00132 }
00133 
00134 int
00135 ccn_charbuf_append_charbuf(struct ccn_charbuf *c, const struct ccn_charbuf *in)
00136 {
00137   return(ccn_charbuf_append(c, in->buf, in->length));
00138 }
00139 
00140 int
00141 ccn_charbuf_append_string(struct ccn_charbuf *c, const char *s)
00142 {
00143   return(ccn_charbuf_append(c, s, strlen(s)));
00144 }
00145 
00146 int
00147 ccn_charbuf_putf(struct ccn_charbuf *c, const char *fmt, ...)
00148 {
00149     int sz;
00150     va_list ap;
00151     char *buf;
00152     buf = (char *)ccn_charbuf_reserve(c, strlen(fmt) + 10); /* estimate */
00153     if (buf == NULL) return(-1);
00154     va_start(ap, fmt);
00155     sz = vsnprintf(buf, c->limit - c->length, fmt, ap);
00156     va_end(ap);
00157     if (sz < 0)
00158         return(sz);
00159     if (c->length + sz < c->limit) {
00160         c->length += sz;
00161         return(sz);
00162     }
00163     va_end(ap);
00164     buf = (char *)ccn_charbuf_reserve(c, sz + 1); /* accurate */
00165     if (buf == NULL) return(-1);
00166     va_start(ap, fmt);
00167     sz = vsnprintf(buf, c->limit - c->length, fmt, ap);
00168     va_end(ap);
00169     if (c->length + sz < c->limit) {
00170         c->length += sz;
00171         return(sz);
00172     }
00173     return(-1);
00174 }
00175 
00176 /* This formats time into xs:dateTime format */
00177 int
00178 ccn_charbuf_append_datetime(struct ccn_charbuf *c, time_t secs, int nsecs)
00179 {
00180     char timestring[32];
00181     int timelen;
00182     struct tm time_tm;
00183     int res;
00184 
00185     timelen = strftime(timestring, sizeof(timestring),
00186                        "%FT%T", gmtime_r(&secs, &time_tm));
00187     if (timelen >= sizeof(timestring))
00188         return(-1);
00189     if (nsecs != 0) {
00190         if (nsecs < 0 || nsecs >= 1000000000)
00191             return(-1);
00192         timelen += snprintf(&timestring[timelen], sizeof(timestring) - timelen,
00193                             ".%09d", nsecs);
00194         if (timelen >= sizeof(timestring))
00195             return(-1);
00196         while (timestring[timelen - 1] == '0') timelen--;
00197     }
00198     timestring[timelen++] = 'Z';
00199     res = ccn_charbuf_append(c, timestring, timelen);
00200     return (res);
00201 }
00202 
00203 char *
00204 ccn_charbuf_as_string(struct ccn_charbuf *c)
00205 {
00206     unsigned char *r;
00207     r = ccn_charbuf_reserve(c, 1);
00208     if (r == NULL)
00209         return(NULL);
00210     r[0] = 0;
00211     return((char *)c->buf);
00212 }

Generated on Thu Feb 16 00:44:00 2012 for Content-Centric Networking in C by  doxygen 1.5.6