Electroneum
Loading...
Searching...
No Matches
portable_storage_from_bin.h
Go to the documentation of this file.
1// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are met:
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above copyright
9// notice, this list of conditions and the following disclaimer in the
10// documentation and/or other materials provided with the distribution.
11// * Neither the name of the Andrey N. Sabelnikov nor the
12// names of its contributors may be used to endorse or promote products
13// derived from this software without specific prior written permission.
14//
15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
19// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25//
26
27
28
29#pragma once
30
31#include "misc_language.h"
33
34#ifdef EPEE_PORTABLE_STORAGE_RECURSION_LIMIT
35#define EPEE_PORTABLE_STORAGE_RECURSION_LIMIT_INTERNAL EPEE_PORTABLE_STORAGE_RECURSION_LIMIT
36#else
37#define EPEE_PORTABLE_STORAGE_RECURSION_LIMIT_INTERNAL 100
38#endif
39
40namespace epee
41{
42 namespace serialization
43 {
45 {
46 throwable_buffer_reader(const void* ptr, size_t sz);
47 void read(void* target, size_t count);
48 void read_sec_name(std::string& sce_name);
49 template<class t_pod_type>
50 void read(t_pod_type& pod_val);
51 template<class t_type>
52 t_type read();
53 template<class type_name>
56 size_t read_varint();
57 template<class t_type>
60 void read(section& sec);
61 void read(std::string& str);
62 void read(array_entry &ae);
63 private:
64 struct recursuion_limitation_guard
65 {
66 size_t& m_counter_ref;
67 recursuion_limitation_guard(size_t& counter):m_counter_ref(counter)
68 {
69 ++m_counter_ref;
70 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");
71 }
72 ~recursuion_limitation_guard() noexcept(false)
73 {
74 CHECK_AND_ASSERT_THROW_MES(m_counter_ref != 0, "Internal error: m_counter_ref == 0 while ~recursuion_limitation_guard()");
75 --m_counter_ref;
76 }
77 };
78#define RECURSION_LIMITATION() recursuion_limitation_guard rl(m_recursion_count)
79
80 const uint8_t* m_ptr;
81 size_t m_count;
82 size_t m_recursion_count;
83 };
84
85 inline throwable_buffer_reader::throwable_buffer_reader(const void* ptr, size_t sz)
86 {
87 if(!ptr)
88 throw std::runtime_error("throwable_buffer_reader: ptr==nullptr");
89 if(!sz)
90 throw std::runtime_error("throwable_buffer_reader: sz==0");
91 m_ptr = (uint8_t*)ptr;
92 m_count = sz;
93 m_recursion_count = 0;
94 }
95 inline
96 void throwable_buffer_reader::read(void* target, size_t count)
97 {
99 CHECK_AND_ASSERT_THROW_MES(m_count >= count, " attempt to read " << count << " bytes from buffer with " << m_count << " bytes remained");
100 memcpy(target, m_ptr, count);
101 m_ptr += count;
102 m_count -= count;
103 }
104 inline
105 void throwable_buffer_reader::read_sec_name(std::string& sce_name)
106 {
108 uint8_t name_len = 0;
109 read(name_len);
110 sce_name.resize(name_len);
111 read((void*)sce_name.data(), name_len);
112 }
113
114 template<class t_pod_type>
115 void throwable_buffer_reader::read(t_pod_type& pod_val)
116 {
118 static_assert(std::is_pod<t_pod_type>::value, "POD type expected");
119 read(&pod_val, sizeof(pod_val));
120 }
121
122 template<class t_type>
124 {
126 t_type v;
127 read(v);
128 return v;
129 }
130
131
132 template<class type_name>
134 {
136 //for pod types
138 size_t size = read_varint();
139 CHECK_AND_ASSERT_THROW_MES(size <= m_count, "Size sanity check failed");
140 sa.reserve(size);
141 //TODO: add some optimization here later
142 while(size--)
143 sa.m_array.push_back(read<type_name>());
144 return storage_entry(array_entry(sa));
145 }
146
147 inline
149 {
151 type &= ~SERIALIZE_FLAG_ARRAY;
152 switch(type)
153 {
163 case SERIALIZE_TYPE_BOOL: return read_ae<bool>();
167 default:
168 CHECK_AND_ASSERT_THROW_MES(false, "unknown entry_type code = " << type);
169 }
170 }
171
172 inline
174 {
176 CHECK_AND_ASSERT_THROW_MES(m_count >= 1, "empty buff, expected place for varint");
177 size_t v = 0;
178 uint8_t size_mask = (*(uint8_t*)m_ptr) &PORTABLE_RAW_SIZE_MARK_MASK;
179 switch (size_mask)
180 {
185 default:
186 CHECK_AND_ASSERT_THROW_MES(false, "unknown varint size_mask = " << size_mask);
187 }
188 v >>= 2;
189 return v;
190 }
191
192 template<class t_type>
194 {
196 t_type v;
197 read(v);
198 return storage_entry(v);
199 }
200
201 template<>
203 {
205 return storage_entry(read<std::string>());
206 }
207
208
209 template<>
211 {
213 section s;//use extra variable due to vs bug, line "storage_entry se(section()); " can't be compiled in visual studio
214 storage_entry se(s);
215 section& section_entry = boost::get<section>(se);
216 read(section_entry);
217 return se;
218 }
219
220 template<>
222 {
224 uint8_t ent_type = 0;
225 read(ent_type);
226 CHECK_AND_ASSERT_THROW_MES(ent_type&SERIALIZE_FLAG_ARRAY, "wrong type sequenses");
227 return load_storage_array_entry(ent_type);
228 }
229
230 inline
232 {
234 uint8_t ent_type = 0;
235 read(ent_type);
236 if(ent_type&SERIALIZE_FLAG_ARRAY)
237 return load_storage_array_entry(ent_type);
238
239 switch(ent_type)
240 {
250 case SERIALIZE_TYPE_BOOL: return read_se<bool>();
254 default:
255 CHECK_AND_ASSERT_THROW_MES(false, "unknown entry_type code = " << ent_type);
256 }
257 }
258 inline
260 {
262 sec.m_entries.clear();
263 size_t count = read_varint();
264 while(count--)
265 {
266 //read section name string
267 std::string sec_name;
268 read_sec_name(sec_name);
269 sec.m_entries.insert(std::make_pair(sec_name, load_storage_entry()));
270 }
271 }
272 inline
273 void throwable_buffer_reader::read(std::string& str)
274 {
276 size_t len = read_varint();
277 CHECK_AND_ASSERT_THROW_MES(len < MAX_STRING_LEN_POSSIBLE, "to big string len value in storage: " << len);
278 CHECK_AND_ASSERT_THROW_MES(m_count >= len, "string len count value " << len << " goes out of remain storage len " << m_count);
279 //do this manually to avoid double memory write in huge strings (first time at resize, second at read)
280 str.assign((const char*)m_ptr, len);
281 m_ptr+=len;
282 m_count -= len;
283 }
284 inline
286 {
288 CHECK_AND_ASSERT_THROW_MES(false, "Reading array entry is not supported");
289 }
290 }
291}
void * memcpy(void *a, const void *b, size_t c)
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
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
storage_entry throwable_buffer_reader::read_se< std::string >()
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
#define PORTABLE_RAW_SIZE_MARK_WORD
#define SERIALIZE_FLAG_ARRAY
#define PORTABLE_RAW_SIZE_MARK_DWORD
#define SERIALIZE_TYPE_UINT32
#define SERIALIZE_TYPE_INT32
#define MAX_STRING_LEN_POSSIBLE
#define SERIALIZE_TYPE_DUOBLE
#define SERIALIZE_TYPE_UINT8
#define PORTABLE_RAW_SIZE_MARK_MASK
#define SERIALIZE_TYPE_UINT16
#define PORTABLE_RAW_SIZE_MARK_BYTE
#define PORTABLE_RAW_SIZE_MARK_INT64
#define SERIALIZE_TYPE_INT64
#define SERIALIZE_TYPE_UINT64
#define SERIALIZE_TYPE_INT8
#define SERIALIZE_TYPE_STRING
#define SERIALIZE_TYPE_INT16
#define SERIALIZE_TYPE_OBJECT
#define SERIALIZE_TYPE_ARRAY
#define SERIALIZE_TYPE_BOOL
#define EPEE_PORTABLE_STORAGE_RECURSION_LIMIT_INTERNAL
#define RECURSION_LIMITATION()
unsigned char uint8_t
Definition stdint.h:124
void reserve(size_t n)
entry_container< t_entry_type >::type m_array
std::map< std::string, storage_entry > m_entries