/src/libplist/src/bytearray.c
Line | Count | Source |
1 | | /* |
2 | | * bytearray.c |
3 | | * simple byte array implementation |
4 | | * |
5 | | * Copyright (c) 2011 Nikias Bassen, All Rights Reserved. |
6 | | * |
7 | | * This library is free software; you can redistribute it and/or |
8 | | * modify it under the terms of the GNU Lesser General Public |
9 | | * License as published by the Free Software Foundation; either |
10 | | * version 2.1 of the License, or (at your option) any later version. |
11 | | * |
12 | | * This library is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | | * Lesser General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU Lesser General Public |
18 | | * License along with this library; if not, write to the Free Software |
19 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | | */ |
21 | | #include <string.h> |
22 | | #include "bytearray.h" |
23 | | |
24 | 0 | #define PAGE_SIZE 4096 |
25 | | |
26 | | bytearray_t *byte_array_new(size_t initial) |
27 | 0 | { |
28 | 0 | bytearray_t *a = (bytearray_t*)malloc(sizeof(bytearray_t)); |
29 | 0 | a->capacity = (initial > PAGE_SIZE) ? (initial+(PAGE_SIZE-1)) & (~(PAGE_SIZE-1)) : PAGE_SIZE; |
30 | 0 | a->data = malloc(a->capacity); |
31 | 0 | a->len = 0; |
32 | 0 | a->stream = NULL; |
33 | 0 | return a; |
34 | 0 | } |
35 | | |
36 | | bytearray_t *byte_array_new_for_stream(FILE *stream) |
37 | 0 | { |
38 | 0 | bytearray_t *a = (bytearray_t*)malloc(sizeof(bytearray_t)); |
39 | 0 | a->capacity = (size_t)-1; |
40 | 0 | a->data = NULL; |
41 | 0 | a->len = 0; |
42 | 0 | a->stream = stream; |
43 | 0 | return a; |
44 | 0 | } |
45 | | |
46 | | void byte_array_free(bytearray_t *ba) |
47 | 0 | { |
48 | 0 | if (!ba) return; |
49 | 0 | if (ba->data) { |
50 | 0 | free(ba->data); |
51 | 0 | } |
52 | 0 | free(ba); |
53 | 0 | } |
54 | | |
55 | | void byte_array_grow(bytearray_t *ba, size_t amount) |
56 | 0 | { |
57 | 0 | if (ba->stream) { |
58 | 0 | return; |
59 | 0 | } |
60 | 0 | size_t increase = (amount > PAGE_SIZE) ? (amount+(PAGE_SIZE-1)) & (~(PAGE_SIZE-1)) : PAGE_SIZE; |
61 | 0 | ba->data = realloc(ba->data, ba->capacity + increase); |
62 | 0 | ba->capacity += increase; |
63 | 0 | } |
64 | | |
65 | | void byte_array_append(bytearray_t *ba, void *buf, size_t len) |
66 | 0 | { |
67 | 0 | if (!ba || (!ba->stream && !ba->data) || (len <= 0)) return; |
68 | 0 | if (ba->stream) { |
69 | 0 | if (fwrite(buf, 1, len, ba->stream) < len) { |
70 | | #if DEBUG |
71 | | fprintf(stderr, "ERROR: Failed to write to stream.\n"); |
72 | | #endif |
73 | 0 | } |
74 | 0 | } else { |
75 | 0 | size_t remaining = ba->capacity-ba->len; |
76 | 0 | if (len > remaining) { |
77 | 0 | size_t needed = len - remaining; |
78 | 0 | byte_array_grow(ba, needed); |
79 | 0 | } |
80 | 0 | memcpy(((char*)ba->data) + ba->len, buf, len); |
81 | 0 | } |
82 | 0 | ba->len += len; |
83 | 0 | } |