/* ------------------------------------------------ Copyright 2020 AT&T Intellectual Property Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ------------------------------------------- */ #include "schemaparser_impl.h" #include namespace mc_schema{ int type_size(int dt){ switch(dt){ case INT_TYPE: return(sizeof(int)); case UINT_TYPE: case USHORT_TYPE: case BOOL_TYPE: case IP_TYPE: return(sizeof(unsigned int)); case ULLONG_TYPE: return(sizeof(unsigned long long int)); case LLONG_TYPE: return(sizeof(long long int)); case FLOAT_TYPE: return(sizeof(double)); case IPV6_TYPE: return(sizeof(mc_ipv6_str)); case TIMEVAL_TYPE: return(sizeof(timeval)); case VSTR_TYPE: return(sizeof(mc_string)); default: return(UNDEFINED_TYPE); } return(UNDEFINED_TYPE); }; int assign_type_from_string(std::string st){ // convert to upper case std::for_each(st.begin(), st.end(), [](char & c) { c = ::toupper(c); }); if(st == "BOOL"){ return BOOL_TYPE; } if(st == "USHORT"){ return USHORT_TYPE; } if(st == "UINT"){ return UINT_TYPE; } if(st == "INT"){ return INT_TYPE; } if(st == "ULLONG"){ return ULLONG_TYPE; } if(st == "LLONG"){ return LLONG_TYPE; } if(st == "FLOAT"){ return FLOAT_TYPE; } if(st == "STRING" || st == "V_STR"){ return VSTR_TYPE; } if(st == "TIMEVAL"){ return TIMEVAL_TYPE; } if(st == "IP"){ return IP_TYPE; } if(st == "IPV6"){ return IPV6_TYPE; } return 0; } std::string type_to_string(int typ){ switch(typ){ case BOOL_TYPE: return "BOOL"; case USHORT_TYPE: return "USHORT"; case UINT_TYPE: return "UINT"; case INT_TYPE: return "INT"; case ULLONG_TYPE: return "ULLONG"; case LLONG_TYPE: return "LLONG"; case FLOAT_TYPE: return "FLOAT"; case VSTR_TYPE: return "STRING"; case TIMEVAL_TYPE: return "TIMEVAL"; case IP_TYPE: return "IP"; case IPV6_TYPE: return "IPV6_TYPE"; default: return "UNDEFINED"; } return "UNDEFINED"; } // there is a casting function bool is_castable(int src, int dst){ switch(src){ case BOOL_TYPE: switch(dst){ case BOOL_TYPE: case USHORT_TYPE: case UINT_TYPE: case INT_TYPE: case ULLONG_TYPE: case LLONG_TYPE: case FLOAT_TYPE: case VSTR_TYPE: return true; default: return false; } case USHORT_TYPE: switch(dst){ case BOOL_TYPE: case USHORT_TYPE: case UINT_TYPE: case INT_TYPE: case ULLONG_TYPE: case LLONG_TYPE: case FLOAT_TYPE: case VSTR_TYPE: return true; default: return false; } case UINT_TYPE: switch(dst){ case BOOL_TYPE: case USHORT_TYPE: case UINT_TYPE: case INT_TYPE: case ULLONG_TYPE: case LLONG_TYPE: case FLOAT_TYPE: case VSTR_TYPE: return true; default: return false; } case INT_TYPE: switch(dst){ case BOOL_TYPE: case USHORT_TYPE: case UINT_TYPE: case INT_TYPE: case ULLONG_TYPE: case LLONG_TYPE: case FLOAT_TYPE: case VSTR_TYPE: return true; default: return false; } case ULLONG_TYPE: switch(dst){ case BOOL_TYPE: case USHORT_TYPE: case UINT_TYPE: case INT_TYPE: case ULLONG_TYPE: case LLONG_TYPE: case FLOAT_TYPE: case VSTR_TYPE: return true; default: return false; } case LLONG_TYPE: switch(dst){ case BOOL_TYPE: case USHORT_TYPE: case UINT_TYPE: case INT_TYPE: case ULLONG_TYPE: case LLONG_TYPE: case FLOAT_TYPE: case VSTR_TYPE: return true; default: return false; } case FLOAT_TYPE: switch(dst){ case FLOAT_TYPE: case VSTR_TYPE: return true; default: return false; } case VSTR_TYPE: switch(dst){ case VSTR_TYPE: return true; default: return false; } case TIMEVAL_TYPE: switch(dst){ case TIMEVAL_TYPE: case VSTR_TYPE: return true; default: return false; } case IP_TYPE: switch(dst){ case IP_TYPE: case VSTR_TYPE: return true; default: return false; } case IPV6_TYPE: switch(dst){ case IPV6_TYPE: case VSTR_TYPE: return true; default: return false; } default: return false; } return false; } // cast without loss of information bool is_compatible(int src, int dst){ switch(src){ case BOOL_TYPE: switch(dst){ case BOOL_TYPE: case USHORT_TYPE: case UINT_TYPE: case INT_TYPE: case ULLONG_TYPE: case LLONG_TYPE: case FLOAT_TYPE: case VSTR_TYPE: return true; default: return false; } case USHORT_TYPE: switch(dst){ case USHORT_TYPE: case UINT_TYPE: case INT_TYPE: case ULLONG_TYPE: case LLONG_TYPE: case FLOAT_TYPE: case VSTR_TYPE: return true; default: return false; } case UINT_TYPE: switch(dst){ case UINT_TYPE: case INT_TYPE: case ULLONG_TYPE: case LLONG_TYPE: case FLOAT_TYPE: case VSTR_TYPE: return true; default: return false; } case INT_TYPE: switch(dst){ case INT_TYPE: case ULLONG_TYPE: case LLONG_TYPE: case FLOAT_TYPE: case VSTR_TYPE: return true; default: return false; } case ULLONG_TYPE: switch(dst){ case ULLONG_TYPE: case LLONG_TYPE: case FLOAT_TYPE: case VSTR_TYPE: return true; default: return false; } case LLONG_TYPE: switch(dst){ case LLONG_TYPE: case FLOAT_TYPE: case VSTR_TYPE: return true; default: return false; } case FLOAT_TYPE: switch(dst){ case FLOAT_TYPE: case VSTR_TYPE: return true; default: return false; } case VSTR_TYPE: switch(dst){ case VSTR_TYPE: return true; default: return false; } case TIMEVAL_TYPE: switch(dst){ case TIMEVAL_TYPE: case VSTR_TYPE: return true; default: return false; } case IP_TYPE: switch(dst){ case IP_TYPE: case VSTR_TYPE: return true; default: return false; } case IPV6_TYPE: switch(dst){ case IPV6_TYPE: case VSTR_TYPE: return true; default: return false; } default: return false; } return false; } ////////////////////////////////////////////////////// // Field_entry std::string field_entry::load_from_json(mc_json::json_value *froot){ this->init(); for(mc_json::json_value *fparts=froot->first_child; fparts!=NULL; fparts=fparts->next_sibling){ if(strcmp(fparts->name, "name")==0){ if(fparts->type!=mc_json::JSON_STRING){ return "Error, the name of a field must be a string ("+std::to_string(fparts->type)+")"; } name = fparts->string_value; } if(strcmp(fparts->name, "type")==0){ if(fparts->type!=mc_json::JSON_STRING){ return "Error, the type of a field must be a string ("+std::to_string(fparts->type)+")"; } type = fparts->string_value; } if(strcmp(fparts->name, "pos")==0){ if(fparts->type!=mc_json::JSON_STRING){ return "Error, the pos of a field must be an int ("+std::to_string(fparts->type)+")"; } pos = atoi(fparts->string_value); } if(strcmp(fparts->name, "is_ts")==0){ if(fparts->type!=mc_json::JSON_BOOL){ return "Error, the is_ts of a field must be a bool ("+std::to_string(fparts->type)+")"; } is_ts = fparts->int_value; } } return ""; } int tuple_access_info::init(field_entry *fe){ field_name = fe->name; pdt = assign_type_from_string(fe->type); is_ts = fe->is_ts; offset = 0; return(pdt); }; std::string tuple_access_info::to_string(){ std::string ret = field_name+": offset="+std::to_string(offset)+", type="+type_to_string(pdt); if(is_ts){ ret+=", is_ts"; } return ret; } ////////////////////////////////////////////////////////////////// // query_rep implementation ///////////////////////////////////////////////////////////////// std::string _query_rep::init(const mc_json::json_value *strm){ min_tuple_size = 0; if(strm->type != mc_json::JSON_OBJECT){ return "Error, json stream must be a dict ("+std::to_string(strm->type)+")."; } this->name = strm->name; for(mc_json::json_value *sparts=strm->first_child; sparts!=NULL; sparts=sparts->next_sibling){ //keys if(strcmp(sparts->name, "keys")==0){ if(sparts->type != mc_json::JSON_ARRAY){ return "Error, the keys in stream must be an array (" +std::to_string(sparts->type)+ ")."; } for(mc_json::json_value *kparts=sparts->first_child; kparts!=NULL; kparts=kparts->next_sibling){ if(kparts->type != mc_json::JSON_STRING){ return "Error, the key entries in a stream must all be strings (" +std::to_string(kparts->type)+")."; } keys.push_back(kparts->string_value); } } // fields if(strcmp(sparts->name, "fields")==0){ if(sparts->type != mc_json::JSON_ARRAY){ return "Error, the fields in a stream must all be dict (" +std::to_string(sparts->type )+ ")."; } for(mc_json::json_value *field=sparts->first_child; field!=NULL; field=field->next_sibling){ if(field->type != mc_json::JSON_OBJECT){ return "Error, the field entries in a stream must all be dicts (" +std::to_string(field->type )+ ")."; } field_entry fe; std::string err = fe.load_from_json(field); if(err!=""){ return "Error loading stream "+std::string(this->name)+": "+err; } tuple_access_info tai; int pdt = tai.init(&fe); if(pdt==UNDEFINED_TYPE){ err = "Error in field "+fe.name+" of stream "+this->name+", unknown type "+fe.type; return err; } field_info.push_back(tai); } } } return ""; } int _query_rep::finalize(){ int f; int curr_pos = 0; int fld_undefined = 0; for(f=0;f0) ret+=","; ret += keys[k]; } ret += "], fields=\n"; for(int f=0;f=field_info.size()) return UNDEFINED_TYPE; return field_info[i].pdt; } std::string _query_rep::get_type_name(int i){ return type_to_string(this->get_type(i)); } // byte offset of ith field in a data block int _query_rep::get_offset(int i){ if(i<0 || i>field_info.size()) return 0; return field_info[i].offset; } // byte offset of ith field in a data block field_handle _query_rep::get_handle(int i){ field_handle ret; ret.offset = -1; if(i<0 || i>field_info.size()) return ret; ret.offset = field_info[i].offset; ret.type = field_info[i].pdt; return ret; } ////////////////////////////////////////////////////////////////// // mc_schemas implementation // n is a char buffer holding the json description of the stream schemas _mc_schemas::_mc_schemas(const char *n) : mc_schemas() { this->init(n); } // n is a string holding the json description of the stream schemas _mc_schemas::_mc_schemas(std::string s){ this->init(s.c_str()); } void _mc_schemas::init(const char *n){ nib_str = strdup(n); char *errorPos = 0; char *errorDesc = 0; int errorLine = 0; mc_json::block_allocator allocator(1 << 10); // 1 KB per block mc_json::json_value *jroot = mc_json::json_parse(nib_str, &errorPos, (const char**)&errorDesc, &errorLine, &allocator); if(jroot->type != mc_json::JSON_OBJECT){ err = "Error, root of the nib json must be a dict."; return ; } for(mc_json::json_value *stream=jroot->first_child; stream!=NULL; stream=stream->next_sibling){ if(stream->type != mc_json::JSON_OBJECT){ err = "Error, the streams in the nib json must all be dict (" +std::to_string(stream->type )+ ")."; return ; } std::string stream_name = stream->name; _query_rep *qr = new _query_rep(); std::string stream_err = qr->init(stream); if(stream_err == ""){ qr->finalize(); qreps[stream_name] = qr; }else{ qerrs[stream_name] = stream_err; delete qr; } } } // true if there are any errors. bool _mc_schemas::has_errors(){ if(err!="") return true; if(qerrs.size()>0) return true; return false; } // string with the error reports. empty if there is no error. std::string _mc_schemas::get_errors(){ std::string ret = this->err; for(auto mi=qerrs.begin(); mi!=qerrs.end(); ++mi){ if(err!="") err += "\n"; err += (*mi).first+": "+(*mi).second; } return err; } // return the names of the parsed streams. std::vector _mc_schemas::get_streams(){ std::vector ret; for(auto mi=qreps.begin(); mi!=qreps.end(); ++mi){ ret.push_back(mi->first); } return ret; } // return the names of the unsucessfully parsed streams std::vector _mc_schemas::get_error_streams(){ std::vector ret; for(auto mi=qerrs.begin(); mi!=qerrs.end(); ++mi){ ret.push_back(mi->first); } return ret; } // true if some stream was parsed successful or not bool _mc_schemas::stream_found(std::string s){ if(qreps.count(s)+qerrs.count(s) > 0) return true; return false; } // true if there is a stream with name s which parsed successfully bool _mc_schemas::stream_ok(std::string s){ return qreps.count(s) > 0; } // return the error associated with a stream, if any. std::string _mc_schemas::get_stream_error(std::string s){ if(qerrs.count(s)>0) return qerrs[s]; if(qreps.count(s)>0) return ""; return "not_found"; } // Get the query representation of a successfully parsed stream query_rep *_mc_schemas::get_query_rep(std::string s){ if(qreps.count(s)>0) return qreps[s]; return NULL; } // Destructor _mc_schemas::~_mc_schemas(){ free(nib_str); for(auto q=qreps.begin(); q!=qreps.end();++q){ delete q->second; } } //////////// // mc_schemas factory mc_schemas *new_mc_schemas(std::string s){ return new _mc_schemas(s); } mc_schemas *new_mc_schemas(const char *s){ return new _mc_schemas(s); } //////////////////////////////////////////// // Direct tuple access functions. unsigned int unpack_uint(void *data, int len, int offset, int *problem){ unsigned int retval; if(offset+sizeof(unsigned int) > len){ *problem = 1; return(0); } memcpy(&retval, ((char *)data)+offset, sizeof(unsigned int)); return(retval); } unsigned int unpack_ushort(void *data, int len, int offset, int *problem){ unsigned int retval; if(offset+sizeof(unsigned int) > len){ *problem = 1; return(0); } memcpy(&retval, ((char *)data)+offset, sizeof(unsigned int)); return(retval); } unsigned int unpack_bool(void *data, int len, int offset, int *problem){ unsigned int retval; if(offset+sizeof(unsigned int) > len){ *problem = 1; return(0); } memcpy(&retval, ((char *)data)+offset, sizeof(unsigned int)); return(retval); } int unpack_int(void *data, int len, int offset, int *problem){ int retval; if(offset+sizeof(int) > len){ *problem = 1; return(0); } memcpy(&retval, ((char *)data)+offset, sizeof(unsigned int)); return(retval); } unsigned long long int unpack_ullong(void *data, int len, int offset, int *problem){ unsigned long long int retval; if(offset+sizeof(unsigned long long int) > len){ *problem = 1; return(0); } memcpy(&retval, ((char *)data)+offset, sizeof(unsigned long long int)); return(retval); } long long int unpack_llong(void *data, int len, int offset, int *problem){ long long int retval; if(offset+sizeof(long long int) > len){ *problem = 1; return(0); } memcpy(&retval, ((char *)data)+offset, sizeof(long long int)); return(retval); } double unpack_float(void *data, int len, int offset, int *problem){ double retval; if(offset+sizeof(double) > len){ *problem = 1; return(0); } memcpy(&retval, ((char *)data)+offset, sizeof(double)); return(retval); } timeval unpack_timeval(void *data, int len, int offset, int *problem){ timeval retval; if(offset+sizeof(timeval) > len){ *problem = 1; retval.tv_sec = 0; retval.tv_usec = 0; return(retval); } memcpy(&retval, ((char *)data)+offset, sizeof(timeval)); return(retval); } mc_string unpack_vstr(void *data, int len, int offset, int *problem){ mc_string retval; vstring32 unpack_s; if(offset+sizeof( vstring32) > len){ *problem = 1; return(retval); } memcpy(&unpack_s, ((char *)data)+offset, sizeof(vstring32)); retval.length = unpack_s.length; if(unpack_s.offset + retval.length > len){ *problem = 1; return(retval); } retval.data = (char *)data + unpack_s.offset; return(retval); } struct mc_ipv6_str unpack_ipv6(void *data, int len, int offset, int *problem){ struct mc_ipv6_str retval; if(offset+sizeof(mc_ipv6_str) > len){ *problem = 1; return(retval); } memcpy(&retval, ((char *)data)+offset, sizeof(mc_ipv6_str)); return(retval); } access_result get_field_by_index(query_rep *qr, int index, void * data, int len){ access_result retval; retval.field_data_type = UNDEFINED_TYPE; int problem = 0; if(index >= qr->get_num_fields()){ return(retval); } switch(qr->get_type(index)){ case UINT_TYPE: retval.r.ui = unpack_uint(data, len, qr->get_offset(index), &problem); if(!problem) retval.field_data_type = UINT_TYPE; break; case IP_TYPE: retval.r.ui = unpack_uint(data, len, qr->get_offset(index), &problem); if(!problem) retval.field_data_type = IP_TYPE; break; case INT_TYPE: retval.r.i = unpack_int(data, len, qr->get_offset(index), &problem); if(!problem) retval.field_data_type = INT_TYPE; break; case ULLONG_TYPE: retval.r.ul = unpack_ullong(data, len, qr->get_offset(index), &problem); if(!problem) retval.field_data_type = ULLONG_TYPE; break; case LLONG_TYPE: retval.r.l = unpack_llong(data, len, qr->get_offset(index), &problem); if(!problem) retval.field_data_type = LLONG_TYPE; break; case USHORT_TYPE: retval.r.ui = unpack_ushort(data, len, qr->get_offset(index), &problem); if(!problem) retval.field_data_type = USHORT_TYPE; break; case FLOAT_TYPE: retval.r.f = unpack_float(data, len, qr->get_offset(index), &problem); if(!problem) retval.field_data_type = FLOAT_TYPE; break; case BOOL_TYPE: retval.r.ui = unpack_bool(data, len, qr->get_offset(index), &problem); if(!problem) retval.field_data_type = BOOL_TYPE; break; case VSTR_TYPE: retval.r.vs = unpack_vstr(data, len, qr->get_offset(index), &problem); if(!problem) retval.field_data_type = VSTR_TYPE; break; case TIMEVAL_TYPE: retval.r.t = unpack_timeval(data, len, qr->get_offset(index), &problem); if(!problem) retval.field_data_type = TIMEVAL_TYPE; break; case IPV6_TYPE: retval.r.ip6 = unpack_ipv6(data, len, qr->get_offset(index), &problem); if(!problem) retval.field_data_type = IPV6_TYPE; break; case UNDEFINED_TYPE: break; } return(retval); } access_result get_field_by_handle(field_handle f, void * data, int len){ access_result retval; retval.field_data_type = UNDEFINED_TYPE; int problem = 0; switch(f.type){ case UINT_TYPE: retval.r.ui = unpack_uint(data, len, f.offset, &problem); if(!problem) retval.field_data_type = UINT_TYPE; break; case IP_TYPE: retval.r.ui = unpack_uint(data, len, f.offset, &problem); if(!problem) retval.field_data_type = IP_TYPE; break; case INT_TYPE: retval.r.i = unpack_int(data, len, f.offset, &problem); if(!problem) retval.field_data_type = INT_TYPE; break; case ULLONG_TYPE: retval.r.ul = unpack_ullong(data, len, f.offset, &problem); if(!problem) retval.field_data_type = ULLONG_TYPE; break; case LLONG_TYPE: retval.r.l = unpack_llong(data, len, f.offset, &problem); if(!problem) retval.field_data_type = LLONG_TYPE; break; case USHORT_TYPE: retval.r.ui = unpack_ushort(data, len, f.offset, &problem); if(!problem) retval.field_data_type = USHORT_TYPE; break; case FLOAT_TYPE: retval.r.f = unpack_float(data, len, f.offset, &problem); if(!problem) retval.field_data_type = FLOAT_TYPE; break; case BOOL_TYPE: retval.r.ui = unpack_bool(data, len, f.offset, &problem); if(!problem) retval.field_data_type = BOOL_TYPE; break; case VSTR_TYPE: retval.r.vs = unpack_vstr(data, len, f.offset, &problem); if(!problem) retval.field_data_type = VSTR_TYPE; break; case TIMEVAL_TYPE: retval.r.t = unpack_timeval(data, len, f.offset, &problem); if(!problem) retval.field_data_type = TIMEVAL_TYPE; break; case IPV6_TYPE: retval.r.ip6 = unpack_ipv6(data, len, f.offset, &problem); if(!problem) retval.field_data_type = IPV6_TYPE; break; case UNDEFINED_TYPE: break; } return(retval); } int get_field_int(field_handle f, void * data, int len){ access_result a = get_field_by_handle(f, data, len); switch(f.type){ case BOOL_TYPE: case USHORT_TYPE: case UINT_TYPE: return (int)(a.r.ui); case INT_TYPE: case IP_TYPE: return (int)(a.r.i); case LLONG_TYPE: return (int)(a.r.l); case ULLONG_TYPE: return (int)(a.r.ul); case FLOAT_TYPE: case VSTR_TYPE: case TIMEVAL_TYPE: case IPV6_TYPE: return 0; default: return 0; } return 0; } unsigned int get_field_uint(field_handle f, void * data, int len){ access_result a = get_field_by_handle(f, data, len); switch(f.type){ case BOOL_TYPE: case USHORT_TYPE: case UINT_TYPE: return (unsigned int)(a.r.ui); case INT_TYPE: case IP_TYPE: return (unsigned int)(a.r.i); case LLONG_TYPE: return (unsigned int)(a.r.l); case ULLONG_TYPE: return (unsigned int)(a.r.ul); case FLOAT_TYPE: case VSTR_TYPE: case TIMEVAL_TYPE: case IPV6_TYPE: return 0; default: return 0; } return 0; } long long int get_field_llong(field_handle f, void * data, int len){ access_result a = get_field_by_handle(f, data, len); switch(f.type){ case BOOL_TYPE: case USHORT_TYPE: case UINT_TYPE: return (long long int)(a.r.ui); case INT_TYPE: case IP_TYPE: return (long long int)(a.r.i); case LLONG_TYPE: return (long long int)(a.r.l); case ULLONG_TYPE: return (long long int)(a.r.ul); case FLOAT_TYPE: case VSTR_TYPE: case TIMEVAL_TYPE: case IPV6_TYPE: return 0; default: return 0; } return 0; } unsigned long long int get_field_ullong(field_handle f, void * data, int len){ access_result a = get_field_by_handle(f, data, len); switch(f.type){ case BOOL_TYPE: case USHORT_TYPE: case UINT_TYPE: return (unsigned long long int)(a.r.ui); case INT_TYPE: case IP_TYPE: return (unsigned long long int)(a.r.i); case LLONG_TYPE: return (unsigned long long int)(a.r.l); case ULLONG_TYPE: return (unsigned long long int)(a.r.ul); case FLOAT_TYPE: case VSTR_TYPE: case TIMEVAL_TYPE: case IPV6_TYPE: return 0; default: return 0; } return 0; } double get_field_float(field_handle f, void * data, int len){ access_result a = get_field_by_handle(f, data, len); switch(f.type){ case BOOL_TYPE: case USHORT_TYPE: case UINT_TYPE: return (unsigned long long int)(a.r.ui); case INT_TYPE: case IP_TYPE: return (unsigned long long int)(a.r.i); case LLONG_TYPE: return (unsigned long long int)(a.r.l); case ULLONG_TYPE: return (unsigned long long int)(a.r.ul); case FLOAT_TYPE: case VSTR_TYPE: case TIMEVAL_TYPE: case IPV6_TYPE: return 0; default: return 0; } return 0; } timeval get_field_timeval(field_handle f, void * data, int len){ access_result a = get_field_by_handle(f, data, len); switch(f.type){ case BOOL_TYPE: case USHORT_TYPE: case UINT_TYPE: case INT_TYPE: case IP_TYPE: case LLONG_TYPE: case ULLONG_TYPE: case FLOAT_TYPE: case VSTR_TYPE: case IPV6_TYPE: a.r.t.tv_sec = 0; a.r.t.tv_usec = 0; return a.r.t; case TIMEVAL_TYPE: return a.r.t; default: a.r.t.tv_sec = 0; a.r.t.tv_usec = 0; return a.r.t; } a.r.t.tv_sec = 0; a.r.t.tv_usec = 0; return a.r.t; } mc_ipv6_str get_field_ipv6(field_handle f, void * data, int len){ access_result a = get_field_by_handle(f, data, len); switch(f.type){ case BOOL_TYPE: case USHORT_TYPE: case UINT_TYPE: case INT_TYPE: case IP_TYPE: case LLONG_TYPE: case ULLONG_TYPE: case FLOAT_TYPE: case VSTR_TYPE: case TIMEVAL_TYPE: a.r.ip6.v[0] = 0; a.r.ip6.v[1] = 0; a.r.ip6.v[2] = 0; a.r.ip6.v[3] = 0; return a.r.ip6; case IPV6_TYPE: return a.r.ip6; default: a.r.ip6.v[0] = 0; a.r.ip6.v[1] = 0; a.r.ip6.v[2] = 0; a.r.ip6.v[3] = 0; return a.r.ip6; } a.r.ip6.v[0] = 0; a.r.ip6.v[1] = 0; a.r.ip6.v[2] = 0; a.r.ip6.v[3] = 0; return a.r.ip6; } std::string get_field_string(field_handle f, void * data, int len){ access_result a = get_field_by_handle(f, data, len); switch(f.type){ case BOOL_TYPE: case USHORT_TYPE: case UINT_TYPE: return std::to_string(a.r.ui); case INT_TYPE: case IP_TYPE: return std::to_string(a.r.i); case LLONG_TYPE: return std::to_string(a.r.l); case ULLONG_TYPE: return std::to_string(a.r.ul); case FLOAT_TYPE: return std::to_string(a.r.f); case VSTR_TYPE:{ std::string rets(a.r.vs.data, a.r.vs.length); return rets; } case TIMEVAL_TYPE:{ double tv = a.r.t.tv_sec + ((double)a.r.t.tv_usec)/1000000.0; return std::to_string(tv); } case IPV6_TYPE:{ char buf[100]; sprintf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", a.r.ip6.v[0] >> 16, (a.r.ip6.v[0]) & 0xffff, a.r.ip6.v[1] >> 16, (a.r.ip6.v[1]) & 0xffff, a.r.ip6.v[2] >> 16, (a.r.ip6.v[2]) & 0xffff, a.r.ip6.v[3] >> 16, (a.r.ip6.v[3]) & 0xffff ); return buf; } default: return ""; } return ""; } }