1/*
2 * Copyright (c) 2009-2012 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 jsonp_free(strbuff->value);
38 strbuff->size = 0;
39 strbuff->length = 0;
40 strbuff->value = NULL;
41}
42
43void strbuffer_clear(strbuffer_t *strbuff)
44{
45 strbuff->length = 0;
46 strbuff->value[0] = '\0';
47}
48
49const char *strbuffer_value(const strbuffer_t *strbuff)
50{
51 return strbuff->value;
52}
53
54char *strbuffer_steal_value(strbuffer_t *strbuff)
55{
56 char *result = strbuff->value;
57 strbuffer_init(strbuff);
58 return result;
59}
60
61int strbuffer_append(strbuffer_t *strbuff, const char *string)
62{
63 return strbuffer_append_bytes(strbuff, string, strlen(string));
64}
65
66int strbuffer_append_byte(strbuffer_t *strbuff, char byte)
67{
68 return strbuffer_append_bytes(strbuff, &byte, 1);
69}
70
71int strbuffer_append_bytes(strbuffer_t *strbuff, const char *data, size_t size)
72{
73 if(size >= strbuff->size - strbuff->length)
74 {
75 size_t new_size;
76 char *new_value;
77
78 /* avoid integer overflow */
79 if (strbuff->size > STRBUFFER_SIZE_MAX / STRBUFFER_FACTOR
80 || size > STRBUFFER_SIZE_MAX - 1
81 || strbuff->length > STRBUFFER_SIZE_MAX - 1 - size)
82 return -1;
83
84 new_size = max(strbuff->size * STRBUFFER_FACTOR,
85 strbuff->length + size + 1);
86
87 new_value = jsonp_malloc(new_size);
88 if(!new_value)
89 return -1;
90
91 memcpy(new_value, strbuff->value, strbuff->length);
92
93 jsonp_free(strbuff->value);
94 strbuff->value = new_value;
95 strbuff->size = new_size;
96 }
97
98 memcpy(strbuff->value + strbuff->length, data, size);
99 strbuff->length += size;
100 strbuff->value[strbuff->length] = '\0';
101
102 return 0;
103}
104
105char strbuffer_pop(strbuffer_t *strbuff)
106{
107 if(strbuff->length > 0) {
108 char c = strbuff->value[--strbuff->length];
109 strbuff->value[strbuff->length] = '\0';
110 return c;
111 }
112 else
113 return '\0';
114}
115