diff --git a/apps/diameter_client/ServerConnection.cpp b/apps/diameter_client/ServerConnection.cpp index fe4c8d47..02d34783 100644 --- a/apps/diameter_client/ServerConnection.cpp +++ b/apps/diameter_client/ServerConnection.cpp @@ -45,7 +45,7 @@ #define CHECK_TIMEOUT_USECS 500000 // 0.5ms #define CHECK_TIMEOUT_INTERVAL (CHECK_TIMEOUT_USECS / CONN_WAIT_USECS) -// #define EXTRA_DEBUG +// #define EXTRA_DEBUG #define CONNECT_CEA_REPLY_TIMEOUT 2 // seconds #define RETRY_CONNECTION_INTERVAL 2 // seconds @@ -53,9 +53,9 @@ // after syserror, wait 30 secs for retry #define RETRY_CONNECTION_SYSERROR 30 // seconds -DiameterServerConnection::DiameterServerConnection() - : in_use(false), dia_conn(0) -{ +DiameterServerConnection::DiameterServerConnection() + : in_use(false), dia_conn(0) +{ memset(&rb, 0, sizeof(rd_buf_t)); h2h = random(); e2e = (time(NULL) & 0xFFF << 20) | (random() % 0xFFFFF); @@ -64,9 +64,9 @@ DiameterServerConnection::DiameterServerConnection() void DiameterServerConnection::terminate(bool tls_shutdown) { if (dia_conn) { - if (tls_shutdown) + if (tls_shutdown) tcp_tls_shutdown(dia_conn); - + tcp_close_connection(dia_conn); tcp_destroy_connection(dia_conn); dia_conn = NULL; @@ -105,7 +105,7 @@ void ServerConnection::process(AmEvent* ev) { req_map_mut.unlock(); } -ServerConnection::ServerConnection() +ServerConnection::ServerConnection() : server_port(-1), open(false), AmEventQueue(this), request_timeout(3000), timeout_check_cntr(0) @@ -117,11 +117,11 @@ ServerConnection::~ServerConnection() { conn.terminate(); } -int ServerConnection::init(const string& _server_name, +int ServerConnection::init(const string& _server_name, int _server_port, const string& _ca_file, const string& _cert_file, - const string& _origin_host, + const string& _origin_host, const string& _origin_realm, const string& _origin_ip, AAAApplicationId _app_id, @@ -147,7 +147,7 @@ int ServerConnection::init(const string& _server_name, struct in_addr inp; if (inet_aton(origin_ip.c_str(), &inp) == 0) { - ERROR("origin_ip %s could not be decoded.\n", + ERROR("origin_ip %s could not be decoded.\n", origin_ip.c_str()); } else { origin_ip_address[2] = inp.s_addr & 0xFF; @@ -173,7 +173,7 @@ void ServerConnection::openConnection() { conn.dia_conn = tcp_create_connection(server_name.c_str(), server_port, ca_file.c_str(), cert_file.c_str()); if (!conn.dia_conn) { - ERROR("establishing connection to %s\n", + ERROR("establishing connection to %s\n", server_name.c_str()); setRetryConnectLater(); return; @@ -188,10 +188,10 @@ void ServerConnection::openConnection() { setRetryConnectLater(); return; } - if (addOrigin(cer) - || addDataAVP(cer, AVP_Host_IP_Address, origin_ip_address, sizeof(origin_ip_address)) - || addDataAVP(cer, AVP_Vendor_Id, (char*)&vendorID, sizeof(vendorID)) - || addDataAVP(cer, AVP_Supported_Vendor_Id, (char*)&vendorID, sizeof(vendorID)) + if (addOrigin(cer) + || addDataAVP(cer, AVP_Host_IP_Address, origin_ip_address, sizeof(origin_ip_address)) + || addDataAVP(cer, AVP_Vendor_Id, (char*)&vendorID, sizeof(vendorID)) + || addDataAVP(cer, AVP_Supported_Vendor_Id, (char*)&vendorID, sizeof(vendorID)) || addStringAVP(cer, AVP_Product_Name, product_name)) { ERROR("openConnection(): adding AVPs failed\n"); conn.terminate(); @@ -201,7 +201,7 @@ void ServerConnection::openConnection() { // supported applications AAA_AVP* vs_appid; - if( (vs_appid=AAACreateAVP(AVP_Vendor_Specific_Application_Id, (AAA_AVPFlag)AAA_AVP_FLAG_NONE, 0, 0, + if( (vs_appid=AAACreateAVP(AVP_Vendor_Specific_Application_Id, (AAA_AVPFlag)AAA_AVP_FLAG_NONE, 0, 0, 0, AVP_DONT_FREE_DATA)) == 0) { ERROR( M_NAME":openConnection(): creating AVP failed." " (no more free memory!)\n"); @@ -211,9 +211,9 @@ void ServerConnection::openConnection() { } // feels like c coding... - if (addGroupedAVP(vs_appid, AVP_Auth_Application_Id, + if (addGroupedAVP(vs_appid, AVP_Auth_Application_Id, (char*)&app_id, sizeof(app_id)) || - addGroupedAVP(vs_appid, AVP_Vendor_Id, + addGroupedAVP(vs_appid, AVP_Vendor_Id, (char*)&vendorID, sizeof(vendorID)) || (AAAAddAVPToMessage(cer, vs_appid, 0) != AAA_ERR_SUCCESS) ) { @@ -224,18 +224,18 @@ void ServerConnection::openConnection() { return; } -#ifdef EXTRA_DEBUG +#ifdef EXTRA_DEBUG AAAPrintMessage(cer); #endif conn.setIDs(cer); - + if(AAABuildMsgBuffer(cer) != AAA_ERR_SUCCESS) { ERROR( " openConnection(): message buffer not created\n"); AAAFreeMessage(&cer); return; } - + int ret = tcp_send(conn.dia_conn, cer->buf.s, cer->buf.len); if (ret) { ERROR( "openConnection(): could not send message\n"); @@ -244,14 +244,14 @@ void ServerConnection::openConnection() { AAAFreeMessage(&cer); return; } - + AAAFreeMessage(&cer); unsigned int cea_receive_cnt = 3; while (true) { int res = tcp_recv_msg(conn.dia_conn, &conn.rb, CONNECT_CEA_REPLY_TIMEOUT, 0); - + if (res <= 0) { if (!res) { ERROR( " openConnection(): did not receive response (CEA).\n"); @@ -262,9 +262,9 @@ void ServerConnection::openConnection() { setRetryConnectLater(); return; } - + /* obtain the structure corresponding to the message */ - AAAMessage* cea = AAATranslateMessage(conn.rb.buf, conn.rb.buf_len, 0); + AAAMessage* cea = AAATranslateMessage(conn.rb.buf, conn.rb.buf_len, 0); if(!cea) { ERROR( " openConnection(): could not decipher response (CEA).\n"); conn.terminate(); @@ -273,7 +273,7 @@ void ServerConnection::openConnection() { } if (cea->commandCode == AAA_CC_CEA) { -#ifdef EXTRA_DEBUG +#ifdef EXTRA_DEBUG AAAPrintMessage(cea); #endif AAAFreeMessage(&cea); @@ -289,7 +289,7 @@ void ServerConnection::openConnection() { return; } } - + DBG("Connection opened.\n"); open = true; } @@ -300,35 +300,35 @@ AAAMessage* ServerConnection::ReqEvent2AAAMessage(DiameterRequestEvent* re) { ERROR("creating new request message.\n"); return NULL; } - + for (int i=re->val.size()-1;i >= 0; i--) { //[int avp_id, int flags, int vendor, int len, blob data] - + AmArg& row = re->val.get(i); int avp_id = row.get(0).asInt(); int flags = row.get(1).asInt(); int vendor = row.get(2).asInt(); - ArgBlob* data = row.get(3).asBlob(); + const ArgBlob& data = row.get(3).asBlob(); #ifdef EXTRA_DEBUG DBG("adding avp id %d, flags %d, vendor %d\n", avp_id, flags, vendor); -#endif +#endif - if (!data->len) { + if (!data.len) { #ifdef EXTRA_DEBUG DBG("skipping empty AVP id %d\n", avp_id); -#endif +#endif continue; } AAA_AVP *avp; - if( (avp=AAACreateAVP(avp_id, (AAA_AVPFlag)flags, vendor, (const char*)data->data, - data->len, AVP_DUPLICATE_DATA)) == 0) { + if( (avp=AAACreateAVP(avp_id, (AAA_AVPFlag)flags, vendor, (const char*)data.data, + data.len, AVP_DUPLICATE_DATA)) == 0) { ERROR( M_NAME ": addDataAVP() no more free memory!\n"); continue; } - + if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS) { ERROR( M_NAME ": addDataAVP(): AVP not added!\n"); continue; @@ -339,12 +339,12 @@ AAAMessage* ServerConnection::ReqEvent2AAAMessage(DiameterRequestEvent* re) { // add origin host and origin realm int ServerConnection::addOrigin(AAAMessage* msg) { - return addStringAVP(msg, AVP_Origin_Host, origin_host, true) || + return addStringAVP(msg, AVP_Origin_Host, origin_host, true) || addStringAVP(msg, AVP_Origin_Realm, origin_realm, true); } -int ServerConnection::addStringAVP(AAAMessage* msg, AAA_AVPCode avp_code, string& val, +int ServerConnection::addStringAVP(AAAMessage* msg, AAA_AVPCode avp_code, string& val, bool attail) { AAA_AVP *avp; if( (avp=AAACreateAVP(avp_code, (AAA_AVPFlag)AAA_AVP_FLAG_NONE, 0, val.c_str(), @@ -385,11 +385,11 @@ int ServerConnection::addDataAVP(AAAMessage* msg, AAA_AVPCode avp_code, char* va } // add a new group member AVP -int ServerConnection::addGroupedAVP(AAA_AVP *avp, AAA_AVPCode avp_code, +int ServerConnection::addGroupedAVP(AAA_AVP *avp, AAA_AVPCode avp_code, char* val, unsigned int len) { AAA_AVP *m_avp; - if( (m_avp=AAACreateAVP(avp_code, (AAA_AVPFlag)AAA_AVP_FLAG_NONE, 0, val, + if( (m_avp=AAACreateAVP(avp_code, (AAA_AVPFlag)AAA_AVP_FLAG_NONE, 0, val, len, AVP_DUPLICATE_DATA)) == 0) { ERROR( M_NAME":addGroupedAVP(): no more free memory!\n"); return -1; @@ -398,7 +398,7 @@ int ServerConnection::addGroupedAVP(AAA_AVP *avp, AAA_AVPCode avp_code, return 0; } -// send request and get response +// send request and get response int ServerConnection::sendRequest(AAAMessage* req, unsigned int& exe) { if (addOrigin(req)) { return AAA_ERROR_MESSAGE; @@ -410,7 +410,7 @@ int ServerConnection::sendRequest(AAAMessage* req, unsigned int& exe) { ERROR( " sendRequest(): message buffer not created\n"); return AAA_ERROR_MESSAGE; } - + int ret = tcp_send(conn.dia_conn, req->buf.s, req->buf.len); if (ret) { ERROR( " sendRequest(): could not send message\n"); @@ -437,7 +437,7 @@ int ServerConnection::handleRequest(AAAMessage* req) { } AAAMessageSetReply(reply); - + if (addOrigin(reply) || addResultCodeAVP(reply, AAA_SUCCESS)) { AAAFreeMessage(&reply); return AAA_ERROR_MESSAGE; @@ -451,7 +451,7 @@ int ServerConnection::handleRequest(AAAMessage* req) { AAAFreeMessage(&reply); return AAA_ERROR_MESSAGE; } - + DBG("sending Device-Watchdog-Answer...\n"); int ret = tcp_send(conn.dia_conn, reply->buf.s, reply->buf.len); if (ret) { @@ -492,7 +492,7 @@ int ServerConnection::handleRequest(AAAMessage* req) { AAAMessageSetReply(reply); - // always send success (causing retry of requests on + // always send success (causing retry of requests on // different connection first, so race is unlikely) if (addOrigin(reply) || addResultCodeAVP(reply, AAA_SUCCESS)) { AAAFreeMessage(&reply); @@ -525,7 +525,7 @@ int ServerConnection::handleRequest(AAAMessage* req) { }; break; default: { - ERROR("ignoring unknown request with command code %i\n", + ERROR("ignoring unknown request with command code %i\n", req->commandCode); }; break; } @@ -537,7 +537,7 @@ int ServerConnection::handleReply(AAAMessage* rep) { unsigned int rep_id = rep->endtoendId; int reply_code = AAAMessageGetReplyCode(rep); DBG("received reply - id %d, reply code %d\n", rep_id, reply_code); - + string sess_link = ""; req_map_mut.lock(); DReqMap::iterator it = req_map.find(rep_id); @@ -550,8 +550,8 @@ int ServerConnection::handleReply(AAAMessage* rep) { req_map_mut.unlock(); if (!sess_link.empty()) { - DiameterReplyEvent* r_ev = - new DiameterReplyEvent((unsigned int)rep->commandCode, (unsigned int)rep->applicationId, + DiameterReplyEvent* r_ev = + new DiameterReplyEvent((unsigned int)rep->commandCode, (unsigned int)rep->applicationId, AAAMessageAVPs2AmArg(rep)); if (!AmSessionContainer::instance()->postEvent(sess_link, r_ev)) { DBG("unhandled reply\n"); @@ -563,14 +563,14 @@ int ServerConnection::handleReply(AAAMessage* rep) { if ((reply_code == AAA_OUT_OF_SPACE) || reply_code >= AAA_PERMANENT_FAILURE_START) { WARN("critical or permanent failure Diameter error reply" - " (code %d) received. Shutdown connection.\n", + " (code %d) received. Shutdown connection.\n", reply_code); shutdownConnection(); } return 0; } - + AmArg ServerConnection::AAAMessageAVPs2AmArg(AAAMessage* rep) { AmArg res; for(AAA_AVP* avp=rep->avpList.head;avp;avp=avp->next) { @@ -624,23 +624,23 @@ void ServerConnection::receive() { return; /* obtain the structure corresponding to the message */ - AAAMessage* msg = AAATranslateMessage(conn.rb.buf, conn.rb.buf_len, 0); + AAAMessage* msg = AAATranslateMessage(conn.rb.buf, conn.rb.buf_len, 0); if(!msg) { - ERROR( M_NAME "receive(): message structure not obtained from message.\n"); + ERROR( M_NAME "receive(): message structure not obtained from message.\n"); closeConnection(); return; } - -#ifdef EXTRA_DEBUG + +#ifdef EXTRA_DEBUG AAAPrintMessage(msg); #endif - - if (is_req(msg)) + + if (is_req(msg)) handleRequest(msg); - else + else handleReply(msg); - - AAAFreeMessage(&msg); + + AAAFreeMessage(&msg); } void ServerConnection::run() { @@ -649,7 +649,7 @@ void ServerConnection::run() { if (!open) { struct timeval now; gettimeofday(&now, NULL); - + if(timercmp(&now,&connect_ts,>)){ DBG("(re)trying to open the connection\n"); openConnection(); @@ -666,7 +666,7 @@ void ServerConnection::run() { } void ServerConnection::checkTimeouts() { - if ((++timeout_check_cntr)%CHECK_TIMEOUT_INTERVAL) + if ((++timeout_check_cntr)%CHECK_TIMEOUT_INTERVAL) return; req_map_mut.lock(); @@ -675,23 +675,23 @@ void ServerConnection::checkTimeouts() { DBG("checking request timeout of %zd pending requests....\n", req_map.size()); #endif - + struct timeval now; gettimeofday(&now, NULL); - for (DReqMap::iterator it = + for (DReqMap::iterator it = req_map.begin();it != req_map.end();) { struct timeval diff; timersub(&now,&it->second.second,&diff); // millisec if (diff.tv_sec * 1000 + diff.tv_usec / 1000 > request_timeout) { - WARN("timeout for DIAMETER request '%u'\n", it->first); + WARN("timeout for DIAMETER request '%u'\n", it->first); string& sess_link = it->second.first; - DBG("notify session '%s' of diameter request timeout\n", + DBG("notify session '%s' of diameter request timeout\n", sess_link.c_str()); - DiameterTimeoutEvent* r_ev = + DiameterTimeoutEvent* r_ev = new DiameterTimeoutEvent(it->first); if (!AmSessionContainer::instance()->postEvent(sess_link, r_ev)) { DBG("unhandled timout event.\n"); @@ -718,7 +718,7 @@ void ServerConnection::shutdownConnection() { for (DReqMap::iterator it = req_map.begin(); it != req_map.end();it++) { string& sess_link = it->second.first; - DiameterTimeoutEvent* r_ev = + DiameterTimeoutEvent* r_ev = new DiameterTimeoutEvent(it->first); if (!AmSessionContainer::instance()->postEvent(sess_link, r_ev)) { DBG("unhandled timout event.\n"); diff --git a/core/AmArg.cpp b/core/AmArg.cpp index 2514d246..ec0d3024 100644 --- a/core/AmArg.cpp +++ b/core/AmArg.cpp @@ -46,65 +46,35 @@ const char* AmArg::t2str(int type) { } } -AmArg::AmArg(const AmArg& v) -{ - type = Undef; - - *this = v; -} - -AmArg& AmArg::operator=(const AmArg& v) { - if (this != &v) { - invalidate(); - - type = v.type; - switch(type){ - case Int: { v_int = v.v_int; } break; - case LongLong: { v_long = v.v_long; } break; - case Bool: { v_bool = v.v_bool; } break; - case Double: { v_double = v.v_double; } break; - case CStr: { v_cstr = strdup(v.v_cstr); } break; - case AObject:{ v_obj = v.v_obj; } break; - case ADynInv:{ v_inv = v.v_inv; } break; - case Array: { v_array = new ValueArray(*v.v_array); } break; - case Struct: { v_struct = new ValueStruct(*v.v_struct); } break; - case Blob: { v_blob = new ArgBlob(*v.v_blob); } break; - case Undef: break; - default: assert(0); - } - } - return *this; -} - -AmArg::AmArg(std::map& v) +AmArg::AmArg(std::map& v) : type(Undef) { assertStruct(); for (std::map::iterator it= v.begin();it!= v.end();it++) - (*v_struct)[it->first] = AmArg(it->second.c_str()); + (*std::get(value))[it->first] = AmArg(it->second.c_str()); } -AmArg::AmArg(std::map& v) +AmArg::AmArg(std::map& v) : type(Undef) { assertStruct(); for (std::map::iterator it= v.begin();it!= v.end();it++) - (*v_struct)[it->first] = it->second; + (*std::get(value))[it->first] = it->second; } AmArg::AmArg(vector& v) : type(Array) { assertArray(0); - for (vector::iterator it + for (vector::iterator it = v.begin(); it != v.end(); it++) { push(AmArg(it->c_str())); } } - -AmArg::AmArg(const vector& v ) + +AmArg::AmArg(const vector& v ) : type(Array) { assertArray(0); - for (vector::const_iterator it + for (vector::const_iterator it = v.begin(); it != v.end(); it++) { push(AmArg(*it)); } @@ -113,7 +83,7 @@ AmArg::AmArg(const vector& v ) AmArg::AmArg(const vector& v) : type(Array) { assertArray(0); - for (vector::const_iterator it + for (vector::const_iterator it = v.begin(); it != v.end(); it++) { push(AmArg(*it)); } @@ -124,9 +94,9 @@ void AmArg::assertArray() { return; if (Undef == type) { type = Array; - v_array = new ValueArray(); + std::get(value) = new ValueArray(); return; - } + } throw TypeMismatchException(); } @@ -136,15 +106,15 @@ void AmArg::assertArray() const { } void AmArg::assertArray(size_t s) { - + if (Undef == type) { type = Array; - v_array = new ValueArray(); + std::get(value) = new ValueArray(); } else if (Array != type) { throw TypeMismatchException(); } - if (v_array->size() < s) - v_array->resize(s); + if (std::get(value)->size() < s) + std::get(value)->resize(s); } void AmArg::assertStruct() { @@ -152,9 +122,9 @@ void AmArg::assertStruct() { return; if (Undef == type) { type = Struct; - v_struct = new ValueStruct(); + value = new ValueStruct(); return; - } + } throw TypeMismatchException(); } @@ -164,214 +134,196 @@ void AmArg::assertStruct() const { } void AmArg::invalidate() { - if(type == CStr) { free((void*)v_cstr); } - else if(type == Array) { delete v_array; } - else if(type == Struct) { delete v_struct; } - else if(type == Blob) { delete v_blob; } + if(type == Array) { delete std::get(value); } + else if(type == Struct) { delete std::get(value); } type = Undef; + value = std::monostate(); } void AmArg::push(const AmArg& a) { assertArray(); - v_array->push_back(a); + std::get(value)->push_back(a); } void AmArg::push(const string &key, const AmArg &val) { assertStruct(); - (*v_struct)[key] = val; + (*std::get(value))[key] = val; } void AmArg::pop(AmArg &a) { assertArray(); if (!size()) { - if (a.getType() == AmArg::Undef) + if (a.getType() == AmArg::Undef) return; a = AmArg(); return; } - a = v_array->front(); - v_array->erase(v_array->begin()); + a = std::get(value)->front(); + std::get(value)->erase(std::get(value)->begin()); } void AmArg::pop_back(AmArg &a) { assertArray(); if (!size()) { - if (a.getType() == AmArg::Undef) + if (a.getType() == AmArg::Undef) return; a = AmArg(); return; } - a = v_array->back(); - v_array->erase(v_array->end()); + a = std::get(value)->back(); + std::get(value)->erase(std::get(value)->end()); } void AmArg::pop_back() { assertArray(); if (!size()) return; - v_array->erase(v_array->end()); + std::get(value)->erase(std::get(value)->end()); } void AmArg::concat(const AmArg& a) { assertArray(); - if (a.getType() == Array) { + if (a.getType() == Array) { for (size_t i=0;ipush_back(a[i]); + std::get(value)->push_back(a[i]); } else { - v_array->push_back(a); + std::get(value)->push_back(a); } } size_t AmArg::size() const { if (Array == type) - return v_array->size(); + return std::get(value)->size(); if (Struct == type) - return v_struct->size(); + return std::get(value)->size(); throw TypeMismatchException(); } AmArg& AmArg::back() { - assertArray(); - if (!v_array->size()) + assertArray(); + if (!std::get(value)->size()) throw OutOfBoundsException(); - return (*v_array)[v_array->size()-1]; + return (*std::get(value))[std::get(value)->size()-1]; } AmArg& AmArg::back() const { assertArray(); - if (!v_array->size()) + if (!std::get(value)->size()) throw OutOfBoundsException(); - return (*v_array)[v_array->size()-1]; + return (*std::get(value))[std::get(value)->size()-1]; } AmArg& AmArg::get(size_t idx) { assertArray(); - if (idx >= v_array->size()) + if (idx >= std::get(value)->size()) throw OutOfBoundsException(); - - return (*v_array)[idx]; + + return (*std::get(value))[idx]; } AmArg& AmArg::get(size_t idx) const { assertArray(); - if (idx >= v_array->size()) + if (idx >= std::get(value)->size()) throw OutOfBoundsException(); - - return (*v_array)[idx]; + + return (*std::get(value))[idx]; } -AmArg& AmArg::operator[](size_t idx) { - assertArray(idx+1); - return (*v_array)[idx]; +AmArg& AmArg::operator[](size_t idx) { + assertArray(idx+1); + return (*std::get(value))[idx]; } -AmArg& AmArg::operator[](size_t idx) const { - assertArray(); - if (idx >= v_array->size()) +AmArg& AmArg::operator[](size_t idx) const { + assertArray(); + if (idx >= std::get(value)->size()) throw OutOfBoundsException(); - - return (*v_array)[idx]; + + return (*std::get(value))[idx]; } -AmArg& AmArg::operator[](int idx) { +AmArg& AmArg::operator[](int idx) { if (idx<0) throw OutOfBoundsException(); - assertArray(idx+1); - return (*v_array)[idx]; + assertArray(idx+1); + return (*std::get(value))[idx]; } -AmArg& AmArg::operator[](int idx) const { +AmArg& AmArg::operator[](int idx) const { if (idx<0) throw OutOfBoundsException(); - assertArray(); - if ((size_t)idx >= v_array->size()) + assertArray(); + if ((size_t)idx >= std::get(value)->size()) throw OutOfBoundsException(); - - return (*v_array)[idx]; + + return (*std::get(value))[idx]; } AmArg& AmArg::operator[](std::string key) { assertStruct(); - return (*v_struct)[key]; + return (*std::get(value))[key]; } AmArg& AmArg::operator[](std::string key) const { assertStruct(); - return (*v_struct)[key]; + return (*std::get(value))[key]; } AmArg& AmArg::operator[](const char* key) { assertStruct(); - return (*v_struct)[key]; + return (*std::get(value))[key]; } AmArg& AmArg::operator[](const char* key) const { assertStruct(); - return (*v_struct)[key]; -} - -bool operator==(const AmArg& lhs, const AmArg& rhs) { - if (lhs.type != rhs.type) - return false; - - switch(lhs.type){ - case AmArg::Int: { return lhs.v_int == rhs.v_int; } break; - case AmArg::LongLong: { return lhs.v_long == rhs.v_long; } break; - case AmArg::Bool: { return lhs.v_bool == rhs.v_bool; } break; - case AmArg::Double: { return lhs.v_double == rhs.v_double; } break; - case AmArg::CStr: { return !strcmp(lhs.v_cstr,rhs.v_cstr); } break; - case AmArg::AObject:{ return lhs.v_obj == rhs.v_obj; } break; - case AmArg::ADynInv:{ return lhs.v_inv == rhs.v_inv; } break; - case AmArg::Array: { return lhs.v_array == rhs.v_array; } break; - case AmArg::Struct: { return lhs.v_struct == rhs.v_struct; } break; - case AmArg::Blob: { return (lhs.v_blob->len == rhs.v_blob->len) && - !memcmp(lhs.v_blob->data, rhs.v_blob->data, lhs.v_blob->len); } break; - case AmArg::Undef: return true; - default: assert(0); - } + return (*std::get(value))[key]; +} + +bool AmArg::operator==(const char *val) const { + return type == CStr && std::get(value) == val; } bool AmArg::hasMember(const char* name) const { - return type == Struct && v_struct->find(name) != v_struct->end(); + return type == Struct && std::get(value)->find(name) != std::get(value)->end(); } bool AmArg::hasMember(const string& name) const { - return type == Struct && v_struct->find(name) != v_struct->end(); + return type == Struct && std::get(value)->find(name) != std::get(value)->end(); } std::vector AmArg::enumerateKeys() const { assertStruct(); std::vector res; - for (ValueStruct::iterator it = - v_struct->begin(); it != v_struct->end(); it++) + for (ValueStruct::iterator it = + std::get(value)->begin(); it != std::get(value)->end(); it++) res.push_back(it->first); return res; } AmArg::ValueStruct::const_iterator AmArg::begin() const { assertStruct(); - return v_struct->begin(); + return std::get(value)->begin(); } AmArg::ValueStruct::const_iterator AmArg::end() const { assertStruct(); - return v_struct->end(); + return std::get(value)->end(); } void AmArg::erase(const char* name) { assertStruct(); - v_struct->erase(name); + std::get(value)->erase(name); } void AmArg::erase(const std::string& name) { assertStruct(); - v_struct->erase(name); + std::get(value)->erase(name); } void AmArg::assertArrayFmt(const char* format) const { @@ -390,7 +342,7 @@ void AmArg::assertArrayFmt(const char* format) const { case 'a': assertArgArray(get(i)); got+='a'; break; case 'b': assertArgBlob(get(i)); got+='b'; break; case 'u': assertArgStruct(get(i)); got+='u'; break; - default: got+='?'; ERROR("ignoring unknown format type '%c'\n", + default: got+='?'; ERROR("ignoring unknown format type '%c'\n", format[i]); break; } } @@ -407,7 +359,7 @@ void AmArg::assertArrayFmt(const char* format) const { for (size_t i=0;i AmArg::asArgBlobVector() const { - vector res; - for (size_t i=0;i AmArg::asArgBlobVector() const { + vector res; + for (size_t i=0;i"; case Blob: - s = "len) + ">"; + s = ""; return s; case Array: s = "["; diff --git a/core/AmArg.h b/core/AmArg.h index 28dd2b5b..6542eff1 100644 --- a/core/AmArg.h +++ b/core/AmArg.h @@ -39,6 +39,7 @@ using std::vector; using std::string; #include +#include #include "log.h" @@ -49,14 +50,14 @@ class AmObject { virtual ~AmObject() { } }; -struct ArgBlob { +struct ArgBlob { void* data; int len; - - ArgBlob() + + ArgBlob() : data(NULL),len(0) - { + { } ArgBlob(const ArgBlob& a) { @@ -65,14 +66,14 @@ struct ArgBlob { if (data) memcpy(data, a.data, len); } - + ArgBlob(const void* _data, int _len) { len = _len; data = malloc(len); if (data) memcpy(data, _data, len); } - + ~ArgBlob() { if (data) free(data); } }; @@ -95,7 +96,7 @@ class AmArg AObject, // pointer to an object not owned by AmArg ADynInv, // pointer to a AmDynInvoke (useful for call backs) Blob, - + Array, Struct }; @@ -107,90 +108,77 @@ class AmArg struct TypeMismatchException { TypeMismatchException() { } }; - + typedef std::vector ValueArray; - typedef std::map ValueStruct; + typedef std::map ValueStruct; private: // type short type; - + // value - union { - long int v_int; - long long int v_long; - bool v_bool; - double v_double; - const char* v_cstr; - AmObject* v_obj; - AmDynInvoke* v_inv; - ArgBlob* v_blob; - ValueArray* v_array; - ValueStruct* v_struct; - }; + std::variant value; void invalidate(); public: - AmArg() - : type(Undef) + AmArg() + : type(Undef) { } - - AmArg(const AmArg& v); - + + AmArg(const AmArg& v) = default; + AmArg(const int& v) : type(Int), - v_int(v) + value(static_cast(v)) { } AmArg(const long int& v) : type(Int), - v_int(v) + value(v) { } AmArg(const long long int& v) : type(LongLong), - v_long(v) + value(v) { } AmArg(const bool& v) : type(Bool), - v_bool(v) + value(v) { } - + AmArg(const double& v) : type(Double), - v_double(v) + value(v) { } - + AmArg(const char* v) - : type(CStr) - { - v_cstr = strdup(v); - } - + : type(CStr), + value(v) + { } + AmArg(const string &v) - : type(CStr) - { - v_cstr = strdup(v.c_str()); - } - - AmArg(const ArgBlob v) - : type(Blob) - { - v_blob = new ArgBlob(v); - } + : type(CStr), + value(v) + { } + + AmArg(const ArgBlob& v) + : type(Blob), + value(v) + { } - AmArg(AmObject* v) - : type(AObject), - v_obj(v) - { } + AmArg(AmObject* v) + : type(AObject), + value(v) + { } - AmArg(AmDynInvoke* v) - : type(ADynInv), - v_inv(v) - { } + AmArg(AmDynInvoke* v) + : type(ADynInv), + value(v) + { } // convenience constructors AmArg(vector& v); @@ -198,7 +186,7 @@ class AmArg AmArg(const vector& v); AmArg(std::map& v); AmArg(std::map& v); - + ~AmArg() { invalidate(); } void assertArray(); @@ -209,7 +197,7 @@ class AmArg short getType() const { return type; } - AmArg& operator=(const AmArg& rhs); + AmArg& operator=(const AmArg& rhs) = default; #define isArgUndef(a) (AmArg::Undef == a.getType()) #define isArgArray(a) (AmArg::Array == a.getType()) @@ -227,7 +215,7 @@ class AmArg do { \ ERROR("type mismatch: expected: %d; received: %d.\n", AmArg::exp, got.getType()); \ throw AmArg::TypeMismatchException(); \ - } while (0) + } while (0) #define assertArgArray(a) \ if (!isArgArray(a)) \ @@ -263,26 +251,26 @@ class AmArg void setBorrowedPointer(AmObject* v) { invalidate(); type = AObject; - v_obj = v; + value = v; } - int asInt() const { return (int)v_int; } - long int asLong() const { return v_int; } - long long asLongLong() const { return v_long; } - int asBool() const { return v_bool; } - double asDouble() const { return v_double; } - const char* asCStr() const { return v_cstr; } - AmObject* asObject() const { return v_obj; } - AmDynInvoke* asDynInv() const { return v_inv; } - ArgBlob* asBlob() const { return v_blob; } - ValueStruct* asStruct() const { return v_struct; } - - vector asStringVector() const; - vector asIntVector() const; - vector asBoolVector() const; - vector asDoubleVector() const; - vector asAmObjectVector() const; - vector asArgBlobVector() const; + int asInt() const { return std::get(value); } + long int asLong() const { return std::get(value); } + long long asLongLong() const { return std::get(value); } + bool asBool() const { return std::get(value); } + double asDouble() const { return std::get(value); } + const char* asCStr() const { return std::get(value).c_str(); } + AmObject* asObject() const { return std::get(value); } + AmDynInvoke* asDynInv() const { return std::get(value); } + const ArgBlob& asBlob() const { return std::get(value); } + ValueStruct* asStruct() const { return std::get(value); } + + vector asStringVector() const; + vector asIntVector() const; + vector asBoolVector() const; + vector asDoubleVector() const; + vector asAmObjectVector() const; + vector asArgBlobVector() const; // operations on arrays void assertArray(size_t s); @@ -294,7 +282,7 @@ class AmArg void pop_back(); void concat(const AmArg& a); - + size_t size() const; /** throws OutOfBoundsException if array too small */ @@ -324,6 +312,8 @@ class AmArg AmArg& operator[](const char* key); AmArg& operator[](const char* key) const; + bool operator==(const char *) const; + /** Check for the existence of a struct member by name. */ bool hasMember(const std::string& name) const; bool hasMember(const char* name) const; @@ -337,9 +327,9 @@ class AmArg /** remove struct member */ void erase(const std::string& name); - /** - * throws exception if arg array does not conform to spec - * i - int + /** + * throws exception if arg array does not conform to spec + * i - int * l - long long * t - bool * f - double @@ -355,7 +345,6 @@ class AmArg void assertArrayFmt(const char* format) const; void clear(); - friend bool operator==(const AmArg& lhs, const AmArg& rhs); friend bool json2arg(std::istream& input, AmArg& res); @@ -364,9 +353,6 @@ class AmArg static const char* t2str(int type); }; -// equality -bool operator==(const AmArg& lhs, const AmArg& rhs); - const int arg2int(const AmArg &a); string arg2str(const AmArg &a); diff --git a/core/jsonArg.cpp b/core/jsonArg.cpp index fa8cf9c9..88ce7346 100644 --- a/core/jsonArg.cpp +++ b/core/jsonArg.cpp @@ -243,18 +243,21 @@ bool json2arg(std::istream& input, AmArg& res) { return true; } - if (parse_float(input, &res.v_double)) { - res.type = AmArg::Double; + double d; + if (parse_float(input, &d)) { + res = d; return true; } - if (parse_number(input, &res.v_int)) { - res.type = AmArg::Int; + long l; + if (parse_number(input, &l)) { + res = l; return true; } - - if (parse_bool(input, &res.v_bool)) { - res.type = AmArg::Bool; + + bool b; + if (parse_bool(input, &b)) { + res = b; return true; }