LCOV - code coverage report
Current view: top level - home/snapwebsites/snapcpp/snapwebsites/snapdatabase/snapdatabase/data - structure.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 63 63 100.0 %
Date: 2019-12-15 17:13:15 Functions: 23 23 100.0 %
Legend: Lines: hit not hit

          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

Generated by: LCOV version 1.13