1 #include <ctype.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include "conf.h"
6 
7 
8 typedef struct _SField
9 {
10     char *name;
11     int type;
12     union {
13         char *str_value;
14         int int_value;
15         double double_value;
16         HTable table_value;
17     } value;
18     struct _SField *next;
19 } SField;
20 
21 
22 typedef struct _STable
23 {
24     SField *fields;
25     char *stat_buf;
26 } STable;
27 
28 
29 typedef struct _STableIterator
30 {
31     HTable table;
32     SField *cur_field;
33     int before_start;
34     char *stat_buf;
35 } STableIterator;
36 
37 
38 
table_create()39 HTable table_create()
40 {
41     HTable table;
42 
43     table = (STable*)calloc(1, sizeof(STable));
44     return table;
45 }
46 
47 
free_field(SField * field)48 static void free_field(SField *field)
49 {
50     if (! field)
51         return;
52     if (field->name)
53         free(field->name);
54     switch (field->type)
55     {
56         case TYPE_STRING: free(field->value.str_value); break;
57         case TYPE_TABLE: table_free(field->value.table_value); break;
58     }
59     free(field);
60 }
61 
62 
find_field(HTable table,const char * name)63 static SField* find_field(HTable table, const char *name)
64 {
65     SField *f;
66 
67     if ((! table) || (! name))
68         return NULL;
69 
70     f = table->fields;
71     while (f)
72     {
73         if (f->name && (! strcmp(f->name, name)))
74             return f;
75         f = f->next;
76     }
77 
78     return NULL;
79 }
80 
81 
table_remove_field(HTable table,char * field)82 int table_remove_field(HTable table, char *field)
83 {
84     SField *f, *pf;
85 
86     if ((! table) || (! field))
87         return -1;
88 
89     f = find_field(table, field);
90     if (f)
91     {
92         if (table->fields == f)
93             table->fields = f->next;
94         else
95         {
96             pf = table->fields;
97             while (pf && (pf->next != f))
98                 pf = pf->next;
99             if (pf)
100                 pf->next = f->next;
101         }
102         free_field(f);
103     }
104 
105     return 0;
106 }
107 
108 
add_empty_field(HTable table,const char * field)109 static SField* add_empty_field(HTable table, const char *field)
110 {
111     SField *f, *nf;
112 
113     if ((! table) || (! field))
114         return NULL;
115 
116     f = find_field(table, field);
117     if (f)
118         table_remove_field(table, f->name);
119 
120     nf = (SField*)calloc(1, sizeof(SField));
121     if (! nf) return NULL;
122     nf->name = strdup(field);
123 
124     f = table->fields;
125     if (f)
126     {
127         while (f->next)
128             f = f->next;
129         f->next = nf;
130     }
131     else
132         table->fields = nf;
133 
134     return nf;
135 }
136 
137 
table_set_str(HTable table,const char * field,const char * value)138 int table_set_str(HTable table, const char *field, const char *value)
139 {
140     SField *f;
141 
142     if ((! table) || (! field) || (! value))
143         return -1;
144 
145     f = add_empty_field(table, field);
146     if (! f) return -1;
147 
148     f->type = TYPE_STRING;
149     f->value.str_value = strdup(value);
150     return 0;
151 }
152 
153 
table_set_int(HTable table,const char * field,int value)154 int table_set_int(HTable table, const char *field, int value)
155 {
156     SField *f;
157 
158     if ((! table) || (! field))
159         return -1;
160 
161     f = add_empty_field(table, field);
162     if (! f) return -1;
163 
164     f->type = TYPE_INT;
165     f->value.int_value = value;
166     return 0;
167 }
168 
169 
table_set_double(HTable table,const char * field,double value)170 int table_set_double(HTable table, const char *field, double value)
171 {
172     SField *f;
173 
174     if ((! table) || (! field))
175         return -1;
176 
177     f = add_empty_field(table, field);
178     if (! f) return -1;
179 
180     f->type = TYPE_FLOAT;
181     f->value.double_value = value;
182     return 0;
183 }
184 
185 
table_set_table(HTable table,const char * field,HTable value)186 int table_set_table(HTable table, const char *field, HTable value)
187 {
188     SField *f;
189 
190     if ((! table) || (! field) || (! value))
191         return -1;
192 
193     f = add_empty_field(table, field);
194     if (! f) return -1;
195 
196     f->type = TYPE_TABLE;
197     f->value.table_value = value;
198     return 0;
199 }
200 
201 
202 static int skip_spaces(char *buf, long int *pos);
203 
204 
skip_multy_comment(char * buf,long int * pos)205 static int skip_multy_comment(char *buf, long int *pos)
206 {
207     while (buf[*pos])
208     {
209         if (buf[*pos] == '*')
210         {
211             (*pos)++;
212             if (buf[*pos] == '/')
213             {
214                 (*pos)++;
215                 return skip_spaces(buf, pos);
216             }
217         }
218         (*pos)++;
219     }
220 
221     return -1;
222 }
223 
224 
skip_line_comment(char * buf,long int * pos)225 static int skip_line_comment(char *buf, long int *pos)
226 {
227     while (buf[*pos] && ((buf[*pos]) != '\n'))
228         (*pos)++;
229     return skip_spaces(buf, pos);
230 }
231 
232 
is_cspace(char * buf,long int * pos)233 static int is_cspace(char *buf, long int *pos)
234 {
235     if (isspace(buf[*pos]))
236         return 1;
237     if (buf[*pos] == '/')
238     {
239         if ((buf[(*pos) + 1] == '*') || (buf[(*pos) + 1] == '/'))
240             return 1;
241     }
242     return 0;
243 }
244 
245 
skip_spaces(char * buf,long int * pos)246 static int skip_spaces(char *buf, long int *pos)
247 {
248     while (buf[*pos] && isspace(buf[*pos]))
249         (*pos)++;
250 
251     if (buf[*pos] == '/')
252     {
253         (*pos)++;
254         if (buf[*pos] == '*')
255         {
256             (*pos)++;
257             return skip_multy_comment(buf, pos);
258         }
259         else if (buf[*pos] == '/')
260         {
261             (*pos)++;
262             return skip_line_comment(buf, pos);
263         }
264         else
265             return -1;
266     }
267     return 0;
268 }
269 
270 
is_symbol(char sym)271 static int is_symbol(char sym)
272 {
273     static char syms[] = { '=', '{', '}', ';', '\'', '"', ',', '/', '\\' };
274     unsigned int i;
275 
276     for (i = 0; i < sizeof(syms) / sizeof(char); i++)
277     {
278         if (sym == syms[i])
279             return 1;
280     }
281 
282     return 0;
283 }
284 
285 
read_string(char * buf,long int * pos)286 static char* read_string(char* buf, long int *pos)
287 {
288     int allocated=50, len=1;
289     char *b;
290 
291     b = (char*)malloc(allocated);
292     if (! b) return NULL;
293     b[0] = buf[*pos];
294     (*pos)++;
295     while (buf[*pos])
296     {
297         if (len + 3 > allocated)
298         {
299             char *s = (char*)realloc(b, allocated+=20);
300             if (! s)
301             {
302                 free(b);
303                 return NULL;
304             }
305             b = s;
306         }
307         if ((buf[*pos] == '\\') && (buf[*pos + 1] == b[0]))
308         {
309             b[len++] = '\\';
310             b[len] = b[0];
311         }
312         else
313         {
314             b[len++] = buf[*pos];
315             if (buf[*pos] == b[0])
316             {
317                 b[len] = 0;
318                 (*pos)++;
319                 return b;
320             }
321         }
322         (*pos)++;
323     }
324     free(b);
325     return NULL;
326 }
327 
328 
read_word(char * buf,long int * pos)329 static char* read_word(char* buf, long int *pos)
330 {
331     int allocated=50, len=0;
332     char *b;
333 
334     b = (char*)malloc(allocated);
335     if (! b) return NULL;
336     while (buf[*pos] && (! is_cspace(buf, pos)) && (! is_symbol(buf[*pos])))
337     {
338         if (len + 3 > allocated)
339         {
340             char *s = (char*)realloc(b, allocated+=20);
341             if (! s)
342             {
343                 free(b);
344                 return NULL;
345             }
346             b = s;
347         }
348         b[len++] = buf[*pos];
349         (*pos)++;
350     }
351     if (! len)
352     {
353         free(b);
354         return NULL;
355     }
356     b[len] = 0;
357     return b;
358 }
359 
360 
read_token(char * buf,long int * pos)361 static char* read_token(char *buf, long int *pos)
362 {
363     if (skip_spaces(buf, pos) || (! buf[*pos]))
364         return NULL;
365 
366     if ((buf[*pos] == '\'') || (buf[*pos] == '"'))
367         return read_string(buf, pos);
368 
369     if (is_symbol(buf[*pos]))
370     {
371         char *b = (char*)malloc(2);
372         if (! b) return NULL;
373         b[0] = buf[*pos];
374         b[1] = 0;
375         (*pos)++;
376         return b;
377     }
378 
379     return read_word(buf, pos);
380 }
381 
382 
get_file_size(FILE * f)383 static long int get_file_size(FILE *f)
384 {
385     long int len;
386 
387     if (fseek(f, 0L, SEEK_END))
388         return -1;
389 
390     len = ftell(f);
391 
392     if (fseek(f, 0L, SEEK_SET))
393         return -1;
394 
395     return len;
396 }
397 
398 
read_file(const char * filename,long int * length)399 static char* read_file(const char *filename, long int *length)
400 {
401     FILE *f;
402     char *buf;
403     long int len;
404 
405     f = fopen(filename, "rb");
406     if (! f) return NULL;
407 
408     len = get_file_size(f);
409     if (len <= 0)
410     {
411         fclose(f);
412         return NULL;
413     }
414 
415     buf = (char*)malloc(len + 1);
416     if (! buf)
417     {
418         fclose(f);
419         return NULL;
420     }
421 
422     if (fread(buf, 1, len, f) != (unsigned)len)
423     {
424         free(buf);
425         fclose(f);
426         return NULL;
427     }
428 
429     buf[len] = 0;
430 
431     fclose(f);
432     *length = len + 1;
433     return buf;
434 }
435 
436 
get_next_index(HTable table)437 static int get_next_index(HTable table)
438 {
439     SField *f;
440     int v, max_v=-1;
441     char *endptr;
442 
443     for (f = table->fields; f; f = f->next)
444     {
445         v = strtol(f->name, &endptr, 10);
446         if ((! f->name[0]) || (endptr[0]))
447             continue;
448         if (v > max_v)
449             max_v = v;
450     }
451 
452     return max_v + 1;
453 }
454 
455 
is_ident(char * str)456 static int is_ident(char *str)
457 {
458     char *p;
459 
460     if (! str)
461         return 0;
462     if (strlen(str) < 1)
463         return 0;
464     if (! isalpha(str[0]))
465         return 0;
466 
467     for (p = str; *p; p++)
468         if (! (isalnum(*p) || (*p == '_') || (*p == '.')))
469             return 0;
470 
471     return 1;
472 }
473 
474 
is_string_value(char * value)475 static int is_string_value(char *value)
476 {
477     int len;
478 
479     if ((value[0] == '\'') || (value[0] == '"'))
480     {
481         if ((len = strlen(value)) >= 2)
482         {
483             if (value[len - 1] == value[0])
484                 return 1;
485         }
486     }
487 
488     return 0;
489 }
490 
491 
is_int_value(char * value)492 static int is_int_value(char *value)
493 {
494     char *p;
495 
496     for (p = value; *p; p++)
497     {
498         if (! isdigit(*p))
499         {
500             if (p != value)
501                 return 0;
502             else
503                 if (! ((*p == '+') || (*p == '-')))
504                     return 0;
505         }
506     }
507     return 1;
508 }
509 
510 
is_float_value(char * value)511 static int is_float_value(char *value)
512 {
513     char *p;
514     int pcount = 0;
515 
516     for (p = value; *p; p++)
517     {
518         if (! isdigit(*p))
519         {
520             if (p != value)
521             {
522                 if (*p != '.')
523                     return 0;
524                 else
525                 {
526                     pcount++;
527                     if (pcount > 1)
528                         return 0;
529                 }
530             }
531             else
532             {
533                 if (! ((*p == '+') || (*p == '-')))
534                     return 0;
535             }
536         }
537     }
538     return 1;
539 }
540 
541 
get_value_type(char * value)542 static int get_value_type(char *value)
543 {
544     if ((! value) || (! value[0]))
545         return -1;
546 
547     if (is_string_value(value))
548         return TYPE_STRING;
549     if (! strcmp(value, "{"))
550         return TYPE_TABLE;
551     if (is_int_value(value))
552         return TYPE_INT;
553     if (is_float_value(value))
554         return TYPE_FLOAT;
555 
556     return -1;
557 }
558 
559 
unescape_string(char * str)560 static char* unescape_string(char *str)
561 {
562     char *buf, quote, *p;
563     int allocated=50, len=0;
564 
565     buf = (char*)malloc(allocated);
566 
567     quote = str[0];
568     p = str + 1;
569     while ((*p) && (*p != quote))
570     {
571         if (len + 10 > allocated)
572         {
573             char *s = (char*)realloc(buf, allocated+=20);
574             if (! s)
575             {
576                 free(buf);
577                 return NULL;
578             }
579             buf = s;
580         }
581         if (*p == '\\')
582         {
583             p++;
584             switch (*p)
585             {
586                 case 'n': buf[len++] = '\n'; break;
587                 case 't': buf[len++] = '\t'; break;
588                 case 'r': buf[len++] = '\r'; break;
589                 default: buf[len++] = *p;
590             }
591         }
592         else
593             buf[len++] = *p;
594         p++;
595     }
596     buf[len] = 0;
597 
598     if ((*p == quote) && (*(p + 1)))
599     {
600         free(buf);
601         return NULL;
602     }
603     return buf;
604 }
605 
606 
607 static int parse_table(HTable table, char *buf, long int *pos, int top_level);
608 
609 
add_field(HTable table,char * name,char * value,char * buf,long int * pos)610 static int add_field(HTable table, char *name, char *value, char *buf, long int *pos)
611 {
612     int value_type;
613     char *s;
614     HTable tbl;
615 
616     value_type = get_value_type(value);
617     switch (value_type)
618     {
619         case TYPE_INT:
620             table_set_int(table, name, atoi(value));
621             break;
622         case TYPE_STRING:
623             s = unescape_string(value);
624             if (! s)
625                 return -1;
626             table_set_str(table, name, s);
627             free(s);
628             break;
629         case TYPE_FLOAT:
630             table_set_double(table, name, atof(value));
631             break;
632         case TYPE_TABLE:
633             tbl = table_create();
634             if (table_set_table(table, name, tbl))
635             {
636                 table_free(tbl);
637                 return -1;
638             }
639             if (parse_table(tbl, buf, pos, 0))
640                 return -1;
641             break;
642         default:
643             return -1;
644     }
645     return 0;
646 }
647 
648 
add_field_to_array(HTable table,char * token,char * buf,long int * pos)649 static int add_field_to_array(HTable table, char *token, char *buf, long int *pos)
650 {
651     int idx = get_next_index(table);
652     char b[100];
653     sprintf(b, "%i", idx);
654     return add_field(table, b, token, buf, pos);
655 }
656 
657 
658 
659 /*
660  * TODO: add field as in array highly unoptimized.  it scans for max index
661  *       number on every element addition, converting idexes from strings
662  *       to numbers where it possible.  optimizations method: process
663  *       indexes in batch
664  */
665 
parse_table(HTable table,char * buf,long int * pos,int top_level)666 static int parse_table(HTable table, char *buf, long int *pos, int top_level)
667 {
668     char *token=NULL;
669     char *name;
670     int res;
671 
672     while (1)
673     {
674         if (! token)
675             token = read_token(buf, pos);
676         if (! token)
677         {
678             if (top_level)
679                 return 0;
680             else
681                 return -1;
682         }
683 
684         if (! strcmp(token, "{"))
685         {
686             if (add_field_to_array(table, token, buf, pos))
687             {
688                 free(token);
689                 return -1;
690             }
691             free(token);
692             token = read_token(buf, pos);
693             if (! token)
694             {
695                 if (top_level)
696                     return 0;
697                 else
698                     return -1;
699             }
700             if ((! strcmp(token, ";")) || (! strcmp(token, ",")))
701             {
702                 free(token);
703                 token = NULL;
704             }
705             continue;
706         }
707         else if (! strcmp(token, "}"))
708         {
709             free(token);
710             if (top_level)
711                 return -1;
712             else
713                 return 0;
714         }
715 
716         name = token;
717 
718         token = read_token(buf, pos);
719 
720         if (token && (! strcmp(token, "=")))
721         {
722             free(token);
723 
724             if (! is_ident(name))
725             {
726                 free(name);
727                 return -1;
728             }
729 
730             token = read_token(buf, pos);
731             if (! token)
732             {
733                 free(name);
734                 return -1;
735             }
736 
737             res = add_field(table, name, token, buf, pos);
738             free(name);
739             free(token);
740             if (res)
741             {
742                 return -1;
743             }
744 
745             token = read_token(buf, pos);
746             if (! token)
747             {
748                 if (top_level)
749                     return 0;
750                 else
751                     return -1;
752             }
753             if ((! strcmp(token, ";")) || (! strcmp(token, ",")))
754             {
755                 free(token);
756                 token = NULL;
757             }
758             else
759                 if (strcmp(token, "}"))
760                 {
761                     free(token);
762                     return -1;
763                 }
764         }
765         else
766         {
767             if ((! token) && (! top_level))
768             {
769                 free(name);
770                 return -1;
771             }
772             if (! (token && ((! strcmp(token, ";")) || (! strcmp(token, ","))
773                         || (! strcmp(token, "}")))))
774             {
775                 free(name);
776                 if (token) free(token);
777                 return -1;
778             }
779 
780             res = add_field_to_array(table, name, buf, pos);
781             free(name);
782             if (res)
783             {
784                 free(token);
785                 return -1;
786             }
787 
788             if ((! token) || (! strcmp(token, "}")))
789             {
790                 if (token) free(token);
791                 return 0;
792             }
793 
794             if (token && ((! strcmp(token, ",")) || ((! strcmp(token, ";")))))
795             {
796                 free(token);
797                 token = NULL;
798             }
799         }
800     }
801 
802     return 0;
803 }
804 
805 
table_read(const char * filename)806 HTable table_read(const char *filename)
807 {
808     long int len, pos;
809     char *buf;
810     HTable table;
811     int res;
812 
813     buf = read_file(filename, &len);
814     if (! buf) return NULL;
815 
816     pos = 0;
817     table = table_create();
818     res = parse_table(table, buf, &pos, 1);
819     if (res)
820     {
821         table_free(table);
822         table = NULL;
823     }
824 
825     free(buf);
826     return table;
827 }
828 
829 
table_free(HTable table)830 void table_free(HTable table)
831 {
832     SField *f, *nf;
833 
834     if (! table) return;
835 
836     f = table->fields;
837     while (f)
838     {
839         nf = f->next;
840         free_field(f);
841         f = nf;
842     }
843     if (table->stat_buf)
844         free(table->stat_buf);
845     free(table);
846 }
847 
848 
table_get_iter(HTable table)849 HTableIterator table_get_iter(HTable table)
850 {
851     HTableIterator it;
852 
853     it = (HTableIterator)calloc(sizeof(STableIterator), 1);
854     if (! it) return NULL;
855 
856     it->table = table;
857     it->before_start = 1;
858 
859     return it;
860 }
861 
862 
table_free_iter(HTableIterator iterator)863 void table_free_iter(HTableIterator iterator)
864 {
865     if (! iterator) return;
866     if (iterator->stat_buf) free(iterator->stat_buf);
867     free(iterator);
868 }
869 
870 
table_iter_next(HTableIterator iterator)871 int table_iter_next(HTableIterator iterator)
872 {
873     if (! iterator)
874         return 0;
875 
876     if (iterator->before_start)
877     {
878         iterator->before_start = 0;
879         iterator->cur_field = iterator->table->fields;
880     }
881     else
882     {
883         if (iterator->cur_field)
884             iterator->cur_field = iterator->cur_field->next;
885     }
886 
887     if (! iterator->cur_field)
888         return 0;
889 
890     return 1;
891 }
892 
893 
table_iter_get_name(HTableIterator iterator)894 char* table_iter_get_name(HTableIterator iterator)
895 {
896     if ((! iterator) || (! iterator->cur_field))
897         return NULL;
898 
899     return iterator->cur_field->name;
900 }
901 
902 
table_iter_get_type(HTableIterator iterator)903 int table_iter_get_type(HTableIterator iterator)
904 {
905     if ((! iterator) || (! iterator->cur_field))
906         return -1;
907 
908     return iterator->cur_field->type;
909 }
910 
911 
encode_string(char * str)912 static char* encode_string(char *str)
913 {
914     char *buf, *s;
915     int allocated, len;
916 
917     if (! str)
918         return strdup("''");
919 
920     allocated = 20;
921     buf = (char*)malloc(allocated);
922     if (! buf) return NULL;
923     buf[0] = '\'';
924     len = 1;
925     for (s = str; *s; s++)
926     {
927         if (len + 2 < allocated - 2)
928         {
929             char *m = (char*)realloc(buf, allocated += 20);
930             if (! m)
931             {
932                 free(buf);
933                 return NULL;
934             }
935             buf = m;
936         }
937         switch (*s)
938         {
939             case '\n':  buf[len++] = '\\';  buf[len++] = 'n';  break;
940             case '\r':  buf[len++] = '\\';  buf[len++] = 'r';  break;
941             case '\'':  buf[len++] = '\\';  buf[len++] = '\'';  break;
942             case '\\':  buf[len++] = '\\';  buf[len++] = '\\';  break;
943             default:
944                 buf[len++] = *s;
945         }
946     }
947     buf[len++] = '\'';
948     buf[len] = 0;
949     return buf;
950 }
951 
952 
print_field(SField * field,int butify,int spaces)953 static char* print_field(SField *field, int butify, int spaces)
954 {
955     char buf[100];
956 
957     if (! field) return NULL;
958 
959     switch (field->type)
960     {
961         case TYPE_STRING:
962             return encode_string(field->value.str_value);
963         case TYPE_INT:
964             sprintf(buf, "%i", field->value.int_value);
965             return strdup(buf);
966         case TYPE_FLOAT:
967             sprintf(buf, "%g", field->value.double_value);
968             if (! strchr(buf, '.'))
969                 strcat(buf, ".0");
970             return strdup(buf);
971         case TYPE_TABLE:
972             return table_to_str(field->value.table_value, 1, butify, spaces);
973     }
974 
975     return NULL;
976 }
977 
978 
isSimpleArray(HTable table)979 static int isSimpleArray(HTable table)
980 {
981     SField *f;
982     char buf[50];
983     int i;
984 
985     for (f = table->fields, i = 0; f; f = f->next, i++)
986     {
987         sprintf(buf, "%i", i);
988         if (! (f && f->name && (! strcmp(f->name, buf))))
989             return 0;
990     }
991     return 1;
992 }
993 
994 
995 #define APPEND_BUF(buf, s) { int l = strlen(s); \
996         if (len + l > allocated - 5) { \
997             char *nb; \
998             allocated += l + 50; \
999             nb = (char*)realloc(buf, allocated); \
1000             if (! nb) { \
1001                 free(buf); \
1002                 return NULL; \
1003             } \
1004             buf = nb; \
1005         } \
1006         strcat(buf, s); \
1007         len += l; \
1008     }
1009 
1010 #define APPEND_SPACES(buf, n) \
1011         for (int i = 0; i < n; i++) { APPEND_BUF(buf, " "); }
1012 
table_to_str(HTable table,int print_braces,int butify,int spaces)1013 char* table_to_str(HTable table, int print_braces, int butify, int spaces)
1014 {
1015     char *b, *fs;
1016     int len=0, allocated;
1017     SField *f;
1018 
1019     if (! table) return NULL;
1020 
1021     allocated = 100;
1022     b = (char*)malloc(allocated);
1023     if (! b) return NULL;
1024 
1025     if (print_braces) {
1026         if (butify)
1027             strcpy(b, "{\n");
1028         else
1029             strcpy(b, "{ ");
1030     } else
1031         strcpy(b, "");
1032     len = strlen(b);
1033     int printNames = ! isSimpleArray(table);
1034     for (f = table->fields; f; f = f->next) {
1035         if (butify) {
1036             APPEND_SPACES(b, spaces);
1037         } else
1038             if (f != table->fields) {
1039                 APPEND_BUF(b, " ");
1040             }
1041         if (printNames) {
1042             APPEND_BUF(b, f->name);
1043             APPEND_BUF(b, " = ");
1044         }
1045         fs = print_field(f, butify, spaces + 4);
1046         APPEND_BUF(b, fs);
1047         free(fs);
1048         if (butify) {
1049             APPEND_BUF(b, ";\n");
1050         } else {
1051             APPEND_BUF(b, ";");
1052         }
1053     }
1054     if (print_braces) {
1055         if (! butify) {
1056             APPEND_BUF(b, " }");
1057         } else {
1058             APPEND_SPACES(b, spaces);
1059             APPEND_BUF(b, "}");
1060         }
1061     }
1062     return b;
1063 }
1064 
1065 
get_field_str(SField * field,int * err)1066 static char* get_field_str(SField *field, int *err)
1067 {
1068     char buf[100];
1069 
1070     if (err) *err = 0;
1071 
1072     if (! field)
1073     {
1074         if (err) *err = 1;
1075         return NULL;
1076     }
1077 
1078     switch (field->type)
1079     {
1080         case TYPE_STRING:
1081             return strdup(field->value.str_value);
1082         case TYPE_INT:
1083             sprintf(buf, "%i", field->value.int_value);
1084             return strdup(buf);
1085         case TYPE_FLOAT:
1086             sprintf(buf, "%f", field->value.double_value);
1087             return strdup(buf);
1088         case TYPE_TABLE:
1089             return table_to_str(field->value.table_value, 1, 0, 0);;
1090     }
1091 
1092     if (err) *err = 1;
1093     return NULL;
1094 }
1095 
1096 
table_iter_get_str(HTableIterator iterator,int * err)1097 char* table_iter_get_str(HTableIterator iterator, int *err)
1098 {
1099     if ((! iterator) || (! iterator->cur_field))
1100     {
1101         if (err) *err = 1;
1102         return NULL;
1103     }
1104 
1105     return get_field_str(iterator->cur_field, err);
1106 }
1107 
1108 
table_iter_get_strs(HTableIterator iterator,int * err)1109 char* table_iter_get_strs(HTableIterator iterator, int *err)
1110 {
1111     if ((! iterator) || (! iterator->cur_field))
1112     {
1113         if (err) *err = 1;
1114         return NULL;
1115     }
1116 
1117     if (iterator->stat_buf)
1118         free(iterator->stat_buf);
1119     iterator->stat_buf = get_field_str(iterator->cur_field, err);
1120     return iterator->stat_buf;
1121 }
1122 
1123 
get_field_int(SField * field,int * err)1124 static int get_field_int(SField *field, int *err)
1125 {
1126     char *endptr;
1127     int n;
1128 
1129     if (err) *err = 0;
1130 
1131     if (! field)
1132     {
1133         if (err) *err = 1;
1134         return 0;
1135     }
1136 
1137     switch (field->type)
1138     {
1139         case TYPE_STRING:
1140             n = strtol(field->value.str_value, &endptr, 10);
1141             if ((! field->value.str_value[0]) || (endptr[0]))
1142             {
1143                 if (err) *err = 1;
1144                 return 0;
1145             }
1146             return n;
1147         case TYPE_INT:
1148             return field->value.int_value;
1149         case TYPE_FLOAT:
1150             return (int)field->value.double_value;
1151     }
1152 
1153     if (err) *err = 1;
1154     return 0;
1155 }
1156 
1157 
table_iter_get_int(HTableIterator iterator,int * err)1158 int table_iter_get_int(HTableIterator iterator, int *err)
1159 {
1160     if ((! iterator) || (! iterator->cur_field))
1161     {
1162         if (err) *err = 1;
1163         return 0;
1164     }
1165 
1166     return get_field_int(iterator->cur_field, err);
1167 }
1168 
1169 
get_field_double(SField * field,int * err)1170 static double get_field_double(SField *field, int *err)
1171 {
1172     char *endptr;
1173     double n;
1174 
1175     if (err) *err = 0;
1176 
1177     if (! field)
1178     {
1179         if (err) *err = 1;
1180         return 0.0;
1181     }
1182 
1183     switch (field->type)
1184     {
1185         case TYPE_STRING:
1186             n = strtod(field->value.str_value, &endptr);
1187             if ((! field->value.str_value[0]) || (endptr[0]))
1188             {
1189                 if (err) *err = 1;
1190                 return 0.0;
1191             }
1192             return n;
1193         case TYPE_INT:
1194             return field->value.int_value;
1195         case TYPE_FLOAT:
1196             return field->value.double_value;
1197     }
1198 
1199     if (err) *err = 1;
1200     return 0.0;
1201 }
1202 
1203 
table_iter_get_double(HTableIterator iterator,int * err)1204 double table_iter_get_double(HTableIterator iterator, int *err)
1205 {
1206     if ((! iterator) || (! iterator->cur_field))
1207     {
1208         if (err) *err = 1;
1209         return 0.0;
1210     }
1211 
1212     return get_field_double(iterator->cur_field, err);
1213 }
1214 
1215 
table_iter_get_table(HTableIterator iterator,int * err)1216 HTable table_iter_get_table(HTableIterator iterator, int *err)
1217 {
1218     if ((! iterator) || (! iterator->cur_field))
1219     {
1220         if (err) *err = 1;
1221         return NULL;
1222     }
1223 
1224     if (iterator->cur_field->type != TYPE_TABLE)
1225     {
1226         if (err) *err = 1;
1227         return NULL;
1228     }
1229 
1230     if (err) *err = 0;
1231     return iterator->cur_field->value.table_value;
1232 }
1233 
1234 
table_is_field_exists(HTable table,char * name)1235 int table_is_field_exists(HTable table, char *name)
1236 {
1237     SField *f;
1238 
1239     f = find_field(table, name);
1240     if (f)
1241         return 1;
1242     else
1243         return 0;
1244 }
1245 
1246 
table_get_field_type(HTable table,char * field)1247 int table_get_field_type(HTable table, char *field)
1248 {
1249     SField *f;
1250 
1251     f = find_field(table, field);
1252     if (! f)
1253         return -1;
1254 
1255     return f->type;
1256 }
1257 
1258 
table_get_str(HTable table,char * field,char * dflt,int * err)1259 char* table_get_str(HTable table, char *field, char *dflt, int *err)
1260 {
1261     SField *f;
1262     char *s;
1263     int e;
1264 
1265     f = find_field(table, field);
1266     if (! f)
1267     {
1268         if (err) *err = 1;
1269         if (dflt)
1270             return strdup(dflt);
1271         else
1272             return NULL;
1273     }
1274 
1275     s = get_field_str(f, &e);
1276     if (err) *err = e;
1277     if (e)
1278     {
1279         if (dflt)
1280             return strdup(dflt);
1281         else
1282             return NULL;
1283     }
1284     else
1285     {
1286         if (s)
1287             return strdup(s);
1288         else
1289             return NULL;
1290     }
1291 }
1292 
1293 
table_get_strs(HTable table,char * field,char * dflt,int * err)1294 char* table_get_strs(HTable table, char *field, char *dflt, int *err)
1295 {
1296     SField *f;
1297     char *s;
1298     int e;
1299 
1300     if (! table)
1301     {
1302         if (err) *err = 1;
1303         return dflt;
1304     }
1305 
1306     if (table->stat_buf)
1307     {
1308         free(table->stat_buf);
1309         table->stat_buf = NULL;
1310     }
1311 
1312     f = find_field(table, field);
1313     if (! f)
1314     {
1315         if (err) *err = 1;
1316         return dflt;
1317     }
1318 
1319     s = get_field_str(f, &e);
1320     table->stat_buf = s;
1321     if (err) *err = e;
1322     if (e)
1323         s = dflt;
1324 
1325     return s;
1326 }
1327 
1328 
table_get_int(HTable table,char * field,int dflt,int * err)1329 int table_get_int(HTable table, char *field, int dflt, int *err)
1330 {
1331     SField *f;
1332     int v, e;
1333 
1334     f = find_field(table, field);
1335     if (! f)
1336     {
1337         if (err) *err = 1;
1338         return dflt;
1339     }
1340 
1341     v = get_field_int(f, &e);
1342     if (err) *err = e;
1343     if (e)
1344         v = dflt;
1345 
1346     return v;
1347 }
1348 
1349 
table_get_double(HTable table,char * field,double dflt,int * err)1350 double table_get_double(HTable table, char *field, double dflt, int *err)
1351 {
1352     SField *f;
1353     double v;
1354     int e;
1355 
1356     f = find_field(table, field);
1357     if (! f)
1358     {
1359         if (err) *err = 1;
1360         return dflt;
1361     }
1362 
1363     v = get_field_double(f, &e);
1364     if (err) *err = e;
1365     if (e)
1366         v = dflt;
1367 
1368     return v;
1369 }
1370 
1371 
table_get_table(HTable table,char * field,HTable dflt,int * err)1372 HTable table_get_table(HTable table, char *field, HTable dflt, int *err)
1373 {
1374     SField *f;
1375     HTable v;
1376 
1377     f = find_field(table, field);
1378     if ((! f) || (f->type != TYPE_TABLE))
1379     {
1380         if (err) *err = 1;
1381         return dflt;
1382     }
1383 
1384     v = f->value.table_value;
1385     if (err) *err = 0;
1386 
1387     return v;
1388 }
1389 
1390 
table_append_str(HTable table,const char * val)1391 int table_append_str(HTable table, const char *val)
1392 {
1393     int idx;
1394     char b[100];
1395 
1396     if ((! table) || (! val))
1397         return -1;
1398 
1399     idx = get_next_index(table);
1400     sprintf(b, "%i", idx);
1401     table_set_str(table, b, val);
1402     return 0;
1403 }
1404 
1405 
table_append_int(HTable table,int val)1406 int table_append_int(HTable table, int val)
1407 {
1408     int idx;
1409     char b[100];
1410 
1411     if ((! table) || (! val))
1412         return -1;
1413 
1414     idx = get_next_index(table);
1415     sprintf(b, "%i", idx);
1416     table_set_int(table, b, val);
1417     return 0;
1418 }
1419 
1420 
table_append_double(HTable table,double val)1421 int table_append_double(HTable table, double val)
1422 {
1423     int idx;
1424     char b[100];
1425 
1426     if ((! table) || (! val))
1427         return -1;
1428 
1429     idx = get_next_index(table);
1430     sprintf(b, "%i", idx);
1431     table_set_double(table, b, val);
1432     return 0;
1433 }
1434 
1435 
table_append_table(HTable table,HTable val)1436 int table_append_table(HTable table, HTable val)
1437 {
1438     int idx;
1439     char b[100];
1440 
1441     if ((! table) || (! val))
1442         return -1;
1443 
1444     idx = get_next_index(table);
1445     sprintf(b, "%i", idx);
1446     table_set_table(table, b, val);
1447     return 0;
1448 }
1449 
1450