2 * Copyright (C) 2012 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
5 * Copyright (C) 2010 Martin Willi
6 * Copyright (C) 2010 revosec AG
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>.
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
19 #include "bio_reader.h"
21 #include <utils/debug.h>
23 typedef struct private_bio_reader_t private_bio_reader_t
;
26 * Private data of an bio_reader_t object.
28 struct private_bio_reader_t
{
31 * Public bio_reader_t interface.
36 * Remaining data to process
41 METHOD(bio_reader_t
, remaining
, u_int32_t
,
42 private_bio_reader_t
*this)
47 METHOD(bio_reader_t
, peek
, chunk_t
,
48 private_bio_reader_t
*this)
54 * A version of chunk_skip() that supports skipping from the end (i.e. simply
57 static inline chunk_t
chunk_skip_end(chunk_t chunk
, size_t bytes
, bool from_end
)
59 if (chunk
.len
> bytes
)
72 * Returns a pointer to the data to read, optionally from the end
74 static inline u_char
*get_ptr_end(private_bio_reader_t
*this, u_int32_t len
,
77 return from_end
? this->buf
.ptr
+ (this->buf
.len
- len
) : this->buf
.ptr
;
81 * Read an u_int8_t from the buffer, optionally from the end of the buffer
83 static bool read_uint8_internal(private_bio_reader_t
*this, u_int8_t
*res
,
86 if (this->buf
.len
< 1)
88 DBG1(DBG_LIB
, "%d bytes insufficient to parse u_int8 data",
92 *res
= *get_ptr_end(this, 1, from_end
);
93 this->buf
= chunk_skip_end(this->buf
, 1, from_end
);
98 * Read an u_int16_t from the buffer, optionally from the end
100 static bool read_uint16_internal(private_bio_reader_t
*this, u_int16_t
*res
,
103 if (this->buf
.len
< 2)
105 DBG1(DBG_LIB
, "%d bytes insufficient to parse u_int16 data",
109 *res
= untoh16(get_ptr_end(this, 2, from_end
));
110 this->buf
= chunk_skip_end(this->buf
, 2, from_end
);
115 * Read an u_int32_t (only 24-bit) from the buffer, optionally from the end
117 static bool read_uint24_internal(private_bio_reader_t
*this, u_int32_t
*res
,
120 if (this->buf
.len
< 3)
122 DBG1(DBG_LIB
, "%d bytes insufficient to parse u_int24 data",
126 *res
= untoh32(get_ptr_end(this, 3, from_end
)) >> 8;
127 this->buf
= chunk_skip_end(this->buf
, 3, from_end
);
132 * Read an u_int32_t from the buffer, optionally from the end
134 static bool read_uint32_internal(private_bio_reader_t
*this, u_int32_t
*res
,
137 if (this->buf
.len
< 4)
139 DBG1(DBG_LIB
, "%d bytes insufficient to parse u_int32 data",
143 *res
= untoh32(get_ptr_end(this, 4, from_end
));
144 this->buf
= chunk_skip_end(this->buf
, 4, from_end
);
149 * Read an u_int64_t from the buffer, optionally from the end
151 static bool read_uint64_internal(private_bio_reader_t
*this, u_int64_t
*res
,
154 if (this->buf
.len
< 8)
156 DBG1(DBG_LIB
, "%d bytes insufficient to parse u_int64 data",
160 *res
= untoh64(get_ptr_end(this, 8, from_end
));
161 this->buf
= chunk_skip_end(this->buf
, 8, from_end
);
166 * Read a chunk of data from the buffer, optionally from the end
168 static bool read_data_internal(private_bio_reader_t
*this, u_int32_t len
,
169 chunk_t
*res
, bool from_end
)
171 if (this->buf
.len
< len
)
173 DBG1(DBG_LIB
, "%d bytes insufficient to parse %d bytes of data",
177 *res
= chunk_create(get_ptr_end(this, len
, from_end
), len
);
178 this->buf
= chunk_skip_end(this->buf
, len
, from_end
);
182 METHOD(bio_reader_t
, read_uint8
, bool,
183 private_bio_reader_t
*this, u_int8_t
*res
)
185 return read_uint8_internal(this, res
, FALSE
);
188 METHOD(bio_reader_t
, read_uint16
, bool,
189 private_bio_reader_t
*this, u_int16_t
*res
)
191 return read_uint16_internal(this, res
, FALSE
);
194 METHOD(bio_reader_t
, read_uint24
, bool,
195 private_bio_reader_t
*this, u_int32_t
*res
)
197 return read_uint24_internal(this, res
, FALSE
);
200 METHOD(bio_reader_t
, read_uint32
, bool,
201 private_bio_reader_t
*this, u_int32_t
*res
)
203 return read_uint32_internal(this, res
, FALSE
);
206 METHOD(bio_reader_t
, read_uint64
, bool,
207 private_bio_reader_t
*this, u_int64_t
*res
)
209 return read_uint64_internal(this, res
, FALSE
);
212 METHOD(bio_reader_t
, read_data
, bool,
213 private_bio_reader_t
*this, u_int32_t len
, chunk_t
*res
)
215 return read_data_internal(this, len
, res
, FALSE
);
218 METHOD(bio_reader_t
, read_uint8_end
, bool,
219 private_bio_reader_t
*this, u_int8_t
*res
)
221 return read_uint8_internal(this, res
, TRUE
);
224 METHOD(bio_reader_t
, read_uint16_end
, bool,
225 private_bio_reader_t
*this, u_int16_t
*res
)
227 return read_uint16_internal(this, res
, TRUE
);
230 METHOD(bio_reader_t
, read_uint24_end
, bool,
231 private_bio_reader_t
*this, u_int32_t
*res
)
233 return read_uint24_internal(this, res
, TRUE
);
236 METHOD(bio_reader_t
, read_uint32_end
, bool,
237 private_bio_reader_t
*this, u_int32_t
*res
)
239 return read_uint32_internal(this, res
, TRUE
);
242 METHOD(bio_reader_t
, read_uint64_end
, bool,
243 private_bio_reader_t
*this, u_int64_t
*res
)
245 return read_uint64_internal(this, res
, TRUE
);
248 METHOD(bio_reader_t
, read_data_end
, bool,
249 private_bio_reader_t
*this, u_int32_t len
, chunk_t
*res
)
251 return read_data_internal(this, len
, res
, TRUE
);
254 METHOD(bio_reader_t
, read_data8
, bool,
255 private_bio_reader_t
*this, chunk_t
*res
)
259 if (!read_uint8(this, &len
))
263 return read_data(this, len
, res
);
266 METHOD(bio_reader_t
, read_data16
, bool,
267 private_bio_reader_t
*this, chunk_t
*res
)
271 if (!read_uint16(this, &len
))
275 return read_data(this, len
, res
);
278 METHOD(bio_reader_t
, read_data24
, bool,
279 private_bio_reader_t
*this, chunk_t
*res
)
283 if (!read_uint24(this, &len
))
287 return read_data(this, len
, res
);
290 METHOD(bio_reader_t
, read_data32
, bool,
291 private_bio_reader_t
*this, chunk_t
*res
)
295 if (!read_uint32(this, &len
))
299 return read_data(this, len
, res
);
302 METHOD(bio_reader_t
, destroy
, void,
303 private_bio_reader_t
*this)
311 bio_reader_t
*bio_reader_create(chunk_t data
)
313 private_bio_reader_t
*this;
317 .remaining
= _remaining
,
319 .read_uint8
= _read_uint8
,
320 .read_uint16
= _read_uint16
,
321 .read_uint24
= _read_uint24
,
322 .read_uint32
= _read_uint32
,
323 .read_uint64
= _read_uint64
,
324 .read_data
= _read_data
,
325 .read_uint8_end
= _read_uint8_end
,
326 .read_uint16_end
= _read_uint16_end
,
327 .read_uint24_end
= _read_uint24_end
,
328 .read_uint32_end
= _read_uint32_end
,
329 .read_uint64_end
= _read_uint64_end
,
330 .read_data_end
= _read_data_end
,
331 .read_data8
= _read_data8
,
332 .read_data16
= _read_data16
,
333 .read_data24
= _read_data24
,
334 .read_data32
= _read_data32
,
340 return &this->public;