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  */
134 qgrow_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  */
178 bool 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  */
193 bool 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  */
208 bool 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  */
229 size_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  */
241 size_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  */
258 void *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  */
276 char *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  */
285 void 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  */
299 bool 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  */
308 void qgrow_free(qgrow_t *grow) {
309  grow->list->free(grow->list);
310  free(grow);
311 }
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
bool qgrow_addstrf(qgrow_t *grow, const char *format,...)
qgrow->addstrf(): Stack formatted string
Definition: qgrow.c:208
char * qgrow_tostring(qgrow_t *grow)
qgrow->tostring(): Returns a string representation of this grow, containing string representation of ...
Definition: qgrow.c:276
qlist_t * qlist(int options)
Create new qlist_t linked-list container.
Definition: qlist.c:124
bool qgrow_addstr(qgrow_t *grow, const char *str)
qgrow->addstr(): Stack string
Definition: qgrow.c:193
void qgrow_free(qgrow_t *grow)
qgrow->free(): De-allocate grow
Definition: qgrow.c:308
void qgrow_clear(qgrow_t *grow)
qgrow->clear(): Removes all of the elements from this grow.
Definition: qgrow.c:285
bool qgrow_add(qgrow_t *grow, const void *data, size_t size)
qgrow->add(): Stack object
Definition: qgrow.c:178
qgrow_t * qgrow(int options)
Initialize grow.
Definition: qgrow.c:134
bool qgrow_debug(qgrow_t *grow, FILE *out)
qgrow->debug(): Print out stored elements for debugging purpose.
Definition: qgrow.c:299
size_t qgrow_size(qgrow_t *grow)
qgrow->size(): Returns the number of elements in this grow.
Definition: qgrow.c:229
size_t qgrow_datasize(qgrow_t *grow)
qgrow->datasize(): Returns the sum of total element size in this grow.
Definition: qgrow.c:241