diff options
Diffstat (limited to 'contrib/epee/include/storages')
-rw-r--r-- | contrib/epee/include/storages/activity_notifier.h | 132 | ||||
-rw-r--r-- | contrib/epee/include/storages/crypted_storage.h | 62 | ||||
-rw-r--r-- | contrib/epee/include/storages/gzipped_inmemstorage.h | 68 | ||||
-rw-r--r-- | contrib/epee/include/storages/http_abstract_invoke.h | 126 | ||||
-rw-r--r-- | contrib/epee/include/storages/levin_abstract_invoke2.h | 289 | ||||
-rw-r--r-- | contrib/epee/include/storages/parserse_base_utils.h | 260 | ||||
-rw-r--r-- | contrib/epee/include/storages/portable_storage.h | 463 | ||||
-rw-r--r-- | contrib/epee/include/storages/portable_storage_base.h | 160 | ||||
-rw-r--r-- | contrib/epee/include/storages/portable_storage_from_bin.h | 281 | ||||
-rw-r--r-- | contrib/epee/include/storages/portable_storage_from_json.h | 379 | ||||
-rw-r--r-- | contrib/epee/include/storages/portable_storage_template_helper.h | 120 | ||||
-rw-r--r-- | contrib/epee/include/storages/portable_storage_to_bin.h | 212 | ||||
-rw-r--r-- | contrib/epee/include/storages/portable_storage_to_json.h | 172 | ||||
-rw-r--r-- | contrib/epee/include/storages/portable_storage_val_converters.h | 169 |
14 files changed, 2893 insertions, 0 deletions
diff --git a/contrib/epee/include/storages/activity_notifier.h b/contrib/epee/include/storages/activity_notifier.h new file mode 100644 index 000000000..14b6ebbfb --- /dev/null +++ b/contrib/epee/include/storages/activity_notifier.h @@ -0,0 +1,132 @@ +// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the Andrey N. Sabelnikov nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + + + +#pragma once + +#include "inmemtoxml.h" + +//#include "levin/levin_server.h" + +namespace epee +{ + +class activity_printer_base +{ +public: + activity_printer_base(){} + virtual ~activity_printer_base(){} +}; + +template<class A> +class notify_activity_printer: public activity_printer_base +{ +public: + notify_activity_printer(int level, A& arg, bool is_notify_mode = true):m_ref_arg(arg), m_level(level), m_is_notify_mode(is_notify_mode) + { + m_command_name = typeid(m_ref_arg).name(); + m_command_name.erase(0, 7); + m_command_name.erase(m_command_name.size()-10, m_command_name.size()-1); + if(level == log_space::get_set_log_detalisation_level()) + { + LOG_PRINT(m_command_name, level); + } + else if(level+1 == log_space::get_set_log_detalisation_level()) + { + LOG_PRINT(" -->>" << m_command_name, level); + } + else if(level+2 == log_space::get_set_log_detalisation_level()) + { + LOG_PRINT(" -->>" << m_command_name << "\n" << StorageNamed::xml::get_t_as_xml(m_ref_arg), level); + } + } + + virtual ~notify_activity_printer() + { + if(m_is_notify_mode) + { + if(m_level+1 == log_space::get_set_log_detalisation_level()) + { + LOG_PRINT(" <<--" << m_command_name, m_level); + } + } + } +protected: + std::string m_command_name; + A& m_ref_arg; + int m_level; + bool m_is_notify_mode; +}; + +template<class A, class R> +class command_activity_printer: public notify_activity_printer<A> +{ +public: + command_activity_printer(int level, A& arg, R& rsp):notify_activity_printer(level, arg, false), m_ref_rsp(rsp) + { + } + + virtual ~command_activity_printer() + { + if(m_level+1 == log_space::get_set_log_detalisation_level()) + { + LOG_PRINT(" <<--" << m_command_name, m_level); + } + else if(m_level+2 == log_space::get_set_log_detalisation_level()) + { + LOG_PRINT(" <<--" << m_command_name << "\n" << StorageNamed::trace_as_xml(m_ref_rsp), m_level); + } + } +private: + R& m_ref_rsp; +}; + +template<class A, class R> +activity_printer_base* create_activity_printer(int level, A& arg, R& rsp) +{ + return new command_activity_printer<A, R>(level, arg, rsp); +} + +template<class A> +activity_printer_base* create_activity_printer(int level, A& arg) +{ + return new notify_activity_printer<A>(level, arg); +} + +} + +#define PRINT_COMMAND_ACTIVITY(level) boost::shared_ptr<activity_printer_base> local_activity_printer(create_activity_printer(level, in_struct, out_struct)); +#define PRINT_NOTIFY_ACTIVITY(level) boost::shared_ptr<activity_printer_base> local_activity_printer(create_activity_printer(level, in_struct)); + +#define PRINT_ACTIVITY(level) \ +{std::string some_str = typeid(in_struct).name(); \ + some_str.erase(0, 7); \ + some_str.erase(some_str.size()-10, some_str.size()-1); \ + LOG_PRINT(some_str, level);} + +} + diff --git a/contrib/epee/include/storages/crypted_storage.h b/contrib/epee/include/storages/crypted_storage.h new file mode 100644 index 000000000..d6e6edcba --- /dev/null +++ b/contrib/epee/include/storages/crypted_storage.h @@ -0,0 +1,62 @@ +// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the Andrey N. Sabelnikov nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + + +#ifndef _CRYPTED_STORAGE_H_ +#define _CRYPTED_STORAGE_H_ + +#include "cryptopp_helper.h" + +namespace epee +{ +template<class t_base_storage, class crypt_provider, class t_key_provider> +class crypted_storage: public t_base_storage +{ +public: + size_t PackToSolidBuffer(std::string& targetObj) + { + size_t res = t_base_storage::PackToSolidBuffer(targetObj); + if(res <= 0) + return res; + + if(!crypt_provider::encrypt(targetObj, t_key_provider::get_storage_default_key())) + return 0; + + return targetObj.size(); + } + + size_t LoadFromSolidBuffer(const std::string& pTargetObj) + { + std::string buff_to_decrypt = pTargetObj; + if(crypt_provider::decrypt(buff_to_decrypt, t_key_provider::get_storage_default_key())) + return t_base_storage::LoadFromSolidBuffer(buff_to_decrypt); + + return 0; + } +}; +} + +#endif //_CRYPTED_STORAGE_H_
\ No newline at end of file diff --git a/contrib/epee/include/storages/gzipped_inmemstorage.h b/contrib/epee/include/storages/gzipped_inmemstorage.h new file mode 100644 index 000000000..5c53fffa7 --- /dev/null +++ b/contrib/epee/include/storages/gzipped_inmemstorage.h @@ -0,0 +1,68 @@ +// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the Andrey N. Sabelnikov nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + + +#ifndef _GZIPPED_INMEMSTORAGE_H_ +#define _GZIPPED_INMEMSTORAGE_H_ + +#include "zlib_helper.h" +namespace epee +{ +namespace StorageNamed +{ + + template<class t_base_storage> + class gziped_storage: public t_base_storage + { + public: + size_t PackToSolidBuffer(std::string& targetObj) + { + size_t res = t_base_storage::PackToSolidBuffer(targetObj); + if(res <= 0) + return res; + + if(!zlib_helper::pack(targetObj)) + return 0; + + return targetObj.size(); + } + + size_t LoadFromSolidBuffer(const std::string& pTargetObj) + { + std::string buff_to_ungzip = pTargetObj; + if(zlib_helper::unpack(buff_to_ungzip)) + return t_base_storage::LoadFromSolidBuffer(buff_to_ungzip); + + return 0; + } + + private: + }; + +} +} + +#endif
\ No newline at end of file diff --git a/contrib/epee/include/storages/http_abstract_invoke.h b/contrib/epee/include/storages/http_abstract_invoke.h new file mode 100644 index 000000000..07720f496 --- /dev/null +++ b/contrib/epee/include/storages/http_abstract_invoke.h @@ -0,0 +1,126 @@ + +// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the Andrey N. Sabelnikov nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#pragma once +#include "portable_storage_template_helper.h" +#include "net/http_base.h" +#include "net/http_server_handlers_map2.h" + +namespace epee +{ + namespace net_utils + { + template<class t_request, class t_response, class t_transport> + bool invoke_http_json_remote_command2(const std::string& url, t_request& out_struct, t_response& result_struct, t_transport& transport, unsigned int timeout = 5000, const std::string& method = "GET") + { + std::string req_param; + if(!serialization::store_t_to_json(out_struct, req_param)) + return false; + + const http::http_response_info* pri = NULL; + if(!invoke_request(url, transport, timeout, &pri, method, req_param)) + { + LOG_PRINT_L1("Failed to invoke http request to " << url); + return false; + } + + if(!pri->m_response_code) + { + LOG_PRINT_L1("Failed to invoke http request to " << url << ", internal error (null response ptr)"); + return false; + } + + if(pri->m_response_code != 200) + { + LOG_PRINT_L1("Failed to invoke http request to " << url << ", wrong response code: " << pri->m_response_code); + return false; + } + + return serialization::load_t_from_json(result_struct, pri->m_body); + } + + + + template<class t_request, class t_response, class t_transport> + bool invoke_http_bin_remote_command2(const std::string& url, t_request& out_struct, t_response& result_struct, t_transport& transport, unsigned int timeout = 5000, const std::string& method = "GET") + { + std::string req_param; + if(!serialization::store_t_to_binary(out_struct, req_param)) + return false; + + const http::http_response_info* pri = NULL; + if(!invoke_request(url, transport, timeout, &pri, method, req_param)) + { + LOG_PRINT_L1("Failed to invoke http request to " << url); + return false; + } + + if(!pri->m_response_code) + { + LOG_PRINT_L1("Failed to invoke http request to " << url << ", internal error (null response ptr)"); + return false; + } + + if(pri->m_response_code != 200) + { + LOG_PRINT_L1("Failed to invoke http request to " << url << ", wrong response code: " << pri->m_response_code); + return false; + } + + return serialization::load_t_from_binary(result_struct, pri->m_body); + } + + template<class t_request, class t_response, class t_transport> + bool invoke_http_json_rpc(const std::string& url, const std::string& method_name, t_request& out_struct, t_response& result_struct, t_transport& transport, unsigned int timeout = 5000, const std::string& http_method = "GET", const std::string& req_id = "0") + { + epee::json_rpc::request<t_request> req_t = AUTO_VAL_INIT(req_t); + req_t.params = out_struct; + req_t.id = req_id; + req_t.method = method_name; + req_t.version = "2.0"; + epee::json_rpc::response<t_response, epee::json_rpc::error> resp_t = AUTO_VAL_INIT(resp_t); + if(!epee::net_utils::invoke_http_json_remote_command2(url, req_t, resp_t, transport, timeout, http_method)) + { + return false; + } + if(resp_t.error.code || resp_t.error.message.size()) + { + LOG_ERROR("RPC call of \"" << method_name << "\" returned error: " << resp_t.error.code << ", message: " << resp_t.error.message); + return false; + } + result_struct = resp_t.result; + return true; + } + + template<class t_command, class t_transport> + bool invoke_http_json_rpc(const std::string& url, typename t_command::request& out_struct, typename t_command::response& result_struct, t_transport& transport, unsigned int timeout = 5000, const std::string& http_method = "GET", const std::string& req_id = "0") + { + return invoke_http_json_rpc(url, t_command::methodname(), out_struct, result_struct, transport, timeout, http_method, req_id); + } + + } +} diff --git a/contrib/epee/include/storages/levin_abstract_invoke2.h b/contrib/epee/include/storages/levin_abstract_invoke2.h new file mode 100644 index 000000000..1b32c51d1 --- /dev/null +++ b/contrib/epee/include/storages/levin_abstract_invoke2.h @@ -0,0 +1,289 @@ +// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the Andrey N. Sabelnikov nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#pragma once + +#include "portable_storage_template_helper.h" +#include <boost/utility/value_init.hpp> +#include "net/levin_base.h" + +namespace epee +{ + namespace net_utils + { + template<class t_arg, class t_result, class t_transport> + bool invoke_remote_command2(int command, const t_arg& out_struct, t_result& result_struct, t_transport& transport) + { + if(!transport.is_connected()) + return false; + + serialization::portable_storage stg; + out_struct.store(stg); + std::string buff_to_send, buff_to_recv; + stg.store_to_binary(buff_to_send); + + int res = transport.invoke(command, buff_to_send, buff_to_recv); + if( res <=0 ) + { + LOG_PRINT_RED("Failed to invoke command " << command << " return code " << res, LOG_LEVEL_1); + return false; + } + serialization::portable_storage stg_ret; + if(!stg_ret.load_from_binary(buff_to_recv)) + { + LOG_ERROR("Failed to load_from_binary on command " << command); + return false; + } + result_struct.load(stg_ret); + return true; + } + + template<class t_arg, class t_transport> + bool notify_remote_command2(int command, const t_arg& out_struct, t_transport& transport) + { + if(!transport.is_connected()) + return false; + + serialization::portable_storage stg; + out_struct.store(&stg); + std::string buff_to_send; + stg.store_to_binary(buff_to_send); + + int res = transport.notify(command, buff_to_send); + if(res <=0 ) + { + LOG_ERROR("Failed to notify command " << command << " return code " << res); + return false; + } + return true; + } + + template<class t_arg, class t_result, class t_transport> + bool invoke_remote_command2(boost::uuids::uuid conn_id, int command, const t_arg& out_struct, t_result& result_struct, t_transport& transport) + { + + typename serialization::portable_storage stg; + out_struct.store(stg); + std::string buff_to_send, buff_to_recv; + stg.store_to_binary(buff_to_send); + + int res = transport.invoke(command, buff_to_send, buff_to_recv, conn_id); + if( res <=0 ) + { + LOG_PRINT_L1("Failed to invoke command " << command << " return code " << res); + return false; + } + typename serialization::portable_storage stg_ret; + if(!stg_ret.load_from_binary(buff_to_recv)) + { + LOG_ERROR("Failed to load_from_binary on command " << command); + return false; + } + result_struct.load(stg_ret); + + return true; + } + + template<class t_result, class t_arg, class callback_t, class t_transport> + bool async_invoke_remote_command2(boost::uuids::uuid conn_id, int command, const t_arg& out_struct, t_transport& transport, callback_t cb, size_t inv_timeout = LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED) + { + typename serialization::portable_storage stg; + const_cast<t_arg&>(out_struct).store(stg);//TODO: add true const support to searilzation + std::string buff_to_send, buff_to_recv; + stg.store_to_binary(buff_to_send); + int res = transport.invoke_async(command, buff_to_send, conn_id, [cb, command](int code, const std::string& buff, typename t_transport::connection_context& context)->bool + { + t_result result_struct = AUTO_VAL_INIT(result_struct); + if( code <=0 ) + { + LOG_PRINT_L1("Failed to invoke command " << command << " return code " << code); + cb(code, result_struct, context); + return false; + } + serialization::portable_storage stg_ret; + if(!stg_ret.load_from_binary(buff)) + { + LOG_ERROR("Failed to load_from_binary on command " << command); + cb(LEVIN_ERROR_FORMAT, result_struct, context); + return false; + } + result_struct.load(stg_ret); + cb(code, result_struct, context); + return true; + }, inv_timeout); + if( res <=0 ) + { + LOG_PRINT_L1("Failed to invoke command " << command << " return code " << res); + return false; + } + return true; + } + + template<class t_arg, class t_transport> + bool notify_remote_command2(boost::uuids::uuid conn_id, int command, const t_arg& out_struct, t_transport& transport) + { + + serialization::portable_storage stg; + out_struct.store(stg); + std::string buff_to_send, buff_to_recv; + stg.store_to_binary(buff_to_send); + + int res = transport.notify(command, buff_to_send, conn_id); + if(res <=0 ) + { + LOG_PRINT_RED_L0("Failed to notify command " << command << " return code " << res); + return false; + } + return true; + } + //---------------------------------------------------------------------------------------------------- + //---------------------------------------------------------------------------------------------------- + template<class t_owner, class t_in_type, class t_out_type, class t_context, class callback_t> + int buff_to_t_adapter(int command, const std::string& in_buff, std::string& buff_out, callback_t cb, t_context& context ) + { + serialization::portable_storage strg; + if(!strg.load_from_binary(in_buff)) + { + LOG_ERROR("Failed to load_from_binary in command " << command); + return -1; + } + boost::value_initialized<t_in_type> in_struct; + boost::value_initialized<t_out_type> out_struct; + + static_cast<t_in_type&>(in_struct).load(strg); + int res = cb(command, static_cast<t_in_type&>(in_struct), static_cast<t_out_type&>(out_struct), context); + serialization::portable_storage strg_out; + static_cast<t_out_type&>(out_struct).store(strg_out); + + if(!strg_out.store_to_binary(buff_out)) + { + LOG_ERROR("Failed to store_to_binary in command" << command); + return -1; + } + + return res; + }; + + template<class t_owner, class t_in_type, class t_context, class callback_t> + int buff_to_t_adapter(t_owner* powner, int command, const std::string& in_buff, callback_t cb, t_context& context) + { + serialization::portable_storage strg; + if(!strg.load_from_binary(in_buff)) + { + LOG_ERROR("Failed to load_from_binary in notify " << command); + return -1; + } + boost::value_initialized<t_in_type> in_struct; + static_cast<t_in_type&>(in_struct).load(strg); + return cb(command, in_struct, context); + }; + +#define CHAIN_LEVIN_INVOKE_MAP2(context_type) \ + int invoke(int command, const std::string& in_buff, std::string& buff_out, context_type& context) \ + { \ + bool handled = false; \ + return handle_invoke_map(false, command, in_buff, buff_out, context, handled); \ + } + +#define CHAIN_LEVIN_NOTIFY_MAP2(context_type) \ + int notify(int command, const std::string& in_buff, context_type& context) \ + { \ + bool handled = false; std::string fake_str;\ + return handle_invoke_map(true, command, in_buff, fake_str, context, handled); \ + } + + +#define CHAIN_LEVIN_INVOKE_MAP() \ + int invoke(int command, const std::string& in_buff, std::string& buff_out, epee::net_utils::connection_context_base& context) \ + { \ + bool handled = false; \ + return handle_invoke_map(false, command, in_buff, buff_out, context, handled); \ + } + +#define CHAIN_LEVIN_NOTIFY_MAP() \ + int notify(int command, const std::string& in_buff, epee::net_utils::connection_context_base& context) \ + { \ + bool handled = false; std::string fake_str;\ + return handle_invoke_map(true, command, in_buff, fake_str, context, handled); \ + } + +#define CHAIN_LEVIN_NOTIFY_STUB() \ + int notify(int command, const std::string& in_buff, epee::net_utils::connection_context_base& context) \ + { \ + return -1; \ + } + +#define BEGIN_INVOKE_MAP2(owner_type) \ + template <class t_context> int handle_invoke_map(bool is_notify, int command, const std::string& in_buff, std::string& buff_out, t_context& context, bool& handled) \ + { \ + typedef owner_type internal_owner_type_name; + +#define HANDLE_INVOKE2(command_id, func, type_name_in, typename_out) \ + if(!is_notify && command_id == command) \ + {handled=true;return epee::net_utils::buff_to_t_adapter<internal_owner_type_name, type_name_in, typename_out>(this, command, in_buff, buff_out, boost::bind(func, this, _1, _2, _3, _4), context);} + +#define HANDLE_INVOKE_T2(COMMAND, func) \ + if(!is_notify && COMMAND::ID == command) \ + {handled=true;return epee::net_utils::buff_to_t_adapter<internal_owner_type_name, typename COMMAND::request, typename COMMAND::response>(command, in_buff, buff_out, boost::bind(func, this, _1, _2, _3, _4), context);} + + +#define HANDLE_NOTIFY2(command_id, func, type_name_in) \ + if(is_notify && command_id == command) \ + {handled=true;return epee::net_utils::buff_to_t_adapter<internal_owner_type_name, type_name_in>(this, command, in_buff, boost::bind(func, this, _1, _2, _3), context);} + +#define HANDLE_NOTIFY_T2(NOTIFY, func) \ + if(is_notify && NOTIFY::ID == command) \ + {handled=true;return epee::net_utils::buff_to_t_adapter<internal_owner_type_name, typename NOTIFY::request>(this, command, in_buff, boost::bind(func, this, _1, _2, _3), context);} + + +#define CHAIN_INVOKE_MAP2(func) \ + { \ + int res = func(is_notify, command, in_buff, buff_out, context, handled); \ + if(handled) \ + return res; \ + } + +#define CHAIN_INVOKE_MAP_TO_OBJ2(obj) \ + { \ + int res = obj.handle_invoke_map(is_notify, command, in_buff, buff_out, context, handled); \ + if(handled) \ + return res; \ + } + +#define CHAIN_INVOKE_MAP_TO_OBJ_FORCE_CONTEXT(obj, context_type) \ + { \ + int res = obj.handle_invoke_map(is_notify, command, in_buff, buff_out, static_cast<context_type>(context), handled); \ + if(handled) return res; \ + } + + +#define END_INVOKE_MAP2() \ + LOG_ERROR("Unkonown command:" << command); \ + return LEVIN_ERROR_CONNECTION_HANDLER_NOT_DEFINED; \ + } + } +} + diff --git a/contrib/epee/include/storages/parserse_base_utils.h b/contrib/epee/include/storages/parserse_base_utils.h new file mode 100644 index 000000000..baafb5623 --- /dev/null +++ b/contrib/epee/include/storages/parserse_base_utils.h @@ -0,0 +1,260 @@ +// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the Andrey N. Sabelnikov nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + + + +#pragma once + +namespace epee +{ +namespace misc_utils +{ + namespace parse + { + inline std::string transform_to_escape_sequence(const std::string& src) + { + //std::stringstream res; + std::string res; + for(std::string::const_iterator it = src.begin(); it!=src.end(); ++it) + { + switch(*it) + { + case '\b': //Backspace (ascii code 08) + res+="\\b"; break; + case '\f': //Form feed (ascii code 0C) + res+="\\f"; break; + case '\n': //New line + res+="\\n"; break; + case '\r': //Carriage return + res+="\\r"; break; + case '\t': //Tab + res+="\\t"; break; + case '\v': //Vertical tab + res+="\\v"; break; + //case '\'': //Apostrophe or single quote + // res+="\\'"; break; + case '"': //Double quote + res+="\\\""; break; + case '\\': //Backslash caracter + res+="\\\\"; break; + case '/': //Backslash caracter + res+="\\/"; break; + default: + res.push_back(*it); + } + } + return res; + } + /* + + \b Backspace (ascii code 08) + \f Form feed (ascii code 0C) + \n New line + \r Carriage return + \t Tab + \v Vertical tab + \' Apostrophe or single quote + \" Double quote + \\ Backslash character + + */ + inline void match_string2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val) + { + val.clear(); + bool escape_mode = false; + std::string::const_iterator it = star_end_string; + ++it; + for(;it != buf_end;it++) + { + if(escape_mode/*prev_ch == '\\'*/) + { + switch(*it) + { + case 'b': //Backspace (ascii code 08) + val.push_back(0x08);break; + case 'f': //Form feed (ascii code 0C) + val.push_back(0x0C);break; + case 'n': //New line + val.push_back('\n');break; + case 'r': //Carriage return + val.push_back('\r');break; + case 't': //Tab + val.push_back('\t');break; + case 'v': //Vertical tab + val.push_back('\v');break; + case '\'': //Apostrophe or single quote + val.push_back('\'');break; + case '"': //Double quote + val.push_back('"');break; + case '\\': //Backslash character + val.push_back('\\');break; + case '/': //Slash character + val.push_back('/');break; + default: + val.push_back(*it); + LOG_PRINT_L0("Unknown escape sequence :\"\\" << *it << "\""); + } + escape_mode = false; + }else if(*it == '"') + { + star_end_string = it; + return; + }else if(*it == '\\') + { + escape_mode = true; + } + else + { + val.push_back(*it); + } + } + ASSERT_MES_AND_THROW("Failed to match string in json entry: " << std::string(star_end_string, buf_end)); + } + inline bool match_string(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val) + { + try + { + + match_string2(star_end_string, buf_end, val); + return true; + } + catch(...) + { + return false; + } + } + inline void match_number2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val, bool& is_float_val, bool& is_signed_val) + { + val.clear(); + is_float_val = false; + for(std::string::const_iterator it = star_end_string;it != buf_end;it++) + { + if(isdigit(*it) || (it == star_end_string && *it == '-') || (val.size() && *it == '.' ) || (is_float_val && (*it == 'e' || *it == 'E' || *it == '-' || *it == '+' )) ) + { + if(!val.size() && *it == '-') + is_signed_val = true; + if(*it == '.' ) + is_float_val = true; + val.push_back(*it); + } + else + { + if(val.size()) + { + star_end_string = --it; + return; + } + else + ASSERT_MES_AND_THROW("wrong number in json entry: " << std::string(star_end_string, buf_end)); + } + } + ASSERT_MES_AND_THROW("wrong number in json entry: " << std::string(star_end_string, buf_end)); + } + inline bool match_number(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val) + { + try + { + bool is_v_float = false;bool is_signed_val = false; + match_number2(star_end_string, buf_end, val, is_v_float, is_signed_val); + return !is_v_float; + } + catch(...) + { + return false; + } + } + inline void match_word2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val) + { + val.clear(); + + for(std::string::const_iterator it = star_end_string;it != buf_end;it++) + { + if(!isalpha(*it)) + { + val.assign(star_end_string, it); + if(val.size()) + { + star_end_string = --it; + return; + }else + ASSERT_MES_AND_THROW("failed to match word number in json entry: " << std::string(star_end_string, buf_end)); + } + } + ASSERT_MES_AND_THROW("failed to match word number in json entry: " << std::string(star_end_string, buf_end)); + } + inline bool match_word(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val) + { + try + { + match_word2(star_end_string, buf_end, val); + return true; + } + catch(...) + { + return false; + } + } + inline bool match_word_with_extrasymb(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val) + { + val.clear(); + + for(std::string::const_iterator it = star_end_string;it != buf_end;it++) + { + if(!isalnum(*it) && *it != '-' && *it != '_') + { + val.assign(star_end_string, it); + if(val.size()) + { + star_end_string = --it; + return true; + }else + return false; + } + } + return false; + } + inline bool match_word_til_equal_mark(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string::const_iterator& word_end) + { + word_end = star_end_string; + + for(std::string::const_iterator it = star_end_string;it != buf_end;it++) + { + if(isspace(*it)) + { + + continue; + }else if( *it == '=' ) + { + star_end_string = it; + word_end = it; + return true; + } + } + return false; + } + } +} +}
\ No newline at end of file diff --git a/contrib/epee/include/storages/portable_storage.h b/contrib/epee/include/storages/portable_storage.h new file mode 100644 index 000000000..8f4ebc6ae --- /dev/null +++ b/contrib/epee/include/storages/portable_storage.h @@ -0,0 +1,463 @@ +// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the Andrey N. Sabelnikov nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + + + +#pragma once + +#include "misc_language.h" +#include "portable_storage_base.h" +#include "portable_storage_to_bin.h" +#include "portable_storage_from_bin.h" +#include "portable_storage_to_json.h" +#include "portable_storage_from_json.h" +#include "portable_storage_val_converters.h" + +namespace epee +{ + namespace serialization + { + /************************************************************************/ + /* */ + /************************************************************************/ + class portable_storage + { + public: + typedef epee::serialization::hsection hsection; + typedef epee::serialization::harray harray; + + portable_storage(){} + virtual ~portable_storage(){} + hsection open_section(const std::string& section_name, hsection hparent_section, bool create_if_notexist = false); + template<class t_value> + bool get_value(const std::string& value_name, t_value& val, hsection hparent_section); + template<class t_value> + bool set_value(const std::string& value_name, const t_value& target, hsection hparent_section); + + //serial access for arrays of values -------------------------------------- + //values + template<class t_value> + harray get_first_value(const std::string& value_name, t_value& target, hsection hparent_section); + template<class t_value> + bool get_next_value(harray hval_array, t_value& target); + template<class t_value> + harray insert_first_value(const std::string& value_name, const t_value& target, hsection hparent_section); + template<class t_value> + bool insert_next_value(harray hval_array, const t_value& target); + //sections + harray get_first_section(const std::string& pSectionName, hsection& h_child_section, hsection hparent_section); + bool get_next_section(harray hSecArray, hsection& h_child_section); + harray insert_first_section(const std::string& pSectionName, hsection& hinserted_childsection, hsection hparent_section); + bool insert_next_section(harray hSecArray, hsection& hinserted_childsection); + //------------------------------------------------------------------------ + //delete entry (section, value or array) + bool delete_entry(const std::string& pentry_name, hsection hparent_section = nullptr); + + //------------------------------------------------------------------------------- + bool store_to_binary(binarybuffer& target); + bool load_from_binary(const binarybuffer& target); + template<class trace_policy> + bool dump_as_xml(std::string& targetObj, const std::string& root_name = ""); + bool dump_as_json(std::string& targetObj, size_t indent = 0); + bool load_from_json(const std::string& source); + + private: + section m_root; + hsection get_root_section() {return &m_root;} + storage_entry* find_storage_entry(const std::string& pentry_name, hsection psection); + template<class entry_type> + storage_entry* insert_new_entry_get_storage_entry(const std::string& pentry_name, hsection psection, const entry_type& entry); + + hsection insert_new_section(const std::string& pentry_name, hsection psection); + +#pragma pack(push) +#pragma pack(1) + struct storage_block_header + { + uint32_t m_signature_a; + uint32_t m_signature_b; + uint8_t m_ver; + }; +#pragma pack(pop) + }; + inline + bool portable_storage::dump_as_json(std::string& buff, size_t indent) + { + TRY_ENTRY(); + std::stringstream ss; + epee::serialization::dump_as_json(ss, m_root, indent); + buff = ss.str(); + return true; + CATCH_ENTRY("portable_storage::dump_as_json", false) + } + inline + bool portable_storage::load_from_json(const std::string& source) + { + TRY_ENTRY(); + return json::load_from_json(source, *this); + CATCH_ENTRY("portable_storage::load_from_json", false) + } + + template<class trace_policy> + bool portable_storage::dump_as_xml(std::string& targetObj, const std::string& root_name) + { + return false;//TODO: don't think i ever again will use xml - ambiguous and "overtagged" format + } + + inline + bool portable_storage::store_to_binary(binarybuffer& target) + { + TRY_ENTRY(); + std::stringstream ss; + storage_block_header sbh = AUTO_VAL_INIT(sbh); + sbh.m_signature_a = PORTABLE_STORAGE_SIGNATUREA; + sbh.m_signature_b = PORTABLE_STORAGE_SIGNATUREB; + sbh.m_ver = PORTABLE_STORAGE_FORMAT_VER; + ss.write((const char*)&sbh, sizeof(storage_block_header)); + pack_entry_to_buff(ss, m_root); + target = ss.str(); + return true; + CATCH_ENTRY("portable_storage::store_to_binary", false) + } + inline + bool portable_storage::load_from_binary(const binarybuffer& source) + { + m_root.m_entries.clear(); + if(source.size() < sizeof(storage_block_header)) + { + LOG_ERROR("portable_storage: wrong binary format, packet size = " << source.size() << " less than expected sizeof(storage_block_header)=" << sizeof(storage_block_header)); + return false; + } + storage_block_header* pbuff = (storage_block_header*)source.data(); + if(pbuff->m_signature_a != PORTABLE_STORAGE_SIGNATUREA || + pbuff->m_signature_b != PORTABLE_STORAGE_SIGNATUREB + ) + { + LOG_ERROR("portable_storage: wrong binary format - signature missmatch"); + return false; + } + if(pbuff->m_ver != PORTABLE_STORAGE_FORMAT_VER) + { + LOG_ERROR("portable_storage: wrong binary format - unknown format ver = " << pbuff->m_ver); + return false; + } + TRY_ENTRY(); + throwable_buffer_reader buf_reader(source.data()+sizeof(storage_block_header), source.size()-sizeof(storage_block_header)); + buf_reader.read(m_root); + return true;//TODO: + CATCH_ENTRY("portable_storage::load_from_binary", false); + } + //--------------------------------------------------------------------------------------------------------------- + inline + hsection portable_storage::open_section(const std::string& section_name, hsection hparent_section, bool create_if_notexist) + { + TRY_ENTRY(); + hparent_section = hparent_section ? hparent_section:&m_root; + storage_entry* pentry = find_storage_entry(section_name, hparent_section); + if(!pentry) + { + if(!create_if_notexist) + return nullptr; + return insert_new_section(section_name, hparent_section); + } + CHECK_AND_ASSERT(pentry , nullptr); + //check that section_entry we find is real "CSSection" + if(pentry->type() != typeid(section)) + { + if(create_if_notexist) + *pentry = storage_entry(section());//replace + else + return nullptr; + } + return &boost::get<section>(*pentry); + CATCH_ENTRY("portable_storage::open_section", nullptr); + } + //--------------------------------------------------------------------------------------------------------------- + template<class to_type> + struct get_value_visitor: boost::static_visitor<void> + { + to_type& m_target; + get_value_visitor(to_type& target):m_target(target){} + template<class from_type> + void operator()(const from_type& v){convert_t(v, m_target);} + }; + + template<class t_value> + bool portable_storage::get_value(const std::string& value_name, t_value& val, hsection hparent_section) + { + BOOST_MPL_ASSERT(( boost::mpl::contains<storage_entry::types, t_value> )); + //TRY_ENTRY(); + if(!hparent_section) hparent_section = &m_root; + storage_entry* pentry = find_storage_entry(value_name, hparent_section); + if(!pentry) + return false; + + get_value_visitor<t_value> gvv(val); + boost::apply_visitor(gvv, *pentry); + return true; + //CATCH_ENTRY("portable_storage::template<>get_value", false); + } + //--------------------------------------------------------------------------------------------------------------- + template<class t_value> + bool portable_storage::set_value(const std::string& value_name, const t_value& v, hsection hparent_section) + { + BOOST_MPL_ASSERT(( boost::mpl::contains<storage_entry::types, t_value> )); + TRY_ENTRY(); + if(!hparent_section) + hparent_section = &m_root; + storage_entry* pentry = find_storage_entry(value_name, hparent_section); + if(!pentry) + { + pentry = insert_new_entry_get_storage_entry(value_name, hparent_section, v); + if(!pentry) + return false; + return true; + } + *pentry = storage_entry(v); + return true; + CATCH_ENTRY("portable_storage::template<>set_value", false); + } + //--------------------------------------------------------------------------------------------------------------- + inline + storage_entry* portable_storage::find_storage_entry(const std::string& pentry_name, hsection psection) + { + TRY_ENTRY(); + CHECK_AND_ASSERT(psection, nullptr); + auto it = psection->m_entries.find(pentry_name); + if(it == psection->m_entries.end()) + return nullptr; + + return &it->second; + CATCH_ENTRY("portable_storage::find_storage_entry", nullptr); + } + //--------------------------------------------------------------------------------------------------------------- + template<class entry_type> + storage_entry* portable_storage::insert_new_entry_get_storage_entry(const std::string& pentry_name, hsection psection, const entry_type& entry) + { + TRY_ENTRY(); + CHECK_AND_ASSERT(psection, nullptr); + auto ins_res = psection->m_entries.insert(std::pair<std::string, storage_entry>(pentry_name, entry)); + return &ins_res.first->second; + CATCH_ENTRY("portable_storage::insert_new_entry_get_storage_entry", nullptr); + } + //--------------------------------------------------------------------------------------------------------------- + inline + hsection portable_storage::insert_new_section(const std::string& pentry_name, hsection psection) + { + TRY_ENTRY(); + storage_entry* pse = insert_new_entry_get_storage_entry(pentry_name, psection, section()); + if(!pse) return nullptr; + return &boost::get<section>(*pse); + CATCH_ENTRY("portable_storage::insert_new_section", nullptr); + } + //--------------------------------------------------------------------------------------------------------------- + template<class to_type> + struct get_first_value_visitor: boost::static_visitor<bool> + { + to_type& m_target; + get_first_value_visitor(to_type& target):m_target(target){} + template<class from_type> + bool operator()(const array_entry_t<from_type>& a) + { + const from_type* pv = a.get_first_val(); + if(!pv) + return false; + convert_t(*pv, m_target); + return true; + } + }; + //--------------------------------------------------------------------------------------------------------------- + template<class t_value> + harray portable_storage::get_first_value(const std::string& value_name, t_value& target, hsection hparent_section) + { + BOOST_MPL_ASSERT(( boost::mpl::contains<storage_entry::types, t_value> )); + //TRY_ENTRY(); + if(!hparent_section) hparent_section = &m_root; + storage_entry* pentry = find_storage_entry(value_name, hparent_section); + if(!pentry) + return nullptr; + if(pentry->type() != typeid(array_entry)) + return nullptr; + array_entry& ar_entry = boost::get<array_entry>(*pentry); + + get_first_value_visitor<t_value> gfv(target); + if(!boost::apply_visitor(gfv, ar_entry)) + return nullptr; + return &ar_entry; + //CATCH_ENTRY("portable_storage::get_first_value", nullptr); + } + //--------------------------------------------------------------------------------------------------------------- + template<class to_type> + struct get_next_value_visitor: boost::static_visitor<bool> + { + to_type& m_target; + get_next_value_visitor(to_type& target):m_target(target){} + template<class from_type> + bool operator()(const array_entry_t<from_type>& a) + { + //TODO: optimize code here: work without get_next_val function + const from_type* pv = a.get_next_val(); + if(!pv) + return false; + convert_t(*pv, m_target); + return true; + } + }; + + + template<class t_value> + bool portable_storage::get_next_value(harray hval_array, t_value& target) + { + BOOST_MPL_ASSERT(( boost::mpl::contains<storage_entry::types, t_value> )); + //TRY_ENTRY(); + CHECK_AND_ASSERT(hval_array, false); + array_entry& ar_entry = *hval_array; + get_next_value_visitor<t_value> gnv(target); + if(!boost::apply_visitor(gnv, ar_entry)) + return false; + return true; + //CATCH_ENTRY("portable_storage::get_next_value", false); + } + //--------------------------------------------------------------------------------------------------------------- + template<class t_value> + harray portable_storage::insert_first_value(const std::string& value_name, const t_value& target, hsection hparent_section) + { + TRY_ENTRY(); + if(!hparent_section) hparent_section = &m_root; + storage_entry* pentry = find_storage_entry(value_name, hparent_section); + if(!pentry) + { + pentry = insert_new_entry_get_storage_entry(value_name, hparent_section, array_entry(array_entry_t<t_value>())); + if(!pentry) + return nullptr; + } + if(pentry->type() != typeid(array_entry)) + *pentry = storage_entry(array_entry(array_entry_t<t_value>())); + + array_entry& arr = boost::get<array_entry>(*pentry); + if(arr.type() != typeid(array_entry_t<t_value>)) + arr = array_entry(array_entry_t<t_value>()); + + array_entry_t<t_value>& arr_typed = boost::get<array_entry_t<t_value> >(arr); + arr_typed.insert_first_val(target); + return &arr; + CATCH_ENTRY("portable_storage::insert_first_value", nullptr); + } + //--------------------------------------------------------------------------------------------------------------- + template<class t_value> + bool portable_storage::insert_next_value(harray hval_array, const t_value& target) + { + TRY_ENTRY(); + CHECK_AND_ASSERT(hval_array, false); + + CHECK_AND_ASSERT_MES(hval_array->type() == typeid(array_entry_t<t_value>), + false, "unexpected type in insert_next_value: " << typeid(array_entry_t<t_value>).name()); + + array_entry_t<t_value>& arr_typed = boost::get<array_entry_t<t_value> >(*hval_array); + arr_typed.insert_next_value(target); + return true; + CATCH_ENTRY("portable_storage::insert_next_value", false); + } + //--------------------------------------------------------------------------------------------------------------- + //sections + inline + harray portable_storage::get_first_section(const std::string& sec_name, hsection& h_child_section, hsection hparent_section) + { + TRY_ENTRY(); + if(!hparent_section) hparent_section = &m_root; + storage_entry* pentry = find_storage_entry(sec_name, hparent_section); + if(!pentry) + return nullptr; + if(pentry->type() != typeid(array_entry)) + return nullptr; + array_entry& ar_entry = boost::get<array_entry>(*pentry); + if(ar_entry.type() != typeid(array_entry_t<section>)) + return nullptr; + array_entry_t<section>& sec_array = boost::get<array_entry_t<section>>(ar_entry); + section* psec = sec_array.get_first_val(); + if(!psec) + return nullptr; + h_child_section = psec; + return &ar_entry; + CATCH_ENTRY("portable_storage::get_first_section", nullptr); + } + //--------------------------------------------------------------------------------------------------------------- + inline + bool portable_storage::get_next_section(harray hsec_array, hsection& h_child_section) + { + TRY_ENTRY(); + CHECK_AND_ASSERT(hsec_array, false); + if(hsec_array->type() != typeid(array_entry_t<section>)) + return nullptr; + array_entry_t<section>& sec_array = boost::get<array_entry_t<section>>(*hsec_array); + h_child_section = sec_array.get_next_val(); + if(!h_child_section) + return false; + return true; + CATCH_ENTRY("portable_storage::get_next_section", false); + } + //--------------------------------------------------------------------------------------------------------------- + inline + harray portable_storage::insert_first_section(const std::string& sec_name, hsection& hinserted_childsection, hsection hparent_section) + { + TRY_ENTRY(); + if(!hparent_section) hparent_section = &m_root; + storage_entry* pentry = find_storage_entry(sec_name, hparent_section); + if(!pentry) + { + pentry = insert_new_entry_get_storage_entry(sec_name, hparent_section, array_entry(array_entry_t<section>())); + if(!pentry) + return nullptr; + } + if(pentry->type() != typeid(array_entry)) + *pentry = storage_entry(array_entry(array_entry_t<section>())); + + array_entry& ar_entry = boost::get<array_entry>(*pentry); + if(ar_entry.type() != typeid(array_entry_t<section>)) + ar_entry = array_entry(array_entry_t<section>()); + + array_entry_t<section>& sec_array = boost::get<array_entry_t<section>>(ar_entry); + hinserted_childsection = &sec_array.insert_first_val(section()); + return &ar_entry; + CATCH_ENTRY("portable_storage::insert_first_section", nullptr); + } + //--------------------------------------------------------------------------------------------------------------- + inline + bool portable_storage::insert_next_section(harray hsec_array, hsection& hinserted_childsection) + { + TRY_ENTRY(); + CHECK_AND_ASSERT(hsec_array, false); + CHECK_AND_ASSERT_MES(hsec_array->type() == typeid(array_entry_t<section>), + false, "unexpected type(not 'section') in insert_next_section, type: " << hsec_array->type().name()); + + array_entry_t<section>& sec_array = boost::get<array_entry_t<section>>(*hsec_array); + hinserted_childsection = &sec_array.insert_next_value(section()); + return true; + CATCH_ENTRY("portable_storage::insert_next_section", false); + } + //--------------------------------------------------------------------------------------------------------------- + } +}
\ No newline at end of file diff --git a/contrib/epee/include/storages/portable_storage_base.h b/contrib/epee/include/storages/portable_storage_base.h new file mode 100644 index 000000000..3f1637538 --- /dev/null +++ b/contrib/epee/include/storages/portable_storage_base.h @@ -0,0 +1,160 @@ +// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the Andrey N. Sabelnikov nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + + + +#pragma once + +#include <boost/variant.hpp> +#include <boost/any.hpp> +#include <string> +#include <list> + +#define PORTABLE_STORAGE_SIGNATUREA 0x01011101 +#define PORTABLE_STORAGE_SIGNATUREB 0x01020101 // bender's nightmare +#define PORTABLE_STORAGE_FORMAT_VER 1 + +#define PORTABLE_RAW_SIZE_MARK_MASK 0x03 +#define PORTABLE_RAW_SIZE_MARK_BYTE 0 +#define PORTABLE_RAW_SIZE_MARK_WORD 1 +#define PORTABLE_RAW_SIZE_MARK_DWORD 2 +#define PORTABLE_RAW_SIZE_MARK_INT64 3 + +#ifndef MAX_STRING_LEN_POSSIBLE +#define MAX_STRING_LEN_POSSIBLE 2000000000 //do not let string be so big +#endif + +//data types +#define SERIALIZE_TYPE_INT64 1 +#define SERIALIZE_TYPE_INT32 2 +#define SERIALIZE_TYPE_INT16 3 +#define SERIALIZE_TYPE_INT8 4 +#define SERIALIZE_TYPE_UINT64 5 +#define SERIALIZE_TYPE_UINT32 6 +#define SERIALIZE_TYPE_UINT16 7 +#define SERIALIZE_TYPE_UINT8 8 +#define SERIALIZE_TYPE_DUOBLE 9 +#define SERIALIZE_TYPE_STRING 10 +#define SERIALIZE_TYPE_BOOL 11 +#define SERIALIZE_TYPE_OBJECT 12 +#define SERIALIZE_TYPE_ARRAY 13 + +#define SERIALIZE_FLAG_ARRAY 0x80 + + +namespace epee +{ + namespace serialization + { + struct section; + + /************************************************************************/ + /* */ + /************************************************************************/ + template<class t_entry_type> + struct array_entry_t + { + array_entry_t():m_it(m_array.end()){} + + const t_entry_type* get_first_val() const + { + m_it = m_array.begin(); + return get_next_val(); + } + + t_entry_type* get_first_val() + { + m_it = m_array.begin(); + return get_next_val(); + } + + + const t_entry_type* get_next_val() const + { + if(m_it == m_array.end()) + return nullptr; + return &(*(m_it++)); + } + + t_entry_type* get_next_val() + { + if(m_it == m_array.end()) + return nullptr; + return (t_entry_type*)&(*(m_it++));//fuckoff + } + + t_entry_type& insert_first_val(const t_entry_type& v) + { + m_array.clear(); + m_it = m_array.end(); + return insert_next_value(v); + } + + t_entry_type& insert_next_value(const t_entry_type& v) + { + m_array.push_back(v); + return m_array.back(); + } + + std::list<t_entry_type> m_array; + mutable typename std::list<t_entry_type>::const_iterator m_it; + }; + + + typedef boost::make_recursive_variant< + array_entry_t<section>, + array_entry_t<uint64_t>, + array_entry_t<uint32_t>, + array_entry_t<uint16_t>, + array_entry_t<uint8_t>, + array_entry_t<int64_t>, + array_entry_t<int32_t>, + array_entry_t<int16_t>, + array_entry_t<int8_t>, + array_entry_t<double>, + array_entry_t<bool>, + array_entry_t<std::string>, + array_entry_t<section>, + array_entry_t<boost::recursive_variant_> + >::type array_entry; + + typedef boost::variant<uint64_t, uint32_t, uint16_t, uint8_t, int64_t, int32_t, int16_t, int8_t, double, bool, std::string, section, array_entry> storage_entry; + + typedef std::string binarybuffer;//it's ok + + /************************************************************************/ + /* */ + /************************************************************************/ + struct section + { + std::map<std::string, storage_entry> m_entries; + }; + + //handle-like aliases + typedef section* hsection; + typedef array_entry* harray; + } +}
\ No newline at end of file diff --git a/contrib/epee/include/storages/portable_storage_from_bin.h b/contrib/epee/include/storages/portable_storage_from_bin.h new file mode 100644 index 000000000..e9b7e2e6f --- /dev/null +++ b/contrib/epee/include/storages/portable_storage_from_bin.h @@ -0,0 +1,281 @@ +// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the Andrey N. Sabelnikov nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + + + +#pragma once + +#include "misc_language.h" +#include "portable_storage_base.h" + +#ifdef EPEE_PORTABLE_STORAGE_RECURSION_LIMIT +#define EPEE_PORTABLE_STORAGE_RECURSION_LIMIT_INTERNAL EPEE_PORTABLE_STORAGE_RECURSION_LIMIT +#else +#define EPEE_PORTABLE_STORAGE_RECURSION_LIMIT_INTERNAL 100 +#endif + +namespace epee +{ + namespace serialization + { + struct throwable_buffer_reader + { + throwable_buffer_reader(const void* ptr, size_t sz); + void read(void* target, size_t count); + void read_sec_name(std::string& sce_name); + template<class t_pod_type> + void read(t_pod_type& pod_val); + template<class t_type> + t_type read(); + template<class type_name> + storage_entry read_ae(); + storage_entry load_storage_array_entry(uint8_t type); + size_t read_varint(); + template<class t_type> + storage_entry read_se(); + storage_entry load_storage_entry(); + void read(section& sec); + void read(std::string& str); + private: + struct recursuion_limitation_guard + { + size_t& m_counter_ref; + recursuion_limitation_guard(size_t& counter):m_counter_ref(counter) + { + ++m_counter_ref; + CHECK_AND_ASSERT_THROW_MES(m_counter_ref < EPEE_PORTABLE_STORAGE_RECURSION_LIMIT_INTERNAL, "Wrong blob data in portable storage: recursion limitation (" << EPEE_PORTABLE_STORAGE_RECURSION_LIMIT_INTERNAL << ") exceeded"); + } + ~recursuion_limitation_guard() + { + CHECK_AND_ASSERT_THROW_MES(m_counter_ref != 0, "Internal error: m_counter_ref == 0 while ~recursuion_limitation_guard()"); + --m_counter_ref; + } + }; +#define RECURSION_LIMITATION() recursuion_limitation_guard rl(m_recursion_count) + + const uint8_t* m_ptr; + size_t m_count; + size_t m_recursion_count; + }; + + inline throwable_buffer_reader::throwable_buffer_reader(const void* ptr, size_t sz) + { + if(!ptr) + throw std::runtime_error("throwable_buffer_reader: ptr==nullptr"); + if(!sz) + throw std::runtime_error("throwable_buffer_reader: sz==0"); + m_ptr = (uint8_t*)ptr; + m_count = sz; + m_recursion_count = 0; + } + inline + void throwable_buffer_reader::read(void* target, size_t count) + { + RECURSION_LIMITATION(); + CHECK_AND_ASSERT_THROW_MES(m_count >= count, " attempt to read " << count << " bytes from buffer with " << m_count << " bytes remained"); + memcpy(target, m_ptr, count); + m_ptr += count; + m_count -= count; + } + inline + void throwable_buffer_reader::read_sec_name(std::string& sce_name) + { + RECURSION_LIMITATION(); + uint8_t name_len = 0; + read(name_len); + sce_name.resize(name_len); + read((void*)sce_name.data(), name_len); + } + + template<class t_pod_type> + void throwable_buffer_reader::read(t_pod_type& pod_val) + { + RECURSION_LIMITATION(); + read(&pod_val, sizeof(pod_val)); + } + + template<class t_type> + t_type throwable_buffer_reader::read() + { + RECURSION_LIMITATION(); + t_type v; + read(v); + return v; + } + + + template<class type_name> + storage_entry throwable_buffer_reader::read_ae() + { + RECURSION_LIMITATION(); + //for pod types + array_entry_t<type_name> sa; + size_t size = read_varint(); + //TODO: add some optimization here later + while(size--) + sa.m_array.push_back(read<type_name>()); + return storage_entry(array_entry(sa)); + } + + inline + storage_entry throwable_buffer_reader::load_storage_array_entry(uint8_t type) + { + RECURSION_LIMITATION(); + type &= ~SERIALIZE_FLAG_ARRAY; + switch(type) + { + case SERIALIZE_TYPE_INT64: return read_ae<int64_t>(); + case SERIALIZE_TYPE_INT32: return read_ae<int32_t>(); + case SERIALIZE_TYPE_INT16: return read_ae<int16_t>(); + case SERIALIZE_TYPE_INT8: return read_ae<int8_t>(); + case SERIALIZE_TYPE_UINT64: return read_ae<uint64_t>(); + case SERIALIZE_TYPE_UINT32: return read_ae<uint32_t>(); + case SERIALIZE_TYPE_UINT16: return read_ae<uint16_t>(); + case SERIALIZE_TYPE_UINT8: return read_ae<uint8_t>(); + case SERIALIZE_TYPE_DUOBLE: return read_ae<double>(); + case SERIALIZE_TYPE_BOOL: return read_ae<bool>(); + case SERIALIZE_TYPE_STRING: return read_ae<std::string>(); + case SERIALIZE_TYPE_OBJECT: return read_ae<section>(); + case SERIALIZE_TYPE_ARRAY: return read_ae<array_entry>(); + default: + CHECK_AND_ASSERT_THROW_MES(false, "unknown entry_type code = " << type); + } + } + + inline + size_t throwable_buffer_reader::read_varint() + { + RECURSION_LIMITATION(); + CHECK_AND_ASSERT_THROW_MES(m_count >= 1, "empty buff, expected place for varint"); + size_t v = 0; + uint8_t size_mask = (*(uint8_t*)m_ptr) &PORTABLE_RAW_SIZE_MARK_MASK; + switch (size_mask) + { + case PORTABLE_RAW_SIZE_MARK_BYTE: v = read<uint8_t>();break; + case PORTABLE_RAW_SIZE_MARK_WORD: v = read<uint16_t>();break; + case PORTABLE_RAW_SIZE_MARK_DWORD: v = read<uint32_t>();break; + case PORTABLE_RAW_SIZE_MARK_INT64: v = read<uint64_t>();break; + default: + CHECK_AND_ASSERT_THROW_MES(false, "unknown varint size_mask = " << size_mask); + } + v >>= 2; + return v; + } + + template<class t_type> + storage_entry throwable_buffer_reader::read_se() + { + RECURSION_LIMITATION(); + t_type v; + read(v); + return storage_entry(v); + } + + template<> + inline storage_entry throwable_buffer_reader::read_se<std::string>() + { + RECURSION_LIMITATION(); + return storage_entry(read<std::string>()); + } + + + template<> + inline storage_entry throwable_buffer_reader::read_se<section>() + { + RECURSION_LIMITATION(); + section s;//use extra variable due to vs bug, line "storage_entry se(section()); " can't be compiled in visual studio + storage_entry se(s); + section& section_entry = boost::get<section>(se); + read(section_entry); + return se; + } + + template<> + inline storage_entry throwable_buffer_reader::read_se<array_entry>() + { + RECURSION_LIMITATION(); + uint8_t ent_type = 0; + read(ent_type); + CHECK_AND_ASSERT_THROW_MES(ent_type&SERIALIZE_FLAG_ARRAY, "wrong type sequenses"); + return load_storage_array_entry(ent_type); + } + + inline + storage_entry throwable_buffer_reader::load_storage_entry() + { + RECURSION_LIMITATION(); + uint8_t ent_type = 0; + read(ent_type); + if(ent_type&SERIALIZE_FLAG_ARRAY) + return load_storage_array_entry(ent_type); + + switch(ent_type) + { + case SERIALIZE_TYPE_INT64: return read_se<int64_t>(); + case SERIALIZE_TYPE_INT32: return read_se<int32_t>(); + case SERIALIZE_TYPE_INT16: return read_se<int16_t>(); + case SERIALIZE_TYPE_INT8: return read_se<int8_t>(); + case SERIALIZE_TYPE_UINT64: return read_se<uint64_t>(); + case SERIALIZE_TYPE_UINT32: return read_se<uint32_t>(); + case SERIALIZE_TYPE_UINT16: return read_se<uint16_t>(); + case SERIALIZE_TYPE_UINT8: return read_se<uint8_t>(); + case SERIALIZE_TYPE_DUOBLE: return read_se<double>(); + case SERIALIZE_TYPE_BOOL: return read_se<bool>(); + case SERIALIZE_TYPE_STRING: return read_se<std::string>(); + case SERIALIZE_TYPE_OBJECT: return read_se<section>(); + case SERIALIZE_TYPE_ARRAY: return read_se<array_entry>(); + default: + CHECK_AND_ASSERT_THROW_MES(false, "unknown entry_type code = " << ent_type); + } + } + inline + void throwable_buffer_reader::read(section& sec) + { + RECURSION_LIMITATION(); + sec.m_entries.clear(); + size_t count = read_varint(); + while(count--) + { + //read section name string + std::string sec_name; + read_sec_name(sec_name); + sec.m_entries.insert(std::make_pair(sec_name, load_storage_entry())); + } + } + inline + void throwable_buffer_reader::read(std::string& str) + { + RECURSION_LIMITATION(); + size_t len = read_varint(); + CHECK_AND_ASSERT_THROW_MES(len < MAX_STRING_LEN_POSSIBLE, "to big string len value in storage: " << len); + CHECK_AND_ASSERT_THROW_MES(m_count >= len, "string len count value " << len << " goes out of remain storage len " << m_count); + //do this manually to avoid double memory write in huge strings (first time at resize, second at read) + str.assign((const char*)m_ptr, len); + m_ptr+=len; + m_count -= len; + } + } +}
\ No newline at end of file diff --git a/contrib/epee/include/storages/portable_storage_from_json.h b/contrib/epee/include/storages/portable_storage_from_json.h new file mode 100644 index 000000000..557db3da6 --- /dev/null +++ b/contrib/epee/include/storages/portable_storage_from_json.h @@ -0,0 +1,379 @@ +// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the Andrey N. Sabelnikov nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#pragma once +#include "parserse_base_utils.h" +#include "file_io_utils.h" + +namespace epee +{ + using namespace misc_utils::parse; + namespace serialization + { + namespace json + { +#define CHECK_ISSPACE() if(!isspace(*it)){ ASSERT_MES_AND_THROW("Wrong JSON character at: " << std::string(it, buf_end));} + + /*inline void parse_error() + { + ASSERT_MES_AND_THROW("json parse error"); + }*/ + template<class t_storage> + inline void run_handler(typename t_storage::hsection current_section, std::string::const_iterator& sec_buf_begin, std::string::const_iterator buf_end, t_storage& stg) + { + + std::string::const_iterator sub_element_start; + std::string name; + typename t_storage::harray h_array = nullptr; + enum match_state + { + match_state_lookup_for_section_start, + match_state_lookup_for_name, + match_state_waiting_separator, + match_state_wonder_after_separator, + match_state_wonder_after_value, + match_state_wonder_array, + match_state_array_after_value, + match_state_array_waiting_value, + match_state_error + }; + + enum array_mode + { + array_mode_undifined = 0, + array_mode_sections, + array_mode_string, + array_mode_numbers, + array_mode_booleans + }; + + match_state state = match_state_lookup_for_section_start; + array_mode array_md = array_mode_undifined; + std::string::const_iterator it = sec_buf_begin; + for(;it != buf_end;it++) + { + switch (state) + { + case match_state_lookup_for_section_start: + if(*it == '{') + state = match_state_lookup_for_name; + else CHECK_ISSPACE(); + break; + case match_state_lookup_for_name: + switch(*it) + { + case '"': + match_string2(it, buf_end, name); + state = match_state_waiting_separator; + break; + case '}': + //this is it! section ends here. + //seems that it is empty section + sec_buf_begin = it; + return; + default: + CHECK_ISSPACE(); + } + break; + case match_state_waiting_separator: + if(*it == ':') + state = match_state_wonder_after_separator; + else CHECK_ISSPACE(); + break; + case match_state_wonder_after_separator: + if(*it == '"') + {//just a named string value started + std::string val; + match_string2(it, buf_end, val); + //insert text value + stg.set_value(name, val, current_section); + state = match_state_wonder_after_value; + }else if (isdigit(*it) || *it == '-') + {//just a named number value started + std::string val; + bool is_v_float = false;bool is_signed = false; + match_number2(it, buf_end, val, is_v_float, is_signed); + if(!is_v_float) + { + if(is_signed) + { + int64_t nval = boost::lexical_cast<int64_t>(val); + stg.set_value(name, nval, current_section); + }else + { + uint64_t nval = boost::lexical_cast<uint64_t >(val); + stg.set_value(name, nval, current_section); + } + }else + { + double nval = boost::lexical_cast<double>(val); + stg.set_value(name, nval, current_section); + } + state = match_state_wonder_after_value; + }else if(isalpha(*it) ) + {// could be null, true or false + std::string word; + match_word2(it, buf_end, word); + if(boost::iequals(word, "null")) + { + state = match_state_wonder_after_value; + //just skip this, + }else if(boost::iequals(word, "true")) + { + stg.set_value(name, true, current_section); + state = match_state_wonder_after_value; + }else if(boost::iequals(word, "false")) + { + stg.set_value(name, false, current_section); + state = match_state_wonder_after_value; + }else ASSERT_MES_AND_THROW("Unknown value keyword " << word); + }else if(*it == '{') + { + //sub section here + typename t_storage::hsection new_sec = stg.open_section(name, current_section, true); + CHECK_AND_ASSERT_THROW_MES(new_sec, "Failed to insert new section in json: " << std::string(it, buf_end)); + run_handler(new_sec, it, buf_end, stg); + state = match_state_wonder_after_value; + }else if(*it == '[') + {//array of something + state = match_state_wonder_array; + }else CHECK_ISSPACE(); + break; + case match_state_wonder_after_value: + if(*it == ',') + state = match_state_lookup_for_name; + else if(*it == '}') + { + //this is it! section ends here. + sec_buf_begin = it; + return; + }else CHECK_ISSPACE(); + break; + case match_state_wonder_array: + if(*it == '[') + { + ASSERT_MES_AND_THROW("array of array not suppoerted yet :( sorry"); + //mean array of array + } + if(*it == '{') + { + //mean array of sections + typename t_storage::hsection new_sec = nullptr; + h_array = stg.insert_first_section(name, new_sec, current_section); + CHECK_AND_ASSERT_THROW_MES(h_array&&new_sec, "failed to create new section"); + run_handler(new_sec, it, buf_end, stg); + state = match_state_array_after_value; + array_md = array_mode_sections; + }else if(*it == '"') + { + //mean array of strings + std::string val; + match_string2(it, buf_end, val); + h_array = stg.insert_first_value(name, val, current_section); + CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values entry"); + state = match_state_array_after_value; + array_md = array_mode_string; + }else if (isdigit(*it) || *it == '-') + {//array of numbers value started + std::string val; + bool is_v_float = false;bool is_signed_val = false; + match_number2(it, buf_end, val, is_v_float, is_signed_val); + if(!is_v_float) + { + int64_t nval = boost::lexical_cast<int64_t>(val);//bool res = string_tools::string_to_num_fast(val, nval); + h_array = stg.insert_first_value(name, nval, current_section); + CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values section entry"); + }else + { + double nval = boost::lexical_cast<double>(val);//bool res = string_tools::string_to_num_fast(val, nval); + h_array = stg.insert_first_value(name, nval, current_section); + CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values section entry"); + } + + state = match_state_array_after_value; + array_md = array_mode_numbers; + }else if(*it == ']')//empty array + { + array_md = array_mode_undifined; + state = match_state_wonder_after_value; + }else if(isalpha(*it) ) + {// array of booleans + std::string word; + match_word2(it, buf_end, word); + if(boost::iequals(word, "true")) + { + h_array = stg.insert_first_value(name, true, current_section); + CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values section entry"); + state = match_state_array_after_value; + array_md = array_mode_booleans; + }else if(boost::iequals(word, "false")) + { + h_array = stg.insert_first_value(name, false, current_section); + CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values section entry"); + state = match_state_array_after_value; + array_md = array_mode_booleans; + + }else ASSERT_MES_AND_THROW("Unknown value keyword " << word) + }else CHECK_ISSPACE(); + break; + case match_state_array_after_value: + if(*it == ',') + state = match_state_array_waiting_value; + else if(*it == ']') + { + h_array = nullptr; + array_md = array_mode_undifined; + state = match_state_wonder_after_value; + }else CHECK_ISSPACE(); + break; + case match_state_array_waiting_value: + switch(array_md) + { + case array_mode_sections: + if(*it == '{') + { + typename t_storage::hsection new_sec = NULL; + bool res = stg.insert_next_section(h_array, new_sec); + CHECK_AND_ASSERT_THROW_MES(res&&new_sec, "failed to insert next section"); + run_handler(new_sec, it, buf_end, stg); + state = match_state_array_after_value; + }else CHECK_ISSPACE(); + break; + case array_mode_string: + if(*it == '"') + { + std::string val; + match_string2(it, buf_end, val); + bool res = stg.insert_next_value(h_array, val); + CHECK_AND_ASSERT_THROW_MES(res, "failed to insert values"); + state = match_state_array_after_value; + }else CHECK_ISSPACE(); + break; + case array_mode_numbers: + if (isdigit(*it) || *it == '-') + {//array of numbers value started + std::string val; + bool is_v_float = false;bool is_signed_val = false; + match_number2(it, buf_end, val, is_v_float, is_signed_val); + bool insert_res = false; + if(!is_v_float) + { + boost::int64_t nval = boost::lexical_cast<int64_t>(val); //bool res = string_tools::string_to_num_fast(val, nval); + insert_res = stg.insert_next_value(h_array, nval); + + }else + { + //TODO: optimize here if need + double nval = boost::lexical_cast<double>(val); //string_tools::string_to_num_fast(val, nval); + insert_res = stg.insert_next_value(h_array, nval); + } + CHECK_AND_ASSERT_THROW_MES(insert_res, "Failed to insert next value"); + state = match_state_array_after_value; + array_md = array_mode_numbers; + }else CHECK_ISSPACE(); + break; + case array_mode_booleans: + if(isalpha(*it) ) + {// array of booleans + std::string word; + match_word2(it, buf_end, word); + if(boost::iequals(word, "true")) + { + bool r = stg.insert_next_value(h_array, true); + CHECK_AND_ASSERT_THROW_MES(r, " failed to insert values section entry"); + state = match_state_array_after_value; + }else if(boost::iequals(word, "false")) + { + bool r = stg.insert_next_value(h_array, false); + CHECK_AND_ASSERT_THROW_MES(r, " failed to insert values section entry"); + state = match_state_array_after_value; + } + else ASSERT_MES_AND_THROW("Unknown value keyword " << word); + }else CHECK_ISSPACE(); + break; + case array_mode_undifined: + default: + ASSERT_MES_AND_THROW("Bad array state"); + } + break; + case match_state_error: + default: + ASSERT_MES_AND_THROW("WRONG JSON STATE"); + } + } + } +/* +{ + "firstName": "John", + "lastName": "Smith", + "age": 25, + "address": { + "streetAddress": "21 2nd Street", + "city": "New York", + "state": "NY", + "postalCode": -10021, + "have_boobs": true, + "have_balls": false + }, + "phoneNumber": [ + { + "type": "home", + "number": "212 555-1234" + }, + { + "type": "fax", + "number": "646 555-4567" + } + ], + "phoneNumbers": [ + "812 123-1234", + "916 123-4567" + ] +} +*/ + template<class t_storage> + inline bool load_from_json(const std::string& buff_json, t_storage& stg) + { + std::string::const_iterator sec_buf_begin = buff_json.begin(); + try + { + run_handler(nullptr, sec_buf_begin, buff_json.end(), stg); + return true; + } + catch(const std::exception& ex) + { + LOG_PRINT_RED_L0("Failed to parse json, what: " << ex.what()); + return false; + } + catch(...) + { + LOG_PRINT_RED_L0("Failed to parse json"); + return false; + } + } + } + } +}
\ No newline at end of file diff --git a/contrib/epee/include/storages/portable_storage_template_helper.h b/contrib/epee/include/storages/portable_storage_template_helper.h new file mode 100644 index 000000000..2163cb879 --- /dev/null +++ b/contrib/epee/include/storages/portable_storage_template_helper.h @@ -0,0 +1,120 @@ +// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the Andrey N. Sabelnikov nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#pragma once +#include "parserse_base_utils.h" +#include "portable_storage.h" +#include "file_io_utils.h" + +namespace epee +{ + namespace serialization + { + //----------------------------------------------------------------------------------------------------------- + template<class t_struct> + bool load_t_from_json(t_struct& out, const std::string& json_buff) + { + portable_storage ps; + bool rs = ps.load_from_json(json_buff); + if(!rs) + return false; + + return out.load(ps); + } + //----------------------------------------------------------------------------------------------------------- + template<class t_struct> + bool load_t_from_json_file(t_struct& out, const std::string& json_file) + { + std::string f_buff; + if(!file_io_utils::load_file_to_string(json_file, f_buff)) + return false; + + return load_t_from_json(out, f_buff); + } + //----------------------------------------------------------------------------------------------------------- + template<class t_struct> + bool store_t_to_json(t_struct& str_in, std::string& json_buff, size_t indent = 0) + { + portable_storage ps; + str_in.store(ps); + ps.dump_as_json(json_buff, indent); + return true; + } + //----------------------------------------------------------------------------------------------------------- + template<class t_struct> + std::string store_t_to_json(t_struct& str_in, size_t indent = 0) + { + std::string json_buff; + store_t_to_json(str_in, json_buff, indent); + return std::move(json_buff); + } + //----------------------------------------------------------------------------------------------------------- + template<class t_struct> + bool store_t_to_json_file(t_struct& str_in, const std::string& fpath) + { + std::string json_buff; + store_t_to_json(str_in, json_buff); + return file_io_utils::save_string_to_file(fpath, json_buff); + } + //----------------------------------------------------------------------------------------------------------- + template<class t_struct> + bool load_t_from_binary(t_struct& out, const std::string& binary_buff) + { + portable_storage ps; + bool rs = ps.load_from_binary(binary_buff); + if(!rs) + return false; + + return out.load(ps); + } + //----------------------------------------------------------------------------------------------------------- + template<class t_struct> + bool load_t_from_binary_file(t_struct& out, const std::string& binary_file) + { + std::string f_buff; + if(!file_io_utils::load_file_to_string(binary_file, f_buff)) + return false; + + return load_t_from_binary(out, f_buff); + } + //----------------------------------------------------------------------------------------------------------- + template<class t_struct> + bool store_t_to_binary(t_struct& str_in, std::string& binary_buff, size_t indent = 0) + { + portable_storage ps; + str_in.store(ps); + return ps.store_to_binary(binary_buff); + } + //----------------------------------------------------------------------------------------------------------- + template<class t_struct> + std::string store_t_to_binary(t_struct& str_in, size_t indent = 0) + { + std::string binary_buff; + store_t_to_binary(str_in, binary_buff, indent); + return std::move(binary_buff); + } + } +}
\ No newline at end of file diff --git a/contrib/epee/include/storages/portable_storage_to_bin.h b/contrib/epee/include/storages/portable_storage_to_bin.h new file mode 100644 index 000000000..baf90290a --- /dev/null +++ b/contrib/epee/include/storages/portable_storage_to_bin.h @@ -0,0 +1,212 @@ +// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the Andrey N. Sabelnikov nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + + + +#pragma once + +#include "misc_language.h" +#include "portable_storage_base.h" + +namespace epee +{ + namespace serialization + { + + template<class pack_value, class t_stream> + size_t pack_varint_t(t_stream& strm, uint8_t type_or, size_t& pv) + { + pack_value v = (*((pack_value*)&pv)) << 2; + v |= type_or; + strm.write((const char*)&v, sizeof(pack_value)); + return sizeof(pack_value); + } + + PRAGMA_WARNING_PUSH + PRAGMA_GCC("GCC diagnostic ignored \"-Wstrict-aliasing\"") + template<class t_stream> + size_t pack_varint(t_stream& strm, size_t val) + { //the first two bits always reserved for size information + + if(val <= 63) + {//mean enough one byte + return pack_varint_t<uint8_t>(strm, PORTABLE_RAW_SIZE_MARK_BYTE, val); + } + else if(val <= 16383) + {//mean need word + return pack_varint_t<uint16_t>(strm, PORTABLE_RAW_SIZE_MARK_WORD, val); + }else if(val <= 1073741823) + {//mean need dword + return pack_varint_t<uint32_t>(strm, PORTABLE_RAW_SIZE_MARK_DWORD, val); + }else + { + CHECK_AND_ASSERT_THROW_MES(val <= 4611686018427387903, "failed to pack varint - too big amount = " << val); + return pack_varint_t<uint64_t>(strm, PORTABLE_RAW_SIZE_MARK_INT64, val); + } + } + PRAGMA_WARNING_POP + + template<class t_stream> + bool put_string(t_stream& strm, const std::string& v) + { + pack_varint(strm, v.size()); + if(v.size()) + strm.write((const char*)v.data(), v.size()); + return true; + } + + template<class t_stream> + struct array_entry_store_visitor: public boost::static_visitor<bool> + { + t_stream& m_strm; + + template<class t_pod_type> + bool pack_pod_array_type(uint8_t contained_type, const array_entry_t<t_pod_type>& arr_pod) + { + uint8_t type = contained_type|SERIALIZE_FLAG_ARRAY; + m_strm.write((const char*)&type, 1); + pack_varint(m_strm, arr_pod.m_array.size()); + for(const t_pod_type& x: arr_pod.m_array) + m_strm.write((const char*)&x, sizeof(t_pod_type)); + return true; + } + + array_entry_store_visitor(t_stream& strm):m_strm(strm){} + bool operator()(const array_entry_t<uint64_t>& v){ return pack_pod_array_type(SERIALIZE_TYPE_UINT64, v);} + bool operator()(const array_entry_t<uint32_t>& v){ return pack_pod_array_type(SERIALIZE_TYPE_UINT32, v);} + bool operator()(const array_entry_t<uint16_t>& v){ return pack_pod_array_type(SERIALIZE_TYPE_UINT16, v);} + bool operator()(const array_entry_t<uint8_t>& v) { return pack_pod_array_type(SERIALIZE_TYPE_UINT8, v);} + bool operator()(const array_entry_t<int64_t>& v) { return pack_pod_array_type(SERIALIZE_TYPE_INT64, v);} + bool operator()(const array_entry_t<int32_t>& v) { return pack_pod_array_type(SERIALIZE_TYPE_INT32, v);} + bool operator()(const array_entry_t<int16_t>& v) { return pack_pod_array_type(SERIALIZE_TYPE_INT16, v);} + bool operator()(const array_entry_t<int8_t>& v) { return pack_pod_array_type(SERIALIZE_TYPE_INT8, v);} + bool operator()(const array_entry_t<double>& v) { return pack_pod_array_type(SERIALIZE_TYPE_DUOBLE, v);} + bool operator()(const array_entry_t<bool>& v) { return pack_pod_array_type(SERIALIZE_TYPE_BOOL, v);} + bool operator()(const array_entry_t<std::string>& arr_str) + { + uint8_t type = SERIALIZE_TYPE_STRING|SERIALIZE_FLAG_ARRAY; + m_strm.write((const char*)&type, 1); + pack_varint(m_strm, arr_str.m_array.size()); + for(const std::string& s: arr_str.m_array) + put_string(m_strm, s); + return true; + } + bool operator()(const array_entry_t<section>& arr_sec) + { + uint8_t type = SERIALIZE_TYPE_OBJECT|SERIALIZE_FLAG_ARRAY; + m_strm.write((const char*)&type, 1); + pack_varint(m_strm, arr_sec.m_array.size()); + for(const section& s: arr_sec.m_array) + pack_entry_to_buff(m_strm, s); + return true; + } + bool operator()(const array_entry_t<array_entry>& arra_ar) + { + uint8_t type = SERIALIZE_TYPE_ARRAY|SERIALIZE_FLAG_ARRAY; + m_strm.write((const char*)&type, 1); + pack_varint(m_strm, arra_ar.m_array.size()); + for(const array_entry& s: arra_ar.m_array) + pack_entry_to_buff(m_strm, s); + return true; + } + }; + + template<class t_stream> + struct storage_entry_store_visitor: public boost::static_visitor<bool> + { + t_stream& m_strm; + storage_entry_store_visitor(t_stream& strm):m_strm(strm){} + template<class pod_type> + bool pack_pod_type(uint8_t type, const pod_type& v) + { + m_strm.write((const char*)&type, 1); + m_strm.write((const char*)&v, sizeof(pod_type)); + return true; + } + //section, array_entry + bool operator()(const uint64_t& v){ return pack_pod_type(SERIALIZE_TYPE_UINT64, v);} + bool operator()(const uint32_t& v){ return pack_pod_type(SERIALIZE_TYPE_UINT32, v);} + bool operator()(const uint16_t& v){ return pack_pod_type(SERIALIZE_TYPE_UINT16, v);} + bool operator()(const uint8_t& v) { return pack_pod_type(SERIALIZE_TYPE_UINT8, v);} + bool operator()(const int64_t& v) { return pack_pod_type(SERIALIZE_TYPE_INT64, v);} + bool operator()(const int32_t& v) { return pack_pod_type(SERIALIZE_TYPE_INT32, v);} + bool operator()(const int16_t& v) { return pack_pod_type(SERIALIZE_TYPE_INT16, v);} + bool operator()(const int8_t& v) { return pack_pod_type(SERIALIZE_TYPE_INT8, v);} + bool operator()(const double& v) { return pack_pod_type(SERIALIZE_TYPE_DUOBLE, v);} + bool operator()(const bool& v) { return pack_pod_type(SERIALIZE_TYPE_BOOL, v);} + bool operator()(const std::string& v) + { + uint8_t type = SERIALIZE_TYPE_STRING; + m_strm.write((const char*)&type, 1); + put_string(m_strm, v); + return true; + } + bool operator()(const section& v) + { + uint8_t type = SERIALIZE_TYPE_OBJECT; + m_strm.write((const char*)&type, 1); + return pack_entry_to_buff(m_strm, v); + } + + bool operator()(const array_entry& v) + { + //uint8_t type = SERIALIZE_TYPE_ARRAY; + //m_strm.write((const char*)&type, 1); + return pack_entry_to_buff(m_strm, v); + } + }; + + template<class t_stream> + bool pack_entry_to_buff(t_stream& strm, const array_entry& ae) + { + array_entry_store_visitor<t_stream> aesv(strm); + return boost::apply_visitor(aesv, ae); + } + + template<class t_stream> + bool pack_entry_to_buff(t_stream& strm, const storage_entry& se) + { + storage_entry_store_visitor<t_stream> sv(strm); + return boost::apply_visitor(sv, se); + } + + template<class t_stream> + bool pack_entry_to_buff(t_stream& strm, const section& sec) + { + typedef std::map<std::string, storage_entry>::value_type section_pair; + pack_varint(strm, sec.m_entries.size()); + for(const section_pair& se: sec.m_entries) + { + CHECK_AND_ASSERT_THROW_MES(se.first.size() < std::numeric_limits<uint8_t>::max(), "storage_entry_name is too long: " << se.first.size() << ", val: " << se.first); + uint8_t len = static_cast<uint8_t>(se.first.size()); + strm.write((const char*)&len, sizeof(len)); + strm.write(se.first.data(), size_t(len)); + pack_entry_to_buff(strm, se.second); + } + return true; + } + } +}
\ No newline at end of file diff --git a/contrib/epee/include/storages/portable_storage_to_json.h b/contrib/epee/include/storages/portable_storage_to_json.h new file mode 100644 index 000000000..aff85b201 --- /dev/null +++ b/contrib/epee/include/storages/portable_storage_to_json.h @@ -0,0 +1,172 @@ +// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the Andrey N. Sabelnikov nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + + + +#pragma once + +#include "misc_language.h" +#include "portable_storage_base.h" + +namespace epee +{ + namespace serialization + { + + template<class t_stream> + void dump_as_json(t_stream& strm, const array_entry& ae, size_t indent); + template<class t_stream> + void dump_as_json(t_stream& strm, const storage_entry& se, size_t indent); + template<class t_stream> + void dump_as_json(t_stream& strm, const std::string& v, size_t indent); + template<class t_stream> + void dump_as_json(t_stream& strm, const int8_t& v, size_t indent); + template<class t_stream> + void dump_as_json(t_stream& strm, const uint8_t& v, size_t indent); + template<class t_stream> + void dump_as_json(t_stream& strm, const bool& v, size_t indent); + template<class t_stream, class t_type> + void dump_as_json(t_stream& strm, const t_type& v, size_t indent); + template<class t_stream> + void dump_as_json(t_stream& strm, const section& sec, size_t indent); + + + inline std::string make_indent(size_t indent) + { + return std::string(indent*2, ' '); + } + + template<class t_stream> + struct array_entry_store_to_json_visitor: public boost::static_visitor<void> + { + t_stream& m_strm; + size_t m_indent; + array_entry_store_to_json_visitor(t_stream& strm, size_t indent):m_strm(strm), m_indent(indent){} + + template<class t_type> + void operator()(const array_entry_t<t_type>& a) + { + m_strm << "["; + if(a.m_array.size()) + { + auto last_it = --a.m_array.end(); + for(auto it = a.m_array.begin(); it != a.m_array.end(); it++) + { + dump_as_json(m_strm, *it, m_indent); + if(it != last_it) + m_strm << ","; + } + } + m_strm << "]"; + } + }; + + template<class t_stream> + struct storage_entry_store_to_json_visitor: public boost::static_visitor<void> + { + t_stream& m_strm; + size_t m_indent; + storage_entry_store_to_json_visitor(t_stream& strm, size_t indent):m_strm(strm), m_indent(indent) + {} + //section, array_entry + template<class visited_type> + void operator()(const visited_type& v) + { + dump_as_json(m_strm, v, m_indent); + } + }; + + template<class t_stream> + void dump_as_json(t_stream& strm, const array_entry& ae, size_t indent) + { + array_entry_store_to_json_visitor<t_stream> aesv(strm, indent); + boost::apply_visitor(aesv, ae); + } + + template<class t_stream> + void dump_as_json(t_stream& strm, const storage_entry& se, size_t indent) + { + storage_entry_store_to_json_visitor<t_stream> sv(strm, indent); + boost::apply_visitor(sv, se); + } + + template<class t_stream> + void dump_as_json(t_stream& strm, const std::string& v, size_t indent) + { + strm << "\"" << misc_utils::parse::transform_to_escape_sequence(v) << "\""; + } + + template<class t_stream> + void dump_as_json(t_stream& strm, const int8_t& v, size_t indent) + { + strm << static_cast<int32_t>(v); + } + + template<class t_stream> + void dump_as_json(t_stream& strm, const uint8_t& v, size_t indent) + { + strm << static_cast<int32_t>(v); + } + + template<class t_stream> + void dump_as_json(t_stream& strm, const bool& v, size_t indent) + { + if(v) + strm << "true"; + else + strm << "false"; + } + + + + template<class t_stream, class t_type> + void dump_as_json(t_stream& strm, const t_type& v, size_t indent) + { + strm << v; + } + + template<class t_stream> + void dump_as_json(t_stream& strm, const section& sec, size_t indent) + { + size_t local_indent = indent + 1; + strm << "{\r\n"; + std::string indent_str = make_indent(local_indent); + if(sec.m_entries.size()) + { + auto it_last = --sec.m_entries.end(); + for(auto it = sec.m_entries.begin(); it!= sec.m_entries.end();it++) + { + strm << indent_str << "\"" << misc_utils::parse::transform_to_escape_sequence(it->first) << "\"" << ": "; + dump_as_json(strm, it->second, local_indent); + if(it_last != it) + strm << ","; + strm << "\r\n"; + } + } + strm << make_indent(indent) << "}"; + } + } +}
\ No newline at end of file diff --git a/contrib/epee/include/storages/portable_storage_val_converters.h b/contrib/epee/include/storages/portable_storage_val_converters.h new file mode 100644 index 000000000..6ea505886 --- /dev/null +++ b/contrib/epee/include/storages/portable_storage_val_converters.h @@ -0,0 +1,169 @@ +// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the Andrey N. Sabelnikov nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + + + +#pragma once + +#include "misc_language.h" +#include "portable_storage_base.h" +#include "warnings.h" + +namespace epee +{ + namespace serialization + { +#define ASSERT_AND_THROW_WRONG_CONVERSION() ASSERT_MES_AND_THROW("WRONG DATA CONVERSION: from type=" << typeid(from).name() << " to type " << typeid(to).name()) + + template<typename from_type, typename to_type> + void convert_int_to_uint(const from_type& from, to_type& to) + { +PUSH_WARNINGS +DISABLE_VS_WARNINGS(4018) + CHECK_AND_ASSERT_THROW_MES(from >=0, "unexpected int value with signed storage value less than 0, and unsigned receiver value"); +DISABLE_GCC_AND_CLANG_WARNING(sign-compare) + CHECK_AND_ASSERT_THROW_MES(from <= std::numeric_limits<to_type>::max(), "int value overhead: try to set value " << from << " to type " << typeid(to_type).name() << " with max possible value = " << std::numeric_limits<to_type>::max()); + to = static_cast<to_type>(from); +POP_WARNINGS + } + template<typename from_type, typename to_type> + void convert_int_to_int(const from_type& from, to_type& to) + { + CHECK_AND_ASSERT_THROW_MES(from >= boost::numeric::bounds<to_type>::lowest(), "int value overhead: try to set value " << from << " to type " << typeid(to_type).name() << " with lowest possible value = " << boost::numeric::bounds<to_type>::lowest()); +PUSH_WARNINGS +DISABLE_CLANG_WARNING(tautological-constant-out-of-range-compare) + CHECK_AND_ASSERT_THROW_MES(from <= std::numeric_limits<to_type>::max(), "int value overhead: try to set value " << from << " to type " << typeid(to_type).name() << " with max possible value = " << std::numeric_limits<to_type>::max()); +POP_WARNINGS + to = static_cast<to_type>(from); + } + template<typename from_type, typename to_type> + void convert_uint_to_any_int(const from_type& from, to_type& to) + { +PUSH_WARNINGS +DISABLE_VS_WARNINGS(4018) +DISABLE_CLANG_WARNING(tautological-constant-out-of-range-compare) + CHECK_AND_ASSERT_THROW_MES(from <= std::numeric_limits<to_type>::max(), "uint value overhead: try to set value " << from << " to type " << typeid(to_type).name() << " with max possible value = " << std::numeric_limits<to_type>::max()); + to = static_cast<to_type>(from); +POP_WARNINGS + } + + template<typename from_type, typename to_type, bool, bool> //is from signed, is from to signed + struct convert_to_signed_unsigned; + + template<typename from_type, typename to_type> + struct convert_to_signed_unsigned<from_type, to_type, true, true> + { + static void convert(const from_type& from, to_type& to) + {//from signed to signed + convert_int_to_int(from, to); + } + }; + + template<typename from_type, typename to_type> + struct convert_to_signed_unsigned<from_type, to_type, true, false> + { + static void convert(const from_type& from, to_type& to) + {//from signed to unsigned + convert_int_to_uint(from, to); + } + }; + + template<typename from_type, typename to_type> + struct convert_to_signed_unsigned<from_type, to_type, false, true> + { + static void convert(const from_type& from, to_type& to) + {//from unsigned to signed + convert_uint_to_any_int(from, to); + } + }; + + template<typename from_type, typename to_type> + struct convert_to_signed_unsigned<from_type, to_type, false, false> + { + static void convert(const from_type& from, to_type& to) + { + //from unsigned to unsigned + convert_uint_to_any_int(from, to); + } + }; + + template<typename from_type, typename to_type, bool> + struct convert_to_integral; + + template<typename from_type, typename to_type> + struct convert_to_integral<from_type, to_type, true> + { + static void convert(const from_type& from, to_type& to) + { + convert_to_signed_unsigned<from_type, to_type, std::is_signed<from_type>::value, std::is_signed<to_type>::value>::convert(from, to); + } + }; + + template<typename from_type, typename to_type> + struct convert_to_integral<from_type, to_type, false> + { + static void convert(const from_type& from, to_type& to) + { + ASSERT_AND_THROW_WRONG_CONVERSION(); + } + }; + + template<class from_type, class to_type> + struct is_convertable: std::integral_constant<bool, + std::is_integral<to_type>::value && + std::is_integral<from_type>::value && + !std::is_same<from_type, bool>::value && + !std::is_same<to_type, bool>::value > {}; + + template<typename from_type, typename to_type, bool> + struct convert_to_same; + + template<typename from_type, typename to_type> + struct convert_to_same<from_type, to_type, true> + { + static void convert(const from_type& from, to_type& to) + { + to = from; + } + }; + + template<typename from_type, typename to_type> + struct convert_to_same<from_type, to_type, false> + { + static void convert(const from_type& from, to_type& to) + { + convert_to_integral<from_type, to_type, is_convertable<from_type, to_type>::value>::convert(from, to);// ASSERT_AND_THROW_WRONG_CONVERSION(); + } + }; + + + template<class from_type, class to_type> + void convert_t(const from_type& from, to_type& to) + { + convert_to_same<from_type, to_type, std::is_same<to_type, from_type>::value>::convert(from, to); + } + } +}
\ No newline at end of file |