1/* 2 * Copyright (c) 2009-2014 Petri Lehtinen <petri@digip.org> 3 * 4 * Jansson is free software; you can redistribute it and/or modify 5 * it under the terms of the MIT license. See LICENSE for details. 6 */ 7 8#ifndef _GNU_SOURCE 9#define _GNU_SOURCE 10#endif 11 12#include <stdlib.h> 13#include <string.h> 14#include "jansson_private.h" 15#include "strbuffer.h" 16 17#define STRBUFFER_MIN_SIZE 16 18#define STRBUFFER_FACTOR 2 19#define STRBUFFER_SIZE_MAX ((size_t)-1) 20 21int strbuffer_init(strbuffer_t *strbuff) 22{ 23 strbuff->size = STRBUFFER_MIN_SIZE; 24 strbuff->length = 0; 25 26 strbuff->value = jsonp_malloc(strbuff->size); 27 if(!strbuff->value) 28 return -1; 29 30 /* initialize to empty */ 31 strbuff->value[0] = '\0'; 32 return 0; 33} 34 35void strbuffer_close(strbuffer_t *strbuff) 36{ 37 if(strbuff->value) 38 jsonp_free(strbuff->value); 39 40 strbuff->size = 0; 41 strbuff->length = 0; 42 strbuff->value = NULL; 43} 44 45void strbuffer_clear(strbuffer_t *strbuff) 46{ 47 strbuff->length = 0; 48 strbuff->value[0] = '\0'; 49} 50 51const char *strbuffer_value(const strbuffer_t *strbuff) 52{ 53 return strbuff->value; 54} 55 56char *strbuffer_steal_value(strbuffer_t *strbuff) 57{ 58 char *result = strbuff->value; 59 strbuff->value = NULL; 60 return result; 61} 62 63int strbuffer_append(strbuffer_t *strbuff, const char *string) 64{ 65 return strbuffer_append_bytes(strbuff, string, strlen(string)); 66} 67 68int strbuffer_append_byte(strbuffer_t *strbuff, char byte) 69{ 70 return strbuffer_append_bytes(strbuff, &byte, 1); 71} 72 73int strbuffer_append_bytes(strbuffer_t *strbuff, const char *data, size_t size) 74{ 75 if(size >= strbuff->size - strbuff->length) 76 { 77 size_t new_size; 78 char *new_value; 79 80 /* avoid integer overflow */ 81 if (strbuff->size > STRBUFFER_SIZE_MAX / STRBUFFER_FACTOR 82 || size > STRBUFFER_SIZE_MAX - 1 83 || strbuff->length > STRBUFFER_SIZE_MAX - 1 - size) 84 return -1; 85 86 new_size = max(strbuff->size * STRBUFFER_FACTOR, 87 strbuff->length + size + 1); 88 89 new_value = jsonp_malloc(new_size); 90 if(!new_value) 91 return -1; 92 93 memcpy(new_value, strbuff->value, strbuff->length); 94 95 jsonp_free(strbuff->value); 96 strbuff->value = new_value; 97 strbuff->size = new_size; 98 } 99 100 memcpy(strbuff->value + strbuff->length, data, size); 101 strbuff->length += size; 102 strbuff->value[strbuff->length] = '\0'; 103 104 return 0; 105} 106 107char strbuffer_pop(strbuffer_t *strbuff) 108{ 109 if(strbuff->length > 0) { 110 char c = strbuff->value[--strbuff->length]; 111 strbuff->value[strbuff->length] = '\0'; 112 return c; 113 } 114 else 115 return '\0'; 116} 117