/******************************************************************************* * libretroshare/src/util: contentvalue.cc * * * * libretroshare: retroshare core library * * * * Copyright 2012 Christopher Evi-Parker * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public License * * along with this program. If not, see . * * * *******************************************************************************/ #include #include #include "contentvalue.h" const uint8_t ContentValue::BOOL_TYPE = 1; const uint8_t ContentValue::DATA_TYPE = 2; const uint8_t ContentValue::STRING_TYPE = 3; const uint8_t ContentValue::DOUBLE_TYPE = 4; const uint8_t ContentValue::INT32_TYPE = 5; const uint8_t ContentValue::INT64_TYPE = 6; /**************** content value implementation ******************/ typedef std::pair KeyTypePair; ContentValue::ContentValue(){ } ContentValue::~ContentValue(){ // release resources held in data clearData(); } ContentValue::ContentValue(const ContentValue &from){ std::map keyTypeMap; from.getKeyTypeMap(keyTypeMap); std::map::const_iterator cit = keyTypeMap.begin(); uint8_t type = 0; std::string currKey; std::string val = ""; char *src = NULL; uint32_t data_len = 0; for(; cit != keyTypeMap.end(); ++cit){ type = cit->second; currKey = cit->first; switch(type){ case INT32_TYPE: { int32_t value = 0; if (from.getAsInt32(currKey, value)) put(currKey, value); break; } case INT64_TYPE: { int64_t value = 0; if (from.getAsInt64(currKey, value)) put(currKey, value); break; } case STRING_TYPE: { if (from.getAsString(currKey, val)) put(currKey, val); break; } case BOOL_TYPE: { bool value = false; if (from.getAsBool(currKey, value)) put(currKey, value); break; } case DATA_TYPE: { if (from.getAsData(currKey, data_len, src)) put(currKey, data_len, src); break; } case DOUBLE_TYPE: { double value = 0; if (from.getAsDouble(currKey, value)) put(currKey, value); break; } default: std::cerr << "ContentValue::ContentValue(ContentValue &from):" << "Error! Unrecognised data type!" << std::endl; break; } } } void ContentValue::put(const std::string &key, bool value){ if(mKvSet.find(key) != mKvSet.end()) removeKeyValue(key); mKvSet.insert(KeyTypePair(key, BOOL_TYPE)); mKvBool.insert(std::pair(key, value)); } void ContentValue::put(const std::string &key, const std::string &value){ if(mKvSet.find(key) != mKvSet.end()) removeKeyValue(key); mKvSet.insert(KeyTypePair(key, STRING_TYPE)); mKvString.insert(std::pair(key, value)); } void ContentValue::put(const std::string &key, double value){ if(mKvSet.find(key) != mKvSet.end()) removeKeyValue(key); mKvSet.insert(KeyTypePair(key,DOUBLE_TYPE)); mKvDouble.insert(std::pair(key, value)); } void ContentValue::put(const std::string &key, int32_t value){ if(mKvSet.find(key) != mKvSet.end()) removeKeyValue(key); mKvSet.insert(KeyTypePair(key, INT32_TYPE)); mKvInt32.insert(std::pair(key, value)); } void ContentValue::put(const std::string &key, int64_t value){ if(mKvSet.find(key) != mKvSet.end()) removeKeyValue(key); mKvSet.insert(KeyTypePair(key, INT64_TYPE)); mKvInt64.insert(std::pair(key, value)); } void ContentValue::put(const std::string &key, uint32_t len, const char* value){ // release memory from old key value if key // exists if(mKvSet.find(key) != mKvSet.end()) { removeKeyValue(key); } mKvSet.insert(KeyTypePair(key, DATA_TYPE)); char* dest = NULL; // len is zero then just put a NULL entry if(len != 0){ dest = new char[len]; memcpy(dest, value, len); } mKvData.insert(std::pair > (key, std::pair(len, dest))); //delete[] dest; //Deleted by clearData() // cppcheck-suppress memleak } bool ContentValue::getAsBool(const std::string &key, bool& value) const{ std::map::const_iterator it; if((it = mKvBool.find(key)) == mKvBool.end()) return false; value = it->second; return true; } bool ContentValue::getAsInt32(const std::string &key, int32_t& value) const{ std::map::const_iterator it; if((it = mKvInt32.find(key)) == mKvInt32.end()) return false; value = it->second; return true; } bool ContentValue::getAsInt64(const std::string &key, int64_t& value) const{ std::map::const_iterator it; if((it = mKvInt64.find(key)) == mKvInt64.end()) return false; value = it->second; return true; } bool ContentValue::getAsString(const std::string &key, std::string &value) const{ std::map::const_iterator it; if((it = mKvString.find(key)) == mKvString.end()) return false; value = it->second; return true; } bool ContentValue::getAsData(const std::string& key, uint32_t &len, char*& value) const{ std::map >::const_iterator it; if((it = mKvData.find(key)) == mKvData.end()) return false; const std::pair &kvRef = it->second; len = kvRef.first; value = kvRef.second; return true; } bool ContentValue::getAsDouble(const std::string &key, double& value) const{ std::map::const_iterator it; if((it = mKvDouble.find(key)) == mKvDouble.end()) return false; value = it->second; return true; } bool ContentValue::removeKeyValue(const std::string &key){ std::map::iterator mit; if((mit = mKvSet.find(key)) == mKvSet.end()) return false; if(mit->second == BOOL_TYPE) mKvBool.erase(key); if(mit->second == INT64_TYPE) mKvInt64.erase(key); if(mit->second == DATA_TYPE){ delete[] (mKvData[key].second); mKvData.erase(key); } if(mit->second == DOUBLE_TYPE) mKvDouble.erase(key); if(mit->second == STRING_TYPE) mKvString.erase(key); if(mit->second == INT32_TYPE) mKvInt32.erase(key); mKvSet.erase(key); return true; } void ContentValue::getKeyTypeMap(std::map &keySet) const { keySet = mKvSet; } void ContentValue::clear(){ mKvSet.clear(); mKvBool.clear(); mKvDouble.clear(); mKvString.clear(); mKvInt32.clear(); mKvInt64.clear(); clearData(); } bool ContentValue::empty() const{ return mKvSet.empty(); } void ContentValue::clearData(){ std::map >::iterator mit = mKvData.begin(); for(; mit != mKvData.end(); ++mit){ if(mit->second.first != 0) delete[] (mit->second.second); } mKvData.clear(); }