RetroShare/libresapi/src/api/JsonStream.cpp

525 lines
12 KiB
C++

#include "JsonStream.h"
#include <iostream>
namespace resource_api
{
JsonStream::JsonStream():
mSerialise(true), mDataType(TYPE_UNDEFINED), mArrayNextRead(0), mIsOk(true), mChild(NULL)
{
}
JsonStream::~JsonStream()
{
deleteCurrentChild();
}
void JsonStream::setJsonString(std::string jsonStr)
{
mRawString = jsonStr;
// have to delay the deserialisation, because this stream can also be a raw data stream without json
// can find this out when others atucally call the operators
mSerialise = false;
}
std::string JsonStream::getJsonString()
{
deleteCurrentChild();
if(mIsOk)
{
switch(mDataType)
{
case TYPE_UNDEFINED:
return "";
case TYPE_ARRAY:
return json::Serialize(mArray);
case TYPE_OBJECT:
return json::Serialize(mObject);
case TYPE_RAW:
return mRawString;
default:
return "";
}
}
std::cerr << "JsonStream::getJsonString() Warning: stream not ok, will return empty string." << std::endl;
return "";
}
void JsonStream::switchToDeserialisation()
{
deleteCurrentChild();
mSerialise = false;
}
//----------Stream Interface ---------------
//----------Array---------------
StreamBase& JsonStream::operator<<(ValueReference<bool> value)
{
if(serialise())
{
setType(TYPE_ARRAY);
mArray.push_back(value.value);
}
else
{
if(checkDeserialisation() && arrayBoundsOk())
{
valueToBool(mArray[mArrayNextRead], value.value);
mArrayNextRead++;
}
}
return *this;
}
StreamBase& JsonStream::operator<<(ValueReference<int> value)
{
if(serialise())
{
setType(TYPE_ARRAY);
mArray.push_back(value.value);
}
else
{
if(checkDeserialisation() && arrayBoundsOk())
{
valueToInt(mArray[mArrayNextRead], value.value);
mArrayNextRead++;
}
}
return *this;
}
StreamBase& JsonStream::operator<<(ValueReference<double> value)
{
if(serialise())
{
setType(TYPE_ARRAY);
mArray.push_back(value.value);
}
else
{
if(checkDeserialisation() && arrayBoundsOk())
{
valueToDouble(mArray[mArrayNextRead], value.value);
mArrayNextRead++;
}
}
return *this;
}
StreamBase& JsonStream::operator<<(ValueReference<std::string> value)
{
if(serialise())
{
setType(TYPE_ARRAY);
mArray.push_back(value.value);
}
else
{
if(checkDeserialisation() && arrayBoundsOk())
{
valueToString(mArray[mArrayNextRead], value.value);
mArrayNextRead++;
}
}
return *this;
}
StreamBase& JsonStream::getStreamToMember()
{
setType(TYPE_ARRAY);
deleteCurrentChild();
mChild = new JsonStream();
if(!serialise())
{
if(checkDeserialisation() && arrayBoundsOk())
{
mChild->mValue = mArray[mArrayNextRead];
mChild->mSerialise = false;
mArrayNextRead++;
}
}
return *mChild;
}
//----------Object---------------
StreamBase& JsonStream::operator<<(KeyValueReference<bool> keyValue)
{
if(serialise())
{
setType(TYPE_OBJECT);
mObject[keyValue.key] = keyValue.value;
}
else
{
if(checkDeserialisation() && checkObjectMember(keyValue.key))
{
valueToBool(mObject[keyValue.key], keyValue.value);
}
}
return *this;
}
StreamBase& JsonStream::operator<<(KeyValueReference<int> keyValue)
{
if(serialise())
{
setType(TYPE_OBJECT);
mObject[keyValue.key] = keyValue.value;
}
else
{
if(checkDeserialisation() && checkObjectMember(keyValue.key))
{
valueToInt(mObject[keyValue.key], keyValue.value);
}
}
return *this;
}
StreamBase& JsonStream::operator<<(KeyValueReference<double> keyValue)
{
if(serialise())
{
setType(TYPE_OBJECT);
mObject[keyValue.key] = keyValue.value;
}
else
{
if(checkDeserialisation() && checkObjectMember(keyValue.key))
{
valueToDouble(mObject[keyValue.key], keyValue.value);
}
}
return *this;
}
StreamBase& JsonStream::operator<<(KeyValueReference<std::string> keyValue)
{
if(serialise())
{
setType(TYPE_OBJECT);
mObject[keyValue.key] = keyValue.value;
}
else
{
if(checkDeserialisation() && checkObjectMember(keyValue.key))
{
valueToString(mObject[keyValue.key], keyValue.value);
}
}
return *this;
}
// usefull if the new object member should be an array or object
// the reference should be at least valid until another method of this class gets called
StreamBase& JsonStream::getStreamToMember(std::string name)
{
setType(TYPE_OBJECT);
deleteCurrentChild();
mChildKey = name;
mChild = new JsonStream();
if(!serialise())
{
mChild->mSerialise = false;
if(checkDeserialisation() && checkObjectMember(name))
{
mChild->mValue = mObject[name];
}
}
return *mChild;
}
// make a binay data object (not a real object, just binary data)
StreamBase& JsonStream::operator<<(std::vector<uint8_t>& data)
{
if(serialise())
{
if((mDataType == TYPE_UNDEFINED)||(mDataType == TYPE_RAW))
{
mDataType = TYPE_RAW;
mRawString = std::string(data.begin(), data.end());
}
else
{
mErrorLog += "Error: trying to set raw data while the type of this object is already another type\n";
mIsOk = false;
}
}
else
{
if((mDataType == TYPE_UNDEFINED)||(mDataType == TYPE_RAW))
{
mDataType = TYPE_RAW;
data = std::vector<uint8_t>(mRawString.begin(), mRawString.end());
}
else
{
mErrorLog += "Error: trying to read raw data while the type of this object is already another type\n";
mIsOk = false;
}
}
return *this;
}
// return true if there are more members in this object/array
// useful for array reading
bool JsonStream::hasMore()
{
return arrayBoundsOk();
}
bool JsonStream::serialise()
{
return mSerialise;
}
bool JsonStream::isOK()
{
return mIsOk;
}
void JsonStream::setError()
{
mIsOk = false;
}
/*
void JsonStream::addLogMsg(std::string msg)
{}
*/
void JsonStream::addErrorMsg(std::string msg)
{
mErrorLog += msg;
}
std::string JsonStream::getLog()
{
return "not implemented yet";
}
std::string JsonStream::getErrorLog()
{
return mErrorLog;
}
bool JsonStream::isRawData()
{
return mDataType == TYPE_RAW;
}
std::string JsonStream::getRawData()
{
return mRawString;
}
void JsonStream::setType(DataType type)
{
if((mDataType == TYPE_UNDEFINED)||(mDataType == type))
{
mDataType = type;
}
else
{
mIsOk = false;
mErrorLog += "JsonStream::setType() Error: type alread set to another type\n";
}
}
bool JsonStream::checkObjectMember(std::string key)
{
if(mDataType == TYPE_OBJECT)
{
if(mObject.HasKey(key))
{
return true;
}
else
{
mErrorLog += "JsonStream::checkObjectMember() Warning: missing key \""+key+"\"\n";
return false;
}
}
else
{
mIsOk = false;
mErrorLog += "JsonStream::checkObjectMember() Error: type is not TYPE_OBJECT\n";
return false;
}
}
bool JsonStream::arrayBoundsOk()
{
if(checkDeserialisation())
{
if(mDataType == TYPE_ARRAY)
{
if(mArrayNextRead < mArray.size())
{
return true;
}
else
{
return false;
}
}
else
{
mIsOk = false;
mErrorLog += "JsonStream::arrayBoundsOk() Error: type is not TYPE_ARRAY\n";
return false;
}
}
return false;
}
bool JsonStream::checkDeserialisation()
{
if(mDataType != TYPE_RAW)
{
if(mDataType == TYPE_UNDEFINED)
{
if((mValue.GetType() == json::NULLVal) && mRawString != "")
{
mValue = json::Deserialize(mRawString);
}
if(mValue.GetType() == json::ObjectVal)
{
mDataType = TYPE_OBJECT;
mObject = mValue;
return true;
}
else if(mValue.GetType() == json::ArrayVal)
{
mDataType = TYPE_ARRAY;
mArray = mValue;
return true;
}
else
{
mIsOk = false;
mErrorLog += "JsonStream::checkDeserialisation() Error: deserialisation did not end with an object or array\n";
return false;
}
}
else
{
// already deserialised
return true;
}
}
else
{
mIsOk = false;
mErrorLog += "JsonStream::checkDeserialisation() Error: type is TYPE_RAW\n";
return false;
}
}
void JsonStream::valueToBool(json::Value &value, bool &boolean)
{
if(value.GetType() == json::BoolVal)
{
boolean = value;
}
else
{
mIsOk = false;
mErrorLog += "JsonStream::valueToBool() Error: wrong type\n";
}
}
void JsonStream::valueToInt(json::Value &value, int &integer)
{
if(value.GetType() == json::IntVal)
{
integer = value;
}
else
{
mIsOk = false;
mErrorLog += "JsonStream::valueToInt() Error: wrong type\n";
}
}
void JsonStream::valueToDouble(json::Value &value, double &doubleVal)
{
if(value.IsNumeric())
{
doubleVal = value;
}
else
{
mIsOk = false;
mErrorLog += "JsonStream::valueToDouble() Error: wrong type\n";
}
}
void JsonStream::valueToString(json::Value &value, std::string& str)
{
if(value.GetType() == json::StringVal)
{
str = value.ToString();
}
else
{
mIsOk = false;
mErrorLog += "JsonStream::valueToString() Error: wrong type\n";
}
}
void JsonStream::deleteCurrentChild()
{
if(mChild)
{
if(serialise())
{
if(mDataType == TYPE_ARRAY)
{
// don't add empty value
if(mChild->getJsonValue().GetType() != json::NULLVal)
mArray.push_back(mChild->getJsonValue());
}
else if(mDataType == TYPE_OBJECT)
{
mObject[mChildKey] = mChild->getJsonValue();
}
else
{
mErrorLog += "JsonStream::deleteCurrentChild() Error: cannot add child because own type is wrong\n";
}
}
else
{
// don't have to do anything for deserialisation
}
delete mChild;
mChild = NULL;
}
}
json::Value JsonStream::getJsonValue()
{
// remove the child and add it to own data
deleteCurrentChild();
switch(mDataType)
{
case TYPE_UNDEFINED:
return json::Value();
case TYPE_ARRAY:
return mArray;
case TYPE_OBJECT:
return mObject;
case TYPE_RAW:
return mRawString;
default:
return json::Value();
}
}
} // namespace resource_api