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