moved all stuff to github

This commit is contained in:
Antonio Juarez 2014-03-03 22:07:58 +00:00
parent 095fbeeb67
commit 296ae46ed8
388 changed files with 95937 additions and 469 deletions

View file

@ -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);}
}

View file

@ -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_

View file

@ -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

View file

@ -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);
}
}
}

View file

@ -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; \
}
}
}

View file

@ -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;
}
}
}
}

View file

@ -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);
}
//---------------------------------------------------------------------------------------------------------------
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}
}

View file

@ -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;
}
}
}
}
}

View file

@ -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);
}
}
}

View file

@ -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;
}
}
}

View file

@ -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) << "}";
}
}
}

View file

@ -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);
}
}
}