qLibc
qgrow.c
Go to the documentation of this file.
1/******************************************************************************
2 * qLibc
3 *
4 * Copyright (c) 2010-2015 Seungyoung Kim.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 *****************************************************************************/
28
29/**
30 * @file qgrow.c Grow container that handles growable objects.
31 *
32 * qgrow container is a grow implementation. It implements a growable array
33 * of objects and it extends qlist container that allow a linked-list to be
34 * treated as a grow.
35 *
36 * @code
37 * [Code sample - Object]
38 * qgrow_t *grow = qgrow(QGROW_THREADSAFE);
39 *
40 * // add elements
41 * grow->addstr(grow, "AB"); // no need to supply size
42 * grow->addstrf(grow, "%d", 12); // for formatted string
43 * grow->addstr(grow, "CD");
44 *
45 * // get the chunk as a string
46 * char *final = grow->tostring(grow);
47 *
48 * // print out
49 * printf("Number of elements = %zu\n", grow->size(grow));
50 * printf("Final string = %s\n", final);
51 *
52 * // release
53 * free(final);
54 * grow->free(grow);
55 *
56 * [Result]
57 * Number of elements = 3
58 * Final string = AB12CD
59 * @endcode
60 *
61 * @code
62 * [Code sample - Object]
63 * // sample object
64 * struct sampleobj {
65 * int num;
66 * char str[10];
67 * };
68 *
69 * // get new grow
70 * qgrow_t *grow = qgrow();
71 *
72 * // add objects
73 * int i;
74 * struct sampleobj obj;
75 * for(i = 0; i < 3; i++) {
76 * // filling object with sample data
77 * obj.num = i;
78 * sprintf(obj.str, "hello%d", i);
79 *
80 * // stack
81 * grow->add(grow, (void *)&obj, sizeof(struct sampleobj));
82 * }
83 *
84 * // final
85 * struct sampleobj *final;
86 * final = (struct sampleobj *)grow->toarray(grow, NULL);
87 *
88 * // print out
89 * printf("Number of Objects = %zu\n", grow->size(grow));
90 * for(i = 0; i < grow->size(grow); i++) {
91 * printf("Object%d %d, %s\n", i+1, final[i].num, final[i].str);
92 * }
93 *
94 * // release
95 * free(final);
96 * grow->free(grow);
97 *
98 * [Result]
99 * Number of Objects = 3
100 * Object1 0, hello0
101 * Object2 1, hello1
102 * Object3 2, hello2
103 * @endcode
104 */
105
106#include <stdio.h>
107#include <stdlib.h>
108#include <stdbool.h>
109#include <stdarg.h>
110#include <string.h>
111#include <errno.h>
112#include "qinternal.h"
113#include "containers/qgrow.h"
114
115/**
116 * Initialize grow.
117 *
118 * @param options combination of initialization options.
119 *
120 * @return qgrow_t container pointer.
121 * @retval errno will be set in error condition.
122 * - ENOMEM : Memory allocation failure.
123 *
124 * @code
125 * // allocate memory
126 * qgrow_t *grow = qgrow(QGROW_THREADSAFE);
127 * grow->free(grow);
128 * @endcode
129 *
130 * @note
131 * Available options:
132 * - QGROW_THREADSAFE - make it thread-safe.
133 */
134qgrow_t *qgrow(int options) {
135 qgrow_t *grow = (qgrow_t *) calloc(1, sizeof(qgrow_t));
136 if (grow == NULL) {
137 errno = ENOMEM;
138 return NULL;
139 }
140
141 grow->list = qlist(options);
142 if (grow->list == NULL) {
143 free(grow);
144 errno = ENOMEM;
145 return NULL;
146 }
147
148 // methods
149 grow->add = qgrow_add;
150 grow->addstr = qgrow_addstr;
151 grow->addstrf = qgrow_addstrf;
152
153 grow->size = qgrow_size;
154 grow->datasize = qgrow_datasize;
155
156 grow->toarray = qgrow_toarray;
157 grow->tostring = qgrow_tostring;
158
159 grow->clear = qgrow_clear;
160 grow->debug = qgrow_debug;
161 grow->free = qgrow_free;
162
163 return grow;
164}
165
166/**
167 * qgrow->add(): Stack object
168 *
169 * @param grow qgrow_t container pointer.
170 * @param object a pointer of object data
171 * @param size size of object
172 *
173 * @return true if successful, otherwise returns false
174 * @retval errno will be set in error condition.
175 * - EINVAL : Invalid argument.
176 * - ENOMEM : Memory allocation failure.
177 */
178bool qgrow_add(qgrow_t *grow, const void *data, size_t size) {
179 return grow->list->addlast(grow->list, data, size);
180}
181
182/**
183 * qgrow->addstr(): Stack string
184 *
185 * @param grow qgrow_t container pointer.
186 * @param str a pointer of string
187 *
188 * @return true if successful, otherwise returns false
189 * @retval errno will be set in error condition.
190 * - EINVAL : Invalid argument.
191 * - ENOMEM : Memory allocation failure.
192 */
193bool qgrow_addstr(qgrow_t *grow, const char *str) {
194 return grow->list->addlast(grow->list, str, strlen(str));
195}
196
197/**
198 * qgrow->addstrf(): Stack formatted string
199 *
200 * @param grow qgrow_t container pointer.
201 * @param format string format
202 *
203 * @return true if successful, otherwise returns false
204 * @retval errno will be set in error condition.
205 * - EINVAL : Invalid argument.
206 * - ENOMEM : Memory allocation failure.
207 */
208bool qgrow_addstrf(qgrow_t *grow, const char *format, ...) {
209 char *str;
210 DYNAMIC_VSPRINTF(str, format);
211 if (str == NULL) {
212 errno = ENOMEM;
213 return false;
214 }
215
216 bool ret = qgrow_addstr(grow, str);
217 free(str);
218
219 return ret;
220}
221
222/**
223 * qgrow->size(): Returns the number of elements in this grow.
224 *
225 * @param grow qgrow_t container pointer.
226 *
227 * @return the number of elements in this grow.
228 */
229size_t qgrow_size(qgrow_t *grow) {
230 return grow->list->size(grow->list);
231}
232
233/**
234 * qgrow->datasize(): Returns the sum of total element size in this
235 * grow.
236 *
237 * @param grow qgrow_t container pointer.
238 *
239 * @return the sum of total element size in this grow.
240 */
241size_t qgrow_datasize(qgrow_t *grow) {
242 return grow->list->datasize(grow->list);
243}
244
245/**
246 * qgrow->toarray(): Returns the serialized chunk containing all the
247 * elements in this grow.
248 *
249 * @param grow qgrow_t container pointer.
250 * @param size if size is not NULL, merged object size will be stored.
251 *
252 * @return a pointer of finally merged elements(malloced), otherwise returns
253 * NULL
254 * @retval errno will be set in error condition.
255 * - ENOENT : empty.
256 * - ENOMEM : Memory allocation failure.
257 */
258void *qgrow_toarray(qgrow_t *grow, size_t *size) {
259 return grow->list->toarray(grow->list, size);
260}
261
262/**
263 * qgrow->tostring(): Returns a string representation of this grow,
264 * containing string representation of each element.
265 *
266 * @param grow qgrow_t container pointer.
267 *
268 * @return a pointer of finally merged strings(malloced), otherwise returns NULL
269 * @retval errno will be set in error condition.
270 * - ENOENT : empty.
271 * - ENOMEM : Memory allocation failure.
272 *
273 * @note
274 * Return string is always terminated by '\0'.
275 */
276char *qgrow_tostring(qgrow_t *grow) {
277 return grow->list->tostring(grow->list);
278}
279
280/**
281 * qgrow->clear(): Removes all of the elements from this grow.
282 *
283 * @param grow qgrow_t container pointer.
284 */
285void qgrow_clear(qgrow_t *grow) {
286 grow->list->clear(grow->list);
287}
288
289/**
290 * qgrow->debug(): Print out stored elements for debugging purpose.
291 *
292 * @param grow qgrow_t container pointer.
293 * @param out output stream FILE descriptor such like stdout, stderr.
294 *
295 * @return true if successful, otherwise returns false.
296 * @retval errno will be set in error condition.
297 * - EIO : Invalid output stream.
298 */
299bool qgrow_debug(qgrow_t *grow, FILE *out) {
300 return grow->list->debug(grow->list, out);
301}
302
303/**
304 * qgrow->free(): De-allocate grow
305 *
306 * @param grow qgrow_t container pointer.
307 */
308void qgrow_free(qgrow_t *grow) {
309 grow->list->free(grow->list);
310 free(grow);
311}
void qgrow_free(qgrow_t *grow)
qgrow->free(): De-allocate grow
Definition qgrow.c:308
bool qgrow_debug(qgrow_t *grow, FILE *out)
qgrow->debug(): Print out stored elements for debugging purpose.
Definition qgrow.c:299
bool qgrow_addstr(qgrow_t *grow, const char *str)
qgrow->addstr(): Stack string
Definition qgrow.c:193
bool qgrow_add(qgrow_t *grow, const void *data, size_t size)
qgrow->add(): Stack object
Definition qgrow.c:178
size_t qgrow_size(qgrow_t *grow)
qgrow->size(): Returns the number of elements in this grow.
Definition qgrow.c:229
qgrow_t * qgrow(int options)
Initialize grow.
Definition qgrow.c:134
bool qgrow_addstrf(qgrow_t *grow, const char *format,...)
qgrow->addstrf(): Stack formatted string
Definition qgrow.c:208
void qgrow_clear(qgrow_t *grow)
qgrow->clear(): Removes all of the elements from this grow.
Definition qgrow.c:285
char * qgrow_tostring(qgrow_t *grow)
qgrow->tostring(): Returns a string representation of this grow, containing string representation of ...
Definition qgrow.c:276
void * qgrow_toarray(qgrow_t *grow, size_t *size)
qgrow->toarray(): Returns the serialized chunk containing all the elements in this grow.
Definition qgrow.c:258
size_t qgrow_datasize(qgrow_t *grow)
qgrow->datasize(): Returns the sum of total element size in this grow.
Definition qgrow.c:241
qlist_t * qlist(int options)
Create new qlist_t linked-list container.
Definition qlist.c:124