1 | /* 2 | * Copyright (c) 2007-2014, Lloyd Hilaiel <me@lloyd.io> 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include "yajl_buf.h" 18 | 19 | #include <assert.h> 20 | #include <stdlib.h> 21 | #include <string.h> 22 | 23 | #define YAJL_BUF_INIT_SIZE 2048 24 | 25 | struct yajl_buf_t { 26 | size_t len; 27 | size_t used; 28 | unsigned char * data; 29 | yajl_alloc_funcs * alloc; 30 | }; 31 | 32 | static 33 | void yajl_buf_ensure_available(yajl_buf buf, size_t want) 34 | { 35 | size_t need; 36 | 37 | assert(buf != NULL); 38 | 39 | /* first call */ 40 | if (buf->data == NULL) { 41 | assert(buf->used == 0); 42 | buf->len = YAJL_BUF_INIT_SIZE; 43 | buf->data = (unsigned char *) YA_MALLOC(buf->alloc, buf->len); 44 | #if 0 45 | memset((void *) buf->data, 0, buf->len); 46 | #else /* it's really just a string, albiet UTF-8.... */ 47 | buf->data[0] = 0; 48 | #endif 49 | } 50 | 51 | need = buf->len; 52 | 53 | while (want >= (need - buf->used)) { 54 | need <<= 1; /* XXX maybe this is a bit too aggressive? */ 55 | } 56 | if (need != buf->len) { 57 | buf->data = (unsigned char *) YA_REALLOC(buf->alloc, buf->data, need); 58 | buf->len = need; 59 | } 60 | } 61 | 62 | /*+ allocate a new buffer +*/ 63 | yajl_buf yajl_buf_alloc(yajl_alloc_funcs * alloc) 64 | { 65 | yajl_buf b = YA_MALLOC(alloc, sizeof(struct yajl_buf_t)); 66 | memset((void *) b, 0, sizeof(struct yajl_buf_t)); 67 | b->alloc = alloc; 68 | return b; 69 | } 70 | 71 | /*+ free the buffer +*/ 72 | void yajl_buf_free(yajl_buf buf) 73 | { 74 | assert(buf != NULL); 75 | if (buf->data) { 76 | YA_FREE(buf->alloc, buf->data); 77 | } 78 | YA_FREE(buf->alloc, buf); 79 | } 80 | 81 | /*+ append a number of bytes to the buffer +*/ 82 | void yajl_buf_append(yajl_buf buf, const void * data, size_t len) 83 | { 84 | yajl_buf_ensure_available(buf, len); 85 | if (len > 0) { 86 | assert(data != NULL); 87 | memcpy(buf->data + buf->used, data, len); 88 | buf->used += len; 89 | buf->data[buf->used] = 0; 90 | } 91 | } 92 | 93 | /*+ empty the buffer +*/ 94 | void yajl_buf_clear(yajl_buf buf) 95 | { 96 | buf->used = 0; 97 | if (buf->data) { 98 | buf->data[buf->used] = 0; 99 | } 100 | } 101 | 102 | /*+ get a pointer to the beginning of the buffer +*/ 103 | const unsigned char * yajl_buf_data(yajl_buf buf) 104 | { 105 | return buf->data; 106 | } 107 | 108 | /*+ get the length of the buffer +*/ 109 | size_t yajl_buf_len(yajl_buf buf) 110 | { 111 | return buf->used; 112 | } 113 | 114 | /*+ truncate the buffer +*/ 115 | void 116 | yajl_buf_truncate(yajl_buf buf, size_t len) 117 | { 118 | assert(len <= buf->used); 119 | buf->used = len; 120 | }