blob: 06c654470a1a69cd43931449e89bc2d52d3b8cca [file] [log] [blame]
Alexander Afanasyevc74a6022011-08-15 20:01:35 -07001/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
Ilya Moiseenkoc115fba2011-08-01 10:53:18 -07002/*
Alexander Afanasyev6b997c52011-08-08 12:55:25 -07003 * Copyright (c) 2011 University of California, Los Angeles
Ilya Moiseenkoc115fba2011-08-01 10:53:18 -07004 *
Alexander Afanasyev6b997c52011-08-08 12:55:25 -07005 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
Ilya Moiseenkoc115fba2011-08-01 10:53:18 -07008 *
Alexander Afanasyev6b997c52011-08-08 12:55:25 -07009 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Ilya Moiseenko <iliamo@cs.ucla.edu>
Ilya Moiseenkoc115fba2011-08-01 10:53:18 -070019 */
20
21#include "ccn_charbuf.h"
22
23/**
24 * @file ccn_charbuf.c
25 * @brief Support expandable buffer for counted sequences of arbitrary bytes.
26 *
27 * Part of the CCNx C Library.
28 *
29 * Copyright (C) 2008, 2009 Palo Alto Research Center, Inc.
30 *
31 * This library is free software; you can redistribute it and/or modify it
32 * under the terms of the GNU Lesser General Public License version 2.1
33 * as published by the Free Software Foundation.
34 * This library is distributed in the hope that it will be useful,
35 * but WITHOUT ANY WARRANTY; without even the implied warranty of
36 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
37 * Lesser General Public License for more details. You should have received
38 * a copy of the GNU Lesser General Public License along with this library;
39 * if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
40 * Fifth Floor, Boston, MA 02110-1301 USA.
41 */
42#include <stdarg.h>
43#include <stdio.h>
44#include <stdlib.h>
45#include <string.h>
46#include <sys/time.h>
47#include "ccn_coding.h"
48
49struct ccn_charbuf *
50ccn_charbuf_create(void)
51{
52 struct ccn_charbuf *c;
53 c = (ccn_charbuf*)calloc(1, sizeof(*c));
54 return(c);
55}
56
57void
58ccn_charbuf_destroy(struct ccn_charbuf **cbp)
59{
60 struct ccn_charbuf *c = *cbp;
61 if (c != NULL) {
62 if (c->buf != NULL)
63 free(c->buf);
64 free(c);
65 *cbp = NULL;
66 }
67}
68
69/*
70 * ccn_charbuf_reserve: expand buffer as necessary to hold n more chars
71 */
72unsigned char *
73ccn_charbuf_reserve(struct ccn_charbuf *c, size_t n)
74{
75 size_t newsz = n + c->length;
76 unsigned char *buf = c->buf;
77 if (newsz < n)
78 return(NULL);
79 if (newsz > c->limit) {
80 if (2 * c->limit > newsz)
81 newsz = 2 * c->limit;
82 buf = (unsigned char*)realloc(c->buf, newsz);
83 if (buf == NULL)
84 return(NULL);
85 memset(buf + c->limit, 0, newsz - c->limit);
86 c->buf = buf;
87 c->limit = newsz;
88 }
89 buf += c->length;
90 return(buf);
91}
92
93void ccn_charbuf_reset(struct ccn_charbuf *c)
94{
95 if (c == NULL) {
96 return;
97 }
98 c->length = 0;
99}
100
101int
102ccn_charbuf_append(struct ccn_charbuf *c, const void *p, size_t n)
103{
104 unsigned char *dst = ccn_charbuf_reserve(c, n);
105 if (dst == NULL)
106 return(-1);
107 memcpy(dst, p, n);
108 c->length += n;
109 return(0);
110}
111
112int
113ccn_charbuf_append_value(struct ccn_charbuf *c, unsigned val, unsigned n)
114{
115 unsigned char *dst;
116 unsigned i;
117 if (n > sizeof(val))
118 return(-1);
119 dst = ccn_charbuf_reserve(c, n);
120 if (dst == NULL)
121 return(-1);
122 for (i = 0; i < n; i++)
123 dst[i] = (unsigned char)(val >> (8 * (n-1-i)));
124 c->length += n;
125 return(0);
126}
127
128int
129ccn_charbuf_append_charbuf(struct ccn_charbuf *c, const struct ccn_charbuf *in)
130{
131 return(ccn_charbuf_append(c, in->buf, in->length));
132}
133
134int
135ccn_charbuf_append_string(struct ccn_charbuf *c, const char *s)
136{
137 return(ccn_charbuf_append(c, s, strlen(s)));
138}
139
140int
141ccn_charbuf_putf(struct ccn_charbuf *c, const char *fmt, ...)
142{
143 int sz;
144 va_list ap;
145 char *buf;
146 buf = (char *)ccn_charbuf_reserve(c, strlen(fmt) + 10); /* estimate */
147 if (buf == NULL) return(-1);
148 va_start(ap, fmt);
149 sz = vsnprintf(buf, c->limit - c->length, fmt, ap);
150 va_end(ap);
151 if (sz < 0)
152 return(sz);
153 if (c->length + sz < c->limit) {
154 c->length += sz;
155 return(sz);
156 }
157 va_end(ap);
158 buf = (char *)ccn_charbuf_reserve(c, sz + 1); /* accurate */
159 if (buf == NULL) return(-1);
160 va_start(ap, fmt);
161 sz = vsnprintf(buf, c->limit - c->length, fmt, ap);
162 va_end(ap);
163 if (c->length + sz < c->limit) {
164 c->length += sz;
165 return(sz);
166 }
167 return(-1);
168}
169
170/* This formats time into xs:dateTime format */
171int
172ccn_charbuf_append_datetime(struct ccn_charbuf *c, time_t secs, int nsecs)
173{
174 char timestring[32];
175 int timelen;
176 struct tm time_tm;
177 int res;
178
179 timelen = strftime(timestring, sizeof(timestring),
180 "%FT%T", gmtime_r(&secs, &time_tm));
181 if (timelen >= (int)sizeof(timestring))
182 return(-1);
183 if (nsecs != 0) {
184 if (nsecs < 0 || nsecs >= 1000000000)
185 return(-1);
186 timelen += snprintf(&timestring[timelen], sizeof(timestring) - timelen,
187 ".%09d", nsecs);
188 if (timelen >= (int)sizeof(timestring))
189 return(-1);
190 while (timestring[timelen - 1] == '0') timelen--;
191 }
192 timestring[timelen++] = 'Z';
193 res = ccn_charbuf_append(c, timestring, timelen);
194 return (res);
195}
196
197char *
198ccn_charbuf_as_string(struct ccn_charbuf *c)
199{
200 unsigned char *r;
201 r = ccn_charbuf_reserve(c, 1);
202 if (r == NULL)
203 return(NULL);
204 r[0] = 0;
205 return((char *)c->buf);
206}
207
208int
209ccn_charbuf_append_closer(struct ccn_charbuf *c)
210{
211 int res;
212 const unsigned char closer = CCN_CLOSE;
213 res = ccn_charbuf_append(c, &closer, 1);
214 return(res);
215}