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_value.h"
31 #include "db_error.h"
32 
33 
34 #include <string.h>
35 
36 /* DB VALUE */
37 
38 
39 
db_value_new()40 db_value_t* db_value_new() {
41     db_value_t* value =
42         (db_value_t*)calloc(1, sizeof(db_value_t));
43 
44     if (value) {
45         value->type = DB_TYPE_EMPTY;
46     }
47 
48     return value;
49 }
50 
db_value_free(db_value_t * value)51 void db_value_free(db_value_t* value) {
52     if (value) {
53         if (value->text) {
54             free(value->text);
55         }
56         free(value);
57     }
58 }
59 
db_value_reset(db_value_t * value)60 void db_value_reset(db_value_t* value) {
61     if (value) {
62         value->type = DB_TYPE_EMPTY;
63         value->primary_key = 0;
64         if (value->text) {
65             free(value->text);
66         }
67         value->text = NULL;
68         value->int32 = 0;
69         value->uint32 = 0;
70         value->int64 = 0;
71         value->uint64 = 0;
72         value->enum_value = 0;
73         value->enum_text = NULL;
74     }
75 }
76 
db_value_copy(db_value_t * value,const db_value_t * from_value)77 int db_value_copy(db_value_t* value, const db_value_t* from_value) {
78     if (!value) {
79         return DB_ERROR_UNKNOWN;
80     }
81     if (value->type != DB_TYPE_EMPTY) {
82         return DB_ERROR_UNKNOWN;
83     }
84     if (!from_value) {
85         return DB_ERROR_UNKNOWN;
86     }
87     if (from_value->type == DB_TYPE_EMPTY) {
88         return DB_ERROR_UNKNOWN;
89     }
90 
91     memcpy(value, from_value, sizeof(db_value_t));
92     if (from_value->text) {
93         value->text = strdup(from_value->text);
94         if (!value->text) {
95             db_value_reset(value);
96             return DB_ERROR_UNKNOWN;
97         }
98     }
99     return DB_OK;
100 }
101 
db_value_cmp(const db_value_t * value_a,const db_value_t * value_b,int * result)102 int db_value_cmp(const db_value_t* value_a, const db_value_t* value_b, int* result) {
103     if (!value_a) {
104         return DB_ERROR_UNKNOWN;
105     }
106     if (!value_b) {
107         return DB_ERROR_UNKNOWN;
108     }
109     if (!result) {
110         return DB_ERROR_UNKNOWN;
111     }
112 
113     if (value_a->type == DB_TYPE_EMPTY && value_b->type != DB_TYPE_EMPTY) {
114         *result = -1;
115         return DB_OK;
116     }
117     else if (value_a->type == DB_TYPE_EMPTY && value_b->type == DB_TYPE_EMPTY) {
118         *result = 0;
119         return DB_OK;
120     }
121     else if (value_a->type != DB_TYPE_EMPTY && value_b->type == DB_TYPE_EMPTY) {
122         *result = 1;
123         return DB_OK;
124     }
125 
126     /* TODO: ability to compare different types to each other */
127     if (value_a->type != value_b->type) {
128         switch (value_a->type) {
129         case DB_TYPE_INT32:
130             if (value_b->type == DB_TYPE_INT64) {
131                 if ((db_type_int64_t)(value_a->int32) < value_b->int64) {
132                     *result = -1;
133                 }
134                 else if ((db_type_int64_t)(value_a->int32) > value_b->int64) {
135                     *result = 1;
136                 }
137                 else {
138                     *result = 0;
139                 }
140                 return DB_OK;
141             }
142             break;
143 
144         case DB_TYPE_INT64:
145             if (value_b->type == DB_TYPE_INT32) {
146                 if (value_a->int64 < (db_type_int64_t)(value_b->int32)) {
147                     *result = -1;
148                 }
149                 else if (value_a->int64 > (db_type_int64_t)(value_b->int32)) {
150                     *result = 1;
151                 }
152                 else {
153                     *result = 0;
154                 }
155                 return DB_OK;
156             }
157             break;
158 
159         case DB_TYPE_UINT32:
160             if (value_b->type == DB_TYPE_UINT64) {
161                 if ((db_type_uint64_t)(value_a->uint32) < value_b->uint64) {
162                     *result = -1;
163                 }
164                 else if ((db_type_uint64_t)(value_a->uint32) > value_b->uint64) {
165                     *result = 1;
166                 }
167                 else {
168                     *result = 0;
169                 }
170                 return DB_OK;
171             }
172             break;
173 
174         case DB_TYPE_UINT64:
175             if (value_b->type == DB_TYPE_UINT32) {
176                 if (value_a->uint64 < (db_type_uint64_t)(value_b->uint32)) {
177                     *result = -1;
178                 }
179                 else if (value_a->uint64 > (db_type_uint64_t)(value_b->uint32)) {
180                     *result = 1;
181                 }
182                 else {
183                     *result = 0;
184                 }
185                 return DB_OK;
186             }
187             break;
188 
189         default:
190             break;
191         }
192 
193         return DB_ERROR_UNKNOWN;
194     }
195 
196     switch (value_a->type) {
197     case DB_TYPE_INT32:
198         if (value_a->int32 < value_b->int32) {
199             *result = -1;
200         }
201         else if (value_a->int32 > value_b->int32) {
202             *result = 1;
203         }
204         else {
205             *result = 0;
206         }
207         break;
208 
209     case DB_TYPE_UINT32:
210         if (value_a->uint32 < value_b->uint32) {
211             *result = -1;
212         }
213         else if (value_a->uint32 > value_b->uint32) {
214             *result = 1;
215         }
216         else {
217             *result = 0;
218         }
219         break;
220 
221     case DB_TYPE_INT64:
222         if (value_a->int64 < value_b->int64) {
223             *result = -1;
224         }
225         else if (value_a->int64 > value_b->int64) {
226             *result = 1;
227         }
228         else {
229             *result = 0;
230         }
231         break;
232 
233     case DB_TYPE_UINT64:
234         if (value_a->uint64 < value_b->uint64) {
235             *result = -1;
236         }
237         else if (value_a->uint64 > value_b->uint64) {
238             *result = 1;
239         }
240         else {
241             *result = 0;
242         }
243         break;
244 
245     case DB_TYPE_TEXT:
246         *result = strcmp(value_a->text, value_b->text);
247         break;
248 
249     case DB_TYPE_ENUM:
250         /* TODO: Document that enum can only really be checked if eq */
251         if (value_a->enum_value < value_b->enum_value) {
252             *result = -1;
253         }
254         else if (value_a->enum_value > value_b->enum_value) {
255             *result = 1;
256         }
257         else {
258             *result = 0;
259         }
260         break;
261 
262     default:
263         return DB_ERROR_UNKNOWN;
264     }
265 
266     return DB_OK;
267 }
268 
db_value_type(const db_value_t * value)269 db_type_t db_value_type(const db_value_t* value) {
270     if (!value) {
271         return DB_TYPE_EMPTY;
272     }
273 
274     return value->type;
275 }
276 
db_value_int32(const db_value_t * value)277 const db_type_int32_t* db_value_int32(const db_value_t* value) {
278     if (!value) {
279         return NULL;
280     }
281     if (value->type != DB_TYPE_INT32) {
282         return NULL;
283     }
284 
285     return &value->int32;
286 }
287 
db_value_uint32(const db_value_t * value)288 const db_type_uint32_t* db_value_uint32(const db_value_t* value) {
289     if (!value) {
290         return NULL;
291     }
292     if (value->type != DB_TYPE_UINT32) {
293         return NULL;
294     }
295 
296     return &value->uint32;
297 }
298 
db_value_int64(const db_value_t * value)299 const db_type_int64_t* db_value_int64(const db_value_t* value) {
300     if (!value) {
301         return NULL;
302     }
303     if (value->type != DB_TYPE_INT64) {
304         return NULL;
305     }
306 
307     return &value->int64;
308 }
309 
db_value_uint64(const db_value_t * value)310 const db_type_uint64_t* db_value_uint64(const db_value_t* value) {
311     if (!value) {
312         return NULL;
313     }
314     if (value->type != DB_TYPE_UINT64) {
315         return NULL;
316     }
317 
318     return &value->uint64;
319 }
320 
db_value_text(const db_value_t * value)321 const char* db_value_text(const db_value_t* value) {
322     if (!value) {
323         return NULL;
324     }
325     if (value->type != DB_TYPE_TEXT) {
326         return NULL;
327     }
328 
329     return value->text;
330 }
331 
db_value_enum_value(const db_value_t * value,int * enum_value)332 int db_value_enum_value(const db_value_t* value, int* enum_value) {
333     if (!value) {
334         return DB_ERROR_UNKNOWN;
335     }
336     if (!enum_value) {
337         return DB_ERROR_UNKNOWN;
338     }
339     if (value->type != DB_TYPE_ENUM) {
340         return DB_ERROR_UNKNOWN;
341     }
342 
343     *enum_value = value->enum_value;
344     return DB_OK;
345 }
346 
db_value_not_empty(const db_value_t * value)347 int db_value_not_empty(const db_value_t* value) {
348     if (!value) {
349         return DB_ERROR_UNKNOWN;
350     }
351     if (value->type == DB_TYPE_EMPTY) {
352         return DB_ERROR_UNKNOWN;
353     }
354     return DB_OK;
355 }
356 
db_value_to_int32(const db_value_t * value,db_type_int32_t * to_int32)357 int db_value_to_int32(const db_value_t* value, db_type_int32_t* to_int32) {
358     if (!value) {
359         return DB_ERROR_UNKNOWN;
360     }
361     if (!to_int32) {
362         return DB_ERROR_UNKNOWN;
363     }
364     if (value->type != DB_TYPE_INT32) {
365         return DB_ERROR_UNKNOWN;
366     }
367 
368     *to_int32 = value->int32;
369     return DB_OK;
370 }
371 
db_value_to_uint32(const db_value_t * value,db_type_uint32_t * to_uint32)372 int db_value_to_uint32(const db_value_t* value, db_type_uint32_t* to_uint32) {
373     if (!value) {
374         return DB_ERROR_UNKNOWN;
375     }
376     if (!to_uint32) {
377         return DB_ERROR_UNKNOWN;
378     }
379     if (value->type != DB_TYPE_UINT32) {
380         return DB_ERROR_UNKNOWN;
381     }
382 
383     *to_uint32 = value->uint32;
384     return DB_OK;
385 }
386 
db_value_to_int64(const db_value_t * value,db_type_int64_t * to_int64)387 int db_value_to_int64(const db_value_t* value, db_type_int64_t* to_int64) {
388     if (!value) {
389         return DB_ERROR_UNKNOWN;
390     }
391     if (!to_int64) {
392         return DB_ERROR_UNKNOWN;
393     }
394     if (value->type != DB_TYPE_INT64) {
395         return DB_ERROR_UNKNOWN;
396     }
397 
398     *to_int64 = value->int64;
399     return DB_OK;
400 }
401 
db_value_to_uint64(const db_value_t * value,db_type_uint64_t * to_uint64)402 int db_value_to_uint64(const db_value_t* value, db_type_uint64_t* to_uint64) {
403     if (!value) {
404         return DB_ERROR_UNKNOWN;
405     }
406     if (!to_uint64) {
407         return DB_ERROR_UNKNOWN;
408     }
409     if (value->type != DB_TYPE_UINT64) {
410         return DB_ERROR_UNKNOWN;
411     }
412 
413     *to_uint64 = value->uint64;
414     return DB_OK;
415 }
416 
db_value_to_text(const db_value_t * value,char ** to_text)417 int db_value_to_text(const db_value_t* value, char** to_text) {
418     if (!value) {
419         return DB_ERROR_UNKNOWN;
420     }
421     if (!to_text) {
422         return DB_ERROR_UNKNOWN;
423     }
424     if (*to_text) {
425         return DB_ERROR_UNKNOWN;
426     }
427     if (value->type != DB_TYPE_TEXT) {
428         return DB_ERROR_UNKNOWN;
429     }
430 
431     *to_text = strdup(value->text);
432     if (!*to_text) {
433         return DB_ERROR_UNKNOWN;
434     }
435     return DB_OK;
436 }
437 
db_value_to_enum_value(const db_value_t * value,int * to_int,const db_enum_t * enum_set)438 int db_value_to_enum_value(const db_value_t* value, int* to_int, const db_enum_t* enum_set) {
439     if (!value) {
440         return DB_ERROR_UNKNOWN;
441     }
442     if (!to_int) {
443         return DB_ERROR_UNKNOWN;
444     }
445     if (!enum_set) {
446         return DB_ERROR_UNKNOWN;
447     }
448 
449     if (value->type == DB_TYPE_ENUM) {
450         while (enum_set->text) {
451             if (enum_set->value == value->enum_value) {
452                 *to_int = enum_set->value;
453                 return DB_OK;
454             }
455             enum_set++;
456         }
457     }
458     else if (value->type == DB_TYPE_TEXT) {
459         while (enum_set->text) {
460             if (!strcmp(enum_set->text, value->text)) {
461                 *to_int = enum_set->value;
462                 return DB_OK;
463             }
464             enum_set++;
465         }
466     }
467     else if (value->type == DB_TYPE_INT32) {
468         while (enum_set->text) {
469             if (enum_set->value == value->int32) {
470                 *to_int = enum_set->value;
471                 return DB_OK;
472             }
473             enum_set++;
474         }
475     }
476     return DB_ERROR_UNKNOWN;
477 }
478 
db_value_from_int32(db_value_t * value,db_type_int32_t from_int32)479 int db_value_from_int32(db_value_t* value, db_type_int32_t from_int32) {
480     if (!value) {
481         return DB_ERROR_UNKNOWN;
482     }
483     if (value->type != DB_TYPE_EMPTY) {
484         return DB_ERROR_UNKNOWN;
485     }
486 
487     value->int32 = from_int32;
488     value->type = DB_TYPE_INT32;
489     return DB_OK;
490 }
491 
db_value_from_uint32(db_value_t * value,db_type_uint32_t from_uint32)492 int db_value_from_uint32(db_value_t* value, db_type_uint32_t from_uint32) {
493     if (!value) {
494         return DB_ERROR_UNKNOWN;
495     }
496     if (value->type != DB_TYPE_EMPTY) {
497         return DB_ERROR_UNKNOWN;
498     }
499 
500     value->uint32 = from_uint32;
501     value->type = DB_TYPE_UINT32;
502     return DB_OK;
503 }
504 
db_value_from_int64(db_value_t * value,db_type_int64_t from_int64)505 int db_value_from_int64(db_value_t* value, db_type_int64_t from_int64) {
506     if (!value) {
507         return DB_ERROR_UNKNOWN;
508     }
509     if (value->type != DB_TYPE_EMPTY) {
510         return DB_ERROR_UNKNOWN;
511     }
512 
513     value->int64 = from_int64;
514     value->type = DB_TYPE_INT64;
515     return DB_OK;
516 }
517 
db_value_from_uint64(db_value_t * value,db_type_uint64_t from_uint64)518 int db_value_from_uint64(db_value_t* value, db_type_uint64_t from_uint64) {
519     if (!value) {
520         return DB_ERROR_UNKNOWN;
521     }
522     if (value->type != DB_TYPE_EMPTY) {
523         return DB_ERROR_UNKNOWN;
524     }
525 
526     value->uint64 = from_uint64;
527     value->type = DB_TYPE_UINT64;
528     return DB_OK;
529 }
530 
db_value_from_text(db_value_t * value,const char * from_text)531 int db_value_from_text(db_value_t* value, const char* from_text) {
532     if (!value) {
533         return DB_ERROR_UNKNOWN;
534     }
535     if (!from_text) {
536         return DB_ERROR_UNKNOWN;
537     }
538     if (value->type != DB_TYPE_EMPTY) {
539         return DB_ERROR_UNKNOWN;
540     }
541 
542     value->text = (void*)strdup(from_text);
543     if (!value->text) {
544         return DB_ERROR_UNKNOWN;
545     }
546     value->type = DB_TYPE_TEXT;
547     return DB_OK;
548 }
549 
db_value_from_text2(db_value_t * value,const char * from_text,size_t size)550 int db_value_from_text2(db_value_t* value, const char* from_text, size_t size) {
551     if (!value) {
552         return DB_ERROR_UNKNOWN;
553     }
554     if (!from_text) {
555         return DB_ERROR_UNKNOWN;
556     }
557     if (!size) {
558         return DB_ERROR_UNKNOWN;
559     }
560     if (value->type != DB_TYPE_EMPTY) {
561         return DB_ERROR_UNKNOWN;
562     }
563 
564     value->text = (void*)strndup(from_text, size);
565     if (!value->text) {
566         return DB_ERROR_UNKNOWN;
567     }
568     value->type = DB_TYPE_TEXT;
569     return DB_OK;
570 }
571 
db_value_from_enum_value(db_value_t * value,int enum_value,const db_enum_t * enum_set)572 int db_value_from_enum_value(db_value_t* value, int enum_value, const db_enum_t* enum_set) {
573     if (!value) {
574         return DB_ERROR_UNKNOWN;
575     }
576     if (!enum_set) {
577         return DB_ERROR_UNKNOWN;
578     }
579     if (value->type != DB_TYPE_EMPTY) {
580         return DB_ERROR_UNKNOWN;
581     }
582 
583     while (enum_set->text) {
584         if (enum_set->value == enum_value) {
585             value->enum_text = enum_set->text;
586             value->enum_value = enum_set->value;
587             value->type = DB_TYPE_ENUM;
588             return DB_OK;
589         }
590         enum_set++;
591     }
592     return DB_ERROR_UNKNOWN;
593 }
594 
db_value_set_primary_key(db_value_t * value)595 int db_value_set_primary_key(db_value_t* value) {
596     if (!value) {
597         return DB_ERROR_UNKNOWN;
598     }
599     if (value->type == DB_TYPE_EMPTY) {
600         return DB_ERROR_UNKNOWN;
601     }
602     if (value->type == DB_TYPE_ENUM) {
603         return DB_ERROR_UNKNOWN;
604     }
605 
606     value->primary_key = 1;
607     return DB_OK;
608 }
609 
610 /* DB VALUE SET */
611 
612 
613 
614 
615 
616 
617 
618 
619 
620 
621 
db_value_set_new(size_t size)622 db_value_set_t* db_value_set_new(size_t size) {
623     db_value_set_t* value_set;
624     size_t i;
625 
626     if (size == 0 || size > 128) {
627         return NULL;
628     }
629 
630     value_set = (db_value_set_t*)calloc(1, sizeof(db_value_set_t));
631     if (value_set) {
632         if (size <= 4) {
633             value_set->values = (db_value_t*)calloc(4, sizeof(db_value_t));
634         }
635         else if (size <= 8) {
636             value_set->values = (db_value_t*)calloc(8, sizeof(db_value_t));
637         }
638         else if (size <= 12) {
639             value_set->values = (db_value_t*)calloc(12, sizeof(db_value_t));
640         }
641         else if (size <= 16) {
642             value_set->values = (db_value_t*)calloc(16, sizeof(db_value_t));
643         }
644         else if (size <= 24) {
645             value_set->values = (db_value_t*)calloc(24, sizeof(db_value_t));
646         }
647         else if (size <= 32) {
648             value_set->values = (db_value_t*)calloc(32, sizeof(db_value_t));
649         }
650         else if (size <= 64) {
651             value_set->values = (db_value_t*)calloc(64, sizeof(db_value_t));
652         }
653         else if (size <= 128) {
654             value_set->values = (db_value_t*)calloc(128, sizeof(db_value_t));
655         }
656         if (!value_set->values) {
657             free(value_set);
658             return NULL;
659         }
660         value_set->size = size;
661         for (i=0; i<value_set->size; i++) {
662             value_set->values[i].type = DB_TYPE_EMPTY;
663         }
664     }
665 
666     return value_set;
667 }
668 
669 /* TODO: unit test */
db_value_set_new_copy(const db_value_set_t * from_value_set)670 db_value_set_t* db_value_set_new_copy(const db_value_set_t* from_value_set) {
671     db_value_set_t* value_set;
672     size_t i;
673 
674     if (!from_value_set) {
675         return NULL;
676     }
677     if (!from_value_set->values) {
678         return NULL;
679     }
680 
681     value_set = db_value_set_new(from_value_set->size);
682     if (value_set) {
683         for (i=0; i<from_value_set->size; i++) {
684             if (db_value_type(&from_value_set->values[i]) == DB_TYPE_EMPTY) {
685                 continue;
686             }
687             if (db_value_copy(&value_set->values[i], &from_value_set->values[i])) {
688                 db_value_set_free(value_set);
689                 return NULL;
690             }
691         }
692     }
693 
694     return value_set;
695 }
696 
db_value_set_free(db_value_set_t * value_set)697 void db_value_set_free(db_value_set_t* value_set) {
698     if (value_set) {
699         if (value_set->values) {
700             size_t i;
701             for (i=0; i<value_set->size; i++) {
702                 db_value_reset(&value_set->values[i]);
703             }
704 
705             if (value_set->size <= 4) {
706                 free(value_set->values);
707             }
708             else if (value_set->size <= 8) {
709                 free(value_set->values);
710             }
711             else if (value_set->size <= 12) {
712                 free(value_set->values);
713             }
714             else if (value_set->size <= 16) {
715                 free(value_set->values);
716             }
717             else if (value_set->size <= 24) {
718                 free(value_set->values);
719             }
720             else if (value_set->size <= 32) {
721                 free(value_set->values);
722             }
723             else if (value_set->size <= 64) {
724                 free(value_set->values);
725             }
726             else if (value_set->size <= 128) {
727                 free(value_set->values);
728             }
729         }
730         free(value_set);
731     }
732 }
733 
db_value_set_size(const db_value_set_t * value_set)734 size_t db_value_set_size(const db_value_set_t* value_set) {
735     if (!value_set) {
736         return DB_OK;
737     }
738 
739     return value_set->size;
740 }
741 
db_value_set_at(const db_value_set_t * value_set,size_t at)742 const db_value_t* db_value_set_at(const db_value_set_t* value_set, size_t at) {
743     if (!value_set) {
744         return NULL;
745     }
746     if (!value_set->values) {
747         return NULL;
748     }
749     if (!(at < value_set->size)) {
750         return NULL;
751     }
752 
753     return &value_set->values[at];
754 }
755 
db_value_set_get(db_value_set_t * value_set,size_t at)756 db_value_t* db_value_set_get(db_value_set_t* value_set, size_t at) {
757     if (!value_set) {
758         return NULL;
759     }
760     if (!value_set->values) {
761         return NULL;
762     }
763     if (!(at < value_set->size)) {
764         return NULL;
765     }
766 
767     return &value_set->values[at];
768 }
769