Line data Source code
1 : // Copyright (c) 2019 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/snapdatabase
4 : // contact@m2osw.com
5 : //
6 : // This program is free software; you can redistribute it and/or modify
7 : // it under the terms of the GNU General Public License as published by
8 : // the Free Software Foundation; either version 2 of the License, or
9 : // (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License along
17 : // with this program; if not, write to the Free Software Foundation, Inc.,
18 : // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 : #pragma once
20 :
21 :
22 : /** \file
23 : * \brief Handle a block structure.
24 : *
25 : * Each block contains a structure. The very first four bytes are always the
26 : * magic characters which define the type of the block. The remained of the
27 : * block is a _lose_ structure which very often changes in size because it
28 : * includes parameters such as a string or an array.
29 : *
30 : * Also in most cases arrays are also themselvess _lose_ structures (a few
31 : * are just numbers such as column ids or block references.)
32 : *
33 : * IMPORTANT: The types defined here are also the types that we accept in
34 : * a user table. Here we define structures and later tables.
35 : */
36 :
37 : // self
38 : //
39 : #include "snapdatabase/exception.h"
40 : #include "snapdatabase/data/virtual_buffer.h"
41 : #include "snapdatabase/bigint/bigint.h"
42 :
43 :
44 : // snapdev lib
45 : //
46 : #include <snapdev/init_structure.h>
47 :
48 :
49 : // C++ lib
50 : //
51 : #include <map>
52 :
53 :
54 :
55 : namespace snapdatabase
56 : {
57 :
58 :
59 :
60 : constexpr std::uint16_t STRUCTURE_VERSION_MAJOR = 0;
61 : constexpr std::uint16_t STRUCTURE_VERSION_MINOR = 1;
62 :
63 :
64 : typedef uint64_t flags_t;
65 :
66 :
67 :
68 :
69 :
70 :
71 :
72 :
73 :
74 :
75 : class version_t
76 : {
77 : public:
78 1 : constexpr version_t()
79 1 : : f_major(0)
80 1 : , f_minor(0)
81 : {
82 1 : }
83 :
84 101 : constexpr version_t(version_t const & v)
85 101 : : f_major(v.f_major)
86 101 : , f_minor(v.f_minor)
87 : {
88 101 : }
89 :
90 400 : constexpr version_t(int major, int minor)
91 400 : : f_major(major)
92 400 : , f_minor(minor)
93 : {
94 400 : if(major < 0 || major >= 65536
95 300 : || minor < 0 || minor >= 65536)
96 : {
97 : throw invalid_parameter(
98 : "major/minor version must be between 0 and 65535 inclusive, "
99 200 : + std::to_string(major)
100 200 : + "."
101 400 : + std::to_string(minor)
102 300 : + " is incorrect.");
103 : }
104 300 : }
105 :
106 5 : constexpr version_t(std::uint32_t v)
107 5 : : f_major(v >> 16)
108 5 : , f_minor(v)
109 : {
110 5 : }
111 :
112 200 : version_t & operator = (version_t const & v)
113 : {
114 200 : f_major = v.f_major;
115 200 : f_minor = v.f_minor;
116 :
117 200 : return *this;
118 : }
119 :
120 100 : std::string to_string() const
121 : {
122 200 : return std::to_string(static_cast<uint32_t>(f_major))
123 200 : + "."
124 300 : + std::to_string(static_cast<uint32_t>(f_minor));
125 : }
126 :
127 518 : std::uint32_t to_binary() const
128 : {
129 518 : return (static_cast<std::uint32_t>(f_major) << 16) + static_cast<std::uint32_t>(f_minor);
130 : }
131 :
132 100 : void from_binary(std::uint32_t v)
133 : {
134 100 : f_major = v >> 16;
135 100 : f_minor = v;
136 100 : }
137 :
138 200 : bool is_null() const { return f_major == 0 && f_minor == 0; }
139 :
140 900 : std::uint16_t get_major() const { return f_major; }
141 101 : void set_major(uint16_t major) { f_major = major; }
142 900 : std::uint16_t get_minor() const { return f_minor; }
143 100 : void set_minor(uint16_t minor) { f_minor = minor; }
144 :
145 100 : void next_branch() { ++f_major; f_minor = 0; }
146 100 : void next_revision() { ++f_minor; if(f_minor == 0) ++f_major; }
147 :
148 403 : bool operator == (version_t const & rhs) const
149 : {
150 403 : return f_major == rhs.f_major
151 403 : && f_minor == rhs.f_minor;
152 : }
153 402 : bool operator != (version_t const & rhs) const
154 : {
155 402 : return f_major != rhs.f_major
156 402 : || f_minor != rhs.f_minor;
157 : }
158 200 : bool operator < (version_t const & rhs) const
159 : {
160 200 : return f_major < rhs.f_major
161 200 : || (f_major == rhs.f_major && f_minor < rhs.f_minor);
162 : }
163 200 : bool operator <= (version_t const & rhs) const
164 : {
165 200 : return f_major < rhs.f_major
166 200 : || (f_major == rhs.f_major && f_minor <= rhs.f_minor);
167 : }
168 200 : bool operator > (version_t const & rhs) const
169 : {
170 200 : return f_major > rhs.f_major
171 200 : || (f_major == rhs.f_major && f_minor > rhs.f_minor);
172 : }
173 200 : bool operator >= (version_t const & rhs) const
174 : {
175 200 : return f_major > rhs.f_major
176 200 : || (f_major == rhs.f_major && f_minor >= rhs.f_minor);
177 : }
178 :
179 : private:
180 : uint16_t f_major = 0;
181 : uint16_t f_minor = 0;
182 : };
183 :
184 :
185 : struct min_max_version_t
186 : {
187 : constexpr min_max_version_t(int min_major = 0, int min_minor = 0, int max_major = 0, int max_minor = 0)
188 : : f_min_version(min_major, min_minor)
189 : , f_max_version(max_major, max_minor)
190 : {
191 : }
192 :
193 : constexpr version_t min() const { return f_min_version; }
194 : constexpr version_t max() const { return f_max_version; }
195 :
196 : version_t const f_min_version = version_t();
197 : version_t const f_max_version = version_t();
198 : };
199 :
200 :
201 :
202 :
203 :
204 :
205 : constexpr int FlagPosition(flags_t const flag)
206 : {
207 : switch(flag)
208 : {
209 : case (1LL<< 0): return 0;
210 : case (1LL<< 1): return 1;
211 : case (1LL<< 2): return 2;
212 : case (1LL<< 3): return 3;
213 : case (1LL<< 4): return 4;
214 : case (1LL<< 5): return 5;
215 : case (1LL<< 6): return 6;
216 : case (1LL<< 7): return 7;
217 : case (1LL<< 8): return 8;
218 : case (1LL<< 9): return 9;
219 : case (1LL<<10): return 10;
220 : case (1LL<<11): return 11;
221 : case (1LL<<12): return 12;
222 : case (1LL<<13): return 13;
223 : case (1LL<<14): return 14;
224 : case (1LL<<15): return 15;
225 : case (1LL<<16): return 16;
226 : case (1LL<<17): return 17;
227 : case (1LL<<18): return 18;
228 : case (1LL<<19): return 19;
229 : case (1LL<<20): return 20;
230 : case (1LL<<21): return 21;
231 : case (1LL<<22): return 22;
232 : case (1LL<<23): return 23;
233 : case (1LL<<24): return 24;
234 : case (1LL<<25): return 25;
235 : case (1LL<<26): return 26;
236 : case (1LL<<27): return 27;
237 : case (1LL<<28): return 28;
238 : case (1LL<<29): return 29;
239 : case (1LL<<30): return 30;
240 : case (1LL<<31): return 31;
241 : case (1LL<<32): return 32;
242 : case (1LL<<33): return 33;
243 : case (1LL<<34): return 34;
244 : case (1LL<<35): return 35;
245 : case (1LL<<36): return 36;
246 : case (1LL<<37): return 37;
247 : case (1LL<<38): return 38;
248 : case (1LL<<39): return 39;
249 : case (1LL<<40): return 40;
250 : case (1LL<<41): return 41;
251 : case (1LL<<42): return 42;
252 : case (1LL<<43): return 43;
253 : case (1LL<<44): return 44;
254 : case (1LL<<45): return 45;
255 : case (1LL<<46): return 46;
256 : case (1LL<<47): return 47;
257 : case (1LL<<48): return 48;
258 : case (1LL<<49): return 49;
259 : case (1LL<<50): return 50;
260 : case (1LL<<51): return 51;
261 : case (1LL<<52): return 52;
262 : case (1LL<<53): return 53;
263 : case (1LL<<54): return 54;
264 : case (1LL<<55): return 55;
265 : case (1LL<<56): return 56;
266 : case (1LL<<57): return 57;
267 : case (1LL<<58): return 58;
268 : case (1LL<<59): return 59;
269 : case (1LL<<60): return 60;
270 : case (1LL<<61): return 61;
271 : case (1LL<<62): return 62;
272 : case (1LL<<63): return 63;
273 : }
274 : return -1;
275 : }
276 :
277 :
278 : /** \brief Type of a field in the database files.
279 : *
280 : * When creating a description, we need to have a type for each item.
281 : * This enumeration gives us all the types that we support.
282 : *
283 : * \note
284 : * For block descriptions, the following types are not saved in the tables.
285 : * It is only part of the description structures. However, the type of a
286 : * field in a table has its type defined in the schema (it's not repeated
287 : * in each cell, though. That would be too heavy!)
288 : */
289 : enum class struct_type_t : uint16_t
290 : {
291 : STRUCT_TYPE_END,
292 : STRUCT_TYPE_VOID,
293 :
294 : // bits are used as flags or numbers that can use less than 8 bit
295 : // (i.e. 3 bits can be enough in many cases); each name defines
296 : // the bit field and its size like so:
297 : //
298 : // <general-name>=<name1>:<size1>/<name2>:<size2>/...
299 : //
300 : // where by default size is 1 bit; we only support unsigned numbers
301 : // here; a field that gets removed can have its name removed and its
302 : // size is kept; this is the equivalent of a pad in the bit field
303 : //
304 : // the `<general-name>` is often set to "flags"
305 : //
306 : // this is very much an equivalent to bit fields in C/C++
307 : //
308 : STRUCT_TYPE_BITS8, // 8 bits of bits
309 : STRUCT_TYPE_BITS16, // 16 bits of bits
310 : STRUCT_TYPE_BITS32, // 32 bits of bits
311 : STRUCT_TYPE_BITS64, // 64 bits of bits
312 : STRUCT_TYPE_BITS128, // 128 bits of bits
313 : STRUCT_TYPE_BITS256, // 256 bits of bits
314 : STRUCT_TYPE_BITS512, // 512 bits of bits
315 :
316 : STRUCT_TYPE_INT8,
317 : STRUCT_TYPE_UINT8,
318 : STRUCT_TYPE_INT16,
319 : STRUCT_TYPE_UINT16,
320 : STRUCT_TYPE_INT32,
321 : STRUCT_TYPE_UINT32,
322 : STRUCT_TYPE_INT64,
323 : STRUCT_TYPE_UINT64,
324 : STRUCT_TYPE_INT128, // practical for MD5 and such
325 : STRUCT_TYPE_UINT128,
326 : STRUCT_TYPE_INT256, // practical for SHA256
327 : STRUCT_TYPE_UINT256,
328 : STRUCT_TYPE_INT512, // practical for SHA512
329 : STRUCT_TYPE_UINT512,
330 :
331 : STRUCT_TYPE_FLOAT32,
332 : STRUCT_TYPE_FLOAT64,
333 : STRUCT_TYPE_FLOAT128,
334 :
335 : STRUCT_TYPE_VERSION, // UINT16:UINT16 (Major:Minor)
336 :
337 : STRUCT_TYPE_TIME, // UINT64 equivalent to time_t (seconds)
338 : STRUCT_TYPE_MSTIME, // UINT64 time in milliseconds
339 : STRUCT_TYPE_USTIME, // UINT64 time in microseconds
340 :
341 : STRUCT_TYPE_P8STRING, // UINT8 for size
342 : STRUCT_TYPE_P16STRING, // UINT16 for size
343 : STRUCT_TYPE_P32STRING, // UINT32 for size
344 :
345 : STRUCT_TYPE_STRUCTURE, // one sub-structure (i.e. to access use "foo.blah")
346 :
347 : // array items get accessed with "foo[index]" (child structure has 1 field) and "foo[index].blah"
348 : // and to get the count use the hash character "#foo"
349 : STRUCT_TYPE_ARRAY8, // UINT8 for count
350 : STRUCT_TYPE_ARRAY16, // UINT16 for count
351 : STRUCT_TYPE_ARRAY32, // UINT32 for count
352 :
353 : // buffers are an equivalent to uint8_t arrays, no need for a sub-structure description
354 : STRUCT_TYPE_BUFFER8, // UINT8 for count
355 : STRUCT_TYPE_BUFFER16, // UINT16 for count
356 : STRUCT_TYPE_BUFFER32, // UINT32 for count
357 :
358 : STRUCT_TYPE_REFERENCE, // UINT64 to another location in the file (offset 0 is start of file)
359 : STRUCT_TYPE_OID, // UINT64 similar to a REFERENCE, but points to the TIND/INDR blocks (sizeof(OID) == sizeof(REFERENCE) must be true)
360 :
361 : STRUCT_TYPE_RENAMED // there is no data attached to this one, the next description is the new name
362 : };
363 :
364 :
365 :
366 :
367 : constexpr struct_type_t INVALID_STRUCT_TYPE(static_cast<struct_type_t>(-1));
368 :
369 : constexpr ssize_t INVALID_SIZE = -1;
370 : constexpr ssize_t VARIABLE_SIZE = -2;
371 :
372 : std::string to_string(struct_type_t const & type);
373 : struct_type_t name_to_struct_type(std::string const & type_name);
374 :
375 :
376 :
377 :
378 : typedef uint16_t struct_description_flags_t;
379 :
380 : constexpr struct_description_flags_t STRUCT_DESCRIPTION_FLAG_NONE = 0x0000;
381 : constexpr struct_description_flags_t STRUCT_DESCRIPTION_MASK_OPTIONAL_BIT = 0x003F; // use a field named "flags"
382 : constexpr struct_description_flags_t STRUCT_DESCRIPTION_FLAG_OPTIONAL = 0x0040;
383 :
384 :
385 : struct struct_description_t
386 : {
387 : char const * const f_field_name = nullptr;
388 : struct_type_t const f_type = struct_type_t::STRUCT_TYPE_VOID;
389 : struct_description_flags_t const f_flags = 0;
390 : char const * const f_default_value = nullptr;
391 : version_t const f_min_version = version_t();
392 : version_t const f_max_version = version_t();
393 : struct_description_t const * const f_sub_description = nullptr; // i.e. for an array, the type of the items
394 : };
395 :
396 :
397 : class FieldName
398 : : public snap::StructureValue<char const *>
399 : {
400 : public:
401 : constexpr FieldName()
402 : : snap::StructureValue<char const *>(nullptr)
403 : {
404 : }
405 :
406 : constexpr FieldName(char const * name)
407 : : snap::StructureValue<char const *>(name)
408 : {
409 : }
410 : };
411 :
412 :
413 : class FieldType
414 : : public snap::StructureValue<struct_type_t>
415 : {
416 : public:
417 : constexpr FieldType()
418 : : snap::StructureValue<struct_type_t>(struct_type_t::STRUCT_TYPE_END)
419 : {
420 : }
421 :
422 : constexpr FieldType(struct_type_t type)
423 : : snap::StructureValue<struct_type_t>(type)
424 : {
425 : }
426 : };
427 :
428 :
429 : class FieldFlags
430 : : public snap::StructureValue<struct_description_flags_t>
431 : {
432 : public:
433 : constexpr FieldFlags()
434 : : snap::StructureValue<struct_description_flags_t>(STRUCT_DESCRIPTION_FLAG_NONE)
435 : {
436 : }
437 :
438 : constexpr FieldFlags(struct_description_flags_t flags)
439 : : snap::StructureValue<struct_description_flags_t>(flags)
440 : {
441 : }
442 : };
443 :
444 :
445 : class FieldDefaultValue
446 : : public snap::StructureValue<char const *>
447 : {
448 : public:
449 : constexpr FieldDefaultValue()
450 : : snap::StructureValue<char const *>(nullptr)
451 : {
452 : }
453 :
454 : constexpr FieldDefaultValue(char const * default_value)
455 : : snap::StructureValue<char const *>(default_value)
456 : {
457 : }
458 : };
459 :
460 :
461 : class FieldVersion
462 : : public snap::StructureValue<min_max_version_t>
463 : {
464 : public:
465 : constexpr FieldVersion()
466 : : snap::StructureValue<min_max_version_t>(min_max_version_t())
467 : {
468 : }
469 :
470 : constexpr FieldVersion(int min_major, int min_minor, int max_major, int max_minor)
471 : : snap::StructureValue<min_max_version_t>(min_max_version_t(min_major, min_minor, max_major, max_minor))
472 : {
473 : }
474 : };
475 :
476 :
477 : class FieldSubDescription
478 : : public snap::StructureValue<struct_description_t const *>
479 : {
480 : public:
481 : constexpr FieldSubDescription()
482 : : snap::StructureValue<struct_description_t const *>(nullptr)
483 : {
484 : }
485 :
486 : constexpr FieldSubDescription(struct_description_t const * sub_description)
487 : : snap::StructureValue<struct_description_t const *>(sub_description)
488 : {
489 : }
490 : };
491 :
492 :
493 : template<class ...ARGS>
494 : constexpr struct_description_t define_description(ARGS ...args)
495 : {
496 : #pragma GCC diagnostic push
497 : #pragma GCC diagnostic ignored "-Wpedantic"
498 : struct_description_t s =
499 : {
500 : .f_field_name = snap::find_field<FieldName >(args...), // no default, mandatory
501 : .f_type = snap::find_field<FieldType >(args...), // no default, mandatory
502 : .f_flags = static_cast<struct_description_flags_t>(
503 : snap::find_field<FieldFlags >(args..., FieldFlags())),
504 : .f_default_value = snap::find_field<FieldDefaultValue >(args..., FieldDefaultValue()),
505 : .f_min_version = snap::find_field<FieldVersion >(args..., FieldVersion()).min(),
506 : .f_max_version = snap::find_field<FieldVersion >(args..., FieldVersion()).max(),
507 : .f_sub_description = snap::find_field<FieldSubDescription>(args..., FieldSubDescription()),
508 : };
509 : #pragma GCC diagnostic pop
510 :
511 : // TODO: once possible (C++17/20?) add verification tests here
512 :
513 : // whether a sub-description is allowed or not varies depending on the type
514 : //if(f_sub_description == nullptr)
515 : //{
516 : //}
517 : //else
518 : //{
519 : //}
520 :
521 : //if(f_min_version > f_max_version) ...
522 :
523 : return s;
524 : }
525 :
526 :
527 : constexpr struct_description_t end_descriptions()
528 : {
529 : return define_description(
530 : FieldName(nullptr)
531 : , FieldType(struct_type_t::STRUCT_TYPE_END)
532 : );
533 : }
534 :
535 :
536 :
537 : struct descriptions_by_version_t
538 : {
539 : version_t f_version = version_t();
540 : struct_description_t const * f_description = nullptr;
541 : };
542 :
543 :
544 :
545 : class DescriptionVersion
546 : : public snap::StructureValue<version_t>
547 : {
548 : public:
549 : constexpr DescriptionVersion()
550 : : snap::StructureValue<version_t>(version_t())
551 : {
552 : }
553 :
554 : constexpr DescriptionVersion(int major, int minor)
555 : : snap::StructureValue<version_t>(version_t(major, minor))
556 : {
557 : }
558 : };
559 :
560 :
561 : class DescriptionDescription
562 : : public snap::StructureValue<struct_description_t const *>
563 : {
564 : public:
565 : constexpr DescriptionDescription()
566 : : snap::StructureValue<struct_description_t const *>(nullptr)
567 : {
568 : }
569 :
570 : constexpr DescriptionDescription(struct_description_t const * description)
571 : : snap::StructureValue<struct_description_t const *>(description)
572 : {
573 : }
574 : };
575 :
576 :
577 : template<class ...ARGS>
578 : constexpr descriptions_by_version_t define_description_by_version(ARGS ...args)
579 : {
580 : #pragma GCC diagnostic push
581 : #pragma GCC diagnostic ignored "-Wpedantic"
582 : descriptions_by_version_t d =
583 : {
584 : .f_version = snap::find_field<DescriptionVersion >(args...), // no default, mandatory
585 : .f_description = snap::find_field<DescriptionDescription >(args...), // no default, mandatory
586 : };
587 : #pragma GCC diagnostic pop
588 :
589 : // TODO: once possible (C++17/20?) add verification tests here
590 :
591 : // either both are null or both are defined
592 : //if((f_description == nullptr) ^ f_version.zero())
593 : //{
594 : // throw ...
595 : //}
596 :
597 : return d;
598 : }
599 :
600 :
601 : constexpr descriptions_by_version_t end_descriptions_by_version()
602 : {
603 : return define_description_by_version(
604 : DescriptionVersion(0, 0)
605 : , DescriptionDescription(nullptr)
606 : );
607 : }
608 :
609 :
610 :
611 :
612 :
613 :
614 52 : class flag_definition
615 : {
616 : public:
617 : typedef std::shared_ptr<flag_definition> pointer_t;
618 : typedef std::map<std::string, pointer_t> map_t;
619 :
620 : flag_definition();
621 : flag_definition(
622 : std::string const & field_name
623 : , std::string const & flag_name
624 : , size_t pos
625 : , size_t size = 1);
626 :
627 : std::string full_name() const;
628 : std::string field_name() const;
629 : std::string flag_name() const;
630 : size_t pos() const;
631 : size_t size() const;
632 : flags_t mask() const;
633 :
634 : private:
635 : std::string f_field_name = std::string();
636 : std::string f_flag_name = std::string();
637 : size_t f_pos = 0;
638 : size_t f_size = 0;
639 : flags_t f_mask = 0;
640 : };
641 :
642 :
643 :
644 :
645 : class structure;
646 : typedef std::shared_ptr<structure> structure_pointer_t;
647 : typedef std::vector<structure_pointer_t> structure_vector_t;
648 :
649 : class field_t
650 : : public std::enable_shared_from_this<field_t>
651 : {
652 : public:
653 : typedef std::shared_ptr<field_t> pointer_t;
654 : typedef std::weak_ptr<field_t> weak_pointer_t;
655 : typedef std::map<std::string, pointer_t> map_t;
656 :
657 : static constexpr std::uint32_t FIELD_FLAG_VARIABLE_SIZE = 0x0001;
658 :
659 : field_t(struct_description_t const * description);
660 : field_t(field_t const & rhs) = delete;
661 : ~field_t();
662 :
663 : field_t operator = (field_t const & rhs) = delete;
664 :
665 : struct_description_t const * description() const;
666 : pointer_t next() const;
667 : void set_next(pointer_t next);
668 : pointer_t previous() const;
669 : void set_previous(pointer_t previous);
670 : pointer_t first() const;
671 : pointer_t last() const;
672 : struct_type_t type() const;
673 : ssize_t type_field_size() const;
674 : std::string field_name() const;
675 : std::string new_name() const; // for RENAMED fields
676 : std::uint32_t size() const;
677 : void set_size(std::uint32_t size);
678 : bool has_flags(std::uint32_t flags) const;
679 : std::uint32_t flags() const;
680 : void set_flags(std::uint32_t flags);
681 : void add_flags(std::uint32_t flags);
682 : void clear_flags(std::uint32_t flags);
683 : flag_definition::pointer_t find_flag_definition(std::string const & name) const;
684 : void add_flag_definition(std::string const & name, flag_definition::pointer_t bits);
685 : std::uint64_t offset() const;
686 : void set_offset(std::uint64_t offset);
687 : void adjust_offset(std::int64_t adjust);
688 : structure_vector_t const & sub_structures() const;
689 : structure_vector_t & sub_structures();
690 : structure_pointer_t operator [] (int idx) const;
691 : void set_sub_structures(structure_vector_t const & v);
692 :
693 : private:
694 : weak_pointer_t f_next = weak_pointer_t();
695 : weak_pointer_t f_previous = weak_pointer_t();
696 : struct_description_t const * f_description = nullptr;
697 : std::uint32_t f_size = 0;
698 : std::uint32_t f_flags = 0;
699 : std::uint64_t f_offset = 0;
700 : structure_vector_t f_sub_structures = structure_vector_t(); // for ARRAY# and STRUCTURE
701 : flag_definition::map_t f_flag_definitions = flag_definition::map_t(); // for BIT representing flags
702 : };
703 :
704 :
705 16 : class structure
706 : : public std::enable_shared_from_this<structure>
707 : {
708 : public:
709 : typedef std::shared_ptr<structure> pointer_t;
710 : typedef std::weak_ptr<structure> weak_pointer_t;
711 : typedef std::vector<pointer_t> vector_t;
712 :
713 : structure(struct_description_t const * descriptions, pointer_t parent = pointer_t());
714 : structure(structure const & rhs) = delete;
715 :
716 : structure & operator = (structure const & rhs) = delete;
717 :
718 : void set_block(
719 : block::pointer_t b
720 : , std::uint64_t offset
721 : , std::uint64_t size);
722 : void init_buffer();
723 : void set_virtual_buffer(
724 : virtual_buffer::pointer_t buffer
725 : , std::uint64_t start_offset);
726 : virtual_buffer::pointer_t get_virtual_buffer(reference_t & start_offset) const;
727 :
728 : size_t get_size() const;
729 : size_t get_current_size() const;
730 :
731 : pointer_t parent() const;
732 : field_t::pointer_t get_field(
733 : std::string const & field_name
734 : , struct_type_t type = struct_type_t::STRUCT_TYPE_END) const;
735 : flag_definition::pointer_t get_flag(
736 : std::string const & flag_name
737 : , field_t::pointer_t & f) const;
738 :
739 : // bits, int/uint, all sizes up to 64 bits, reference
740 : std::int64_t get_integer(std::string const & field_name) const;
741 : void set_integer(std::string const & field_name, std::int64_t value);
742 :
743 : std::uint64_t get_uinteger(std::string const & field_name) const;
744 : void set_uinteger(std::string const & field_name, std::uint64_t value);
745 :
746 : uint64_t get_bits(std::string const & flag_name) const;
747 : void set_bits(std::string const & flag_name, std::uint64_t value);
748 :
749 : // bits, int/uint, all sizes up to 512 bits
750 : int512_t get_large_integer(std::string const & field_name) const;
751 : void set_large_integer(std::string const & field_name, int512_t value);
752 :
753 : uint512_t get_large_uinteger(std::string const & field_name) const;
754 : void set_large_uinteger(std::string const & field_name, uint512_t value);
755 :
756 : // floating points (long double, even today, are not likely 128 bits, more like 80 to 102)
757 : float get_float32(std::string const & field_name) const;
758 : void set_float32(std::string const & field_name, float value);
759 :
760 : double get_float64(std::string const & field_name) const;
761 : void set_float64(std::string const & field_name, double value);
762 :
763 : long double get_float128(std::string const & field_name) const;
764 : void set_float128(std::string const & field_name, long double value);
765 :
766 : // strings/buffers
767 : std::string get_string(std::string const & field_name) const;
768 : void set_string(std::string const & field_name, std::string const & value);
769 :
770 : structure::pointer_t get_structure(std::string const & field_name) const;
771 : void set_structure(std::string const & field_name, structure::pointer_t & value);
772 :
773 : structure::vector_t get_array(std::string const & field_name) const;
774 : structure::pointer_t new_array_item(std::string const & field_name);
775 : void set_array(std::string const & field_name, structure::vector_t const & value);
776 :
777 : buffer_t get_buffer(std::string const & field_name) const;
778 : void set_buffer(std::string const & field_name, buffer_t const & value);
779 :
780 : void adjust_offsets(
781 : reference_t offset_cutoff
782 : , std::int64_t diff);
783 :
784 : private:
785 : std::uint64_t parse() const;
786 : std::uint64_t parse_descriptions(std::uint64_t offset) const;
787 : void verify_buffer_size();
788 : field_t::pointer_t find_field(std::string const & field_name);
789 :
790 : struct_description_t const * f_descriptions = nullptr;
791 : weak_pointer_t f_parent = weak_pointer_t();
792 : virtual_buffer::pointer_t f_buffer = virtual_buffer::pointer_t();
793 : reference_t f_start_offset = 0;
794 : mutable std::uint64_t f_original_size = 0;
795 : field_t::map_t f_fields_by_name = field_t::map_t();
796 : };
797 :
798 :
799 :
800 : std::ostream & operator << (std::ostream & out, version_t const & v);
801 :
802 :
803 :
804 : } // namespace snapdatabase
805 : // vim: ts=4 sw=4 et
|