1 | /* |
2 | * dynbuf.h |
3 | * |
4 | * Copyright (C) 2009 Aerospike, Inc. |
5 | * |
6 | * Portions may be licensed to Aerospike, Inc. under one or more contributor |
7 | * license agreements. |
8 | * |
9 | * This program is free software: you can redistribute it and/or modify it under |
10 | * the terms of the GNU Affero General Public License as published by the Free |
11 | * Software Foundation, either version 3 of the License, or (at your option) any |
12 | * later version. |
13 | * |
14 | * This program is distributed in the hope that it will be useful, but WITHOUT |
15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
16 | * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more |
17 | * details. |
18 | * |
19 | * You should have received a copy of the GNU Affero General Public License |
20 | * along with this program. If not, see http://www.gnu.org/licenses/ |
21 | */ |
22 | |
23 | /* |
24 | * A simple dynamic buffer implementation |
25 | * Allows the first, simpler part of the buffer to be on the stack |
26 | * which is usually all that's needed |
27 | * |
28 | */ |
29 | |
30 | #pragma once |
31 | |
32 | #include <stdarg.h> |
33 | #include <stdbool.h> |
34 | #include <stddef.h> |
35 | #include <stdint.h> |
36 | |
37 | typedef struct cf_dyn_buf_s { |
38 | uint8_t *buf; |
39 | bool is_stack; |
40 | size_t alloc_sz; |
41 | size_t used_sz; |
42 | } cf_dyn_buf; |
43 | |
44 | #define cf_dyn_buf_define(__x) uint8_t dyn_buf##__x[1024]; cf_dyn_buf __x = { dyn_buf##__x, true, 1024, 0 } |
45 | #define cf_dyn_buf_define_size(__x, __sz) uint8_t dyn_buf##__x[__sz]; cf_dyn_buf __x = { dyn_buf##__x, true, __sz, 0 } |
46 | |
47 | extern void cf_dyn_buf_init_heap(cf_dyn_buf *db, size_t sz); |
48 | extern void cf_dyn_buf_reserve(cf_dyn_buf *db, size_t sz, uint8_t **from); |
49 | extern void cf_dyn_buf_append_string(cf_dyn_buf *db, const char *s); |
50 | extern void cf_dyn_buf_append_char(cf_dyn_buf *db, char c); |
51 | extern void cf_dyn_buf_append_bool(cf_dyn_buf *db, bool b); |
52 | extern void cf_dyn_buf_append_buf(cf_dyn_buf *db, uint8_t *buf, size_t sz); |
53 | extern void cf_dyn_buf_append_int(cf_dyn_buf *db, int i); |
54 | extern void cf_dyn_buf_append_uint64_x(cf_dyn_buf *db, uint64_t i); // HEX FORMAT! |
55 | extern void cf_dyn_buf_append_uint64(cf_dyn_buf *db, uint64_t i); |
56 | extern void cf_dyn_buf_append_uint32(cf_dyn_buf *db, uint32_t i); |
57 | extern void cf_dyn_buf_append_format_va(cf_dyn_buf *db, const char *form, va_list va); |
58 | extern void cf_dyn_buf_append_format(cf_dyn_buf *db, const char *form, ...); |
59 | extern void cf_dyn_buf_chomp(cf_dyn_buf *db); |
60 | extern char *cf_dyn_buf_strdup(cf_dyn_buf *db); |
61 | extern void cf_dyn_buf_free(cf_dyn_buf *db); |
62 | |
63 | // Helpers to append name value pairs to a cf_dyn_buf in pattern: name=value; |
64 | void info_append_bool(cf_dyn_buf *db, const char *name, bool value); |
65 | void info_append_int(cf_dyn_buf *db, const char *name, int value); |
66 | void info_append_string(cf_dyn_buf *db, const char *name, const char *value); |
67 | void info_append_string_safe(cf_dyn_buf *db, const char *name, const char *value); |
68 | void info_append_uint32(cf_dyn_buf *db, const char *name, uint32_t value); |
69 | void info_append_uint64(cf_dyn_buf *db, const char *name, uint64_t value); |
70 | void info_append_uint64_x(cf_dyn_buf *db, const char *name, uint64_t value); |
71 | void info_append_format(cf_dyn_buf *db, const char *name, const char *form, ...); |
72 | |
73 | // Append indexed name with optional attribute and value: name[ix].attr=value; |
74 | void info_append_indexed_string(cf_dyn_buf *db, const char *name, uint32_t ix, const char *attr, const char *value); |
75 | void info_append_indexed_int(cf_dyn_buf *db, const char *name, uint32_t ix, const char *attr, int value); |
76 | void info_append_indexed_uint32(cf_dyn_buf *db, const char *name, uint32_t ix, const char *attr, uint32_t value); |
77 | void info_append_indexed_uint64(cf_dyn_buf *db, const char *name, uint32_t ix, const char *attr, uint64_t value); |
78 | |
79 | typedef struct cf_buf_builder_s { |
80 | size_t alloc_sz; |
81 | size_t used_sz; |
82 | uint8_t buf[]; |
83 | } cf_buf_builder; |
84 | |
85 | extern cf_buf_builder *cf_buf_builder_create(size_t sz); |
86 | extern void cf_buf_builder_free(cf_buf_builder *bb); |
87 | extern void cf_buf_builder_reset(cf_buf_builder *bb); |
88 | extern void cf_buf_builder_chomp(cf_buf_builder *bb_r); |
89 | |
90 | extern void cf_buf_builder_append_string(cf_buf_builder **bb_r, const char *s); |
91 | extern void cf_buf_builder_append_char(cf_buf_builder **bb_r, char c); |
92 | extern void cf_buf_builder_append_buf(cf_buf_builder **bb_r, uint8_t *buf, size_t sz); |
93 | // These append ASCII versions: |
94 | extern void cf_buf_builder_append_ascii_uint64_x(cf_buf_builder **bb_r, uint64_t i); // HEX FORMAT! |
95 | extern void cf_buf_builder_append_ascii_uint64(cf_buf_builder **bb_r, uint64_t i); |
96 | extern void cf_buf_builder_append_ascii_uint32(cf_buf_builder **bb_r, uint32_t i); |
97 | extern void cf_buf_builder_append_ascii_int(cf_buf_builder **bb_r, int i); |
98 | // These append network-order bytes: |
99 | extern void cf_buf_builder_append_uint64(cf_buf_builder **bb_r, uint64_t i); |
100 | extern void cf_buf_builder_append_uint32(cf_buf_builder **bb_r, uint32_t i); |
101 | extern void cf_buf_builder_append_uint16(cf_buf_builder **bb_r, uint16_t i); |
102 | extern void cf_buf_builder_append_uint8(cf_buf_builder **bb_r, uint8_t i); |
103 | // Reserve the bytes and give me the handle to the spot reserved: |
104 | extern void cf_buf_builder_reserve(cf_buf_builder **bb_r, int sz, uint8_t **buf); |
105 | extern int cf_buf_builder_size(cf_buf_builder *bb); |
106 | extern size_t get_new_size(int alloc, int used, int requested); |
107 | |
108 | // TODO - We've only implemented a few cf_ll_buf methods for now. We'll add more |
109 | // functionality if and when it's needed. |
110 | |
111 | typedef struct cf_ll_buf_stage_s { |
112 | struct cf_ll_buf_stage_s *next; |
113 | size_t buf_sz; |
114 | size_t used_sz; |
115 | uint8_t buf[]; |
116 | } cf_ll_buf_stage; |
117 | |
118 | typedef struct cf_ll_buf_s { |
119 | bool head_is_stack; |
120 | cf_ll_buf_stage *head; |
121 | cf_ll_buf_stage *tail; |
122 | } cf_ll_buf; |
123 | |
124 | #define cf_ll_buf_define(__x, __sz) \ |
125 | uint8_t llb_stage##__x[sizeof(cf_ll_buf_stage) + __sz]; \ |
126 | cf_ll_buf_stage* ll_buf_stage##__x = (cf_ll_buf_stage*)llb_stage##__x; \ |
127 | ll_buf_stage##__x->next = NULL; \ |
128 | ll_buf_stage##__x->buf_sz = __sz; \ |
129 | ll_buf_stage##__x->used_sz = 0; \ |
130 | cf_ll_buf __x = { true, ll_buf_stage##__x, ll_buf_stage##__x } |
131 | |
132 | extern void cf_ll_buf_reserve(cf_ll_buf *llb, size_t sz, uint8_t **from); |
133 | extern void cf_ll_buf_free(cf_ll_buf *llb); |
134 | |