/src/jansson-2.14/src/strbuffer.c
Line | Count | Source |
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 "strbuffer.h" |
13 | | #include "jansson_private.h" |
14 | | #include <stdlib.h> |
15 | | #include <string.h> |
16 | | |
17 | 1 | #define STRBUFFER_MIN_SIZE 16 |
18 | 0 | #define STRBUFFER_FACTOR 2 |
19 | 0 | #define STRBUFFER_SIZE_MAX ((size_t)-1) |
20 | | |
21 | 1 | int strbuffer_init(strbuffer_t *strbuff) { |
22 | 1 | strbuff->size = STRBUFFER_MIN_SIZE; |
23 | 1 | strbuff->length = 0; |
24 | | |
25 | 1 | strbuff->value = jsonp_malloc(strbuff->size); |
26 | 1 | if (!strbuff->value) |
27 | 0 | return -1; |
28 | | |
29 | | /* initialize to empty */ |
30 | 1 | strbuff->value[0] = '\0'; |
31 | 1 | return 0; |
32 | 1 | } |
33 | | |
34 | 1 | void strbuffer_close(strbuffer_t *strbuff) { |
35 | 1 | if (strbuff->value) |
36 | 1 | jsonp_free(strbuff->value); |
37 | | |
38 | 1 | strbuff->size = 0; |
39 | 1 | strbuff->length = 0; |
40 | 1 | strbuff->value = NULL; |
41 | 1 | } |
42 | | |
43 | 1 | void strbuffer_clear(strbuffer_t *strbuff) { |
44 | 1 | strbuff->length = 0; |
45 | 1 | strbuff->value[0] = '\0'; |
46 | 1 | } |
47 | | |
48 | 1 | const char *strbuffer_value(const strbuffer_t *strbuff) { return strbuff->value; } |
49 | | |
50 | 0 | char *strbuffer_steal_value(strbuffer_t *strbuff) { |
51 | 0 | char *result = strbuff->value; |
52 | 0 | strbuff->value = NULL; |
53 | 0 | return result; |
54 | 0 | } |
55 | | |
56 | 0 | int strbuffer_append_byte(strbuffer_t *strbuff, char byte) { |
57 | 0 | return strbuffer_append_bytes(strbuff, &byte, 1); |
58 | 0 | } |
59 | | |
60 | 0 | int strbuffer_append_bytes(strbuffer_t *strbuff, const char *data, size_t size) { |
61 | 0 | if (size >= strbuff->size - strbuff->length) { |
62 | 0 | size_t new_size; |
63 | 0 | char *new_value; |
64 | | |
65 | | /* avoid integer overflow */ |
66 | 0 | if (strbuff->size > STRBUFFER_SIZE_MAX / STRBUFFER_FACTOR || |
67 | 0 | size > STRBUFFER_SIZE_MAX - 1 || |
68 | 0 | strbuff->length > STRBUFFER_SIZE_MAX - 1 - size) |
69 | 0 | return -1; |
70 | | |
71 | 0 | new_size = max(strbuff->size * STRBUFFER_FACTOR, strbuff->length + size + 1); |
72 | |
|
73 | 0 | new_value = jsonp_malloc(new_size); |
74 | 0 | if (!new_value) |
75 | 0 | return -1; |
76 | | |
77 | 0 | memcpy(new_value, strbuff->value, strbuff->length); |
78 | |
|
79 | 0 | jsonp_free(strbuff->value); |
80 | 0 | strbuff->value = new_value; |
81 | 0 | strbuff->size = new_size; |
82 | 0 | } |
83 | | |
84 | 0 | memcpy(strbuff->value + strbuff->length, data, size); |
85 | 0 | strbuff->length += size; |
86 | 0 | strbuff->value[strbuff->length] = '\0'; |
87 | |
|
88 | 0 | return 0; |
89 | 0 | } |
90 | | |
91 | 0 | char strbuffer_pop(strbuffer_t *strbuff) { |
92 | 0 | if (strbuff->length > 0) { |
93 | 0 | char c = strbuff->value[--strbuff->length]; |
94 | 0 | strbuff->value[strbuff->length] = '\0'; |
95 | 0 | return c; |
96 | 0 | } else |
97 | 0 | return '\0'; |
98 | 0 | } |