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