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
37typedef 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
47extern void cf_dyn_buf_init_heap(cf_dyn_buf *db, size_t sz);
48extern void cf_dyn_buf_reserve(cf_dyn_buf *db, size_t sz, uint8_t **from);
49extern void cf_dyn_buf_append_string(cf_dyn_buf *db, const char *s);
50extern void cf_dyn_buf_append_char(cf_dyn_buf *db, char c);
51extern void cf_dyn_buf_append_bool(cf_dyn_buf *db, bool b);
52extern void cf_dyn_buf_append_buf(cf_dyn_buf *db, uint8_t *buf, size_t sz);
53extern void cf_dyn_buf_append_int(cf_dyn_buf *db, int i);
54extern void cf_dyn_buf_append_uint64_x(cf_dyn_buf *db, uint64_t i); // HEX FORMAT!
55extern void cf_dyn_buf_append_uint64(cf_dyn_buf *db, uint64_t i);
56extern void cf_dyn_buf_append_uint32(cf_dyn_buf *db, uint32_t i);
57extern void cf_dyn_buf_append_format_va(cf_dyn_buf *db, const char *form, va_list va);
58extern void cf_dyn_buf_append_format(cf_dyn_buf *db, const char *form, ...);
59extern void cf_dyn_buf_chomp(cf_dyn_buf *db);
60extern char *cf_dyn_buf_strdup(cf_dyn_buf *db);
61extern 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;
64void info_append_bool(cf_dyn_buf *db, const char *name, bool value);
65void info_append_int(cf_dyn_buf *db, const char *name, int value);
66void info_append_string(cf_dyn_buf *db, const char *name, const char *value);
67void info_append_string_safe(cf_dyn_buf *db, const char *name, const char *value);
68void info_append_uint32(cf_dyn_buf *db, const char *name, uint32_t value);
69void info_append_uint64(cf_dyn_buf *db, const char *name, uint64_t value);
70void info_append_uint64_x(cf_dyn_buf *db, const char *name, uint64_t value);
71void 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;
74void info_append_indexed_string(cf_dyn_buf *db, const char *name, uint32_t ix, const char *attr, const char *value);
75void info_append_indexed_int(cf_dyn_buf *db, const char *name, uint32_t ix, const char *attr, int value);
76void info_append_indexed_uint32(cf_dyn_buf *db, const char *name, uint32_t ix, const char *attr, uint32_t value);
77void info_append_indexed_uint64(cf_dyn_buf *db, const char *name, uint32_t ix, const char *attr, uint64_t value);
78
79typedef struct cf_buf_builder_s {
80 size_t alloc_sz;
81 size_t used_sz;
82 uint8_t buf[];
83} cf_buf_builder;
84
85extern cf_buf_builder *cf_buf_builder_create(size_t sz);
86extern void cf_buf_builder_free(cf_buf_builder *bb);
87extern void cf_buf_builder_reset(cf_buf_builder *bb);
88extern void cf_buf_builder_chomp(cf_buf_builder *bb_r);
89
90extern void cf_buf_builder_append_string(cf_buf_builder **bb_r, const char *s);
91extern void cf_buf_builder_append_char(cf_buf_builder **bb_r, char c);
92extern void cf_buf_builder_append_buf(cf_buf_builder **bb_r, uint8_t *buf, size_t sz);
93// These append ASCII versions:
94extern void cf_buf_builder_append_ascii_uint64_x(cf_buf_builder **bb_r, uint64_t i); // HEX FORMAT!
95extern void cf_buf_builder_append_ascii_uint64(cf_buf_builder **bb_r, uint64_t i);
96extern void cf_buf_builder_append_ascii_uint32(cf_buf_builder **bb_r, uint32_t i);
97extern void cf_buf_builder_append_ascii_int(cf_buf_builder **bb_r, int i);
98// These append network-order bytes:
99extern void cf_buf_builder_append_uint64(cf_buf_builder **bb_r, uint64_t i);
100extern void cf_buf_builder_append_uint32(cf_buf_builder **bb_r, uint32_t i);
101extern void cf_buf_builder_append_uint16(cf_buf_builder **bb_r, uint16_t i);
102extern 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:
104extern void cf_buf_builder_reserve(cf_buf_builder **bb_r, int sz, uint8_t **buf);
105extern int cf_buf_builder_size(cf_buf_builder *bb);
106extern 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
111typedef 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
118typedef 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
132extern void cf_ll_buf_reserve(cf_ll_buf *llb, size_t sz, uint8_t **from);
133extern void cf_ll_buf_free(cf_ll_buf *llb);
134