]> git.ipfire.org Git - people/ms/strongswan.git/blob - src/libstrongswan/bio/bio_writer.c
Added a method to bio_writer_t that allows to skip a number of bytes
[people/ms/strongswan.git] / src / libstrongswan / bio / bio_writer.c
1 /*
2 * Copyright (C) 2012 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
4 *
5 * Copyright (C) 2010 Martin Willi
6 * Copyright (C) 2010 revosec AG
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 */
18
19 #include "bio_writer.h"
20
21 typedef struct private_bio_writer_t private_bio_writer_t;
22
23 /**
24 * Private data of an bio_writer_t object.
25 */
26 struct private_bio_writer_t {
27
28 /**
29 * Public bio_writer_t interface.
30 */
31 bio_writer_t public;
32
33 /**
34 * Allocated buffer
35 */
36 chunk_t buf;
37
38 /**
39 * Used bytes in buffer
40 */
41 size_t used;
42
43 /**
44 * Number of bytes to increase buffer size
45 */
46 size_t increase;
47 };
48
49 /**
50 * Increase buffer size
51 */
52 static void increase(private_bio_writer_t *this)
53 {
54 this->buf.len += this->increase;
55 this->buf.ptr = realloc(this->buf.ptr, this->buf.len);
56 }
57
58 METHOD(bio_writer_t, write_uint8, void,
59 private_bio_writer_t *this, u_int8_t value)
60 {
61 if (this->used + 1 > this->buf.len)
62 {
63 increase(this);
64 }
65 this->buf.ptr[this->used] = value;
66 this->used += 1;
67 }
68
69 METHOD(bio_writer_t, write_uint16, void,
70 private_bio_writer_t *this, u_int16_t value)
71 {
72 if (this->used + 2 > this->buf.len)
73 {
74 increase(this);
75 }
76 htoun16(this->buf.ptr + this->used, value);
77 this->used += 2;
78 }
79
80 METHOD(bio_writer_t, write_uint24, void,
81 private_bio_writer_t *this, u_int32_t value)
82 {
83 if (this->used + 3 > this->buf.len)
84 {
85 increase(this);
86 }
87 value = htonl(value);
88 memcpy(this->buf.ptr + this->used, ((char*)&value) + 1, 3);
89 this->used += 3;
90 }
91
92 METHOD(bio_writer_t, write_uint32, void,
93 private_bio_writer_t *this, u_int32_t value)
94 {
95 if (this->used + 4 > this->buf.len)
96 {
97 increase(this);
98 }
99 htoun32(this->buf.ptr + this->used, value);
100 this->used += 4;
101 }
102
103 METHOD(bio_writer_t, write_uint64, void,
104 private_bio_writer_t *this, u_int64_t value)
105 {
106 if (this->used + 8 > this->buf.len)
107 {
108 increase(this);
109 }
110 htoun64(this->buf.ptr + this->used, value);
111 this->used += 8;
112 }
113
114 METHOD(bio_writer_t, write_data, void,
115 private_bio_writer_t *this, chunk_t value)
116 {
117 while (this->used + value.len > this->buf.len)
118 {
119 increase(this);
120 }
121 memcpy(this->buf.ptr + this->used, value.ptr, value.len);
122 this->used += value.len;
123 }
124
125 METHOD(bio_writer_t, write_data8, void,
126 private_bio_writer_t *this, chunk_t value)
127 {
128 write_uint8(this, value.len);
129 write_data(this, value);
130 }
131
132 METHOD(bio_writer_t, write_data16, void,
133 private_bio_writer_t *this, chunk_t value)
134 {
135 write_uint16(this, value.len);
136 write_data(this, value);
137 }
138
139 METHOD(bio_writer_t, write_data24, void,
140 private_bio_writer_t *this, chunk_t value)
141 {
142 write_uint24(this, value.len);
143 write_data(this, value);
144 }
145
146 METHOD(bio_writer_t, write_data32, void,
147 private_bio_writer_t *this, chunk_t value)
148 {
149 write_uint32(this, value.len);
150 write_data(this, value);
151 }
152
153 METHOD(bio_writer_t, wrap8, void,
154 private_bio_writer_t *this)
155 {
156 if (this->used + 1 > this->buf.len)
157 {
158 increase(this);
159 }
160 memmove(this->buf.ptr + 1, this->buf.ptr, this->used);
161 this->buf.ptr[0] = this->used;
162 this->used += 1;
163 }
164
165 METHOD(bio_writer_t, wrap16, void,
166 private_bio_writer_t *this)
167 {
168 if (this->used + 2 > this->buf.len)
169 {
170 increase(this);
171 }
172 memmove(this->buf.ptr + 2, this->buf.ptr, this->used);
173 htoun16(this->buf.ptr, this->used);
174 this->used += 2;
175 }
176
177 METHOD(bio_writer_t, wrap24, void,
178 private_bio_writer_t *this)
179 {
180 u_int32_t len;
181
182 if (this->used + 3 > this->buf.len)
183 {
184 increase(this);
185 }
186 memmove(this->buf.ptr + 3, this->buf.ptr, this->used);
187
188 len = htonl(this->used);
189 memcpy(this->buf.ptr, ((char*)&len) + 1, 3);
190 this->used += 3;
191 }
192
193 METHOD(bio_writer_t, wrap32, void,
194 private_bio_writer_t *this)
195 {
196 if (this->used + 4 > this->buf.len)
197 {
198 increase(this);
199 }
200 memmove(this->buf.ptr + 4, this->buf.ptr, this->used);
201 htoun32(this->buf.ptr, this->used);
202 this->used += 4;
203 }
204
205 METHOD(bio_writer_t, skip, chunk_t,
206 private_bio_writer_t *this, size_t len)
207 {
208 chunk_t skipped;
209
210 while (this->used + len > this->buf.len)
211 {
212 increase(this);
213 }
214 skipped = chunk_create(this->buf.ptr + this->used, len);
215 this->used += len;
216 return skipped;
217 }
218
219 METHOD(bio_writer_t, get_buf, chunk_t,
220 private_bio_writer_t *this)
221 {
222 return chunk_create(this->buf.ptr, this->used);
223 }
224
225 METHOD(bio_writer_t, extract_buf, chunk_t,
226 private_bio_writer_t *this)
227 {
228 chunk_t buf = get_buf(this);
229 this->buf = chunk_empty;
230 this->used = 0;
231 return buf;
232 }
233
234 METHOD(bio_writer_t, destroy, void,
235 private_bio_writer_t *this)
236 {
237 free(this->buf.ptr);
238 free(this);
239 }
240
241 /**
242 * See header
243 */
244 bio_writer_t *bio_writer_create(u_int32_t bufsize)
245 {
246 private_bio_writer_t *this;
247
248 INIT(this,
249 .public = {
250 .write_uint8 = _write_uint8,
251 .write_uint16 = _write_uint16,
252 .write_uint24 = _write_uint24,
253 .write_uint32 = _write_uint32,
254 .write_uint64 = _write_uint64,
255 .write_data = _write_data,
256 .write_data8 = _write_data8,
257 .write_data16 = _write_data16,
258 .write_data24 = _write_data24,
259 .write_data32 = _write_data32,
260 .wrap8 = _wrap8,
261 .wrap16 = _wrap16,
262 .wrap24 = _wrap24,
263 .wrap32 = _wrap32,
264 .skip = _skip,
265 .get_buf = _get_buf,
266 .extract_buf = _extract_buf,
267 .destroy = _destroy,
268 },
269 .increase = bufsize ? max(bufsize, 4) : 32,
270 );
271 if (bufsize)
272 {
273 this->buf = chunk_alloc(bufsize);
274 }
275
276 return &this->public;
277 }