1 /*
2 * Copyright (c) 2014 Jerry Lundström <lundstrom.jerry@gmail.com>
3 * Copyright (c) 2014 .SE (The Internet Infrastructure Foundation).
4 * Copyright (c) 2014 OpenDNSSEC AB (svb)
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
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
24 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29
30 #include "db_result.h"
31 #include "db_error.h"
32
33
34 /* DB RESULT */
35
36
37
db_result_new(void)38 db_result_t* db_result_new(void) {
39 db_result_t* result =
40 (db_result_t*)calloc(1, sizeof(db_result_t));
41
42 return result;
43 }
44
45 /* TODO: unit test */
db_result_new_copy(const db_result_t * from_result)46 db_result_t* db_result_new_copy(const db_result_t* from_result) {
47 db_result_t* result;
48
49 if (!from_result) {
50 return NULL;
51 }
52
53 if ((result = db_result_new())) {
54 if (db_result_copy(result, from_result)) {
55 db_result_free(result);
56 return NULL;
57 }
58 }
59
60 return result;
61 }
62
db_result_free(db_result_t * result)63 void db_result_free(db_result_t* result) {
64 if (result) {
65 if (result->value_set) {
66 db_value_set_free(result->value_set);
67 }
68 free(result);
69 }
70 }
71
72 /* TODO: unit test */
db_result_copy(db_result_t * result,const db_result_t * from_result)73 int db_result_copy(db_result_t* result, const db_result_t* from_result) {
74 db_value_set_t* value_set = NULL;
75
76 if (!result) {
77 return DB_ERROR_UNKNOWN;
78 }
79 if (!from_result) {
80 return DB_ERROR_UNKNOWN;
81 }
82
83 if (from_result->value_set
84 && !(value_set = db_value_set_new_copy(from_result->value_set)))
85 {
86 return DB_ERROR_UNKNOWN;
87 }
88
89 if (result->value_set) {
90 db_value_set_free(result->value_set);
91 }
92 result->value_set = value_set;
93
94 return DB_OK;
95 }
96
db_result_value_set(const db_result_t * result)97 const db_value_set_t* db_result_value_set(const db_result_t* result) {
98 if (!result) {
99 return NULL;
100 }
101
102 return result->value_set;
103 }
104
db_result_set_value_set(db_result_t * result,db_value_set_t * value_set)105 int db_result_set_value_set(db_result_t* result, db_value_set_t* value_set) {
106 if (!result) {
107 return DB_ERROR_UNKNOWN;
108 }
109 if (!value_set) {
110 return DB_ERROR_UNKNOWN;
111 }
112 if (result->value_set) {
113 return DB_ERROR_UNKNOWN;
114 }
115
116 result->value_set = value_set;
117 return DB_OK;
118 }
119
db_result_not_empty(const db_result_t * result)120 int db_result_not_empty(const db_result_t* result) {
121 if (!result) {
122 return DB_ERROR_UNKNOWN;
123 }
124 if (!result->value_set) {
125 return DB_ERROR_UNKNOWN;
126 }
127 return DB_OK;
128 }
129
130 /* DB RESULT LIST */
131
132
133
db_result_list_new(void)134 db_result_list_t* db_result_list_new(void) {
135 db_result_list_t* result_list =
136 (db_result_list_t*)calloc(1, sizeof(db_result_list_t));
137
138 return result_list;
139 }
140
141 /* TODO: unit test */
db_result_list_new_copy(const db_result_list_t * from_result_list)142 db_result_list_t* db_result_list_new_copy(const db_result_list_t* from_result_list) {
143 db_result_list_t* result_list;
144
145 if (!from_result_list) {
146 return NULL;
147 }
148
149 result_list = (db_result_list_t*)calloc(1, sizeof(db_result_list_t));
150 if (result_list) {
151 if (db_result_list_copy(result_list, from_result_list)) {
152 db_result_list_free(result_list);
153 return NULL;
154 }
155 }
156
157 return result_list;
158 }
159
db_result_list_free(db_result_list_t * result_list)160 void db_result_list_free(db_result_list_t* result_list) {
161 if (result_list) {
162 if (result_list->begin) {
163 db_result_t* this = result_list->begin;
164 db_result_t* next = NULL;
165
166 while (this) {
167 next = this->next;
168 db_result_free(this);
169 this = next;
170 }
171 }
172 if (result_list->next_function) {
173 (void)result_list->next_function(result_list->next_data, 1);
174 if (result_list->current) {
175 db_result_free(result_list->current);
176 }
177 }
178 free(result_list);
179 }
180 }
181
182 /* TODO: unit test */
db_result_list_copy(db_result_list_t * result_list,const db_result_list_t * from_result_list)183 int db_result_list_copy(db_result_list_t* result_list, const db_result_list_t* from_result_list) {
184 db_result_t* result;
185 db_result_t* result_copy;
186
187 if (!result_list) {
188 return DB_ERROR_UNKNOWN;
189 }
190 /*
191 * TODO: Should we be able to copy into a result list that already contains
192 * data?
193 */
194 if (result_list->begin) {
195 return DB_ERROR_UNKNOWN;
196 }
197 if (result_list->end) {
198 return DB_ERROR_UNKNOWN;
199 }
200 if (result_list->current) {
201 return DB_ERROR_UNKNOWN;
202 }
203 if (result_list->size) {
204 return DB_ERROR_UNKNOWN;
205 }
206 if (result_list->next_function) {
207 return DB_ERROR_UNKNOWN;
208 }
209 if (!from_result_list) {
210 return DB_ERROR_UNKNOWN;
211 }
212 if (from_result_list->next_function) {
213 return DB_ERROR_UNKNOWN;
214 }
215
216 result = from_result_list->begin;
217 while (result) {
218 if (!(result_copy = db_result_new_copy(result))
219 || db_result_list_add(result_list, result_copy))
220 {
221 return DB_ERROR_UNKNOWN;
222 }
223
224 if (result == from_result_list->current) {
225 result_list->current = result_copy;
226 }
227
228 result = result->next;
229 }
230
231 return DB_OK;
232 }
233
db_result_list_set_next(db_result_list_t * result_list,db_result_list_next_t next_function,void * next_data,size_t size)234 int db_result_list_set_next(db_result_list_t* result_list, db_result_list_next_t next_function, void* next_data, size_t size) {
235 if (!result_list) {
236 return DB_ERROR_UNKNOWN;
237 }
238 if (result_list->begin) {
239 return DB_ERROR_UNKNOWN;
240 }
241 if (result_list->next_function) {
242 return DB_ERROR_UNKNOWN;
243 }
244 if (!next_data) {
245 return DB_ERROR_UNKNOWN;
246 }
247 if (result_list->next_data) {
248 return DB_ERROR_UNKNOWN;
249 }
250
251 result_list->next_function = next_function;
252 result_list->next_data = next_data;
253 result_list->size = size;
254 return 0;
255 }
256
db_result_list_add(db_result_list_t * result_list,db_result_t * result)257 int db_result_list_add(db_result_list_t* result_list, db_result_t* result) {
258 if (!result_list) {
259 return DB_ERROR_UNKNOWN;
260 }
261 if (!result) {
262 return DB_ERROR_UNKNOWN;
263 }
264 if (db_result_not_empty(result)) {
265 return DB_ERROR_UNKNOWN;
266 }
267 if (result->next) {
268 return DB_ERROR_UNKNOWN;
269 }
270 if (result_list->next_function) {
271 return DB_ERROR_UNKNOWN;
272 }
273
274 if (result_list->begin) {
275 if (!result_list->end) {
276 return DB_ERROR_UNKNOWN;
277 }
278 result_list->end->next = result;
279 result_list->end = result;
280 }
281 else {
282 result_list->begin = result;
283 result_list->end = result;
284 }
285 result_list->size++;
286
287 return DB_OK;
288 }
289
db_result_list_begin(db_result_list_t * result_list)290 const db_result_t* db_result_list_begin(db_result_list_t* result_list) {
291 if (!result_list) {
292 return NULL;
293 }
294 if (result_list->next_function) {
295 /*
296 * Can not start over a list that uses next function
297 */
298 if (result_list->current) {
299 return NULL;
300 }
301 result_list->current = result_list->next_function(result_list->next_data, 0);
302 return result_list->current;
303 }
304
305 result_list->current = result_list->begin;
306 result_list->begun = 1;
307 return result_list->current;
308 }
309
db_result_list_next(db_result_list_t * result_list)310 const db_result_t* db_result_list_next(db_result_list_t* result_list) {
311 if (!result_list) {
312 return NULL;
313 }
314
315 if (result_list->next_function) {
316 if (result_list->current) {
317 db_result_free(result_list->current);
318 }
319 result_list->current = result_list->next_function(result_list->next_data, 0);
320 return result_list->current;
321 }
322
323 if (!result_list->begun) {
324 result_list->begun = 1;
325 result_list->current = result_list->begin;
326 }
327 else if (result_list->current) {
328 result_list->current = result_list->current->next;
329 }
330 return result_list->current;
331 }
332
db_result_list_size(const db_result_list_t * result_list)333 size_t db_result_list_size(const db_result_list_t* result_list) {
334 if (!result_list) {
335 return 0;
336 }
337
338 return result_list->size;
339 }
340
db_result_list_fetch_all(db_result_list_t * result_list)341 int db_result_list_fetch_all(db_result_list_t* result_list) {
342 db_result_t* result;
343 db_result_list_next_t next_function;
344
345 if (!result_list) {
346 return DB_ERROR_UNKNOWN;
347 }
348
349 if (result_list->next_function) {
350 if (result_list->current) {
351 return DB_ERROR_UNKNOWN;
352 }
353
354 next_function = result_list->next_function;
355 result_list->next_function = NULL;
356 result_list->size = 0;
357
358 while ((result = next_function(result_list->next_data, 0))) {
359 if (db_result_list_add(result_list, result)) {
360 next_function(result_list->next_data, 1);
361 result_list->next_data = NULL;
362 db_result_free(result);
363 return DB_ERROR_UNKNOWN;
364 }
365 }
366 next_function(result_list->next_data, 1);
367 result_list->next_data = NULL;
368 }
369
370 return DB_OK;
371 }
372