Fix: update the correct pre-built script to cmake-sonar.sh
[ric-app/mc.git] / schemaparser / schemaparser.cc
1 /* ------------------------------------------------
2 Copyright 2020 AT&T Intellectual Property
3    Licensed under the Apache License, Version 2.0 (the "License");
4    you may not use this file except in compliance with the License.
5    You may obtain a copy of the License at
6
7      http://www.apache.org/licenses/LICENSE-2.0
8
9    Unless required by applicable law or agreed to in writing, software
10    distributed under the License is distributed on an "AS IS" BASIS,
11    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12    See the License for the specific language governing permissions and
13    limitations under the License.
14  ------------------------------------------- */
15
16 #include "schemaparser_impl.h"
17 #include<string.h>
18
19 namespace mc_schema{
20
21 int type_size(int dt){
22         switch(dt){
23         case INT_TYPE:
24                 return(sizeof(int));
25         case UINT_TYPE:
26         case USHORT_TYPE:
27         case BOOL_TYPE:
28         case IP_TYPE:
29                 return(sizeof(unsigned int));
30         case ULLONG_TYPE:
31                 return(sizeof(unsigned long long int));
32         case LLONG_TYPE:
33                 return(sizeof(long long int));
34         case FLOAT_TYPE:
35                 return(sizeof(double));
36         case IPV6_TYPE:
37                 return(sizeof(mc_ipv6_str));
38         case TIMEVAL_TYPE:
39                 return(sizeof(timeval));
40         case VSTR_TYPE:
41                 return(sizeof(mc_string));      
42         default:
43                 return(UNDEFINED_TYPE);
44         }
45         return(UNDEFINED_TYPE);
46 };
47
48 int assign_type_from_string(std::string st){
49 //              convert to upper case
50         std::for_each(st.begin(), st.end(), [](char & c) {
51                 c = ::toupper(c);
52         });
53
54         if(st == "BOOL"){
55                 return BOOL_TYPE;
56         }
57         if(st == "USHORT"){
58                 return USHORT_TYPE;
59         }
60         if(st == "UINT"){
61                 return UINT_TYPE;
62         }
63         if(st == "INT"){
64                 return INT_TYPE;
65         }
66         if(st == "ULLONG"){
67                 return ULLONG_TYPE;
68         }
69         if(st == "LLONG"){
70                 return LLONG_TYPE;
71         }
72         if(st == "FLOAT"){
73                 return FLOAT_TYPE;
74         }
75         if(st == "STRING" || st == "V_STR"){
76                 return VSTR_TYPE;               
77         }
78         if(st == "TIMEVAL"){
79                 return TIMEVAL_TYPE;
80         }
81         if(st == "IP"){
82                 return IP_TYPE;
83         }
84         if(st == "IPV6"){
85                 return IPV6_TYPE;
86         }
87         return 0;
88 }
89
90 std::string type_to_string(int typ){
91         switch(typ){
92         case BOOL_TYPE:
93                 return "BOOL";
94         case USHORT_TYPE:
95                 return "USHORT";
96         case UINT_TYPE:
97                 return "UINT";
98         case INT_TYPE:
99                 return "INT";
100         case ULLONG_TYPE:
101                 return  "ULLONG";
102         case LLONG_TYPE:
103                 return "LLONG";
104         case FLOAT_TYPE:
105                 return "FLOAT";
106         case VSTR_TYPE:
107                 return "STRING";
108         case TIMEVAL_TYPE:
109                 return "TIMEVAL";
110         case IP_TYPE:
111                 return "IP";
112         case IPV6_TYPE:
113                 return "IPV6_TYPE";
114         default:
115                 return "UNDEFINED";
116         }
117         return "UNDEFINED";
118 }
119         
120 //              there is a casting function
121 bool is_castable(int src, int dst){
122         switch(src){
123         case BOOL_TYPE:
124                 switch(dst){
125                 case BOOL_TYPE:
126                 case USHORT_TYPE:
127                 case UINT_TYPE:
128                 case INT_TYPE:
129                 case ULLONG_TYPE:
130                 case LLONG_TYPE:
131                 case FLOAT_TYPE:
132                 case VSTR_TYPE:
133                         return true;
134                 default:
135                         return false;
136                 }
137         case USHORT_TYPE:
138                 switch(dst){
139                 case BOOL_TYPE:
140                 case USHORT_TYPE:
141                 case UINT_TYPE:
142                 case INT_TYPE:
143                 case ULLONG_TYPE:
144                 case LLONG_TYPE:
145                 case FLOAT_TYPE:
146                 case VSTR_TYPE:
147                         return true;
148                 default:
149                         return false;
150                 }
151         case UINT_TYPE:
152                 switch(dst){
153                 case BOOL_TYPE:
154                 case USHORT_TYPE:
155                 case UINT_TYPE:
156                 case INT_TYPE:
157                 case ULLONG_TYPE:
158                 case LLONG_TYPE:
159                 case FLOAT_TYPE:
160                 case VSTR_TYPE:
161                         return true;
162                 default:
163                         return false;
164                 }
165         case INT_TYPE:
166                 switch(dst){
167                 case BOOL_TYPE:
168                 case USHORT_TYPE:
169                 case UINT_TYPE:
170                 case INT_TYPE:
171                 case ULLONG_TYPE:
172                 case LLONG_TYPE:
173                 case FLOAT_TYPE:
174                 case VSTR_TYPE:
175                         return true;
176                 default:
177                         return false;
178                 }
179         case ULLONG_TYPE:
180                 switch(dst){
181                 case BOOL_TYPE:
182                 case USHORT_TYPE:
183                 case UINT_TYPE:
184                 case INT_TYPE:
185                 case ULLONG_TYPE:
186                 case LLONG_TYPE:
187                 case FLOAT_TYPE:
188                 case VSTR_TYPE:
189                         return true;
190                 default:
191                         return false;
192                 }
193         case LLONG_TYPE:
194                 switch(dst){
195                 case BOOL_TYPE:
196                 case USHORT_TYPE:
197                 case UINT_TYPE:
198                 case INT_TYPE:
199                 case ULLONG_TYPE:
200                 case LLONG_TYPE:
201                 case FLOAT_TYPE:
202                 case VSTR_TYPE:
203                         return true;
204                 default:
205                         return false;
206                 }
207         case FLOAT_TYPE:
208                 switch(dst){
209                 case FLOAT_TYPE:
210                 case VSTR_TYPE:
211                         return true;
212                 default:
213                         return false;
214                 }
215         case VSTR_TYPE:
216                 switch(dst){
217                 case VSTR_TYPE:
218                         return true;
219                 default:
220                         return false;
221                 }
222         case TIMEVAL_TYPE:
223                 switch(dst){
224                 case TIMEVAL_TYPE:
225                 case VSTR_TYPE:
226                         return true;
227                 default:
228                         return false;
229                 }
230         case IP_TYPE:
231                 switch(dst){
232                 case IP_TYPE:
233                 case VSTR_TYPE:
234                         return true;
235                 default:
236                         return false;
237                 }
238         case IPV6_TYPE:
239                 switch(dst){
240                 case IPV6_TYPE:
241                 case VSTR_TYPE:
242                         return true;
243                 default:
244                         return false;
245                 }
246         default:
247                 return false;
248         }
249         return false;
250 }
251
252 //              cast without loss of information
253 bool is_compatible(int src, int dst){
254         switch(src){
255         case BOOL_TYPE:
256                 switch(dst){
257                 case BOOL_TYPE:
258                 case USHORT_TYPE:
259                 case UINT_TYPE:
260                 case INT_TYPE:
261                 case ULLONG_TYPE:
262                 case LLONG_TYPE:
263                 case FLOAT_TYPE:
264                 case VSTR_TYPE:
265                         return true;
266                 default:
267                         return false;
268                 }
269         case USHORT_TYPE:
270                 switch(dst){
271                 case USHORT_TYPE:
272                 case UINT_TYPE:
273                 case INT_TYPE:
274                 case ULLONG_TYPE:
275                 case LLONG_TYPE:
276                 case FLOAT_TYPE:
277                 case VSTR_TYPE:
278                         return true;
279                 default:
280                         return false;
281                 }
282         case UINT_TYPE:
283                 switch(dst){
284                 case UINT_TYPE:
285                 case INT_TYPE:
286                 case ULLONG_TYPE:
287                 case LLONG_TYPE:
288                 case FLOAT_TYPE:
289                 case VSTR_TYPE:
290                         return true;
291                 default:
292                         return false;
293                 }
294         case INT_TYPE:
295                 switch(dst){
296                 case INT_TYPE:
297                 case ULLONG_TYPE:
298                 case LLONG_TYPE:
299                 case FLOAT_TYPE:
300                 case VSTR_TYPE:
301                         return true;
302                 default:
303                         return false;
304                 }
305         case ULLONG_TYPE:
306                 switch(dst){
307                 case ULLONG_TYPE:
308                 case LLONG_TYPE:
309                 case FLOAT_TYPE:
310                 case VSTR_TYPE:
311                         return true;
312                 default:
313                         return false;
314                 }
315         case LLONG_TYPE:
316                 switch(dst){
317                 case LLONG_TYPE:
318                 case FLOAT_TYPE:
319                 case VSTR_TYPE:
320                         return true;
321                 default:
322                         return false;
323                 }
324         case FLOAT_TYPE:
325                 switch(dst){
326                 case FLOAT_TYPE:
327                 case VSTR_TYPE:
328                         return true;
329                 default:
330                         return false;
331                 }
332         case VSTR_TYPE:
333                 switch(dst){
334                 case VSTR_TYPE:
335                         return true;
336                 default:
337                         return false;
338                 }
339         case TIMEVAL_TYPE:
340                 switch(dst){
341                 case TIMEVAL_TYPE:
342                 case VSTR_TYPE:
343                         return true;
344                 default:
345                         return false;
346                 }
347         case IP_TYPE:
348                 switch(dst){
349                 case IP_TYPE:
350                 case VSTR_TYPE:
351                         return true;
352                 default:
353                         return false;
354                 }
355         case IPV6_TYPE:
356                 switch(dst){
357                 case IPV6_TYPE:
358                 case VSTR_TYPE:
359                         return true;
360                 default:
361                         return false;
362                 }
363         default:
364                 return false;
365         }
366         return false;
367 }
368
369 //////////////////////////////////////////////////////
370 //              Field_entry
371
372 std::string field_entry::load_from_json(mc_json::json_value *froot){
373         this->init();
374         for(mc_json::json_value *fparts=froot->first_child; fparts!=NULL; fparts=fparts->next_sibling){
375                 if(strcmp(fparts->name, "name")==0){
376                         if(fparts->type!=mc_json::JSON_STRING){
377                                 return "Error, the name of a field must be a string ("+std::to_string(fparts->type)+")";
378                         }
379                         name = fparts->string_value;
380                 }
381                 if(strcmp(fparts->name, "type")==0){
382                         if(fparts->type!=mc_json::JSON_STRING){
383                                 return "Error, the type of a field must be a string ("+std::to_string(fparts->type)+")";
384                         }
385                         type = fparts->string_value;
386                 }
387                 if(strcmp(fparts->name, "pos")==0){
388                         if(fparts->type!=mc_json::JSON_STRING){
389                                 return "Error, the pos of a field must be an int ("+std::to_string(fparts->type)+")";
390                         }
391                         pos = atoi(fparts->string_value);
392                 }
393                 if(strcmp(fparts->name, "is_ts")==0){
394                         if(fparts->type!=mc_json::JSON_BOOL){
395                                 return "Error, the is_ts of a field must be a bool ("+std::to_string(fparts->type)+")";
396                         }
397                         is_ts = fparts->int_value;
398                 }
399         }
400         return "";
401 }
402
403         
404         
405
406
407 int tuple_access_info::init(field_entry *fe){
408         field_name = fe->name;
409         pdt = assign_type_from_string(fe->type);
410         is_ts = fe->is_ts;
411         offset = 0;
412         return(pdt);
413 };
414
415 std::string tuple_access_info::to_string(){
416         std::string ret = field_name+": offset="+std::to_string(offset)+", type="+type_to_string(pdt);
417         if(is_ts){
418                 ret+=", is_ts";
419         }
420         return ret;
421 }
422
423 //////////////////////////////////////////////////////////////////
424 //              query_rep implementation
425 /////////////////////////////////////////////////////////////////
426
427
428 std::string _query_rep::init(const mc_json::json_value *strm){
429         min_tuple_size = 0;
430
431         if(strm->type != mc_json::JSON_OBJECT){
432                 return "Error, json stream must be a dict ("+std::to_string(strm->type)+").";
433         }
434         this->name = strm->name;
435         for(mc_json::json_value *sparts=strm->first_child; sparts!=NULL; sparts=sparts->next_sibling){
436 //keys
437                 if(strcmp(sparts->name, "keys")==0){
438                         if(sparts->type != mc_json::JSON_ARRAY){
439                                 return "Error, the keys in stream must be an array (" +std::to_string(sparts->type)+ ").";
440                                 }
441                                 for(mc_json::json_value *kparts=sparts->first_child; kparts!=NULL; kparts=kparts->next_sibling){
442                                         if(kparts->type != mc_json::JSON_STRING){
443                                                 return "Error, the key entries in a stream must all be strings (" +std::to_string(kparts->type)+").";
444                                         }
445                                         keys.push_back(kparts->string_value);
446                                 }
447                         }
448 // fields
449                 if(strcmp(sparts->name, "fields")==0){
450                         if(sparts->type != mc_json::JSON_ARRAY){
451                                 return "Error, the fields in a stream must all be dict (" +std::to_string(sparts->type )+ ").";
452                         }
453                         for(mc_json::json_value *field=sparts->first_child; field!=NULL; field=field->next_sibling){
454                                 if(field->type != mc_json::JSON_OBJECT){
455                                         return "Error, the field entries in a stream must all be dicts (" +std::to_string(field->type )+ ").";
456                                 }
457                                 field_entry fe;
458                                 std::string err = fe.load_from_json(field);
459                                 if(err!=""){
460                                         return "Error loading stream "+std::string(this->name)+": "+err;
461                                 }
462                                 tuple_access_info tai;
463                                 int pdt = tai.init(&fe);
464                                 if(pdt==UNDEFINED_TYPE){
465                                         err = "Error in field "+fe.name+" of stream "+this->name+", unknown type "+fe.type;
466                                         return err;
467                                 }
468                                 field_info.push_back(tai);
469                         }
470                 }
471         }
472
473         return "";
474 }
475
476
477 int _query_rep::finalize(){
478         int f;
479         int curr_pos = 0;
480         int fld_undefined = 0;
481         for(f=0;f<field_info.size();++f){
482                 field_info[f].offset = curr_pos;
483                 int sz = type_size(field_info[f].pdt);
484                 if(sz==0) fld_undefined = 1;
485                 curr_pos += sz;
486         }
487         min_tuple_size = curr_pos;
488         if(fld_undefined) return(-1);
489         else return(0);
490 }
491
492 //              Return a text representation
493 std::string _query_rep::to_string(){
494         std::string ret = name + ": keys=[";
495         for(int k=0;k<keys.size();++k){
496                 if(k>0)
497                         ret+=",";
498                 ret += keys[k];
499         }
500         ret += "], fields=\n";
501         for(int f=0;f<field_info.size();++f){
502                 ret += field_info[f].to_string()+"\n";
503         }
504         ret+="\tmin_size="+std::to_string(min_tuple_size)+"\n";
505         return ret;
506 }
507
508 //              Number of fields
509 int  _query_rep::get_num_fields(){
510         return field_info.size();
511 }
512
513 //              name of ith field (starting at zero)
514 std::string _query_rep::get_field_name(int i){
515         return field_info[i].field_name;
516 }
517
518 //              lookup field index by name, -1 if not found
519 int _query_rep::get_index_of_field(std::string name){
520         for(int i=0;i<field_info.size();++i){
521                 if(field_info[i].field_name==name)
522                         return i;
523         }
524         return -1;
525 }
526
527 //              lookup field handle by name, offset is -1 if not found
528 field_handle _query_rep::get_handle_of_field(std::string name){
529         field_handle ret;
530         ret.offset = -1;
531         for(int i=0;i<field_info.size();++i){
532                 if(field_info[i].field_name==name){
533                         ret.offset = field_info[i].offset;
534                         ret.type = field_info[i].pdt;
535                         return ret;
536                 }
537         }
538         return ret;
539 }
540
541
542 //              data type of ith field.
543 int _query_rep::get_type(int i){
544         if(i<0 || i>=field_info.size())
545                 return UNDEFINED_TYPE;
546         return field_info[i].pdt;
547 }
548
549 std::string _query_rep::get_type_name(int i){
550         return type_to_string(this->get_type(i));
551 }
552
553 //              byte offset of ith field in a data block
554 int _query_rep::get_offset(int i){
555         if(i<0 || i>field_info.size())
556                 return 0;
557         return field_info[i].offset;
558 }
559
560 //              byte offset of ith field in a data block
561 field_handle _query_rep::get_handle(int i){
562         field_handle ret;
563         ret.offset = -1;
564         if(i<0 || i>field_info.size())
565                 return ret;
566         ret.offset = field_info[i].offset;
567         ret.type = field_info[i].pdt;
568         return ret;
569 }
570
571
572
573
574 //////////////////////////////////////////////////////////////////
575 //      mc_schemas implementation
576
577 //              n is a char buffer holding the json description of the stream schemas
578 _mc_schemas::_mc_schemas(const char *n) : mc_schemas() {
579         this->init(n);
580 }
581 //              n is a string holding the json description of the stream schemas
582 _mc_schemas::_mc_schemas(std::string s){
583         this->init(s.c_str());
584 }
585
586 void _mc_schemas::init(const char *n){
587         nib_str = strdup(n);
588
589         char *errorPos = 0;
590         char *errorDesc = 0;
591         int errorLine = 0;
592         mc_json::block_allocator allocator(1 << 10); // 1 KB per block
593         mc_json::json_value *jroot = mc_json::json_parse(nib_str, &errorPos, (const char**)&errorDesc, &errorLine, &allocator);
594
595         if(jroot->type != mc_json::JSON_OBJECT){
596                 err =  "Error, root of the nib json must be a dict.";
597                 return ; 
598         }
599
600         for(mc_json::json_value *stream=jroot->first_child; stream!=NULL; stream=stream->next_sibling){
601                 if(stream->type != mc_json::JSON_OBJECT){
602                         err = "Error, the streams in the nib json must all be dict (" +std::to_string(stream->type )+ ").";
603                         return ;
604                 }
605                 std::string stream_name = stream->name;
606                 _query_rep *qr = new _query_rep();
607                 std::string stream_err = qr->init(stream);
608                 if(stream_err == ""){
609                         qr->finalize();
610                         qreps[stream_name] = qr;
611                 }else{
612                         qerrs[stream_name] = stream_err;
613                         delete qr;
614                 }
615         }
616 }
617
618 //              true if there are any errors.
619 bool _mc_schemas::has_errors(){
620         if(err!="")
621                 return true;
622         if(qerrs.size()>0)
623                 return true;
624         return false;
625 }
626
627 //              string with the error reports.  empty if there is no error.
628 std::string _mc_schemas::get_errors(){
629         std::string ret = this->err;
630         for(auto mi=qerrs.begin(); mi!=qerrs.end(); ++mi){
631                 if(err!="")
632                         err += "\n";
633                 err += (*mi).first+": "+(*mi).second;
634         }
635         return err;
636 }
637
638 //              return the names of the parsed streams.
639 std::vector<std::string> _mc_schemas::get_streams(){
640         std::vector<std::string> ret;
641         for(auto mi=qreps.begin(); mi!=qreps.end(); ++mi){
642                 ret.push_back(mi->first);
643         }
644         return ret;
645 }
646
647 //              return the names of the unsucessfully parsed streams
648 std::vector<std::string> _mc_schemas::get_error_streams(){
649         std::vector<std::string> ret;
650         for(auto mi=qerrs.begin(); mi!=qerrs.end(); ++mi){
651                 ret.push_back(mi->first);
652         }
653         return ret;
654 }
655
656 //              true if some stream was parsed successful or not
657 bool _mc_schemas::stream_found(std::string s){
658         if(qreps.count(s)+qerrs.count(s) > 0)
659                 return true;
660         return false;
661 }
662
663 //              true if there is a stream with name s which parsed successfully
664 bool _mc_schemas::stream_ok(std::string s){
665         return qreps.count(s) > 0;
666 }
667
668 //              return the error associated with a stream, if any.
669 std::string _mc_schemas::get_stream_error(std::string s){
670         if(qerrs.count(s)>0)
671                 return qerrs[s];
672         if(qreps.count(s)>0)
673                 return "";
674         return "not_found";
675 }
676
677 //              Get the query representation of a successfully parsed stream
678 query_rep *_mc_schemas::get_query_rep(std::string s){
679         if(qreps.count(s)>0)
680                 return qreps[s];
681         return NULL;
682 }
683
684 //      Destructor
685 _mc_schemas::~_mc_schemas(){
686         free(nib_str);
687         for(auto q=qreps.begin(); q!=qreps.end();++q){
688                 delete q->second;
689         }
690 }
691
692
693 ////////////
694 //      mc_schemas factory
695 mc_schemas *new_mc_schemas(std::string s){
696         return new _mc_schemas(s);
697 }
698 mc_schemas *new_mc_schemas(const char *s){
699         return new _mc_schemas(s);
700 }
701
702
703 ////////////////////////////////////////////
704 //                      Direct tuple access functions.
705
706 unsigned int unpack_uint(void *data, int len, int offset, int *problem){
707         unsigned int retval;
708         if(offset+sizeof(unsigned int) > len){
709                 *problem = 1;
710                 return(0);
711         }
712         memcpy(&retval, ((char *)data)+offset, sizeof(unsigned int));
713         return(retval);
714 }
715 unsigned int unpack_ushort(void *data, int len, int offset, int *problem){
716         unsigned int retval;
717         if(offset+sizeof(unsigned int) > len){
718                 *problem = 1;
719                 return(0);
720         }
721         memcpy(&retval, ((char *)data)+offset, sizeof(unsigned int));
722         return(retval);
723 }
724 unsigned int unpack_bool(void *data, int len, int offset, int *problem){
725         unsigned int retval;
726         if(offset+sizeof(unsigned int) > len){
727                 *problem = 1;
728                 return(0);
729         }
730         memcpy(&retval, ((char *)data)+offset, sizeof(unsigned int));
731         return(retval);
732 }
733 int unpack_int(void *data, int len, int offset, int *problem){
734         int retval;
735         if(offset+sizeof(int) > len){
736                 *problem = 1;
737                 return(0);
738         }
739         memcpy(&retval, ((char *)data)+offset, sizeof(unsigned int));
740         return(retval);
741 }
742 unsigned long long int unpack_ullong(void *data, int len, int offset, int *problem){
743         unsigned long long int retval;
744         if(offset+sizeof(unsigned long long int) > len){
745                 *problem = 1;
746                 return(0);
747         }
748         memcpy(&retval, ((char *)data)+offset, sizeof(unsigned long long int));
749         return(retval);
750 }
751 long long int unpack_llong(void *data, int len, int offset, int *problem){
752         long long int retval;
753         if(offset+sizeof(long long int) > len){
754                 *problem = 1;
755                 return(0);
756         }
757         memcpy(&retval, ((char *)data)+offset, sizeof(long long int));
758         return(retval);
759 }
760 double unpack_float(void *data, int len, int offset, int *problem){
761         double retval;
762         if(offset+sizeof(double) > len){
763                 *problem = 1;
764                 return(0);
765         }
766         memcpy(&retval, ((char *)data)+offset, sizeof(double));
767         return(retval);
768 }
769 timeval unpack_timeval(void *data, int len, int offset, int *problem){
770         timeval retval;
771         if(offset+sizeof(timeval) > len){
772                 *problem = 1;
773                 retval.tv_sec = 0;
774                 retval.tv_usec = 0;
775                 return(retval);
776         }
777         memcpy(&retval, ((char *)data)+offset, sizeof(timeval));
778         return(retval);
779 }
780 mc_string unpack_vstr(void *data,  int len, int offset, int *problem){
781         mc_string retval;
782         vstring32 unpack_s;
783
784         if(offset+sizeof( vstring32) > len){
785                 *problem = 1;
786                 return(retval);
787         }
788
789         memcpy(&unpack_s, ((char *)data)+offset, sizeof(vstring32));
790
791         retval.length = unpack_s.length;
792
793         if(unpack_s.offset + retval.length > len){
794                 *problem = 1;
795                 return(retval);
796         }
797         retval.data = (char *)data + unpack_s.offset;
798         return(retval);
799 }
800
801 struct mc_ipv6_str unpack_ipv6(void *data,  int len, int offset, int *problem){
802         struct mc_ipv6_str retval;
803         if(offset+sizeof(mc_ipv6_str) > len){
804                 *problem = 1;
805                 return(retval);
806         }
807         memcpy(&retval, ((char *)data)+offset, sizeof(mc_ipv6_str));
808         return(retval);
809 }
810
811
812 access_result get_field_by_index(query_rep *qr, int index,
813                         void * data, int len){
814         access_result retval;
815         retval.field_data_type = UNDEFINED_TYPE;
816         int problem = 0;
817
818         if(index >= qr->get_num_fields()){
819                 return(retval);
820         }
821
822         switch(qr->get_type(index)){
823         case UINT_TYPE:
824                 retval.r.ui = unpack_uint(data,  len,
825                         qr->get_offset(index), &problem);
826                 if(!problem) retval.field_data_type = UINT_TYPE;
827                 break;
828         case IP_TYPE:
829                 retval.r.ui = unpack_uint(data,  len,
830                         qr->get_offset(index), &problem);
831                 if(!problem) retval.field_data_type = IP_TYPE;
832                 break;
833         case INT_TYPE:
834                 retval.r.i = unpack_int(data,  len,
835                         qr->get_offset(index), &problem);
836                 if(!problem) retval.field_data_type = INT_TYPE;
837                 break;
838         case ULLONG_TYPE:
839                 retval.r.ul = unpack_ullong(data,  len,
840                         qr->get_offset(index), &problem);
841                 if(!problem) retval.field_data_type = ULLONG_TYPE;
842                 break;
843         case LLONG_TYPE:
844                 retval.r.l = unpack_llong(data,  len,
845                         qr->get_offset(index), &problem);
846                 if(!problem) retval.field_data_type = LLONG_TYPE;
847                 break;
848         case USHORT_TYPE:
849                 retval.r.ui = unpack_ushort(data,  len,
850                         qr->get_offset(index), &problem);
851                 if(!problem) retval.field_data_type = USHORT_TYPE;
852                 break;
853         case FLOAT_TYPE:
854                 retval.r.f = unpack_float(data,  len,
855                         qr->get_offset(index), &problem);
856                 if(!problem) retval.field_data_type = FLOAT_TYPE;
857                 break;
858         case BOOL_TYPE:
859                 retval.r.ui = unpack_bool(data,  len,
860                         qr->get_offset(index), &problem);
861                 if(!problem) retval.field_data_type = BOOL_TYPE;
862                 break;
863         case VSTR_TYPE:
864                 retval.r.vs = unpack_vstr(data,  len,
865                         qr->get_offset(index), &problem);
866                 if(!problem) retval.field_data_type = VSTR_TYPE;
867                 break;
868         case TIMEVAL_TYPE:
869                 retval.r.t = unpack_timeval(data,  len,
870                         qr->get_offset(index), &problem);
871                 if(!problem) retval.field_data_type = TIMEVAL_TYPE;
872                 break;
873         case IPV6_TYPE:
874                 retval.r.ip6 = unpack_ipv6(data,  len,
875                         qr->get_offset(index), &problem);
876                 if(!problem) retval.field_data_type = IPV6_TYPE;
877                 break;
878         case UNDEFINED_TYPE:
879                 break;
880         }
881         return(retval);
882 }
883
884 access_result get_field_by_handle(field_handle f, void * data, int len){
885         access_result retval;
886         retval.field_data_type = UNDEFINED_TYPE;
887         int problem = 0;
888
889         switch(f.type){
890         case UINT_TYPE:
891                 retval.r.ui = unpack_uint(data,  len, f.offset, &problem);
892                 if(!problem) retval.field_data_type = UINT_TYPE;
893                 break;
894         case IP_TYPE:
895                 retval.r.ui = unpack_uint(data,  len, f.offset, &problem);
896                 if(!problem) retval.field_data_type = IP_TYPE;
897                 break;
898         case INT_TYPE:
899                 retval.r.i = unpack_int(data,  len, f.offset, &problem);
900                 if(!problem) retval.field_data_type = INT_TYPE;
901                 break;
902         case ULLONG_TYPE:
903                 retval.r.ul = unpack_ullong(data,  len, f.offset, &problem);
904                 if(!problem) retval.field_data_type = ULLONG_TYPE;
905                 break;
906         case LLONG_TYPE:
907                 retval.r.l = unpack_llong(data,  len, f.offset, &problem);
908                 if(!problem) retval.field_data_type = LLONG_TYPE;
909                 break;
910         case USHORT_TYPE:
911                 retval.r.ui = unpack_ushort(data,  len, f.offset, &problem);
912                 if(!problem) retval.field_data_type = USHORT_TYPE;
913                 break;
914         case FLOAT_TYPE:
915                 retval.r.f = unpack_float(data,  len, f.offset, &problem);
916                 if(!problem) retval.field_data_type = FLOAT_TYPE;
917                 break;
918         case BOOL_TYPE:
919                 retval.r.ui = unpack_bool(data,  len, f.offset, &problem);
920                 if(!problem) retval.field_data_type = BOOL_TYPE;
921                 break;
922         case VSTR_TYPE:
923                 retval.r.vs = unpack_vstr(data,  len, f.offset, &problem);
924                 if(!problem) retval.field_data_type = VSTR_TYPE;
925                 break;
926         case TIMEVAL_TYPE:
927                 retval.r.t = unpack_timeval(data,  len, f.offset, &problem);
928                 if(!problem) retval.field_data_type = TIMEVAL_TYPE;
929                 break;
930         case IPV6_TYPE:
931                 retval.r.ip6 = unpack_ipv6(data,  len, f.offset, &problem);
932                 if(!problem) retval.field_data_type = IPV6_TYPE;
933                 break;
934         case UNDEFINED_TYPE:
935                 break;
936         }
937         return(retval);
938 }
939
940 int get_field_int(field_handle f, void * data, int len){
941         access_result a = get_field_by_handle(f, data, len);
942         switch(f.type){
943                 case BOOL_TYPE:
944                 case USHORT_TYPE:
945                 case UINT_TYPE:
946                         return (int)(a.r.ui);
947                 case INT_TYPE:
948                 case IP_TYPE:
949                         return (int)(a.r.i);
950                 case LLONG_TYPE:
951                         return (int)(a.r.l);
952                 case ULLONG_TYPE:
953                         return (int)(a.r.ul);
954                 case FLOAT_TYPE:
955                 case VSTR_TYPE:
956                 case TIMEVAL_TYPE:
957                 case IPV6_TYPE:
958                         return 0;
959                 default:
960                         return 0;
961         }
962         return 0;
963 }
964
965 unsigned int get_field_uint(field_handle f, void * data, int len){
966         access_result a = get_field_by_handle(f, data, len);
967         switch(f.type){
968                 case BOOL_TYPE:
969                 case USHORT_TYPE:
970                 case UINT_TYPE:
971                         return (unsigned int)(a.r.ui);
972                 case INT_TYPE:
973                 case IP_TYPE:
974                         return (unsigned int)(a.r.i);
975                 case LLONG_TYPE:
976                         return (unsigned int)(a.r.l);
977                 case ULLONG_TYPE:
978                         return (unsigned int)(a.r.ul);
979                 case FLOAT_TYPE:
980                 case VSTR_TYPE:
981                 case TIMEVAL_TYPE:
982                 case IPV6_TYPE:
983                         return 0;
984                 default:
985                         return 0;
986         }
987         return 0;
988 }
989
990 long long int get_field_llong(field_handle f, void * data, int len){
991         access_result a = get_field_by_handle(f, data, len);
992         switch(f.type){
993                 case BOOL_TYPE:
994                 case USHORT_TYPE:
995                 case UINT_TYPE:
996                         return (long long int)(a.r.ui);
997                 case INT_TYPE:
998                 case IP_TYPE:
999                         return (long long int)(a.r.i);
1000                 case LLONG_TYPE:
1001                         return (long long int)(a.r.l);
1002                 case ULLONG_TYPE:
1003                         return (long long int)(a.r.ul);
1004                 case FLOAT_TYPE:
1005                 case VSTR_TYPE:
1006                 case TIMEVAL_TYPE:
1007                 case IPV6_TYPE:
1008                         return 0;
1009                 default:
1010                         return 0;
1011         }
1012         return 0;
1013 }
1014                         
1015 unsigned long long int get_field_ullong(field_handle f, void * data, int len){
1016         access_result a = get_field_by_handle(f, data, len);
1017         switch(f.type){
1018                 case BOOL_TYPE:
1019                 case USHORT_TYPE:
1020                 case UINT_TYPE:
1021                         return (unsigned long long int)(a.r.ui);
1022                 case INT_TYPE:
1023                 case IP_TYPE:
1024                         return (unsigned long long int)(a.r.i);
1025                 case LLONG_TYPE:
1026                         return (unsigned long long int)(a.r.l);
1027                 case ULLONG_TYPE:
1028                         return (unsigned long long int)(a.r.ul);
1029                 case FLOAT_TYPE:
1030                 case VSTR_TYPE:
1031                 case TIMEVAL_TYPE:
1032                 case IPV6_TYPE:
1033                         return 0;
1034                 default:
1035                         return 0;
1036         }
1037         return 0;
1038 }
1039
1040 double get_field_float(field_handle f, void * data, int len){
1041         access_result a = get_field_by_handle(f, data, len);
1042         switch(f.type){
1043                 case BOOL_TYPE:
1044                 case USHORT_TYPE:
1045                 case UINT_TYPE:
1046                         return (unsigned long long int)(a.r.ui);
1047                 case INT_TYPE:
1048                 case IP_TYPE:
1049                         return (unsigned long long int)(a.r.i);
1050                 case LLONG_TYPE:
1051                         return (unsigned long long int)(a.r.l);
1052                 case ULLONG_TYPE:
1053                         return (unsigned long long int)(a.r.ul);
1054                 case FLOAT_TYPE:
1055                 case VSTR_TYPE:
1056                 case TIMEVAL_TYPE:
1057                 case IPV6_TYPE:
1058                         return 0;
1059                 default:
1060                         return 0;
1061         }
1062         return 0;
1063 }
1064 timeval get_field_timeval(field_handle f, void * data, int len){
1065         access_result a = get_field_by_handle(f, data, len);
1066         switch(f.type){
1067                 case BOOL_TYPE:
1068                 case USHORT_TYPE:
1069                 case UINT_TYPE:
1070                 case INT_TYPE:
1071                 case IP_TYPE:
1072                 case LLONG_TYPE:
1073                 case ULLONG_TYPE:
1074                 case FLOAT_TYPE:
1075                 case VSTR_TYPE:
1076                 case IPV6_TYPE:
1077                         a.r.t.tv_sec = 0;
1078                         a.r.t.tv_usec = 0;
1079                         return a.r.t;
1080                 case TIMEVAL_TYPE:
1081                         return a.r.t;
1082                 default:
1083                         a.r.t.tv_sec = 0;
1084                         a.r.t.tv_usec = 0;
1085                         return a.r.t;
1086         }
1087         a.r.t.tv_sec = 0;
1088         a.r.t.tv_usec = 0;
1089         return a.r.t;
1090 }
1091
1092 mc_ipv6_str get_field_ipv6(field_handle f, void * data, int len){
1093         access_result a = get_field_by_handle(f, data, len);
1094         switch(f.type){
1095                 case BOOL_TYPE:
1096                 case USHORT_TYPE:
1097                 case UINT_TYPE:
1098                 case INT_TYPE:
1099                 case IP_TYPE:
1100                 case LLONG_TYPE:
1101                 case ULLONG_TYPE:
1102                 case FLOAT_TYPE:
1103                 case VSTR_TYPE:
1104                 case TIMEVAL_TYPE:
1105                         a.r.ip6.v[0] = 0;
1106                         a.r.ip6.v[1] = 0;
1107                         a.r.ip6.v[2] = 0;
1108                         a.r.ip6.v[3] = 0;
1109                         return a.r.ip6;
1110                 case IPV6_TYPE:
1111                         return a.r.ip6;
1112                 default:
1113                         a.r.ip6.v[0] = 0;
1114                         a.r.ip6.v[1] = 0;
1115                         a.r.ip6.v[2] = 0;
1116                         a.r.ip6.v[3] = 0;
1117                         return a.r.ip6;
1118         }
1119         a.r.ip6.v[0] = 0;
1120         a.r.ip6.v[1] = 0;
1121         a.r.ip6.v[2] = 0;
1122         a.r.ip6.v[3] = 0;
1123         return a.r.ip6;
1124 }
1125         
1126
1127 std::string get_field_string(field_handle f, void * data, int len){
1128         access_result a = get_field_by_handle(f, data, len);
1129         switch(f.type){
1130                 case BOOL_TYPE:
1131                 case USHORT_TYPE:
1132                 case UINT_TYPE:
1133                         return std::to_string(a.r.ui);
1134                 case INT_TYPE:
1135                 case IP_TYPE:
1136                         return std::to_string(a.r.i);
1137                 case LLONG_TYPE:
1138                         return std::to_string(a.r.l);
1139                 case ULLONG_TYPE:
1140                         return std::to_string(a.r.ul);
1141                 case FLOAT_TYPE:
1142                         return std::to_string(a.r.f);
1143                 case VSTR_TYPE:{
1144                         std::string rets(a.r.vs.data, a.r.vs.length);
1145                         return rets;
1146                 }
1147                 case TIMEVAL_TYPE:{
1148                         double tv = a.r.t.tv_sec + ((double)a.r.t.tv_usec)/1000000.0;
1149                         return std::to_string(tv);
1150                 }
1151                 case IPV6_TYPE:{
1152                         char buf[100];
1153                         sprintf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
1154                                 a.r.ip6.v[0] >> 16, (a.r.ip6.v[0]) & 0xffff,
1155                                 a.r.ip6.v[1] >> 16, (a.r.ip6.v[1]) & 0xffff,
1156                                 a.r.ip6.v[2] >> 16, (a.r.ip6.v[2]) & 0xffff,
1157                                 a.r.ip6.v[3] >> 16, (a.r.ip6.v[3]) & 0xffff
1158                         );
1159                         return buf;
1160                 }
1161                 default:
1162                         return "";
1163         }
1164         return "";
1165 }
1166                 
1167 }
1168
1169