/* This file is part of MAUS: http://micewww.pp.rl.ac.uk/projects/maus
*
* MAUS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MAUS 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MAUS. If not, see .
*
*/
#ifndef SRC_COMMON_CPP_CONVERTERS_DATACONVERTERS_PRIMITIVECONVERTERS_H
#define SRC_COMMON_CPP_CONVERTERS_DATACONVERTERS_PRIMITIVECONVERTERS_H
#include
#include "json/json.h"
#include "src/common_cpp/Utils/JsonWrapper.hh"
#include "src/common_cpp/Converter/ConverterBase.hh"
// Tested in ConverterFactoryTest
namespace MAUS {
////////////////////////// DISALLOWED //////////////////////////////////////
template
class DisallowedConverter : public ConverterBase {
public:
DisallowedConverter()
: ConverterBase("DisallowedConverter") {}
private:
TEMP2* _convert(const TEMP1* input) const {
throw MAUS::Exception(MAUS::Exception::recoverable,
"Attempt to make disallowed conversion between types",
"DisallowedConverter::convert");
}
};
/////////////////////////// STRING TO X ////////////////////////////
class StringJsonConverter : public ConverterBase {
public:
StringJsonConverter()
: ConverterBase("StringJsonConverter") {}
private:
Json::Value* _convert(const std::string* json) const {
return new Json::Value(JsonWrapper::StringToJson(*json));
}
};
class StringStringConverter : public ConverterBase {
public:
StringStringConverter()
: ConverterBase("SelfConverter") {}
private:
std::string* _convert(const std::string* str) const {
return new std::string(*str);
}
};
class StringPyDictConverter : public ConverterBase {
public:
StringPyDictConverter()
: ConverterBase("StringPyObjectConverter") {}
private:
inline PyObject* _convert(const std::string* str) const;
};
/////////////////////////// JSON TO X ////////////////////////////
class JsonStringConverter : public ConverterBase {
public:
JsonStringConverter()
: ConverterBase("JsonStringConverter") {}
private:
std::string* _convert(const Json::Value* json) const {
return new std::string(JsonWrapper::JsonToString(*json));
}
};
class JsonJsonConverter : public ConverterBase {
public:
JsonJsonConverter()
: ConverterBase("JsonJsonConverter") {}
private:
Json::Value* _convert(const Json::Value* json) const {
return new Json::Value(*json);
}
};
class JsonPyDictConverter : public ConverterBase {
public:
JsonPyDictConverter()
: ConverterBase("JsonJsonConverter") {}
private:
PyObject* _convert(const Json::Value* json) const {
std::string* str = JsonStringConverter().convert(json);
PyObject* py_dict = StringPyDictConverter().convert(str);
delete str;
return py_dict;
}
};
/////////////////////////// PYDICT TO X ////////////////////////////
class PyDictStringConverter : public ConverterBase {
public:
PyDictStringConverter()
: ConverterBase("PyDictStringConverter") {}
private:
inline std::string* _convert(const PyObject* obj) const;
};
class PyDictJsonConverter : public ConverterBase {
public:
PyDictJsonConverter()
: ConverterBase("PyDictJsonConverter") {}
private:
Json::Value* _convert(const PyObject* obj) const {
std::string* str = PyDictStringConverter().convert(obj);
Json::Value* json = StringJsonConverter().convert(str);
delete str;
return json;
}
};
class PyDictPyDictConverter : public ConverterBase {
public:
PyDictPyDictConverter()
: ConverterBase("PyDictPyDictConverter") {}
private:
PyObject* _convert(const PyObject* obj) const {
PyObject* obj_non_const = const_cast(obj);
return PyDict_Copy(obj_non_const);
}
};
PyObject* StringPyDictConverter::_convert(const std::string* str) const {
if (!str)
throw Exception(Exception::recoverable,
"string was NULL",
"StringPyDictConverter::_convert");
// import json
PyObject* json_module = PyImport_ImportModule("json");
if (!json_module) {
throw Exception(Exception::recoverable,
"Failed to import json",
"StringPyDictConverter::_convert");
}
// json.getattr("loads")
PyObject* loads_function = PyObject_GetAttrString(json_module, "loads");
Py_DECREF(json_module);
if (!PyCallable_Check(loads_function))
throw Exception(Exception::recoverable,
"Failed to get loads function",
"StringPyDictConverter::_convert");
// json.loads(str)
char* c_string = const_cast(str->c_str());
char* format = const_cast("s");
PyObject* py_dict = PyObject_CallFunction(loads_function,
format,
c_string);
Py_DECREF(loads_function);
if (!py_dict || !PyDict_Check(py_dict)) {
if (py_dict)
Py_DECREF(py_dict);
throw Exception(Exception::recoverable,
"Failed to call loads and extract a dict",
"StringPyDictConverter::_convert");
}
return py_dict;
}
std::string* PyDictStringConverter::_convert(const PyObject* py_dict) const {
if (!PyDict_Check(py_dict))
throw Exception(Exception::recoverable,
"PyDict was NULL",
"PyDictStringConverter::_convert");
// import json
PyObject* json_module = PyImport_ImportModule("json");
if (!json_module) {
throw Exception(Exception::recoverable,
"Failed to import json",
"PyDictStringConverter::_convert");
}
// json.dumps(py_dict)
PyObject* dumps_function = PyObject_GetAttrString(json_module, "dumps");
Py_DECREF(json_module);
if (!PyCallable_Check(dumps_function))
throw Exception(Exception::recoverable,
"Failed to get dumps function",
"PyDictStringConverter::_convert");
char* format = const_cast("O");
PyObject* py_str = PyObject_CallFunction(dumps_function,
format,
py_dict);
Py_DECREF(dumps_function);
// memory owned by py_str; py_str checking done as part of this call
char* c_string = PyString_AsString(py_str);
if (!c_string)
throw Exception(Exception::recoverable,
"Failed to extract string from dumps output",
"PyDictStringConverter::_convert");
std::string* cpp_string = new std::string(c_string);
Py_DECREF(py_str);
return cpp_string;
}
}
#endif // SRC_COMMON_CPP_CONVERTERS_DATACONVERTERS_PRIMITIVECONVERTERS_H