aboutsummaryrefslogtreecommitdiff
path: root/contrib/epee/include/storages
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/epee/include/storages')
-rw-r--r--contrib/epee/include/storages/activity_notifier.h132
-rw-r--r--contrib/epee/include/storages/crypted_storage.h62
-rw-r--r--contrib/epee/include/storages/gzipped_inmemstorage.h68
-rw-r--r--contrib/epee/include/storages/http_abstract_invoke.h126
-rw-r--r--contrib/epee/include/storages/levin_abstract_invoke2.h289
-rw-r--r--contrib/epee/include/storages/parserse_base_utils.h260
-rw-r--r--contrib/epee/include/storages/portable_storage.h463
-rw-r--r--contrib/epee/include/storages/portable_storage_base.h160
-rw-r--r--contrib/epee/include/storages/portable_storage_from_bin.h281
-rw-r--r--contrib/epee/include/storages/portable_storage_from_json.h379
-rw-r--r--contrib/epee/include/storages/portable_storage_template_helper.h120
-rw-r--r--contrib/epee/include/storages/portable_storage_to_bin.h212
-rw-r--r--contrib/epee/include/storages/portable_storage_to_json.h172
-rw-r--r--contrib/epee/include/storages/portable_storage_val_converters.h169
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