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 void
00036 ccn_charbuf_destroy(struct ccn_charbuf **cbp)
00037 {
00038     struct ccn_charbuf *c = *cbp;
00039     if (c != NULL) {
00040         if (c->buf != NULL)
00041             free(c->buf);
00042         free(c);
00043         *cbp = NULL;
00044     }
00045 }
00046 
00047 /*
00048  * ccn_charbuf_reserve: expand buffer as necessary to hold n more chars
00049  */
00050 unsigned char *
00051 ccn_charbuf_reserve(struct ccn_charbuf *c, size_t n)
00052 {
00053     size_t newsz = n + c->length;
00054     unsigned char *buf = c->buf;
00055     if (newsz < n)
00056         return(NULL);
00057     if (newsz > c->limit) {
00058         if (2 * c->limit > newsz)
00059             newsz = 2 * c->limit;
00060         buf = realloc(c->buf, newsz);
00061         if (buf == NULL)
00062             return(NULL);
00063         memset(buf + c->limit, 0, newsz - c->limit);
00064         c->buf = buf;
00065         c->limit = newsz;
00066     }
00067     buf += c->length;
00068     return(buf);
00069 }
00070 
00071 void ccn_charbuf_reset(struct ccn_charbuf *c)
00072 {
00073     if (c == NULL) {
00074       return;
00075     } 
00076     c->length = 0;
00077 }
00078 
00079 int
00080 ccn_charbuf_append(struct ccn_charbuf *c, const void *p, size_t n)
00081 {
00082     unsigned char *dst = ccn_charbuf_reserve(c, n);
00083     if (dst == NULL)
00084         return(-1);
00085     memcpy(dst, p, n);
00086     c->length += n;
00087     return(0);
00088 }
00089 
00090 int
00091 ccn_charbuf_append_value(struct ccn_charbuf *c, unsigned val, unsigned n)
00092 {
00093     unsigned char *dst;
00094     unsigned i;
00095     if (n > sizeof(val))
00096         return(-1);
00097     dst = ccn_charbuf_reserve(c, n);
00098     if (dst == NULL)
00099         return(-1);
00100     for (i = 0; i < n; i++)
00101         dst[i] = (unsigned char)(val >> (8 * (n-1-i)));
00102     c->length += n;
00103     return(0);
00104 }
00105 
00106 int
00107 ccn_charbuf_append_charbuf(struct ccn_charbuf *c, const struct ccn_charbuf *in)
00108 {
00109   return(ccn_charbuf_append(c, in->buf, in->length));
00110 }
00111 
00112 int
00113 ccn_charbuf_append_string(struct ccn_charbuf *c, const char *s)
00114 {
00115   return(ccn_charbuf_append(c, s, strlen(s)));
00116 }
00117 
00118 int
00119 ccn_charbuf_putf(struct ccn_charbuf *c, const char *fmt, ...)
00120 {
00121     int sz;
00122     va_list ap;
00123     char *buf;
00124     buf = (char *)ccn_charbuf_reserve(c, strlen(fmt) + 10); /* estimate */
00125     if (buf == NULL) return(-1);
00126     va_start(ap, fmt);
00127     sz = vsnprintf(buf, c->limit - c->length, fmt, ap);
00128     va_end(ap);
00129     if (sz < 0)
00130         return(sz);
00131     if (c->length + sz < c->limit) {
00132         c->length += sz;
00133         return(sz);
00134     }
00135     va_end(ap);
00136     buf = (char *)ccn_charbuf_reserve(c, sz + 1); /* accurate */
00137     if (buf == NULL) return(-1);
00138     va_start(ap, fmt);
00139     sz = vsnprintf(buf, c->limit - c->length, fmt, ap);
00140     va_end(ap);
00141     if (c->length + sz < c->limit) {
00142         c->length += sz;
00143         return(sz);
00144     }
00145     return(-1);
00146 }
00147 
00148 /* This formats time into xs:dateTime format */
00149 int
00150 ccn_charbuf_append_datetime(struct ccn_charbuf *c, time_t secs, int nsecs)
00151 {
00152     char timestring[32];
00153     int timelen;
00154     struct tm time_tm;
00155     int res;
00156 
00157     timelen = strftime(timestring, sizeof(timestring),
00158                        "%FT%T", gmtime_r(&secs, &time_tm));
00159     if (timelen >= sizeof(timestring))
00160         return(-1);
00161     if (nsecs != 0) {
00162         if (nsecs < 0 || nsecs >= 1000000000)
00163             return(-1);
00164         timelen += snprintf(&timestring[timelen], sizeof(timestring) - timelen,
00165                             ".%09d", nsecs);
00166         if (timelen >= sizeof(timestring))
00167             return(-1);
00168         while (timestring[timelen - 1] == '0') timelen--;
00169     }
00170     timestring[timelen++] = 'Z';
00171     res = ccn_charbuf_append(c, timestring, timelen);
00172     return (res);
00173 }
00174 
00175 char *
00176 ccn_charbuf_as_string(struct ccn_charbuf *c)
00177 {
00178     unsigned char *r;
00179     r = ccn_charbuf_reserve(c, 1);
00180     if (r == NULL)
00181         return(NULL);
00182     r[0] = 0;
00183     return((char *)c->buf);
00184 }
Generated on Fri May 13 16:27:02 2011 for Content-Centric Networking in C by  doxygen 1.6.3