1 /* 2 * Copyright (c) 2015, Juniper Networks, Inc. 3 * All rights reserved. 4 * This SOFTWARE is licensed under the LICENSE provided in the 5 * ../Copyright file. By downloading, installing, copying, or otherwise 6 * using the SOFTWARE, you agree to be bound by the terms of that 7 * LICENSE. 8 * Phil Shafer, August 2015 9 */ 10 11 /* 12 * This file is an _internal_ part of the libxo plumbing, not suitable 13 * for external use. It is not considered part of the libxo API and 14 * will not be a stable part of that API. Mine, not your's, dude... 15 * The real hope is that something like this will become a standard part 16 * of libc and I can kill this off. 17 */ 18 19 #ifndef XO_BUF_H 20 #define XO_BUF_H 21 22 #define XO_BUFSIZ (8*1024) /* Initial buffer size */ 23 24 /* 25 * xo_buffer_t: a memory buffer that can be grown as needed. We 26 * use them for building format strings and output data. 27 */ 28 typedef struct xo_buffer_s { 29 char *xb_bufp; /* Buffer memory */ 30 char *xb_curp; /* Current insertion point */ 31 unsigned xb_size; /* Size of buffer */ 32 } xo_buffer_t; 33 34 /* 35 * Initialize the contents of an xo_buffer_t. 36 */ 37 static inline void 38 xo_buf_init (xo_buffer_t *xbp) 39 { 40 xbp->xb_size = XO_BUFSIZ; 41 xbp->xb_bufp = xo_realloc(NULL, xbp->xb_size); 42 xbp->xb_curp = xbp->xb_bufp; 43 } 44 45 /* 46 * Reset the buffer to empty 47 */ 48 static inline void 49 xo_buf_reset (xo_buffer_t *xbp) 50 { 51 xbp->xb_curp = xbp->xb_bufp; 52 } 53 54 /* 55 * Return the number of bytes left in the buffer 56 */ 57 static inline int 58 xo_buf_left (xo_buffer_t *xbp) 59 { 60 return xbp->xb_size - (xbp->xb_curp - xbp->xb_bufp); 61 } 62 63 /* 64 * See if the buffer to empty 65 */ 66 static inline int 67 xo_buf_is_empty (xo_buffer_t *xbp) 68 { 69 return (xbp->xb_curp == xbp->xb_bufp); 70 } 71 72 /* 73 * Return the current offset 74 */ 75 static inline unsigned 76 xo_buf_offset (xo_buffer_t *xbp) 77 { 78 return xbp ? (xbp->xb_curp - xbp->xb_bufp) : 0; 79 } 80 81 static inline char * 82 xo_buf_data (xo_buffer_t *xbp, unsigned offset) 83 { 84 if (xbp == NULL) 85 return NULL; 86 return xbp->xb_bufp + offset; 87 } 88 89 static inline char * 90 xo_buf_cur (xo_buffer_t *xbp) 91 { 92 if (xbp == NULL) 93 return NULL; 94 return xbp->xb_curp; 95 } 96 97 /* 98 * Initialize the contents of an xo_buffer_t. 99 */ 100 static inline void 101 xo_buf_cleanup (xo_buffer_t *xbp) 102 { 103 if (xbp->xb_bufp) 104 xo_free(xbp->xb_bufp); 105 bzero(xbp, sizeof(*xbp)); 106 } 107 108 /* 109 * Does the buffer have room for the given number of bytes of data? 110 * If not, realloc the buffer to make room. If that fails, we 111 * return 0 to tell the caller they are in trouble. 112 */ 113 static inline int 114 xo_buf_has_room (xo_buffer_t *xbp, int len) 115 { 116 if (xbp->xb_curp + len >= xbp->xb_bufp + xbp->xb_size) { 117 int sz = xbp->xb_size + XO_BUFSIZ; 118 char *bp = xo_realloc(xbp->xb_bufp, sz); 119 if (bp == NULL) 120 return 0; 121 122 xbp->xb_curp = bp + (xbp->xb_curp - xbp->xb_bufp); 123 xbp->xb_bufp = bp; 124 xbp->xb_size = sz; 125 } 126 127 return 1; 128 } 129 130 /* 131 * Append the given string to the given buffer 132 */ 133 static inline void 134 xo_buf_append (xo_buffer_t *xbp, const char *str, int len) 135 { 136 if (!xo_buf_has_room(xbp, len)) 137 return; 138 139 memcpy(xbp->xb_curp, str, len); 140 xbp->xb_curp += len; 141 } 142 143 /* 144 * Append the given NUL-terminated string to the given buffer 145 */ 146 static inline void 147 xo_buf_append_str (xo_buffer_t *xbp, const char *str) 148 { 149 int len = strlen(str); 150 151 if (!xo_buf_has_room(xbp, len)) 152 return; 153 154 memcpy(xbp->xb_curp, str, len); 155 xbp->xb_curp += len; 156 } 157 158 #endif /* XO_BUF_H */ 159