| 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 |  | 
|---|