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