1 /*
2 * Copyright (c) 2015-2017 Red Hat, Inc.
3 *
4 * All rights reserved.
5 *
6 * Author: Jan Friesse (jfriesse@redhat.com)
7 *
8 * This software licensed under BSD license, the text of which follows:
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are met:
12 *
13 * - Redistributions of source code must retain the above copyright notice,
14 * this list of conditions and the following disclaimer.
15 * - Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 * - Neither the name of the Red Hat, Inc. nor the names of its
19 * contributors may be used to endorse or promote products derived from this
20 * software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32 * THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 #include <sys/types.h>
36
37 #include <stdlib.h>
38 #include <string.h>
39
40 #include "dynar.h"
41
42 void
dynar_init(struct dynar * array,size_t maximum_size)43 dynar_init(struct dynar *array, size_t maximum_size)
44 {
45
46 memset(array, 0, sizeof(*array));
47 array->maximum_size = maximum_size;
48 }
49
50 void
dynar_set_max_size(struct dynar * array,size_t maximum_size)51 dynar_set_max_size(struct dynar *array, size_t maximum_size)
52 {
53
54 array->maximum_size = maximum_size;
55 }
56
57 int
dynar_set_size(struct dynar * array,size_t size)58 dynar_set_size(struct dynar *array, size_t size)
59 {
60
61 if (size > dynar_max_size(array)) {
62 dynar_set_max_size(array, size);
63 }
64
65 if (size > dynar_size(array)) {
66 if (dynar_prealloc(array, size - dynar_size(array)) == -1) {
67 return (-1);
68 }
69 }
70
71 array->size = size;
72
73 return (0);
74 }
75
76 void
dynar_destroy(struct dynar * array)77 dynar_destroy(struct dynar *array)
78 {
79
80 free(array->data);
81 dynar_init(array, array->maximum_size);
82 }
83
84 void
dynar_clean(struct dynar * array)85 dynar_clean(struct dynar *array)
86 {
87
88 array->size = 0;
89 }
90
91 size_t
dynar_size(const struct dynar * array)92 dynar_size(const struct dynar *array)
93 {
94
95 return (array->size);
96 }
97
98 size_t
dynar_max_size(const struct dynar * array)99 dynar_max_size(const struct dynar *array)
100 {
101
102 return (array->maximum_size);
103 }
104
105 char *
dynar_data(const struct dynar * array)106 dynar_data(const struct dynar *array)
107 {
108
109 return (array->data);
110 }
111
112 static int
dynar_realloc(struct dynar * array,size_t new_array_size)113 dynar_realloc(struct dynar *array, size_t new_array_size)
114 {
115 char *new_data;
116
117 if (new_array_size > array->maximum_size) {
118 return (-1);
119 }
120
121 new_data = realloc(array->data, new_array_size);
122
123 if (new_data == NULL) {
124 return (-1);
125 }
126
127 array->allocated = new_array_size;
128 array->data = new_data;
129
130 return (0);
131 }
132
133 int
dynar_prealloc(struct dynar * array,size_t size)134 dynar_prealloc(struct dynar *array, size_t size)
135 {
136 size_t new_size;
137
138 if (array->size + size > array->maximum_size) {
139 return (-1);
140 }
141
142 if (array->size + size > array->allocated) {
143 new_size = (array->allocated + size) * 2;
144 if (new_size > array->maximum_size) {
145 new_size = array->maximum_size;
146 }
147
148 if (dynar_realloc(array, new_size) == -1) {
149 return (-1);
150 }
151 }
152
153 return (0);
154 }
155
156 int
dynar_cat(struct dynar * array,const void * src,size_t size)157 dynar_cat(struct dynar *array, const void *src, size_t size)
158 {
159
160 if (dynar_prealloc(array, size) != 0) {
161 return (-1);
162 }
163
164 memmove(array->data + array->size, src, size);
165 array->size += size;
166
167 return (0);
168 }
169
170 int
dynar_prepend(struct dynar * array,const void * src,size_t size)171 dynar_prepend(struct dynar *array, const void *src, size_t size)
172 {
173
174 if (dynar_prealloc(array, size) != 0) {
175 return (-1);
176 }
177
178 memmove(array->data + size, array->data, array->size);
179 memmove(array->data, src, size);
180 array->size += size;
181
182 return (0);
183 }
184