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
7 http://www.apache.org/licenses/LICENSE-2.0
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 ------------------------------------------- */
16 #include "schemaparser_impl.h"
21 int type_size(int dt){
29 return(sizeof(unsigned int));
31 return(sizeof(unsigned long long int));
33 return(sizeof(long long int));
35 return(sizeof(double));
37 return(sizeof(mc_ipv6_str));
39 return(sizeof(timeval));
41 return(sizeof(mc_string));
43 return(UNDEFINED_TYPE);
45 return(UNDEFINED_TYPE);
48 int assign_type_from_string(std::string st){
49 // convert to upper case
50 std::for_each(st.begin(), st.end(), [](char & c) {
75 if(st == "STRING" || st == "V_STR"){
90 std::string type_to_string(int typ){
120 // there is a casting function
121 bool is_castable(int src, int dst){
252 // cast without loss of information
253 bool is_compatible(int src, int dst){
369 //////////////////////////////////////////////////////
372 std::string field_entry::load_from_json(mc_json::json_value *froot){
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)+")";
379 name = fparts->string_value;
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)+")";
385 type = fparts->string_value;
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)+")";
391 pos = atoi(fparts->string_value);
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)+")";
397 is_ts = fparts->int_value;
407 int tuple_access_info::init(field_entry *fe){
408 field_name = fe->name;
409 pdt = assign_type_from_string(fe->type);
415 std::string tuple_access_info::to_string(){
416 std::string ret = field_name+": offset="+std::to_string(offset)+", type="+type_to_string(pdt);
423 //////////////////////////////////////////////////////////////////
424 // query_rep implementation
425 /////////////////////////////////////////////////////////////////
428 std::string _query_rep::init(const mc_json::json_value *strm){
431 if(strm->type != mc_json::JSON_OBJECT){
432 return "Error, json stream must be a dict ("+std::to_string(strm->type)+").";
434 this->name = strm->name;
435 for(mc_json::json_value *sparts=strm->first_child; sparts!=NULL; sparts=sparts->next_sibling){
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)+ ").";
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)+").";
445 keys.push_back(kparts->string_value);
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 )+ ").";
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 )+ ").";
458 std::string err = fe.load_from_json(field);
460 return "Error loading stream "+std::string(this->name)+": "+err;
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;
468 field_info.push_back(tai);
477 int _query_rep::finalize(){
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;
487 min_tuple_size = curr_pos;
488 if(fld_undefined) return(-1);
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){
500 ret += "], fields=\n";
501 for(int f=0;f<field_info.size();++f){
502 ret += field_info[f].to_string()+"\n";
504 ret+="\tmin_size="+std::to_string(min_tuple_size)+"\n";
509 int _query_rep::get_num_fields(){
510 return field_info.size();
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;
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)
527 // lookup field handle by name, offset is -1 if not found
528 field_handle _query_rep::get_handle_of_field(std::string name){
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;
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;
549 std::string _query_rep::get_type_name(int i){
550 return type_to_string(this->get_type(i));
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())
557 return field_info[i].offset;
560 // byte offset of ith field in a data block
561 field_handle _query_rep::get_handle(int i){
564 if(i<0 || i>field_info.size())
566 ret.offset = field_info[i].offset;
567 ret.type = field_info[i].pdt;
574 //////////////////////////////////////////////////////////////////
575 // mc_schemas implementation
577 // n is a char buffer holding the json description of the stream schemas
578 _mc_schemas::_mc_schemas(const char *n) : mc_schemas() {
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());
586 void _mc_schemas::init(const char *n){
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);
595 if(jroot->type != mc_json::JSON_OBJECT){
596 err = "Error, root of the nib json must be a dict.";
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 )+ ").";
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 == ""){
610 qreps[stream_name] = qr;
612 qerrs[stream_name] = stream_err;
618 // true if there are any errors.
619 bool _mc_schemas::has_errors(){
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){
633 err += (*mi).first+": "+(*mi).second;
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);
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);
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)
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;
668 // return the error associated with a stream, if any.
669 std::string _mc_schemas::get_stream_error(std::string s){
677 // Get the query representation of a successfully parsed stream
678 query_rep *_mc_schemas::get_query_rep(std::string s){
685 _mc_schemas::~_mc_schemas(){
687 for(auto q=qreps.begin(); q!=qreps.end();++q){
694 // mc_schemas factory
695 mc_schemas *new_mc_schemas(std::string s){
696 return new _mc_schemas(s);
698 mc_schemas *new_mc_schemas(const char *s){
699 return new _mc_schemas(s);
703 ////////////////////////////////////////////
704 // Direct tuple access functions.
706 unsigned int unpack_uint(void *data, int len, int offset, int *problem){
708 if(offset+sizeof(unsigned int) > len){
712 memcpy(&retval, ((char *)data)+offset, sizeof(unsigned int));
715 unsigned int unpack_ushort(void *data, int len, int offset, int *problem){
717 if(offset+sizeof(unsigned int) > len){
721 memcpy(&retval, ((char *)data)+offset, sizeof(unsigned int));
724 unsigned int unpack_bool(void *data, int len, int offset, int *problem){
726 if(offset+sizeof(unsigned int) > len){
730 memcpy(&retval, ((char *)data)+offset, sizeof(unsigned int));
733 int unpack_int(void *data, int len, int offset, int *problem){
735 if(offset+sizeof(int) > len){
739 memcpy(&retval, ((char *)data)+offset, sizeof(unsigned int));
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){
748 memcpy(&retval, ((char *)data)+offset, sizeof(unsigned long long int));
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){
757 memcpy(&retval, ((char *)data)+offset, sizeof(long long int));
760 double unpack_float(void *data, int len, int offset, int *problem){
762 if(offset+sizeof(double) > len){
766 memcpy(&retval, ((char *)data)+offset, sizeof(double));
769 timeval unpack_timeval(void *data, int len, int offset, int *problem){
771 if(offset+sizeof(timeval) > len){
777 memcpy(&retval, ((char *)data)+offset, sizeof(timeval));
780 mc_string unpack_vstr(void *data, int len, int offset, int *problem){
784 if(offset+sizeof( vstring32) > len){
789 memcpy(&unpack_s, ((char *)data)+offset, sizeof(vstring32));
791 retval.length = unpack_s.length;
793 if(unpack_s.offset + retval.length > len){
797 retval.data = (char *)data + unpack_s.offset;
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){
807 memcpy(&retval, ((char *)data)+offset, sizeof(mc_ipv6_str));
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;
818 if(index >= qr->get_num_fields()){
822 switch(qr->get_type(index)){
824 retval.r.ui = unpack_uint(data, len,
825 qr->get_offset(index), &problem);
826 if(!problem) retval.field_data_type = UINT_TYPE;
829 retval.r.ui = unpack_uint(data, len,
830 qr->get_offset(index), &problem);
831 if(!problem) retval.field_data_type = IP_TYPE;
834 retval.r.i = unpack_int(data, len,
835 qr->get_offset(index), &problem);
836 if(!problem) retval.field_data_type = INT_TYPE;
839 retval.r.ul = unpack_ullong(data, len,
840 qr->get_offset(index), &problem);
841 if(!problem) retval.field_data_type = ULLONG_TYPE;
844 retval.r.l = unpack_llong(data, len,
845 qr->get_offset(index), &problem);
846 if(!problem) retval.field_data_type = LLONG_TYPE;
849 retval.r.ui = unpack_ushort(data, len,
850 qr->get_offset(index), &problem);
851 if(!problem) retval.field_data_type = USHORT_TYPE;
854 retval.r.f = unpack_float(data, len,
855 qr->get_offset(index), &problem);
856 if(!problem) retval.field_data_type = FLOAT_TYPE;
859 retval.r.ui = unpack_bool(data, len,
860 qr->get_offset(index), &problem);
861 if(!problem) retval.field_data_type = BOOL_TYPE;
864 retval.r.vs = unpack_vstr(data, len,
865 qr->get_offset(index), &problem);
866 if(!problem) retval.field_data_type = VSTR_TYPE;
869 retval.r.t = unpack_timeval(data, len,
870 qr->get_offset(index), &problem);
871 if(!problem) retval.field_data_type = TIMEVAL_TYPE;
874 retval.r.ip6 = unpack_ipv6(data, len,
875 qr->get_offset(index), &problem);
876 if(!problem) retval.field_data_type = IPV6_TYPE;
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;
891 retval.r.ui = unpack_uint(data, len, f.offset, &problem);
892 if(!problem) retval.field_data_type = UINT_TYPE;
895 retval.r.ui = unpack_uint(data, len, f.offset, &problem);
896 if(!problem) retval.field_data_type = IP_TYPE;
899 retval.r.i = unpack_int(data, len, f.offset, &problem);
900 if(!problem) retval.field_data_type = INT_TYPE;
903 retval.r.ul = unpack_ullong(data, len, f.offset, &problem);
904 if(!problem) retval.field_data_type = ULLONG_TYPE;
907 retval.r.l = unpack_llong(data, len, f.offset, &problem);
908 if(!problem) retval.field_data_type = LLONG_TYPE;
911 retval.r.ui = unpack_ushort(data, len, f.offset, &problem);
912 if(!problem) retval.field_data_type = USHORT_TYPE;
915 retval.r.f = unpack_float(data, len, f.offset, &problem);
916 if(!problem) retval.field_data_type = FLOAT_TYPE;
919 retval.r.ui = unpack_bool(data, len, f.offset, &problem);
920 if(!problem) retval.field_data_type = BOOL_TYPE;
923 retval.r.vs = unpack_vstr(data, len, f.offset, &problem);
924 if(!problem) retval.field_data_type = VSTR_TYPE;
927 retval.r.t = unpack_timeval(data, len, f.offset, &problem);
928 if(!problem) retval.field_data_type = TIMEVAL_TYPE;
931 retval.r.ip6 = unpack_ipv6(data, len, f.offset, &problem);
932 if(!problem) retval.field_data_type = IPV6_TYPE;
940 int get_field_int(field_handle f, void * data, int len){
941 access_result a = get_field_by_handle(f, data, len);
946 return (int)(a.r.ui);
953 return (int)(a.r.ul);
965 unsigned int get_field_uint(field_handle f, void * data, int len){
966 access_result a = get_field_by_handle(f, data, len);
971 return (unsigned int)(a.r.ui);
974 return (unsigned int)(a.r.i);
976 return (unsigned int)(a.r.l);
978 return (unsigned int)(a.r.ul);
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);
996 return (long long int)(a.r.ui);
999 return (long long int)(a.r.i);
1001 return (long long int)(a.r.l);
1003 return (long long int)(a.r.ul);
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);
1021 return (unsigned long long int)(a.r.ui);
1024 return (unsigned long long int)(a.r.i);
1026 return (unsigned long long int)(a.r.l);
1028 return (unsigned long long int)(a.r.ul);
1040 double get_field_float(field_handle f, void * data, int len){
1041 access_result a = get_field_by_handle(f, data, len);
1046 return (unsigned long long int)(a.r.ui);
1049 return (unsigned long long int)(a.r.i);
1051 return (unsigned long long int)(a.r.l);
1053 return (unsigned long long int)(a.r.ul);
1064 timeval get_field_timeval(field_handle f, void * data, int len){
1065 access_result a = get_field_by_handle(f, data, len);
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);
1127 std::string get_field_string(field_handle f, void * data, int len){
1128 access_result a = get_field_by_handle(f, data, len);
1133 return std::to_string(a.r.ui);
1136 return std::to_string(a.r.i);
1138 return std::to_string(a.r.l);
1140 return std::to_string(a.r.ul);
1142 return std::to_string(a.r.f);
1144 std::string rets(a.r.vs.data, a.r.vs.length);
1148 double tv = a.r.t.tv_sec + ((double)a.r.t.tv_usec)/1000000.0;
1149 return std::to_string(tv);
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