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