Electroneum
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"
32 #include "portable_storage_base.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 
40 namespace 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
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  {
154  case SERIALIZE_TYPE_INT64: return read_ae<int64_t>();
155  case SERIALIZE_TYPE_INT32: return read_ae<int32_t>();
156  case SERIALIZE_TYPE_INT16: return read_ae<int16_t>();
157  case SERIALIZE_TYPE_INT8: return read_ae<int8_t>();
158  case SERIALIZE_TYPE_UINT64: return read_ae<uint64_t>();
159  case SERIALIZE_TYPE_UINT32: return read_ae<uint32_t>();
160  case SERIALIZE_TYPE_UINT16: return read_ae<uint16_t>();
161  case SERIALIZE_TYPE_UINT8: return read_ae<uint8_t>();
162  case SERIALIZE_TYPE_DUOBLE: return read_ae<double>();
163  case SERIALIZE_TYPE_BOOL: return read_ae<bool>();
164  case SERIALIZE_TYPE_STRING: return read_ae<std::string>();
165  case SERIALIZE_TYPE_OBJECT: return read_ae<section>();
166  case SERIALIZE_TYPE_ARRAY: return read_ae<array_entry>();
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  {
181  case PORTABLE_RAW_SIZE_MARK_BYTE: v = read<uint8_t>();break;
182  case PORTABLE_RAW_SIZE_MARK_WORD: v = read<uint16_t>();break;
183  case PORTABLE_RAW_SIZE_MARK_DWORD: v = read<uint32_t>();break;
184  case PORTABLE_RAW_SIZE_MARK_INT64: v = read<uint64_t>();break;
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<>
202  inline storage_entry throwable_buffer_reader::read_se<std::string>()
203  {
205  return storage_entry(read<std::string>());
206  }
207 
208 
209  template<>
210  inline storage_entry throwable_buffer_reader::read_se<section>()
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<>
221  inline storage_entry throwable_buffer_reader::read_se<array_entry>()
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  {
241  case SERIALIZE_TYPE_INT64: return read_se<int64_t>();
242  case SERIALIZE_TYPE_INT32: return read_se<int32_t>();
243  case SERIALIZE_TYPE_INT16: return read_se<int16_t>();
244  case SERIALIZE_TYPE_INT8: return read_se<int8_t>();
245  case SERIALIZE_TYPE_UINT64: return read_se<uint64_t>();
246  case SERIALIZE_TYPE_UINT32: return read_se<uint32_t>();
247  case SERIALIZE_TYPE_UINT16: return read_se<uint16_t>();
248  case SERIALIZE_TYPE_UINT8: return read_se<uint8_t>();
249  case SERIALIZE_TYPE_DUOBLE: return read_se<double>();
250  case SERIALIZE_TYPE_BOOL: return read_se<bool>();
251  case SERIALIZE_TYPE_STRING: return read_se<std::string>();
252  case SERIALIZE_TYPE_OBJECT: return read_se<section>();
253  case SERIALIZE_TYPE_ARRAY: return read_se<array_entry>();
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
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 }
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
#define PORTABLE_RAW_SIZE_MARK_BYTE
::std::string string
Definition: gtest-port.h:1097
#define PORTABLE_RAW_SIZE_MARK_WORD
#define SERIALIZE_TYPE_INT32
void reserve(size_t n)
#define SERIALIZE_TYPE_INT16
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
#define MAX_STRING_LEN_POSSIBLE
unsigned char uint8_t
Definition: stdint.h:124
#define SERIALIZE_TYPE_STRING
#define SERIALIZE_TYPE_INT64
#define SERIALIZE_TYPE_OBJECT
#define SERIALIZE_TYPE_UINT32
#define SERIALIZE_TYPE_UINT64
#define SERIALIZE_TYPE_BOOL
mdb_size_t count(MDB_cursor *cur)
#define SERIALIZE_TYPE_UINT16
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 SERIALIZE_FLAG_ARRAY
#define SERIALIZE_TYPE_ARRAY
#define SERIALIZE_TYPE_INT8
entry_container< t_entry_type >::type m_array
#define SERIALIZE_TYPE_UINT8
#define PORTABLE_RAW_SIZE_MARK_MASK
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1225
void * memcpy(void *a, const void *b, size_t c)
#define PORTABLE_RAW_SIZE_MARK_DWORD
#define PORTABLE_RAW_SIZE_MARK_INT64
#define SERIALIZE_TYPE_DUOBLE
#define RECURSION_LIMITATION()
std::map< std::string, storage_entry > m_entries
#define EPEE_PORTABLE_STORAGE_RECURSION_LIMIT_INTERNAL