/* 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