CUBRID Engine  latest
packer.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Search Solution Corporation
3  * Copyright 2016 CUBRID Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 /*
20  * packer.hpp
21  */
22 
23 #ifndef _PACKER_HPP_
24 #define _PACKER_HPP_
25 
26 #include "dbtype_def.h"
27 #include "mem_block.hpp"
28 
29 #include <vector>
30 #include <string>
31 #include <utility>
32 
33 // forward definition
34 struct or_buf;
35 struct db_value;
36 
37 namespace cubpacking
38 {
39  class packable_object;
40 };
41 
42 /*
43  * the packer object packs primitive objects from a buffer and unpacker unpacks same objects from the buffer.
44  * the packer & unpacker implementations should be mirrored.
45  *
46  * the buffer is provided at initialization; packer/unpacker classes are not meant for multi-threaded access.
47  */
48 namespace cubpacking
49 {
50  class packer
51  {
52  public:
53  packer ();
54  packer (char *storage, const size_t amount);
55  void set_buffer (char *storage, const size_t amount);
56 
57  size_t get_packed_int_size (size_t curr_offset);
58  void pack_int (const int value);
59  size_t get_packed_size_overloaded (int value, size_t curr_offset);
60  void pack_overloaded (int value);
61 
62  size_t get_packed_bool_size (size_t curr_offset);
63  void pack_bool (bool value);
64  size_t get_packed_size_overloaded (bool value, size_t curr_offset);
65  void pack_overloaded (bool value);
66 
67  size_t get_packed_short_size (size_t curr_offset);
68  void pack_short (const short value);
69  size_t get_packed_size_overloaded (short value, size_t curr_offset);
70  void pack_overloaded (short value);
71 
72  size_t get_packed_bigint_size (size_t curr_offset);
73  void pack_bigint (const std::int64_t &value);
74  void pack_bigint (const std::uint64_t &value);
75  size_t get_packed_size_overloaded (const std::int64_t &value, size_t curr_offset);
76  size_t get_packed_size_overloaded (const std::uint64_t &value, size_t curr_offset);
77  void pack_overloaded (const std::int64_t &value);
78  void pack_overloaded (const std::uint64_t &value);
79 
80  void pack_int_array (const int *array, const int count);
81 
82  size_t get_packed_int_vector_size (size_t curr_offset, const size_t count);
83  void pack_int_vector (const std::vector<int> &array);
84 
85  size_t get_packed_db_value_size (const db_value &value, size_t curr_offset);
86  void pack_db_value (const db_value &value);
87  size_t get_packed_size_overloaded (const db_value &value, size_t curr_offset);
88  void pack_overloaded (const db_value &value);
89 
90  size_t get_packed_small_string_size (const char *string, const size_t curr_offset);
91  void pack_small_string (const char *string, const size_t str_size = 0);
92 
93  size_t get_packed_large_string_size (const std::string &str, const size_t curr_offset);
94  void pack_large_string (const std::string &str);
95 
96  size_t get_packed_string_size (const std::string &str, const size_t curr_offset);
97  void pack_string (const std::string &str);
98  size_t get_packed_size_overloaded (const std::string &value, size_t curr_offset);
99  void pack_overloaded (const std::string &str);
100 
101  size_t get_packed_c_string_size (const char *str, const size_t str_size, const size_t curr_offset);
102  void pack_c_string (const char *str, const size_t str_size);
103 
104  size_t get_packed_size_overloaded (const packable_object &po, size_t curr_offset);
105  void pack_overloaded (const packable_object &po);
106 
107  size_t get_packed_oid_size (const size_t curr_offset);
108  void pack_oid (const OID &oid);
109  size_t get_packed_size_overloaded (const OID &oid, size_t curr_offset);
110  void pack_overloaded (const OID &oid);
111 
112  // packer should gradually replace OR_BUF, but they will coexist for a while. there will be functionality
113  // strictly dependent on or_buf, so packer will have to cede at least some of the packing to or_buf
114  //
115  void delegate_to_or_buf (const size_t size, or_buf &buf);
116 
117  const char *get_curr_ptr (void);;
118  size_t get_current_size (void);
119  void align (const size_t req_alignment);
120  const char *get_buffer_start (void);
121  const char *get_buffer_end (void);
122  bool is_ended (void);
123 
124  std::size_t get_packed_buffer_size (const char *stream, const std::size_t length, const std::size_t curr_offset) const;
125  void pack_buffer_with_length (const char *stream, const std::size_t length);
126 
127  // template function to pack object as int type
128  template <typename T>
129  void pack_to_int (const T &t);
130 
131  // template functions to pack objects in bulk
132  // note - it requires versions of get_packed_size_overloaded and pack_overloaded
133 
134  // get packed size of all arguments. equivalent to:
135  //
136  // size_t total_size = 0;
137  // for (arg : args)
138  // total_size += get_packed_size_overloaded (arg);
139  // return total_size;
140  //
141  template <typename ... Args>
142  size_t get_all_packed_size (Args &&... args);
143  template <typename ... Args>
144  size_t get_all_packed_size_starting_offset (size_t start_offset, Args &&... args);
145 
146  // pack all arguments. equivalent to:
147  //
148  // for (arg : args)
149  // pack_overloaded (arg);
150  //
151  template <typename ... Args>
152  void pack_all (Args &&... args);
153 
154  // compute size of all arguments, extend the buffer to required size and then pack all arguments
155  template <typename ExtBlk, typename ... Args>
156  void set_buffer_and_pack_all (ExtBlk &eb, Args &&... args);
157 
158  // compute size of all arguments, extend the buffer by new required size
159  // and then pack all arguments and then end of previous end of buffer
160  template <typename ExtBlk, typename ... Args>
161  void append_to_buffer_and_pack_all (ExtBlk &eb, Args &&... args);
162 
163  private:
164  void pack_large_c_string (const char *string, const size_t str_size);
165 
166  template <typename T, typename ... Args>
167  size_t get_all_packed_size_recursive (size_t curr_offset, T &&t, Args &&... args);
168  template <typename T>
169  size_t get_all_packed_size_recursive (size_t curr_offset, T &&t);
170 
171  template <typename T, typename ... Args>
172  void pack_all_recursive (T &&t, Args &&... args);
173  template <typename T>
174  void pack_all_recursive (T &&t);
175 
176  const char *m_start_ptr; /* start of buffer */
177  const char *m_end_ptr; /* end of available serialization scope */
178  char *m_ptr;
179  };
180 
181  class unpacker
182  {
183  public:
184  unpacker () = default;
185  unpacker (const char *storage, const size_t amount);
186  void set_buffer (const char *storage, const size_t amount);
187 
188  void unpack_int (int &value);
189  void unpack_overloaded (int &value);
190  void peek_unpack_int (int &value);
191  void unpack_int_array (int *array, int &count);
192  void unpack_int_vector (std::vector <int> &array);
193 
194  void unpack_bool (bool &value);
195  void unpack_overloaded (bool &value);
196 
197  void unpack_short (short &value);
198  void unpack_overloaded (short &value);
199 
200  void unpack_bigint (std::int64_t &value);
201  void unpack_bigint (std::uint64_t &value);
202  void unpack_overloaded (std::int64_t &value);
203  void unpack_overloaded (std::uint64_t &value);
204 
205  void unpack_small_string (char *string, const size_t max_size);
206  void unpack_large_string (std::string &str);
207  void unpack_string (std::string &str);
208  void unpack_overloaded (std::string &str);
209  void unpack_c_string (char *str, const size_t max_str_size);
210  void unpack_string_to_memblock (cubmem::extensible_block &blk);
211 
212  void unpack_db_value (db_value &value);
213  void unpack_overloaded (db_value &value);
214 
215  void unpack_overloaded (packable_object &po);
216 
217  void peek_unpack_buffer_length (int &value);
218  void unpack_buffer_with_length (char *stream, const std::size_t max_length);
219 
220  void unpack_oid (OID &oid);
221  void unpack_overloaded (OID &oid);
222 
223  const char *get_curr_ptr (void);
224  void align (const size_t req_alignment);
225  size_t get_current_size (void);
226  const char *get_buffer_start (void);
227  const char *get_buffer_end (void);
228  bool is_ended (void);
229 
230  // packer should gradually replace OR_BUF, but they will coexist for a while. there will be functionality
231  // strictly dependent on or_buf, so packer will have to cede at least some of the packing to or_buf
232  //
233  void delegate_to_or_buf (const size_t size, or_buf &buf);
234 
235  // template function to unpack object from int type to T type
236  template <typename T>
237  void unpack_from_int (T &t);
238 
239  // template functions to unpack object in bulk
240  // note - it requires implementations of unpack_overloaded for all types
241 
242  // unpack all arguments. equivalent to:
243  //
244  // for (arg : args)
245  // unpack_overloaded (arg);
246  //
247  // note - arguments should be of same type and order like when they were packed.
248  template <typename ... Args>
249  void unpack_all (Args &&... args);
250 
251  private:
252  void unpack_string_size (size_t &len);
253 
254  template <typename T, typename ... Args>
255  void unpack_all_recursive (T &&t, Args &&... args);
256  template <typename T>
257  void unpack_all_recursive (T &&t);
258 
259  const char *m_start_ptr; /* start of buffer */
260  const char *m_end_ptr; /* end of available serialization scope */
261  const char *m_ptr;
262  };
263 
264 } // namespace cubpacking
265 
266 // for legacy C files, because indent is confused by namespaces
269 
271 // Template/inline implementation
273 
274 namespace cubpacking
275 {
276  //
277  // packer
278  //
279 
280  template <typename T>
281  void
282  packer::pack_to_int (const T &t)
283  {
284  pack_int ((int) t);
285  }
286 
287  template <typename ... Args>
288  size_t
289  packer::get_all_packed_size (Args &&... args)
290  {
291  return get_all_packed_size_recursive (0, std::forward<Args> (args)...);
292  }
293 
294  template <typename ... Args>
295  size_t
296  packer::get_all_packed_size_starting_offset (size_t start_offset, Args &&... args)
297  {
298  size_t total_size = get_all_packed_size_recursive (start_offset, std::forward<Args> (args)...);
299  return total_size - start_offset;
300  }
301 
302  template <typename T>
303  size_t
304  packer::get_all_packed_size_recursive (size_t curr_offset, T &&t)
305  {
306  return curr_offset + get_packed_size_overloaded (std::forward<T> (t), curr_offset);
307  }
308 
309  template <typename T, typename ... Args>
310  size_t
311  packer::get_all_packed_size_recursive (size_t curr_offset, T &&t, Args &&... args)
312  {
313  size_t next_offset = curr_offset + get_packed_size_overloaded (std::forward<T> (t), curr_offset);
314  return get_all_packed_size_recursive (next_offset, std::forward<Args> (args)...);
315  }
316 
317  template <typename ... Args>
318  void
319  packer::pack_all (Args &&... args)
320  {
321  pack_all_recursive (std::forward<Args> (args)...);
322  }
323 
324  template <typename T>
325  void
327  {
328  pack_overloaded (std::forward<T> (t));
329  }
330 
331  template <typename T, typename ... Args>
332  void
333  packer::pack_all_recursive (T &&t, Args &&... args)
334  {
335  pack_overloaded (std::forward<T> (t));
336  pack_all (std::forward<Args> (args)...);
337  }
338 
339  template <typename ExtBlk, typename ... Args>
340  void
341  packer::set_buffer_and_pack_all (ExtBlk &eb, Args &&... args)
342  {
343  size_t total_size = get_all_packed_size (std::forward<Args> (args)...);
344  eb.extend_to (total_size);
345 
346  set_buffer (eb.get_ptr (), total_size);
347  pack_all (std::forward<Args> (args)...);
348  }
349 
350 
351  template <typename ExtBlk, typename ... Args>
352  void
353  packer::append_to_buffer_and_pack_all (ExtBlk &eb, Args &&... args)
354  {
355  if (get_buffer_start () != eb.get_ptr ())
356  {
357  /* first call */
358  return set_buffer_and_pack_all (eb, std::forward<Args> (args)...);
359  }
360 
361  assert (get_curr_ptr () >= eb.get_ptr () && get_curr_ptr () <= eb.get_ptr () + eb.get_size ());
362 
363  size_t offset = get_curr_ptr () - get_buffer_start ();
364  assert (offset >= 0);
365 
366  size_t available = eb.get_ptr () + eb.get_size () - get_curr_ptr ();
367 
368  size_t total_size = get_all_packed_size (std::forward<Args> (args)...);
369 
370  if (available < total_size)
371  {
372  eb.extend_by (total_size - available);
373  }
374 
375  m_start_ptr = eb.get_ptr ();
376  m_ptr = eb.get_ptr () + offset;
377  m_end_ptr = eb.get_ptr () + offset + total_size;
378 
379  pack_all (std::forward<Args> (args)...);
380  }
381 
382  //
383  // unpacker
384  //
385 
386  template <typename T>
387  void
389  {
390  int int_val;
391  unpack_int (int_val);
392  t = (T) int_val;
393  }
394 
395  template <typename ... Args>
396  void
397  unpacker::unpack_all (Args &&... args)
398  {
399  unpack_all_recursive (std::forward<Args> (args)...);
400  }
401 
402  template <typename T, typename ... Args>
403  void
404  unpacker::unpack_all_recursive (T &&t, Args &&... args)
405  {
406  unpack_overloaded (std::forward<T> (t));
407  unpack_all_recursive (std::forward<Args> (args)...);
408  }
409 
410  template <typename T>
411  void
413  {
414  unpack_overloaded (std::forward<T> (t));
415  }
416 } // namespace cubpacking
417 
418 #endif /* _PACKER_HPP_ */
size_t get_packed_string_size(const std::string &str, const size_t curr_offset)
Definition: packer.cpp:593
void set_buffer_and_pack_all(ExtBlk &eb, Args &&...args)
Definition: packer.hpp:341
size_t get_packed_oid_size(const size_t curr_offset)
Definition: packer.cpp:771
void pack_int(const int value)
Definition: packer.cpp:101
void pack_int_array(const int *array, const int count)
Definition: packer.cpp:313
void pack_large_c_string(const char *string, const size_t str_size)
Definition: packer.cpp:539
void pack_to_int(const T &t)
Definition: packer.hpp:282
void pack_small_string(const char *string, const size_t str_size=0)
Definition: packer.cpp:463
void align(const size_t req_alignment)
Definition: packer.cpp:942
bool is_ended(void)
Definition: packer.cpp:960
const char * m_start_ptr
Definition: packer.hpp:176
void pack_overloaded(int value)
Definition: packer.cpp:117
void pack_buffer_with_length(const char *stream, const std::size_t length)
Definition: packer.cpp:866
size_t get_all_packed_size_starting_offset(size_t start_offset, Args &&...args)
Definition: packer.hpp:296
void pack_short(const short value)
Definition: packer.cpp:193
const char * m_start_ptr
Definition: packer.hpp:259
size_t get_packed_size_overloaded(int value, size_t curr_offset)
Definition: packer.cpp:111
size_t get_packed_c_string_size(const char *str, const size_t str_size, const size_t curr_offset)
Definition: packer.cpp:650
void pack_all(Args &&...args)
Definition: packer.hpp:319
const char * get_buffer_end(void)
Definition: packer.cpp:954
size_t get_packed_int_size(size_t curr_offset)
Definition: packer.cpp:95
#define assert(x)
void unpack_all_recursive(T &&t, Args &&...args)
Definition: packer.hpp:404
const char * m_end_ptr
Definition: packer.hpp:260
size_t get_current_size(void)
Definition: packer.cpp:936
std::size_t get_packed_buffer_size(const char *stream, const std::size_t length, const std::size_t curr_offset) const
Definition: packer.cpp:851
void pack_large_string(const std::string &str)
Definition: packer.cpp:565
size_t get_all_packed_size(Args &&...args)
Definition: packer.hpp:289
size_t get_packed_bool_size(size_t curr_offset)
Definition: packer.cpp:148
void pack_db_value(const db_value &value)
Definition: packer.cpp:403
const char * m_end_ptr
Definition: packer.hpp:177
int count(int &result, const cub_regex_object &reg, const std::string &src, const int position, const INTL_CODESET codeset)
void pack_bool(bool value)
Definition: packer.cpp:154
void unpack_from_int(T &t)
Definition: packer.hpp:388
size_t get_packed_db_value_size(const db_value &value, size_t curr_offset)
Definition: packer.cpp:394
const char * m_ptr
Definition: packer.hpp:261
size_t get_packed_short_size(size_t curr_offset)
Definition: packer.cpp:187
void pack_c_string(const char *str, const size_t str_size)
Definition: packer.cpp:667
size_t get_all_packed_size_recursive(size_t curr_offset, T &&t, Args &&...args)
Definition: packer.hpp:311
const char * get_buffer_start(void)
Definition: packer.cpp:948
void pack_oid(const OID &oid)
Definition: packer.cpp:777
void set_buffer(char *storage, const size_t amount)
Definition: packer.cpp:74
void pack_bigint(const std::int64_t &value)
Definition: packer.cpp:237
void unpack_all(Args &&...args)
Definition: packer.hpp:397
void pack_string(const std::string &str)
Definition: packer.cpp:599
size_t get_packed_small_string_size(const char *string, const size_t curr_offset)
Definition: packer.cpp:453
size_t get_packed_large_string_size(const std::string &str, const size_t curr_offset)
Definition: packer.cpp:529
size_t get_packed_int_vector_size(size_t curr_offset, const size_t count)
Definition: packer.cpp:351
void append_to_buffer_and_pack_all(ExtBlk &eb, Args &&...args)
Definition: packer.hpp:353
const char * get_curr_ptr(void)
Definition: packer.cpp:930
void delegate_to_or_buf(const size_t size, or_buf &buf)
Definition: packer.cpp:922
size_t get_packed_bigint_size(size_t curr_offset)
Definition: packer.cpp:231
void pack_int_vector(const std::vector< int > &array)
Definition: packer.cpp:357
void pack_all_recursive(T &&t, Args &&...args)
Definition: packer.hpp:333