Super User's BSD Cross Reference: /OpenBSD/usr.sbin/nsd/buffer.h

1 /*
2 * buffer.h -- generic memory buffer.
3 *
4 * Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
5 *
6 * See LICENSE for the license.
7 *
8 *
9 * The buffer module implements a generic buffer. The API is based on
10 * the java.nio.Buffer interface.
11 */
12
13#ifndef BUFFER_H
14#define BUFFER_H
15
16#include <assert.h>
17#include <stdarg.h>
18#include <string.h>
19
20#include "region-allocator.h"
21#include "util.h"
22
23 typedef struct buffer buffer_type;
24
25 struct buffer
26{
27 /*
28 * The current position used for reading/writing.
29 */
30 size_t _position;
31
32 /*
33 * The read/write limit.
34 */
35 size_t _limit;
36
37 /*
38 * The amount of data the buffer can contain.
39 */
40 size_t _capacity;
41
42 /*
43 * The data contained in the buffer.
44 */
45 uint8_t *_data;
46
47 /*
48 * If the buffer is fixed it cannot be resized.
49 */
50 unsigned _fixed : 1;
51};
52
53#ifdef NDEBUG
54 static inline void
55 buffer_invariant(buffer_type *ATTR_UNUSED(buffer))
56{
57}
58#else
59 static inline void
60 buffer_invariant(buffer_type *buffer)
61{
62 assert(buffer);
63 assert(buffer->_position <= buffer->_limit);
64 assert(buffer->_limit <= buffer->_capacity);
65 assert(buffer->_data);
66}
67#endif
68
69 /*
70 * Create a new buffer with the specified capacity.
71 */
72 buffer_type *buffer_create(region_type *region, size_t capacity);
73
74 /*
75 * Create a buffer with the specified data. The data is not copied
76 * and no memory allocations are done. The buffer is fixed and cannot
77 * be resized using buffer_reserve().
78 */
79 void buffer_create_from(buffer_type *buffer, const void *data, size_t size);
80
81 /*
82 * Clear the buffer and make it ready for writing. The buffer's limit
83 * is set to the capacity and the position is set to 0.
84 */
85 void buffer_clear(buffer_type *buffer);
86
87 /*
88 * Make the buffer ready for reading the data that has been written to
89 * the buffer. The buffer's limit is set to the current position and
90 * the position is set to 0.
91 */
92 void buffer_flip(buffer_type *buffer);
93
94 /*
95 * Make the buffer ready for re-reading the data. The buffer's
96 * position is reset to 0.
97 */
98 void buffer_rewind(buffer_type *buffer);
99
100 static inline size_t
101 buffer_position(buffer_type *buffer)
102{
103 return buffer->_position;
104}
105
106 /*
107 * Set the buffer's position to MARK. The position must be less than
108 * or equal to the buffer's limit.
109 */
110 static inline void
111 buffer_set_position(buffer_type *buffer, size_t mark)
112{
113 assert(mark <= buffer->_limit);
114 buffer->_position = mark;
115}
116
117 /*
118 * Change the buffer's position by COUNT bytes. The position must not
119 * be moved behind the buffer's limit or before the beginning of the
120 * buffer.
121 */
122 static inline void
123 buffer_skip(buffer_type *buffer, ssize_t count)
124{
125 assert(buffer->_position + count <= buffer->_limit);
126 buffer->_position += count;
127}
128
129 static inline size_t
130 buffer_limit(buffer_type *buffer)
131{
132 return buffer->_limit;
133}
134
135 /*
136 * Change the buffer's limit. If the buffer's position is greater
137 * than the new limit the position is set to the limit.
138 */
139 static inline void
140 buffer_set_limit(buffer_type *buffer, size_t limit)
141{
142 assert(limit <= buffer->_capacity);
143 buffer->_limit = limit;
144 if (buffer->_position > buffer->_limit)
145 buffer->_position = buffer->_limit;
146}
147
148
149 static inline size_t
150 buffer_capacity(buffer_type *buffer)
151{
152 return buffer->_capacity;
153}
154
155 /*
156 * Change the buffer's capacity. The data is reallocated so any
157 * pointers to the data may become invalid. The buffer's limit is set
158 * to the buffer's new capacity.
159 */
160 void buffer_set_capacity(buffer_type *buffer, size_t capacity);
161
162 /*
163 * Ensure BUFFER can contain at least AMOUNT more bytes. The buffer's
164 * capacity is increased if necessary using buffer_set_capacity().
165 *
166 * The buffer's limit is always set to the (possibly increased)
167 * capacity.
168 */
169 void buffer_reserve(buffer_type *buffer, size_t amount);
170
171 /*
172 * Return a pointer to the data at the indicated position.
173 */
174 static inline uint8_t *
175 buffer_at(buffer_type *buffer, size_t at)
176{
177 assert(at <= buffer->_limit);
178 return buffer->_data + at;
179}
180
181 /*
182 * Return a pointer to the beginning of the buffer (the data at
183 * position 0).
184 */
185 static inline uint8_t *
186 buffer_begin(buffer_type *buffer)
187{
188 return buffer_at(buffer, 0);
189}
190
191 /*
192 * Return a pointer to the end of the buffer (the data at the buffer's
193 * limit).
194 */
195 static inline uint8_t *
196 buffer_end(buffer_type *buffer)
197{
198 return buffer_at(buffer, buffer->_limit);
199}
200
201 /*
202 * Return a pointer to the data at the buffer's current position.
203 */
204 static inline uint8_t *
205 buffer_current(buffer_type *buffer)
206{
207 return buffer_at(buffer, buffer->_position);
208}
209
210 /*
211 * The number of bytes remaining between the indicated position and
212 * the limit.
213 */
214 static inline size_t
215 buffer_remaining_at(buffer_type *buffer, size_t at)
216{
217 buffer_invariant(buffer);
218 assert(at <= buffer->_limit);
219 return buffer->_limit - at;
220}
221
222 /*
223 * The number of bytes remaining between the buffer's position and
224 * limit.
225 */
226 static inline size_t
227 buffer_remaining(buffer_type *buffer)
228{
229 return buffer_remaining_at(buffer, buffer->_position);
230}
231
232 /*
233 * Check if the buffer has at least COUNT more bytes available.
234 * Before reading or writing the caller needs to ensure enough space
235 * is available!
236 */
237 static inline int
238 buffer_available_at(buffer_type *buffer, size_t at, size_t count)
239{
240 return count <= buffer_remaining_at(buffer, at);
241}
242
243 static inline int
244 buffer_available(buffer_type *buffer, size_t count)
245{
246 return buffer_available_at(buffer, buffer->_position, count);
247}
248
249 static inline void
250 buffer_write_at(buffer_type *buffer, size_t at, const void *data, size_t count)
251{
252 assert(buffer_available_at(buffer, at, count));
253 memcpy(buffer->_data + at, data, count);
254}
255
256 static inline void
257 buffer_write(buffer_type *buffer, const void *data, size_t count)
258{
259 buffer_write_at(buffer, buffer->_position, data, count);
260 buffer->_position += count;
261}
262
263 static inline int
264 try_buffer_write_at(buffer_type *buffer, size_t at, const void *data, size_t count)
265{
266 if(!buffer_available_at(buffer, at, count))
267 return 0;
268 memcpy(buffer->_data + at, data, count);
269 return 1;
270}
271
272 static inline int
273 try_buffer_write(buffer_type *buffer, const void *data, size_t count)
274{
275 if(!try_buffer_write_at(buffer, buffer->_position, data, count))
276 return 0;
277 buffer->_position += count;
278 return 1;
279}
280
281 static inline void
282 buffer_write_string_at(buffer_type *buffer, size_t at, const char *str)
283{
284 buffer_write_at(buffer, at, str, strlen(str));
285}
286
287 static inline void
288 buffer_write_string(buffer_type *buffer, const char *str)
289{
290 buffer_write(buffer, str, strlen(str));
291}
292
293 static inline int
294 try_buffer_write_string_at(buffer_type *buffer, size_t at, const char *str)
295{
296 return try_buffer_write_at(buffer, at, str, strlen(str));
297}
298
299 static inline int
300 try_buffer_write_string(buffer_type *buffer, const char *str)
301{
302 return try_buffer_write(buffer, str, strlen(str));
303}
304
305 static inline void
306 buffer_write_u8_at(buffer_type *buffer, size_t at, uint8_t data)
307{
308 assert(buffer_available_at(buffer, at, sizeof(data)));
309 buffer->_data[at] = data;
310}
311
312 static inline void
313 buffer_write_u8(buffer_type *buffer, uint8_t data)
314{
315 buffer_write_u8_at(buffer, buffer->_position, data);
316 buffer->_position += sizeof(data);
317}
318
319 static inline void
320 buffer_write_u16_at(buffer_type *buffer, size_t at, uint16_t data)
321{
322 assert(buffer_available_at(buffer, at, sizeof(data)));
323 write_uint16(buffer->_data + at, data);
324}
325
326 static inline void
327 buffer_write_u16(buffer_type *buffer, uint16_t data)
328{
329 buffer_write_u16_at(buffer, buffer->_position, data);
330 buffer->_position += sizeof(data);
331}
332
333 static inline void
334 buffer_write_u32_at(buffer_type *buffer, size_t at, uint32_t data)
335{
336 assert(buffer_available_at(buffer, at, sizeof(data)));
337 write_uint32(buffer->_data + at, data);
338}
339
340 static inline void
341 buffer_write_u32(buffer_type *buffer, uint32_t data)
342{
343 buffer_write_u32_at(buffer, buffer->_position, data);
344 buffer->_position += sizeof(data);
345}
346
347 static inline void
348 buffer_write_u64_at(buffer_type *buffer, size_t at, uint64_t data)
349{
350 assert(buffer_available_at(buffer, at, sizeof(data)));
351 write_uint64(buffer->_data + at, data);
352}
353
354 static inline void
355 buffer_write_u64(buffer_type *buffer, uint64_t data)
356{
357 buffer_write_u64_at(buffer, buffer->_position, data);
358 buffer->_position += sizeof(data);
359}
360
361 static inline int
362 try_buffer_write_u8_at(buffer_type *buffer, size_t at, uint8_t data)
363{
364 if(!buffer_available_at(buffer, at, sizeof(data)))
365 return 0;
366 buffer->_data[at] = data;
367 return 1;
368}
369
370 static inline int
371 try_buffer_write_u8(buffer_type *buffer, uint8_t data)
372{
373 if(!try_buffer_write_u8_at(buffer, buffer->_position, data))
374 return 0;
375 buffer->_position += sizeof(data);
376 return 1;
377}
378
379 static inline int
380 try_buffer_write_u16_at(buffer_type *buffer, size_t at, uint16_t data)
381{
382 if(!buffer_available_at(buffer, at, sizeof(data)))
383 return 0;
384 write_uint16(buffer->_data + at, data);
385 return 1;
386}
387
388 static inline int
389 try_buffer_write_u16(buffer_type *buffer, uint16_t data)
390{
391 if(!try_buffer_write_u16_at(buffer, buffer->_position, data))
392 return 0;
393 buffer->_position += sizeof(data);
394 return 1;
395}
396
397 static inline int
398 try_buffer_write_u32_at(buffer_type *buffer, size_t at, uint32_t data)
399{
400 if(!buffer_available_at(buffer, at, sizeof(data)))
401 return 0;
402 write_uint32(buffer->_data + at, data);
403 return 1;
404}
405
406 static inline int
407 try_buffer_write_u32(buffer_type *buffer, uint32_t data)
408{
409 if(!try_buffer_write_u32_at(buffer, buffer->_position, data))
410 return 0;
411 buffer->_position += sizeof(data);
412 return 1;
413}
414
415 static inline int
416 try_buffer_write_u64_at(buffer_type *buffer, size_t at, uint64_t data)
417{
418 if(!buffer_available_at(buffer, at, sizeof(data)))
419 return 0;
420 write_uint64(buffer->_data + at, data);
421 return 1;
422}
423
424 static inline int
425 try_buffer_write_u64(buffer_type *buffer, uint64_t data)
426{
427 if(!try_buffer_write_u64_at(buffer, buffer->_position, data))
428 return 0;
429 buffer->_position += sizeof(data);
430 return 1;
431}
432
433 static inline void
434 buffer_read_at(buffer_type *buffer, size_t at, void *data, size_t count)
435{
436 assert(buffer_available_at(buffer, at, count));
437 memcpy(data, buffer->_data + at, count);
438}
439
440 static inline void
441 buffer_read(buffer_type *buffer, void *data, size_t count)
442{
443 buffer_read_at(buffer, buffer->_position, data, count);
444 buffer->_position += count;
445}
446
447 static inline uint8_t
448 buffer_read_u8_at(buffer_type *buffer, size_t at)
449{
450 assert(buffer_available_at(buffer, at, sizeof(uint8_t)));
451 return buffer->_data[at];
452}
453
454 static inline uint8_t
455 buffer_read_u8(buffer_type *buffer)
456{
457 uint8_t result = buffer_read_u8_at(buffer, buffer->_position);
458 buffer->_position += sizeof(uint8_t);
459 return result;
460}
461
462 static inline uint16_t
463 buffer_read_u16_at(buffer_type *buffer, size_t at)
464{
465 assert(buffer_available_at(buffer, at, sizeof(uint16_t)));
466 return read_uint16(buffer->_data + at);
467}
468
469 static inline uint16_t
470 buffer_read_u16(buffer_type *buffer)
471{
472 uint16_t result = buffer_read_u16_at(buffer, buffer->_position);
473 buffer->_position += sizeof(uint16_t);
474 return result;
475}
476
477 static inline uint32_t
478 buffer_read_u32_at(buffer_type *buffer, size_t at)
479{
480 assert(buffer_available_at(buffer, at, sizeof(uint32_t)));
481 return read_uint32(buffer->_data + at);
482}
483
484 static inline uint32_t
485 buffer_read_u32(buffer_type *buffer)
486{
487 uint32_t result = buffer_read_u32_at(buffer, buffer->_position);
488 buffer->_position += sizeof(uint32_t);
489 return result;
490}
491
492 static inline uint64_t
493 buffer_read_u64_at(buffer_type *buffer, size_t at)
494{
495 assert(buffer_available_at(buffer, at, sizeof(uint64_t)));
496 return read_uint64(buffer->_data + at);
497}
498
499 static inline uint64_t
500 buffer_read_u64(buffer_type *buffer)
501{
502 uint64_t result = buffer_read_u64_at(buffer, buffer->_position);
503 buffer->_position += sizeof(uint64_t);
504 return result;
505}
506
507 /*
508 * Print to the buffer, increasing the capacity if required using
509 * buffer_reserve(). The buffer's position is set to the terminating
510 * '0円'. Returns the number of characters written (not including the
511 * terminating '0円').
512 */
513 int buffer_printf(buffer_type *buffer, const char *format, ...)
514 ATTR_FORMAT(printf, 2, 3);
515
516#endif /* BUFFER_H */
517 

AltStyle によって変換されたページ (->オリジナル) /