git repos / blockattack-game

blame: source/code/Libs/include/cereal/archives/json.hpp

normal view · raw

7a956470 sago007 2016-02-14 17:09 1
/*! \file json.hpp
7a956470 sago007 2016-02-14 17:09 2
    \brief JSON input and output archives */
7a956470 sago007 2016-02-14 17:09 3
/*
7a956470 sago007 2016-02-14 17:09 4
  Copyright (c) 2014, Randolph Voorhies, Shane Grant
7a956470 sago007 2016-02-14 17:09 5
  All rights reserved.
7a956470 sago007 2016-02-14 17:09 6
7a956470 sago007 2016-02-14 17:09 7
  Redistribution and use in source and binary forms, with or without
7a956470 sago007 2016-02-14 17:09 8
  modification, are permitted provided that the following conditions are met:
7a956470 sago007 2016-02-14 17:09 9
      * Redistributions of source code must retain the above copyright
7a956470 sago007 2016-02-14 17:09 10
        notice, this list of conditions and the following disclaimer.
7a956470 sago007 2016-02-14 17:09 11
      * Redistributions in binary form must reproduce the above copyright
7a956470 sago007 2016-02-14 17:09 12
        notice, this list of conditions and the following disclaimer in the
7a956470 sago007 2016-02-14 17:09 13
        documentation and/or other materials provided with the distribution.
7a956470 sago007 2016-02-14 17:09 14
      * Neither the name of cereal nor the
7a956470 sago007 2016-02-14 17:09 15
        names of its contributors may be used to endorse or promote products
7a956470 sago007 2016-02-14 17:09 16
        derived from this software without specific prior written permission.
7a956470 sago007 2016-02-14 17:09 17
7a956470 sago007 2016-02-14 17:09 18
  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
7a956470 sago007 2016-02-14 17:09 19
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
7a956470 sago007 2016-02-14 17:09 20
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
7a956470 sago007 2016-02-14 17:09 21
  DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
7a956470 sago007 2016-02-14 17:09 22
  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
7a956470 sago007 2016-02-14 17:09 23
  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
7a956470 sago007 2016-02-14 17:09 24
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
7a956470 sago007 2016-02-14 17:09 25
  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
7a956470 sago007 2016-02-14 17:09 26
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
7a956470 sago007 2016-02-14 17:09 27
  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
7a956470 sago007 2016-02-14 17:09 28
*/
7a956470 sago007 2016-02-14 17:09 29
#ifndef CEREAL_ARCHIVES_JSON_HPP_
7a956470 sago007 2016-02-14 17:09 30
#define CEREAL_ARCHIVES_JSON_HPP_
7a956470 sago007 2016-02-14 17:09 31
6c5f2c01 sago007 2017-03-15 17:56 32
#include "cereal/cereal.hpp"
6c5f2c01 sago007 2017-03-15 17:56 33
#include "cereal/details/util.hpp"
7a956470 sago007 2016-02-14 17:09 34
7a956470 sago007 2016-02-14 17:09 35
namespace cereal
7a956470 sago007 2016-02-14 17:09 36
{
7a956470 sago007 2016-02-14 17:09 37
  //! An exception thrown when rapidjson fails an internal assertion
7a956470 sago007 2016-02-14 17:09 38
  /*! @ingroup Utility */
7a956470 sago007 2016-02-14 17:09 39
  struct RapidJSONException : Exception
7a956470 sago007 2016-02-14 17:09 40
  { RapidJSONException( const char * what_ ) : Exception( what_ ) {} };
7a956470 sago007 2016-02-14 17:09 41
}
7a956470 sago007 2016-02-14 17:09 42
8f94a7f5 sago007 2020-05-10 10:26 43
// Inform rapidjson that assert will throw
8f94a7f5 sago007 2020-05-10 10:26 44
#ifndef CEREAL_RAPIDJSON_ASSERT_THROWS
8f94a7f5 sago007 2020-05-10 10:26 45
#define CEREAL_RAPIDJSON_ASSERT_THROWS
8f94a7f5 sago007 2020-05-10 10:26 46
#endif // CEREAL_RAPIDJSON_ASSERT_THROWS
8f94a7f5 sago007 2020-05-10 10:26 47
7a956470 sago007 2016-02-14 17:09 48
// Override rapidjson assertions to throw exceptions by default
6c5f2c01 sago007 2017-03-15 17:56 49
#ifndef CEREAL_RAPIDJSON_ASSERT
6c5f2c01 sago007 2017-03-15 17:56 50
#define CEREAL_RAPIDJSON_ASSERT(x) if(!(x)){ \
7a956470 sago007 2016-02-14 17:09 51
  throw ::cereal::RapidJSONException("rapidjson internal assertion failure: " #x); }
7a956470 sago007 2016-02-14 17:09 52
#endif // RAPIDJSON_ASSERT
7a956470 sago007 2016-02-14 17:09 53
6c5f2c01 sago007 2017-03-15 17:56 54
// Enable support for parsing of nan, inf, -inf
8f94a7f5 sago007 2020-05-10 10:26 55
#ifndef CEREAL_RAPIDJSON_WRITE_DEFAULT_FLAGS
6c5f2c01 sago007 2017-03-15 17:56 56
#define CEREAL_RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNanAndInfFlag
8f94a7f5 sago007 2020-05-10 10:26 57
#endif
8f94a7f5 sago007 2020-05-10 10:26 58
8f94a7f5 sago007 2020-05-10 10:26 59
// Enable support for parsing of nan, inf, -inf
8f94a7f5 sago007 2020-05-10 10:26 60
#ifndef CEREAL_RAPIDJSON_PARSE_DEFAULT_FLAGS
6c5f2c01 sago007 2017-03-15 17:56 61
#define CEREAL_RAPIDJSON_PARSE_DEFAULT_FLAGS kParseFullPrecisionFlag | kParseNanAndInfFlag
8f94a7f5 sago007 2020-05-10 10:26 62
#endif
6c5f2c01 sago007 2017-03-15 17:56 63
6c5f2c01 sago007 2017-03-15 17:56 64
#include "cereal/external/rapidjson/prettywriter.h"
6c5f2c01 sago007 2017-03-15 17:56 65
#include "cereal/external/rapidjson/ostreamwrapper.h"
6c5f2c01 sago007 2017-03-15 17:56 66
#include "cereal/external/rapidjson/istreamwrapper.h"
6c5f2c01 sago007 2017-03-15 17:56 67
#include "cereal/external/rapidjson/document.h"
6c5f2c01 sago007 2017-03-15 17:56 68
#include "cereal/external/base64.hpp"
7a956470 sago007 2016-02-14 17:09 69
7a956470 sago007 2016-02-14 17:09 70
#include <limits>
7a956470 sago007 2016-02-14 17:09 71
#include <sstream>
7a956470 sago007 2016-02-14 17:09 72
#include <stack>
7a956470 sago007 2016-02-14 17:09 73
#include <vector>
7a956470 sago007 2016-02-14 17:09 74
#include <string>
7a956470 sago007 2016-02-14 17:09 75
7a956470 sago007 2016-02-14 17:09 76
namespace cereal
7a956470 sago007 2016-02-14 17:09 77
{
7a956470 sago007 2016-02-14 17:09 78
  // ######################################################################
7a956470 sago007 2016-02-14 17:09 79
  //! An output archive designed to save data to JSON
6c5f2c01 sago007 2017-03-15 17:56 80
  /*! This archive uses RapidJSON to build serialize data to JSON.
7a956470 sago007 2016-02-14 17:09 81
7a956470 sago007 2016-02-14 17:09 82
      JSON archives provides a human readable output but at decreased
7a956470 sago007 2016-02-14 17:09 83
      performance (both in time and space) compared to binary archives.
7a956470 sago007 2016-02-14 17:09 84
6c5f2c01 sago007 2017-03-15 17:56 85
      JSON archives are only guaranteed to finish flushing their contents
6c5f2c01 sago007 2017-03-15 17:56 86
      upon destruction and should thus be used in an RAII fashion.
6c5f2c01 sago007 2017-03-15 17:56 87
7a956470 sago007 2016-02-14 17:09 88
      JSON benefits greatly from name-value pairs, which if present, will
7a956470 sago007 2016-02-14 17:09 89
      name the nodes in the output.  If these are not present, each level
7a956470 sago007 2016-02-14 17:09 90
      of the output will be given an automatically generated delimited name.
7a956470 sago007 2016-02-14 17:09 91
7a956470 sago007 2016-02-14 17:09 92
      The precision of the output archive controls the number of decimals output
7a956470 sago007 2016-02-14 17:09 93
      for floating point numbers and should be sufficiently large (i.e. at least 20)
7a956470 sago007 2016-02-14 17:09 94
      if there is a desire to have binary equality between the numbers output and
7a956470 sago007 2016-02-14 17:09 95
      those read in.  In general you should expect a loss of precision when going
7a956470 sago007 2016-02-14 17:09 96
      from floating point to text and back.
7a956470 sago007 2016-02-14 17:09 97
7a956470 sago007 2016-02-14 17:09 98
      JSON archives do not output the size information for any dynamically sized structure
7a956470 sago007 2016-02-14 17:09 99
      and instead infer it from the number of children for a node.  This means that data
7a956470 sago007 2016-02-14 17:09 100
      can be hand edited for dynamic sized structures and will still be readable.  This
7a956470 sago007 2016-02-14 17:09 101
      is accomplished through the cereal::SizeTag object, which will cause the archive
7a956470 sago007 2016-02-14 17:09 102
      to output the data as a JSON array (e.g. marked by [] instead of {}), which indicates
7a956470 sago007 2016-02-14 17:09 103
      that the container is variable sized and may be edited.
7a956470 sago007 2016-02-14 17:09 104
7a956470 sago007 2016-02-14 17:09 105
      \ingroup Archives */
7a956470 sago007 2016-02-14 17:09 106
  class JSONOutputArchive : public OutputArchive<JSONOutputArchive>, public traits::TextArchive
7a956470 sago007 2016-02-14 17:09 107
  {
7a956470 sago007 2016-02-14 17:09 108
    enum class NodeType { StartObject, InObject, StartArray, InArray };
7a956470 sago007 2016-02-14 17:09 109
6c5f2c01 sago007 2017-03-15 17:56 110
    using WriteStream = CEREAL_RAPIDJSON_NAMESPACE::OStreamWrapper;
6c5f2c01 sago007 2017-03-15 17:56 111
    using JSONWriter = CEREAL_RAPIDJSON_NAMESPACE::PrettyWriter<WriteStream>;
7a956470 sago007 2016-02-14 17:09 112
7a956470 sago007 2016-02-14 17:09 113
    public:
7a956470 sago007 2016-02-14 17:09 114
      /*! @name Common Functionality
7a956470 sago007 2016-02-14 17:09 115
          Common use cases for directly interacting with an JSONOutputArchive */
7a956470 sago007 2016-02-14 17:09 116
      //! @{
7a956470 sago007 2016-02-14 17:09 117
7a956470 sago007 2016-02-14 17:09 118
      //! A class containing various advanced options for the JSON archive
7a956470 sago007 2016-02-14 17:09 119
      class Options
7a956470 sago007 2016-02-14 17:09 120
      {
7a956470 sago007 2016-02-14 17:09 121
        public:
7a956470 sago007 2016-02-14 17:09 122
          //! Default options
7a956470 sago007 2016-02-14 17:09 123
          static Options Default(){ return Options(); }
7a956470 sago007 2016-02-14 17:09 124
7a956470 sago007 2016-02-14 17:09 125
          //! Default options with no indentation
6c5f2c01 sago007 2017-03-15 17:56 126
          static Options NoIndent(){ return Options( JSONWriter::kDefaultMaxDecimalPlaces, IndentChar::space, 0 ); }
7a956470 sago007 2016-02-14 17:09 127
7a956470 sago007 2016-02-14 17:09 128
          //! The character to use for indenting
7a956470 sago007 2016-02-14 17:09 129
          enum class IndentChar : char
7a956470 sago007 2016-02-14 17:09 130
          {
7a956470 sago007 2016-02-14 17:09 131
            space = ' ',
7a956470 sago007 2016-02-14 17:09 132
            tab = '\t',
7a956470 sago007 2016-02-14 17:09 133
            newline = '\n',
7a956470 sago007 2016-02-14 17:09 134
            carriage_return = '\r'
7a956470 sago007 2016-02-14 17:09 135
          };
7a956470 sago007 2016-02-14 17:09 136
7a956470 sago007 2016-02-14 17:09 137
          //! Specify specific options for the JSONOutputArchive
7a956470 sago007 2016-02-14 17:09 138
          /*! @param precision The precision used for floating point numbers
7a956470 sago007 2016-02-14 17:09 139
              @param indentChar The type of character to indent with
7a956470 sago007 2016-02-14 17:09 140
              @param indentLength The number of indentChar to use for indentation
7a956470 sago007 2016-02-14 17:09 141
                             (0 corresponds to no indentation) */
6c5f2c01 sago007 2017-03-15 17:56 142
          explicit Options( int precision = JSONWriter::kDefaultMaxDecimalPlaces,
7a956470 sago007 2016-02-14 17:09 143
                            IndentChar indentChar = IndentChar::space,
7a956470 sago007 2016-02-14 17:09 144
                            unsigned int indentLength = 4 ) :
7a956470 sago007 2016-02-14 17:09 145
            itsPrecision( precision ),
7a956470 sago007 2016-02-14 17:09 146
            itsIndentChar( static_cast<char>(indentChar) ),
7a956470 sago007 2016-02-14 17:09 147
            itsIndentLength( indentLength ) { }
7a956470 sago007 2016-02-14 17:09 148
7a956470 sago007 2016-02-14 17:09 149
        private:
7a956470 sago007 2016-02-14 17:09 150
          friend class JSONOutputArchive;
7a956470 sago007 2016-02-14 17:09 151
          int itsPrecision;
7a956470 sago007 2016-02-14 17:09 152
          char itsIndentChar;
7a956470 sago007 2016-02-14 17:09 153
          unsigned int itsIndentLength;
7a956470 sago007 2016-02-14 17:09 154
      };
7a956470 sago007 2016-02-14 17:09 155
7a956470 sago007 2016-02-14 17:09 156
      //! Construct, outputting to the provided stream
7a956470 sago007 2016-02-14 17:09 157
      /*! @param stream The stream to output to.
7a956470 sago007 2016-02-14 17:09 158
          @param options The JSON specific options to use.  See the Options struct
7a956470 sago007 2016-02-14 17:09 159
                         for the values of default parameters */
7a956470 sago007 2016-02-14 17:09 160
      JSONOutputArchive(std::ostream & stream, Options const & options = Options::Default() ) :
7a956470 sago007 2016-02-14 17:09 161
        OutputArchive<JSONOutputArchive>(this),
7a956470 sago007 2016-02-14 17:09 162
        itsWriteStream(stream),
6c5f2c01 sago007 2017-03-15 17:56 163
        itsWriter(itsWriteStream),
7a956470 sago007 2016-02-14 17:09 164
        itsNextName(nullptr)
7a956470 sago007 2016-02-14 17:09 165
      {
6c5f2c01 sago007 2017-03-15 17:56 166
        itsWriter.SetMaxDecimalPlaces( options.itsPrecision );
7a956470 sago007 2016-02-14 17:09 167
        itsWriter.SetIndent( options.itsIndentChar, options.itsIndentLength );
7a956470 sago007 2016-02-14 17:09 168
        itsNameCounter.push(0);
7a956470 sago007 2016-02-14 17:09 169
        itsNodeStack.push(NodeType::StartObject);
7a956470 sago007 2016-02-14 17:09 170
      }
7a956470 sago007 2016-02-14 17:09 171
7a956470 sago007 2016-02-14 17:09 172
      //! Destructor, flushes the JSON
6c5f2c01 sago007 2017-03-15 17:56 173
      ~JSONOutputArchive() CEREAL_NOEXCEPT
7a956470 sago007 2016-02-14 17:09 174
      {
7a956470 sago007 2016-02-14 17:09 175
        if (itsNodeStack.top() == NodeType::InObject)
7a956470 sago007 2016-02-14 17:09 176
          itsWriter.EndObject();
6c5f2c01 sago007 2017-03-15 17:56 177
        else if (itsNodeStack.top() == NodeType::InArray)
6c5f2c01 sago007 2017-03-15 17:56 178
          itsWriter.EndArray();
7a956470 sago007 2016-02-14 17:09 179
      }
7a956470 sago007 2016-02-14 17:09 180
7a956470 sago007 2016-02-14 17:09 181
      //! Saves some binary data, encoded as a base64 string, with an optional name
7a956470 sago007 2016-02-14 17:09 182
      /*! This will create a new node, optionally named, and insert a value that consists of
7a956470 sago007 2016-02-14 17:09 183
          the data encoded as a base64 string */
7a956470 sago007 2016-02-14 17:09 184
      void saveBinaryValue( const void * data, size_t size, const char * name = nullptr )
7a956470 sago007 2016-02-14 17:09 185
      {
7a956470 sago007 2016-02-14 17:09 186
        setNextName( name );
7a956470 sago007 2016-02-14 17:09 187
        writeName();
7a956470 sago007 2016-02-14 17:09 188
7a956470 sago007 2016-02-14 17:09 189
        auto base64string = base64::encode( reinterpret_cast<const unsigned char *>( data ), size );
7a956470 sago007 2016-02-14 17:09 190
        saveValue( base64string );
7a956470 sago007 2016-02-14 17:09 191
      };
7a956470 sago007 2016-02-14 17:09 192
7a956470 sago007 2016-02-14 17:09 193
      //! @}
7a956470 sago007 2016-02-14 17:09 194
      /*! @name Internal Functionality
7a956470 sago007 2016-02-14 17:09 195
          Functionality designed for use by those requiring control over the inner mechanisms of
7a956470 sago007 2016-02-14 17:09 196
          the JSONOutputArchive */
7a956470 sago007 2016-02-14 17:09 197
      //! @{
7a956470 sago007 2016-02-14 17:09 198
7a956470 sago007 2016-02-14 17:09 199
      //! Starts a new node in the JSON output
7a956470 sago007 2016-02-14 17:09 200
      /*! The node can optionally be given a name by calling setNextName prior
7a956470 sago007 2016-02-14 17:09 201
          to creating the node
7a956470 sago007 2016-02-14 17:09 202
7a956470 sago007 2016-02-14 17:09 203
          Nodes only need to be started for types that are themselves objects or arrays */
7a956470 sago007 2016-02-14 17:09 204
      void startNode()
7a956470 sago007 2016-02-14 17:09 205
      {
7a956470 sago007 2016-02-14 17:09 206
        writeName();
7a956470 sago007 2016-02-14 17:09 207
        itsNodeStack.push(NodeType::StartObject);
7a956470 sago007 2016-02-14 17:09 208
        itsNameCounter.push(0);
7a956470 sago007 2016-02-14 17:09 209
      }
7a956470 sago007 2016-02-14 17:09 210
7a956470 sago007 2016-02-14 17:09 211
      //! Designates the most recently added node as finished
7a956470 sago007 2016-02-14 17:09 212
      void finishNode()
7a956470 sago007 2016-02-14 17:09 213
      {
7a956470 sago007 2016-02-14 17:09 214
        // if we ended up serializing an empty object or array, writeName
7a956470 sago007 2016-02-14 17:09 215
        // will never have been called - so start and then immediately end
7a956470 sago007 2016-02-14 17:09 216
        // the object/array.
7a956470 sago007 2016-02-14 17:09 217
        //
7a956470 sago007 2016-02-14 17:09 218
        // We'll also end any object/arrays we happen to be in
7a956470 sago007 2016-02-14 17:09 219
        switch(itsNodeStack.top())
7a956470 sago007 2016-02-14 17:09 220
        {
7a956470 sago007 2016-02-14 17:09 221
          case NodeType::StartArray:
7a956470 sago007 2016-02-14 17:09 222
            itsWriter.StartArray();
8f94a7f5 sago007 2020-05-10 10:26 223
            // fall through
7a956470 sago007 2016-02-14 17:09 224
          case NodeType::InArray:
7a956470 sago007 2016-02-14 17:09 225
            itsWriter.EndArray();
7a956470 sago007 2016-02-14 17:09 226
            break;
7a956470 sago007 2016-02-14 17:09 227
          case NodeType::StartObject:
7a956470 sago007 2016-02-14 17:09 228
            itsWriter.StartObject();
8f94a7f5 sago007 2020-05-10 10:26 229
            // fall through
7a956470 sago007 2016-02-14 17:09 230
          case NodeType::InObject:
7a956470 sago007 2016-02-14 17:09 231
            itsWriter.EndObject();
7a956470 sago007 2016-02-14 17:09 232
            break;
7a956470 sago007 2016-02-14 17:09 233
        }
7a956470 sago007 2016-02-14 17:09 234
7a956470 sago007 2016-02-14 17:09 235
        itsNodeStack.pop();
7a956470 sago007 2016-02-14 17:09 236
        itsNameCounter.pop();
7a956470 sago007 2016-02-14 17:09 237
      }
7a956470 sago007 2016-02-14 17:09 238
7a956470 sago007 2016-02-14 17:09 239
      //! Sets the name for the next node created with startNode
7a956470 sago007 2016-02-14 17:09 240
      void setNextName( const char * name )
7a956470 sago007 2016-02-14 17:09 241
      {
7a956470 sago007 2016-02-14 17:09 242
        itsNextName = name;
7a956470 sago007 2016-02-14 17:09 243
      }
7a956470 sago007 2016-02-14 17:09 244
7a956470 sago007 2016-02-14 17:09 245
      //! Saves a bool to the current node
6c5f2c01 sago007 2017-03-15 17:56 246
      void saveValue(bool b)                { itsWriter.Bool(b);                                                         }
7a956470 sago007 2016-02-14 17:09 247
      //! Saves an int to the current node
7a956470 sago007 2016-02-14 17:09 248
      void saveValue(int i)                 { itsWriter.Int(i);                                                          }
7a956470 sago007 2016-02-14 17:09 249
      //! Saves a uint to the current node
7a956470 sago007 2016-02-14 17:09 250
      void saveValue(unsigned u)            { itsWriter.Uint(u);                                                         }
7a956470 sago007 2016-02-14 17:09 251
      //! Saves an int64 to the current node
7a956470 sago007 2016-02-14 17:09 252
      void saveValue(int64_t i64)           { itsWriter.Int64(i64);                                                      }
7a956470 sago007 2016-02-14 17:09 253
      //! Saves a uint64 to the current node
7a956470 sago007 2016-02-14 17:09 254
      void saveValue(uint64_t u64)          { itsWriter.Uint64(u64);                                                     }
7a956470 sago007 2016-02-14 17:09 255
      //! Saves a double to the current node
7a956470 sago007 2016-02-14 17:09 256
      void saveValue(double d)              { itsWriter.Double(d);                                                       }
7a956470 sago007 2016-02-14 17:09 257
      //! Saves a string to the current node
6c5f2c01 sago007 2017-03-15 17:56 258
      void saveValue(std::string const & s) { itsWriter.String(s.c_str(), static_cast<CEREAL_RAPIDJSON_NAMESPACE::SizeType>( s.size() )); }
7a956470 sago007 2016-02-14 17:09 259
      //! Saves a const char * to the current node
7a956470 sago007 2016-02-14 17:09 260
      void saveValue(char const * s)        { itsWriter.String(s);                                                       }
6c5f2c01 sago007 2017-03-15 17:56 261
      //! Saves a nullptr to the current node
6c5f2c01 sago007 2017-03-15 17:56 262
      void saveValue(std::nullptr_t)        { itsWriter.Null();                                                          }
7a956470 sago007 2016-02-14 17:09 263
7a956470 sago007 2016-02-14 17:09 264
    private:
7a956470 sago007 2016-02-14 17:09 265
      // Some compilers/OS have difficulty disambiguating the above for various flavors of longs, so we provide
7a956470 sago007 2016-02-14 17:09 266
      // special overloads to handle these cases.
7a956470 sago007 2016-02-14 17:09 267
7a956470 sago007 2016-02-14 17:09 268
      //! 32 bit signed long saving to current node
7a956470 sago007 2016-02-14 17:09 269
      template <class T, traits::EnableIf<sizeof(T) == sizeof(std::int32_t),
7a956470 sago007 2016-02-14 17:09 270
                                          std::is_signed<T>::value> = traits::sfinae> inline
7a956470 sago007 2016-02-14 17:09 271
      void saveLong(T l){ saveValue( static_cast<std::int32_t>( l ) ); }
7a956470 sago007 2016-02-14 17:09 272
7a956470 sago007 2016-02-14 17:09 273
      //! non 32 bit signed long saving to current node
7a956470 sago007 2016-02-14 17:09 274
      template <class T, traits::EnableIf<sizeof(T) != sizeof(std::int32_t),
7a956470 sago007 2016-02-14 17:09 275
                                          std::is_signed<T>::value> = traits::sfinae> inline
7a956470 sago007 2016-02-14 17:09 276
      void saveLong(T l){ saveValue( static_cast<std::int64_t>( l ) ); }
7a956470 sago007 2016-02-14 17:09 277
7a956470 sago007 2016-02-14 17:09 278
      //! 32 bit unsigned long saving to current node
7a956470 sago007 2016-02-14 17:09 279
      template <class T, traits::EnableIf<sizeof(T) == sizeof(std::int32_t),
7a956470 sago007 2016-02-14 17:09 280
                                          std::is_unsigned<T>::value> = traits::sfinae> inline
7a956470 sago007 2016-02-14 17:09 281
      void saveLong(T lu){ saveValue( static_cast<std::uint32_t>( lu ) ); }
7a956470 sago007 2016-02-14 17:09 282
7a956470 sago007 2016-02-14 17:09 283
      //! non 32 bit unsigned long saving to current node
7a956470 sago007 2016-02-14 17:09 284
      template <class T, traits::EnableIf<sizeof(T) != sizeof(std::int32_t),
7a956470 sago007 2016-02-14 17:09 285
                                          std::is_unsigned<T>::value> = traits::sfinae> inline
7a956470 sago007 2016-02-14 17:09 286
      void saveLong(T lu){ saveValue( static_cast<std::uint64_t>( lu ) ); }
7a956470 sago007 2016-02-14 17:09 287
7a956470 sago007 2016-02-14 17:09 288
    public:
7a956470 sago007 2016-02-14 17:09 289
#ifdef _MSC_VER
7a956470 sago007 2016-02-14 17:09 290
      //! MSVC only long overload to current node
7a956470 sago007 2016-02-14 17:09 291
      void saveValue( unsigned long lu ){ saveLong( lu ); };
7a956470 sago007 2016-02-14 17:09 292
#else // _MSC_VER
7a956470 sago007 2016-02-14 17:09 293
      //! Serialize a long if it would not be caught otherwise
7a956470 sago007 2016-02-14 17:09 294
      template <class T, traits::EnableIf<std::is_same<T, long>::value,
7a956470 sago007 2016-02-14 17:09 295
                                          !std::is_same<T, std::int32_t>::value,
7a956470 sago007 2016-02-14 17:09 296
                                          !std::is_same<T, std::int64_t>::value> = traits::sfinae> inline
7a956470 sago007 2016-02-14 17:09 297
      void saveValue( T t ){ saveLong( t ); }
7a956470 sago007 2016-02-14 17:09 298
7a956470 sago007 2016-02-14 17:09 299
      //! Serialize an unsigned long if it would not be caught otherwise
7a956470 sago007 2016-02-14 17:09 300
      template <class T, traits::EnableIf<std::is_same<T, unsigned long>::value,
7a956470 sago007 2016-02-14 17:09 301
                                          !std::is_same<T, std::uint32_t>::value,
7a956470 sago007 2016-02-14 17:09 302
                                          !std::is_same<T, std::uint64_t>::value> = traits::sfinae> inline
7a956470 sago007 2016-02-14 17:09 303
      void saveValue( T t ){ saveLong( t ); }
7a956470 sago007 2016-02-14 17:09 304
#endif // _MSC_VER
7a956470 sago007 2016-02-14 17:09 305
7a956470 sago007 2016-02-14 17:09 306
      //! Save exotic arithmetic as strings to current node
7a956470 sago007 2016-02-14 17:09 307
      /*! Handles long long (if distinct from other types), unsigned long (if distinct), and long double */
7a956470 sago007 2016-02-14 17:09 308
      template <class T, traits::EnableIf<std::is_arithmetic<T>::value,
7a956470 sago007 2016-02-14 17:09 309
                                          !std::is_same<T, long>::value,
7a956470 sago007 2016-02-14 17:09 310
                                          !std::is_same<T, unsigned long>::value,
7a956470 sago007 2016-02-14 17:09 311
                                          !std::is_same<T, std::int64_t>::value,
7a956470 sago007 2016-02-14 17:09 312
                                          !std::is_same<T, std::uint64_t>::value,
7a956470 sago007 2016-02-14 17:09 313
                                          (sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long))> = traits::sfinae> inline
7a956470 sago007 2016-02-14 17:09 314
      void saveValue(T const & t)
7a956470 sago007 2016-02-14 17:09 315
      {
7a956470 sago007 2016-02-14 17:09 316
        std::stringstream ss; ss.precision( std::numeric_limits<long double>::max_digits10 );
7a956470 sago007 2016-02-14 17:09 317
        ss << t;
7a956470 sago007 2016-02-14 17:09 318
        saveValue( ss.str() );
7a956470 sago007 2016-02-14 17:09 319
      }
7a956470 sago007 2016-02-14 17:09 320
7a956470 sago007 2016-02-14 17:09 321
      //! Write the name of the upcoming node and prepare object/array state
7a956470 sago007 2016-02-14 17:09 322
      /*! Since writeName is called for every value that is output, regardless of
7a956470 sago007 2016-02-14 17:09 323
          whether it has a name or not, it is the place where we will do a deferred
7a956470 sago007 2016-02-14 17:09 324
          check of our node state and decide whether we are in an array or an object.
7a956470 sago007 2016-02-14 17:09 325
7a956470 sago007 2016-02-14 17:09 326
          The general workflow of saving to the JSON archive is:
7a956470 sago007 2016-02-14 17:09 327
7a956470 sago007 2016-02-14 17:09 328
            1. (optional) Set the name for the next node to be created, usually done by an NVP
7a956470 sago007 2016-02-14 17:09 329
            2. Start the node
7a956470 sago007 2016-02-14 17:09 330
            3. (if there is data to save) Write the name of the node (this function)
7a956470 sago007 2016-02-14 17:09 331
            4. (if there is data to save) Save the data (with saveValue)
7a956470 sago007 2016-02-14 17:09 332
            5. Finish the node
7a956470 sago007 2016-02-14 17:09 333
          */
7a956470 sago007 2016-02-14 17:09 334
      void writeName()
7a956470 sago007 2016-02-14 17:09 335
      {
7a956470 sago007 2016-02-14 17:09 336
        NodeType const & nodeType = itsNodeStack.top();
7a956470 sago007 2016-02-14 17:09 337
7a956470 sago007 2016-02-14 17:09 338
        // Start up either an object or an array, depending on state
7a956470 sago007 2016-02-14 17:09 339
        if(nodeType == NodeType::StartArray)
7a956470 sago007 2016-02-14 17:09 340
        {
7a956470 sago007 2016-02-14 17:09 341
          itsWriter.StartArray();
7a956470 sago007 2016-02-14 17:09 342
          itsNodeStack.top() = NodeType::InArray;
7a956470 sago007 2016-02-14 17:09 343
        }
7a956470 sago007 2016-02-14 17:09 344
        else if(nodeType == NodeType::StartObject)
7a956470 sago007 2016-02-14 17:09 345
        {
7a956470 sago007 2016-02-14 17:09 346
          itsNodeStack.top() = NodeType::InObject;
7a956470 sago007 2016-02-14 17:09 347
          itsWriter.StartObject();
7a956470 sago007 2016-02-14 17:09 348
        }
7a956470 sago007 2016-02-14 17:09 349
7a956470 sago007 2016-02-14 17:09 350
        // Array types do not output names
7a956470 sago007 2016-02-14 17:09 351
        if(nodeType == NodeType::InArray) return;
7a956470 sago007 2016-02-14 17:09 352
7a956470 sago007 2016-02-14 17:09 353
        if(itsNextName == nullptr)
7a956470 sago007 2016-02-14 17:09 354
        {
7a956470 sago007 2016-02-14 17:09 355
          std::string name = "value" + std::to_string( itsNameCounter.top()++ ) + "\0";
7a956470 sago007 2016-02-14 17:09 356
          saveValue(name);
7a956470 sago007 2016-02-14 17:09 357
        }
7a956470 sago007 2016-02-14 17:09 358
        else
7a956470 sago007 2016-02-14 17:09 359
        {
7a956470 sago007 2016-02-14 17:09 360
          saveValue(itsNextName);
7a956470 sago007 2016-02-14 17:09 361
          itsNextName = nullptr;
7a956470 sago007 2016-02-14 17:09 362
        }
7a956470 sago007 2016-02-14 17:09 363
      }
7a956470 sago007 2016-02-14 17:09 364
7a956470 sago007 2016-02-14 17:09 365
      //! Designates that the current node should be output as an array, not an object
7a956470 sago007 2016-02-14 17:09 366
      void makeArray()
7a956470 sago007 2016-02-14 17:09 367
      {
7a956470 sago007 2016-02-14 17:09 368
        itsNodeStack.top() = NodeType::StartArray;
7a956470 sago007 2016-02-14 17:09 369
      }
7a956470 sago007 2016-02-14 17:09 370
7a956470 sago007 2016-02-14 17:09 371
      //! @}
7a956470 sago007 2016-02-14 17:09 372
7a956470 sago007 2016-02-14 17:09 373
    private:
7a956470 sago007 2016-02-14 17:09 374
      WriteStream itsWriteStream;          //!< Rapidjson write stream
7a956470 sago007 2016-02-14 17:09 375
      JSONWriter itsWriter;                //!< Rapidjson writer
7a956470 sago007 2016-02-14 17:09 376
      char const * itsNextName;            //!< The next name
7a956470 sago007 2016-02-14 17:09 377
      std::stack<uint32_t> itsNameCounter; //!< Counter for creating unique names for unnamed nodes
7a956470 sago007 2016-02-14 17:09 378
      std::stack<NodeType> itsNodeStack;
7a956470 sago007 2016-02-14 17:09 379
  }; // JSONOutputArchive
7a956470 sago007 2016-02-14 17:09 380
7a956470 sago007 2016-02-14 17:09 381
  // ######################################################################
7a956470 sago007 2016-02-14 17:09 382
  //! An input archive designed to load data from JSON
7a956470 sago007 2016-02-14 17:09 383
  /*! This archive uses RapidJSON to read in a JSON archive.
7a956470 sago007 2016-02-14 17:09 384
6c5f2c01 sago007 2017-03-15 17:56 385
      As with the output JSON archive, the preferred way to use this archive is in
6c5f2c01 sago007 2017-03-15 17:56 386
      an RAII fashion, ensuring its destruction after all data has been read.
6c5f2c01 sago007 2017-03-15 17:56 387
7a956470 sago007 2016-02-14 17:09 388
      Input JSON should have been produced by the JSONOutputArchive.  Data can
7a956470 sago007 2016-02-14 17:09 389
      only be added to dynamically sized containers (marked by JSON arrays) -
7a956470 sago007 2016-02-14 17:09 390
      the input archive will determine their size by looking at the number of child nodes.
7a956470 sago007 2016-02-14 17:09 391
      Only JSON originating from a JSONOutputArchive is officially supported, but data
7a956470 sago007 2016-02-14 17:09 392
      from other sources may work if properly formatted.
7a956470 sago007 2016-02-14 17:09 393
7a956470 sago007 2016-02-14 17:09 394
      The JSONInputArchive does not require that nodes are loaded in the same
7a956470 sago007 2016-02-14 17:09 395
      order they were saved by JSONOutputArchive.  Using name value pairs (NVPs),
7a956470 sago007 2016-02-14 17:09 396
      it is possible to load in an out of order fashion or otherwise skip/select
7a956470 sago007 2016-02-14 17:09 397
      specific nodes to load.
7a956470 sago007 2016-02-14 17:09 398
7a956470 sago007 2016-02-14 17:09 399
      The default behavior of the input archive is to read sequentially starting
7a956470 sago007 2016-02-14 17:09 400
      with the first node and exploring its children.  When a given NVP does
7a956470 sago007 2016-02-14 17:09 401
      not match the read in name for a node, the archive will search for that
7a956470 sago007 2016-02-14 17:09 402
      node at the current level and load it if it exists.  After loading an out of
7a956470 sago007 2016-02-14 17:09 403
      order node, the archive will then proceed back to loading sequentially from
7a956470 sago007 2016-02-14 17:09 404
      its new position.
7a956470 sago007 2016-02-14 17:09 405
7a956470 sago007 2016-02-14 17:09 406
      Consider this simple example where loading of some data is skipped:
7a956470 sago007 2016-02-14 17:09 407
7a956470 sago007 2016-02-14 17:09 408
      @code{cpp}
7a956470 sago007 2016-02-14 17:09 409
      // imagine the input file has someData(1-9) saved in order at the top level node
7a956470 sago007 2016-02-14 17:09 410
      ar( someData1, someData2, someData3 );        // XML loads in the order it sees in the file
7a956470 sago007 2016-02-14 17:09 411
      ar( cereal::make_nvp( "hello", someData6 ) ); // NVP given does not
7a956470 sago007 2016-02-14 17:09 412
                                                    // match expected NVP name, so we search
7a956470 sago007 2016-02-14 17:09 413
                                                    // for the given NVP and load that value
7a956470 sago007 2016-02-14 17:09 414
      ar( someData7, someData8, someData9 );        // with no NVP given, loading resumes at its
7a956470 sago007 2016-02-14 17:09 415
                                                    // current location, proceeding sequentially
7a956470 sago007 2016-02-14 17:09 416
      @endcode
7a956470 sago007 2016-02-14 17:09 417
7a956470 sago007 2016-02-14 17:09 418
      \ingroup Archives */
7a956470 sago007 2016-02-14 17:09 419
  class JSONInputArchive : public InputArchive<JSONInputArchive>, public traits::TextArchive
7a956470 sago007 2016-02-14 17:09 420
  {
7a956470 sago007 2016-02-14 17:09 421
    private:
6c5f2c01 sago007 2017-03-15 17:56 422
      using ReadStream = CEREAL_RAPIDJSON_NAMESPACE::IStreamWrapper;
6c5f2c01 sago007 2017-03-15 17:56 423
      typedef CEREAL_RAPIDJSON_NAMESPACE::GenericValue<CEREAL_RAPIDJSON_NAMESPACE::UTF8<>> JSONValue;
7a956470 sago007 2016-02-14 17:09 424
      typedef JSONValue::ConstMemberIterator MemberIterator;
7a956470 sago007 2016-02-14 17:09 425
      typedef JSONValue::ConstValueIterator ValueIterator;
6c5f2c01 sago007 2017-03-15 17:56 426
      typedef CEREAL_RAPIDJSON_NAMESPACE::Document::GenericValue GenericValue;
7a956470 sago007 2016-02-14 17:09 427
7a956470 sago007 2016-02-14 17:09 428
    public:
7a956470 sago007 2016-02-14 17:09 429
      /*! @name Common Functionality
7a956470 sago007 2016-02-14 17:09 430
          Common use cases for directly interacting with an JSONInputArchive */
7a956470 sago007 2016-02-14 17:09 431
      //! @{
7a956470 sago007 2016-02-14 17:09 432
7a956470 sago007 2016-02-14 17:09 433
      //! Construct, reading from the provided stream
7a956470 sago007 2016-02-14 17:09 434
      /*! @param stream The stream to read from */
7a956470 sago007 2016-02-14 17:09 435
      JSONInputArchive(std::istream & stream) :
7a956470 sago007 2016-02-14 17:09 436
        InputArchive<JSONInputArchive>(this),
7a956470 sago007 2016-02-14 17:09 437
        itsNextName( nullptr ),
7a956470 sago007 2016-02-14 17:09 438
        itsReadStream(stream)
7a956470 sago007 2016-02-14 17:09 439
      {
6c5f2c01 sago007 2017-03-15 17:56 440
        itsDocument.ParseStream<>(itsReadStream);
6c5f2c01 sago007 2017-03-15 17:56 441
        if (itsDocument.IsArray())
6c5f2c01 sago007 2017-03-15 17:56 442
          itsIteratorStack.emplace_back(itsDocument.Begin(), itsDocument.End());
6c5f2c01 sago007 2017-03-15 17:56 443
        else
6c5f2c01 sago007 2017-03-15 17:56 444
          itsIteratorStack.emplace_back(itsDocument.MemberBegin(), itsDocument.MemberEnd());
7a956470 sago007 2016-02-14 17:09 445
      }
7a956470 sago007 2016-02-14 17:09 446
6c5f2c01 sago007 2017-03-15 17:56 447
      ~JSONInputArchive() CEREAL_NOEXCEPT = default;
6c5f2c01 sago007 2017-03-15 17:56 448
7a956470 sago007 2016-02-14 17:09 449
      //! Loads some binary data, encoded as a base64 string
7a956470 sago007 2016-02-14 17:09 450
      /*! This will automatically start and finish a node to load the data, and can be called directly by
7a956470 sago007 2016-02-14 17:09 451
          users.
7a956470 sago007 2016-02-14 17:09 452
7a956470 sago007 2016-02-14 17:09 453
          Note that this follows the same ordering rules specified in the class description in regards
7a956470 sago007 2016-02-14 17:09 454
          to loading in/out of order */
7a956470 sago007 2016-02-14 17:09 455
      void loadBinaryValue( void * data, size_t size, const char * name = nullptr )
7a956470 sago007 2016-02-14 17:09 456
      {
7a956470 sago007 2016-02-14 17:09 457
        itsNextName = name;
7a956470 sago007 2016-02-14 17:09 458
7a956470 sago007 2016-02-14 17:09 459
        std::string encoded;
7a956470 sago007 2016-02-14 17:09 460
        loadValue( encoded );
7a956470 sago007 2016-02-14 17:09 461
        auto decoded = base64::decode( encoded );
7a956470 sago007 2016-02-14 17:09 462
7a956470 sago007 2016-02-14 17:09 463
        if( size != decoded.size() )
7a956470 sago007 2016-02-14 17:09 464
          throw Exception("Decoded binary data size does not match specified size");
7a956470 sago007 2016-02-14 17:09 465
7a956470 sago007 2016-02-14 17:09 466
        std::memcpy( data, decoded.data(), decoded.size() );
7a956470 sago007 2016-02-14 17:09 467
        itsNextName = nullptr;
7a956470 sago007 2016-02-14 17:09 468
      };
7a956470 sago007 2016-02-14 17:09 469
7a956470 sago007 2016-02-14 17:09 470
    private:
7a956470 sago007 2016-02-14 17:09 471
      //! @}
7a956470 sago007 2016-02-14 17:09 472
      /*! @name Internal Functionality
7a956470 sago007 2016-02-14 17:09 473
          Functionality designed for use by those requiring control over the inner mechanisms of
7a956470 sago007 2016-02-14 17:09 474
          the JSONInputArchive */
7a956470 sago007 2016-02-14 17:09 475
      //! @{
7a956470 sago007 2016-02-14 17:09 476
7a956470 sago007 2016-02-14 17:09 477
      //! An internal iterator that handles both array and object types
7a956470 sago007 2016-02-14 17:09 478
      /*! This class is a variant and holds both types of iterators that
7a956470 sago007 2016-02-14 17:09 479
          rapidJSON supports - one for arrays and one for objects. */
7a956470 sago007 2016-02-14 17:09 480
      class Iterator
7a956470 sago007 2016-02-14 17:09 481
      {
7a956470 sago007 2016-02-14 17:09 482
        public:
7a956470 sago007 2016-02-14 17:09 483
          Iterator() : itsIndex( 0 ), itsType(Null_) {}
7a956470 sago007 2016-02-14 17:09 484
7a956470 sago007 2016-02-14 17:09 485
          Iterator(MemberIterator begin, MemberIterator end) :
7a956470 sago007 2016-02-14 17:09 486
            itsMemberItBegin(begin), itsMemberItEnd(end), itsIndex(0), itsType(Member)
6c5f2c01 sago007 2017-03-15 17:56 487
          {
6c5f2c01 sago007 2017-03-15 17:56 488
            if( std::distance( begin, end ) == 0 )
6c5f2c01 sago007 2017-03-15 17:56 489
              itsType = Null_;
6c5f2c01 sago007 2017-03-15 17:56 490
          }
7a956470 sago007 2016-02-14 17:09 491
7a956470 sago007 2016-02-14 17:09 492
          Iterator(ValueIterator begin, ValueIterator end) :
8f94a7f5 sago007 2020-05-10 10:26 493
            itsValueItBegin(begin), itsIndex(0), itsType(Value)
6c5f2c01 sago007 2017-03-15 17:56 494
          {
6c5f2c01 sago007 2017-03-15 17:56 495
            if( std::distance( begin, end ) == 0 )
6c5f2c01 sago007 2017-03-15 17:56 496
              itsType = Null_;
6c5f2c01 sago007 2017-03-15 17:56 497
          }
7a956470 sago007 2016-02-14 17:09 498
7a956470 sago007 2016-02-14 17:09 499
          //! Advance to the next node
7a956470 sago007 2016-02-14 17:09 500
          Iterator & operator++()
7a956470 sago007 2016-02-14 17:09 501
          {
7a956470 sago007 2016-02-14 17:09 502
            ++itsIndex;
7a956470 sago007 2016-02-14 17:09 503
            return *this;
7a956470 sago007 2016-02-14 17:09 504
          }
7a956470 sago007 2016-02-14 17:09 505
7a956470 sago007 2016-02-14 17:09 506
          //! Get the value of the current node
7a956470 sago007 2016-02-14 17:09 507
          GenericValue const & value()
7a956470 sago007 2016-02-14 17:09 508
          {
7a956470 sago007 2016-02-14 17:09 509
            switch(itsType)
7a956470 sago007 2016-02-14 17:09 510
            {
7a956470 sago007 2016-02-14 17:09 511
              case Value : return itsValueItBegin[itsIndex];
7a956470 sago007 2016-02-14 17:09 512
              case Member: return itsMemberItBegin[itsIndex].value;
6c5f2c01 sago007 2017-03-15 17:56 513
              default: throw cereal::Exception("JSONInputArchive internal error: null or empty iterator to object or array!");
7a956470 sago007 2016-02-14 17:09 514
            }
7a956470 sago007 2016-02-14 17:09 515
          }
7a956470 sago007 2016-02-14 17:09 516
7a956470 sago007 2016-02-14 17:09 517
          //! Get the name of the current node, or nullptr if it has no name
7a956470 sago007 2016-02-14 17:09 518
          const char * name() const
7a956470 sago007 2016-02-14 17:09 519
          {
7a956470 sago007 2016-02-14 17:09 520
            if( itsType == Member && (itsMemberItBegin + itsIndex) != itsMemberItEnd )
7a956470 sago007 2016-02-14 17:09 521
              return itsMemberItBegin[itsIndex].name.GetString();
7a956470 sago007 2016-02-14 17:09 522
            else
7a956470 sago007 2016-02-14 17:09 523
              return nullptr;
7a956470 sago007 2016-02-14 17:09 524
          }
7a956470 sago007 2016-02-14 17:09 525
7a956470 sago007 2016-02-14 17:09 526
          //! Adjust our position such that we are at the node with the given name
7a956470 sago007 2016-02-14 17:09 527
          /*! @throws Exception if no such named node exists */
7a956470 sago007 2016-02-14 17:09 528
          inline void search( const char * searchName )
7a956470 sago007 2016-02-14 17:09 529
          {
7a956470 sago007 2016-02-14 17:09 530
            const auto len = std::strlen( searchName );
7a956470 sago007 2016-02-14 17:09 531
            size_t index = 0;
7a956470 sago007 2016-02-14 17:09 532
            for( auto it = itsMemberItBegin; it != itsMemberItEnd; ++it, ++index )
7a956470 sago007 2016-02-14 17:09 533
            {
7a956470 sago007 2016-02-14 17:09 534
              const auto currentName = it->name.GetString();
7a956470 sago007 2016-02-14 17:09 535
              if( ( std::strncmp( searchName, currentName, len ) == 0 ) &&
7a956470 sago007 2016-02-14 17:09 536
                  ( std::strlen( currentName ) == len ) )
7a956470 sago007 2016-02-14 17:09 537
              {
7a956470 sago007 2016-02-14 17:09 538
                itsIndex = index;
7a956470 sago007 2016-02-14 17:09 539
                return;
7a956470 sago007 2016-02-14 17:09 540
              }
7a956470 sago007 2016-02-14 17:09 541
            }
7a956470 sago007 2016-02-14 17:09 542
6c5f2c01 sago007 2017-03-15 17:56 543
            throw Exception("JSON Parsing failed - provided NVP (" + std::string(searchName) + ") not found");
7a956470 sago007 2016-02-14 17:09 544
          }
7a956470 sago007 2016-02-14 17:09 545
7a956470 sago007 2016-02-14 17:09 546
        private:
7a956470 sago007 2016-02-14 17:09 547
          MemberIterator itsMemberItBegin, itsMemberItEnd; //!< The member iterator (object)
8f94a7f5 sago007 2020-05-10 10:26 548
          ValueIterator itsValueItBegin;                   //!< The value iterator (array)
7a956470 sago007 2016-02-14 17:09 549
          size_t itsIndex;                                 //!< The current index of this iterator
6c5f2c01 sago007 2017-03-15 17:56 550
          enum Type {Value, Member, Null_} itsType;        //!< Whether this holds values (array) or members (objects) or nothing
7a956470 sago007 2016-02-14 17:09 551
      };
7a956470 sago007 2016-02-14 17:09 552
7a956470 sago007 2016-02-14 17:09 553
      //! Searches for the expectedName node if it doesn't match the actualName
7a956470 sago007 2016-02-14 17:09 554
      /*! This needs to be called before every load or node start occurs.  This function will
7a956470 sago007 2016-02-14 17:09 555
          check to see if an NVP has been provided (with setNextName) and if so, see if that name matches the actual
7a956470 sago007 2016-02-14 17:09 556
          next name given.  If the names do not match, it will search in the current level of the JSON for that name.
7a956470 sago007 2016-02-14 17:09 557
          If the name is not found, an exception will be thrown.
7a956470 sago007 2016-02-14 17:09 558
7a956470 sago007 2016-02-14 17:09 559
          Resets the NVP name after called.
7a956470 sago007 2016-02-14 17:09 560
7a956470 sago007 2016-02-14 17:09 561
          @throws Exception if an expectedName is given and not found */
7a956470 sago007 2016-02-14 17:09 562
      inline void search()
7a956470 sago007 2016-02-14 17:09 563
      {
7a956470 sago007 2016-02-14 17:09 564
        // The name an NVP provided with setNextName()
7a956470 sago007 2016-02-14 17:09 565
        if( itsNextName )
7a956470 sago007 2016-02-14 17:09 566
        {
7a956470 sago007 2016-02-14 17:09 567
          // The actual name of the current node
7a956470 sago007 2016-02-14 17:09 568
          auto const actualName = itsIteratorStack.back().name();
7a956470 sago007 2016-02-14 17:09 569
7a956470 sago007 2016-02-14 17:09 570
          // Do a search if we don't see a name coming up, or if the names don't match
7a956470 sago007 2016-02-14 17:09 571
          if( !actualName || std::strcmp( itsNextName, actualName ) != 0 )
7a956470 sago007 2016-02-14 17:09 572
            itsIteratorStack.back().search( itsNextName );
7a956470 sago007 2016-02-14 17:09 573
        }
7a956470 sago007 2016-02-14 17:09 574
7a956470 sago007 2016-02-14 17:09 575
        itsNextName = nullptr;
7a956470 sago007 2016-02-14 17:09 576
      }
7a956470 sago007 2016-02-14 17:09 577
7a956470 sago007 2016-02-14 17:09 578
    public:
7a956470 sago007 2016-02-14 17:09 579
      //! Starts a new node, going into its proper iterator
7a956470 sago007 2016-02-14 17:09 580
      /*! This places an iterator for the next node to be parsed onto the iterator stack.  If the next
7a956470 sago007 2016-02-14 17:09 581
          node is an array, this will be a value iterator, otherwise it will be a member iterator.
7a956470 sago007 2016-02-14 17:09 582
7a956470 sago007 2016-02-14 17:09 583
          By default our strategy is to start with the document root node and then recursively iterate through
7a956470 sago007 2016-02-14 17:09 584
          all children in the order they show up in the document.
7a956470 sago007 2016-02-14 17:09 585
          We don't need to know NVPs to do this; we'll just blindly load in the order things appear in.
7a956470 sago007 2016-02-14 17:09 586
7a956470 sago007 2016-02-14 17:09 587
          If we were given an NVP, we will search for it if it does not match our the name of the next node
7a956470 sago007 2016-02-14 17:09 588
          that would normally be loaded.  This functionality is provided by search(). */
7a956470 sago007 2016-02-14 17:09 589
      void startNode()
7a956470 sago007 2016-02-14 17:09 590
      {
7a956470 sago007 2016-02-14 17:09 591
        search();
7a956470 sago007 2016-02-14 17:09 592
7a956470 sago007 2016-02-14 17:09 593
        if(itsIteratorStack.back().value().IsArray())
7a956470 sago007 2016-02-14 17:09 594
          itsIteratorStack.emplace_back(itsIteratorStack.back().value().Begin(), itsIteratorStack.back().value().End());
7a956470 sago007 2016-02-14 17:09 595
        else
7a956470 sago007 2016-02-14 17:09 596
          itsIteratorStack.emplace_back(itsIteratorStack.back().value().MemberBegin(), itsIteratorStack.back().value().MemberEnd());
7a956470 sago007 2016-02-14 17:09 597
      }
7a956470 sago007 2016-02-14 17:09 598
7a956470 sago007 2016-02-14 17:09 599
      //! Finishes the most recently started node
7a956470 sago007 2016-02-14 17:09 600
      void finishNode()
7a956470 sago007 2016-02-14 17:09 601
      {
7a956470 sago007 2016-02-14 17:09 602
        itsIteratorStack.pop_back();
7a956470 sago007 2016-02-14 17:09 603
        ++itsIteratorStack.back();
7a956470 sago007 2016-02-14 17:09 604
      }
7a956470 sago007 2016-02-14 17:09 605
7a956470 sago007 2016-02-14 17:09 606
      //! Retrieves the current node name
7a956470 sago007 2016-02-14 17:09 607
      /*! @return nullptr if no name exists */
7a956470 sago007 2016-02-14 17:09 608
      const char * getNodeName() const
7a956470 sago007 2016-02-14 17:09 609
      {
7a956470 sago007 2016-02-14 17:09 610
        return itsIteratorStack.back().name();
7a956470 sago007 2016-02-14 17:09 611
      }
7a956470 sago007 2016-02-14 17:09 612
7a956470 sago007 2016-02-14 17:09 613
      //! Sets the name for the next node created with startNode
7a956470 sago007 2016-02-14 17:09 614
      void setNextName( const char * name )
7a956470 sago007 2016-02-14 17:09 615
      {
7a956470 sago007 2016-02-14 17:09 616
        itsNextName = name;
7a956470 sago007 2016-02-14 17:09 617
      }
7a956470 sago007 2016-02-14 17:09 618
7a956470 sago007 2016-02-14 17:09 619
      //! Loads a value from the current node - small signed overload
7a956470 sago007 2016-02-14 17:09 620
      template <class T, traits::EnableIf<std::is_signed<T>::value,
7a956470 sago007 2016-02-14 17:09 621
                                          sizeof(T) < sizeof(int64_t)> = traits::sfinae> inline
7a956470 sago007 2016-02-14 17:09 622
      void loadValue(T & val)
7a956470 sago007 2016-02-14 17:09 623
      {
7a956470 sago007 2016-02-14 17:09 624
        search();
7a956470 sago007 2016-02-14 17:09 625
7a956470 sago007 2016-02-14 17:09 626
        val = static_cast<T>( itsIteratorStack.back().value().GetInt() );
7a956470 sago007 2016-02-14 17:09 627
        ++itsIteratorStack.back();
7a956470 sago007 2016-02-14 17:09 628
      }
7a956470 sago007 2016-02-14 17:09 629
7a956470 sago007 2016-02-14 17:09 630
      //! Loads a value from the current node - small unsigned overload
7a956470 sago007 2016-02-14 17:09 631
      template <class T, traits::EnableIf<std::is_unsigned<T>::value,
7a956470 sago007 2016-02-14 17:09 632
                                          sizeof(T) < sizeof(uint64_t),
7a956470 sago007 2016-02-14 17:09 633
                                          !std::is_same<bool, T>::value> = traits::sfinae> inline
7a956470 sago007 2016-02-14 17:09 634
      void loadValue(T & val)
7a956470 sago007 2016-02-14 17:09 635
      {
7a956470 sago007 2016-02-14 17:09 636
        search();
7a956470 sago007 2016-02-14 17:09 637
7a956470 sago007 2016-02-14 17:09 638
        val = static_cast<T>( itsIteratorStack.back().value().GetUint() );
7a956470 sago007 2016-02-14 17:09 639
        ++itsIteratorStack.back();
7a956470 sago007 2016-02-14 17:09 640
      }
7a956470 sago007 2016-02-14 17:09 641
7a956470 sago007 2016-02-14 17:09 642
      //! Loads a value from the current node - bool overload
6c5f2c01 sago007 2017-03-15 17:56 643
      void loadValue(bool & val)        { search(); val = itsIteratorStack.back().value().GetBool(); ++itsIteratorStack.back(); }
7a956470 sago007 2016-02-14 17:09 644
      //! Loads a value from the current node - int64 overload
6c5f2c01 sago007 2017-03-15 17:56 645
      void loadValue(int64_t & val)     { search(); val = itsIteratorStack.back().value().GetInt64(); ++itsIteratorStack.back(); }
7a956470 sago007 2016-02-14 17:09 646
      //! Loads a value from the current node - uint64 overload
7a956470 sago007 2016-02-14 17:09 647
      void loadValue(uint64_t & val)    { search(); val = itsIteratorStack.back().value().GetUint64(); ++itsIteratorStack.back(); }
7a956470 sago007 2016-02-14 17:09 648
      //! Loads a value from the current node - float overload
7a956470 sago007 2016-02-14 17:09 649
      void loadValue(float & val)       { search(); val = static_cast<float>(itsIteratorStack.back().value().GetDouble()); ++itsIteratorStack.back(); }
7a956470 sago007 2016-02-14 17:09 650
      //! Loads a value from the current node - double overload
7a956470 sago007 2016-02-14 17:09 651
      void loadValue(double & val)      { search(); val = itsIteratorStack.back().value().GetDouble(); ++itsIteratorStack.back(); }
7a956470 sago007 2016-02-14 17:09 652
      //! Loads a value from the current node - string overload
7a956470 sago007 2016-02-14 17:09 653
      void loadValue(std::string & val) { search(); val = itsIteratorStack.back().value().GetString(); ++itsIteratorStack.back(); }
6c5f2c01 sago007 2017-03-15 17:56 654
      //! Loads a nullptr from the current node
6c5f2c01 sago007 2017-03-15 17:56 655
      void loadValue(std::nullptr_t&)   { search(); CEREAL_RAPIDJSON_ASSERT(itsIteratorStack.back().value().IsNull()); ++itsIteratorStack.back(); }
7a956470 sago007 2016-02-14 17:09 656
7a956470 sago007 2016-02-14 17:09 657
      // Special cases to handle various flavors of long, which tend to conflict with
7a956470 sago007 2016-02-14 17:09 658
      // the int32_t or int64_t on various compiler/OS combinations.  MSVC doesn't need any of this.
7a956470 sago007 2016-02-14 17:09 659
      #ifndef _MSC_VER
7a956470 sago007 2016-02-14 17:09 660
    private:
7a956470 sago007 2016-02-14 17:09 661
      //! 32 bit signed long loading from current node
7a956470 sago007 2016-02-14 17:09 662
      template <class T> inline
7a956470 sago007 2016-02-14 17:09 663
      typename std::enable_if<sizeof(T) == sizeof(std::int32_t) && std::is_signed<T>::value, void>::type
7a956470 sago007 2016-02-14 17:09 664
      loadLong(T & l){ loadValue( reinterpret_cast<std::int32_t&>( l ) ); }
7a956470 sago007 2016-02-14 17:09 665
7a956470 sago007 2016-02-14 17:09 666
      //! non 32 bit signed long loading from current node
7a956470 sago007 2016-02-14 17:09 667
      template <class T> inline
7a956470 sago007 2016-02-14 17:09 668
      typename std::enable_if<sizeof(T) == sizeof(std::int64_t) && std::is_signed<T>::value, void>::type
7a956470 sago007 2016-02-14 17:09 669
      loadLong(T & l){ loadValue( reinterpret_cast<std::int64_t&>( l ) ); }
7a956470 sago007 2016-02-14 17:09 670
7a956470 sago007 2016-02-14 17:09 671
      //! 32 bit unsigned long loading from current node
7a956470 sago007 2016-02-14 17:09 672
      template <class T> inline
7a956470 sago007 2016-02-14 17:09 673
      typename std::enable_if<sizeof(T) == sizeof(std::uint32_t) && !std::is_signed<T>::value, void>::type
7a956470 sago007 2016-02-14 17:09 674
      loadLong(T & lu){ loadValue( reinterpret_cast<std::uint32_t&>( lu ) ); }
7a956470 sago007 2016-02-14 17:09 675
7a956470 sago007 2016-02-14 17:09 676
      //! non 32 bit unsigned long loading from current node
7a956470 sago007 2016-02-14 17:09 677
      template <class T> inline
7a956470 sago007 2016-02-14 17:09 678
      typename std::enable_if<sizeof(T) == sizeof(std::uint64_t) && !std::is_signed<T>::value, void>::type
7a956470 sago007 2016-02-14 17:09 679
      loadLong(T & lu){ loadValue( reinterpret_cast<std::uint64_t&>( lu ) ); }
6c5f2c01 sago007 2017-03-15 17:56 680
7a956470 sago007 2016-02-14 17:09 681
    public:
7a956470 sago007 2016-02-14 17:09 682
      //! Serialize a long if it would not be caught otherwise
7a956470 sago007 2016-02-14 17:09 683
      template <class T> inline
7a956470 sago007 2016-02-14 17:09 684
      typename std::enable_if<std::is_same<T, long>::value &&
6c5f2c01 sago007 2017-03-15 17:56 685
                              sizeof(T) >= sizeof(std::int64_t) &&
7a956470 sago007 2016-02-14 17:09 686
                              !std::is_same<T, std::int64_t>::value, void>::type
7a956470 sago007 2016-02-14 17:09 687
      loadValue( T & t ){ loadLong(t); }
7a956470 sago007 2016-02-14 17:09 688
7a956470 sago007 2016-02-14 17:09 689
      //! Serialize an unsigned long if it would not be caught otherwise
7a956470 sago007 2016-02-14 17:09 690
      template <class T> inline
7a956470 sago007 2016-02-14 17:09 691
      typename std::enable_if<std::is_same<T, unsigned long>::value &&
6c5f2c01 sago007 2017-03-15 17:56 692
                              sizeof(T) >= sizeof(std::uint64_t) &&
7a956470 sago007 2016-02-14 17:09 693
                              !std::is_same<T, std::uint64_t>::value, void>::type
7a956470 sago007 2016-02-14 17:09 694
      loadValue( T & t ){ loadLong(t); }
7a956470 sago007 2016-02-14 17:09 695
      #endif // _MSC_VER
7a956470 sago007 2016-02-14 17:09 696
7a956470 sago007 2016-02-14 17:09 697
    private:
7a956470 sago007 2016-02-14 17:09 698
      //! Convert a string to a long long
7a956470 sago007 2016-02-14 17:09 699
      void stringToNumber( std::string const & str, long long & val ) { val = std::stoll( str ); }
7a956470 sago007 2016-02-14 17:09 700
      //! Convert a string to an unsigned long long
7a956470 sago007 2016-02-14 17:09 701
      void stringToNumber( std::string const & str, unsigned long long & val ) { val = std::stoull( str ); }
7a956470 sago007 2016-02-14 17:09 702
      //! Convert a string to a long double
7a956470 sago007 2016-02-14 17:09 703
      void stringToNumber( std::string const & str, long double & val ) { val = std::stold( str ); }
7a956470 sago007 2016-02-14 17:09 704
7a956470 sago007 2016-02-14 17:09 705
    public:
7a956470 sago007 2016-02-14 17:09 706
      //! Loads a value from the current node - long double and long long overloads
7a956470 sago007 2016-02-14 17:09 707
      template <class T, traits::EnableIf<std::is_arithmetic<T>::value,
7a956470 sago007 2016-02-14 17:09 708
                                          !std::is_same<T, long>::value,
7a956470 sago007 2016-02-14 17:09 709
                                          !std::is_same<T, unsigned long>::value,
7a956470 sago007 2016-02-14 17:09 710
                                          !std::is_same<T, std::int64_t>::value,
7a956470 sago007 2016-02-14 17:09 711
                                          !std::is_same<T, std::uint64_t>::value,
7a956470 sago007 2016-02-14 17:09 712
                                          (sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long))> = traits::sfinae>
7a956470 sago007 2016-02-14 17:09 713
      inline void loadValue(T & val)
7a956470 sago007 2016-02-14 17:09 714
      {
7a956470 sago007 2016-02-14 17:09 715
        std::string encoded;
7a956470 sago007 2016-02-14 17:09 716
        loadValue( encoded );
7a956470 sago007 2016-02-14 17:09 717
        stringToNumber( encoded, val );
7a956470 sago007 2016-02-14 17:09 718
      }
7a956470 sago007 2016-02-14 17:09 719
7a956470 sago007 2016-02-14 17:09 720
      //! Loads the size for a SizeTag
7a956470 sago007 2016-02-14 17:09 721
      void loadSize(size_type & size)
7a956470 sago007 2016-02-14 17:09 722
      {
6c5f2c01 sago007 2017-03-15 17:56 723
        if (itsIteratorStack.size() == 1)
6c5f2c01 sago007 2017-03-15 17:56 724
          size = itsDocument.Size();
6c5f2c01 sago007 2017-03-15 17:56 725
        else
6c5f2c01 sago007 2017-03-15 17:56 726
          size = (itsIteratorStack.rbegin() + 1)->value().Size();
7a956470 sago007 2016-02-14 17:09 727
      }
7a956470 sago007 2016-02-14 17:09 728
7a956470 sago007 2016-02-14 17:09 729
      //! @}
7a956470 sago007 2016-02-14 17:09 730
7a956470 sago007 2016-02-14 17:09 731
    private:
7a956470 sago007 2016-02-14 17:09 732
      const char * itsNextName;               //!< Next name set by NVP
7a956470 sago007 2016-02-14 17:09 733
      ReadStream itsReadStream;               //!< Rapidjson write stream
7a956470 sago007 2016-02-14 17:09 734
      std::vector<Iterator> itsIteratorStack; //!< 'Stack' of rapidJSON iterators
6c5f2c01 sago007 2017-03-15 17:56 735
      CEREAL_RAPIDJSON_NAMESPACE::Document itsDocument; //!< Rapidjson document
7a956470 sago007 2016-02-14 17:09 736
  };
7a956470 sago007 2016-02-14 17:09 737
7a956470 sago007 2016-02-14 17:09 738
  // ######################################################################
7a956470 sago007 2016-02-14 17:09 739
  // JSONArchive prologue and epilogue functions
7a956470 sago007 2016-02-14 17:09 740
  // ######################################################################
7a956470 sago007 2016-02-14 17:09 741
7a956470 sago007 2016-02-14 17:09 742
  // ######################################################################
7a956470 sago007 2016-02-14 17:09 743
  //! Prologue for NVPs for JSON archives
7a956470 sago007 2016-02-14 17:09 744
  /*! NVPs do not start or finish nodes - they just set up the names */
7a956470 sago007 2016-02-14 17:09 745
  template <class T> inline
7a956470 sago007 2016-02-14 17:09 746
  void prologue( JSONOutputArchive &, NameValuePair<T> const & )
7a956470 sago007 2016-02-14 17:09 747
  { }
7a956470 sago007 2016-02-14 17:09 748
7a956470 sago007 2016-02-14 17:09 749
  //! Prologue for NVPs for JSON archives
7a956470 sago007 2016-02-14 17:09 750
  template <class T> inline
7a956470 sago007 2016-02-14 17:09 751
  void prologue( JSONInputArchive &, NameValuePair<T> const & )
7a956470 sago007 2016-02-14 17:09 752
  { }
7a956470 sago007 2016-02-14 17:09 753
7a956470 sago007 2016-02-14 17:09 754
  // ######################################################################
7a956470 sago007 2016-02-14 17:09 755
  //! Epilogue for NVPs for JSON archives
7a956470 sago007 2016-02-14 17:09 756
  /*! NVPs do not start or finish nodes - they just set up the names */
7a956470 sago007 2016-02-14 17:09 757
  template <class T> inline
7a956470 sago007 2016-02-14 17:09 758
  void epilogue( JSONOutputArchive &, NameValuePair<T> const & )
7a956470 sago007 2016-02-14 17:09 759
  { }
7a956470 sago007 2016-02-14 17:09 760
7a956470 sago007 2016-02-14 17:09 761
  //! Epilogue for NVPs for JSON archives
7a956470 sago007 2016-02-14 17:09 762
  /*! NVPs do not start or finish nodes - they just set up the names */
7a956470 sago007 2016-02-14 17:09 763
  template <class T> inline
7a956470 sago007 2016-02-14 17:09 764
  void epilogue( JSONInputArchive &, NameValuePair<T> const & )
7a956470 sago007 2016-02-14 17:09 765
  { }
7a956470 sago007 2016-02-14 17:09 766
7a956470 sago007 2016-02-14 17:09 767
  // ######################################################################
8f94a7f5 sago007 2020-05-10 10:26 768
  //! Prologue for deferred data for JSON archives
8f94a7f5 sago007 2020-05-10 10:26 769
  /*! Do nothing for the defer wrapper */
8f94a7f5 sago007 2020-05-10 10:26 770
  template <class T> inline
8f94a7f5 sago007 2020-05-10 10:26 771
  void prologue( JSONOutputArchive &, DeferredData<T> const & )
8f94a7f5 sago007 2020-05-10 10:26 772
  { }
8f94a7f5 sago007 2020-05-10 10:26 773
8f94a7f5 sago007 2020-05-10 10:26 774
  //! Prologue for deferred data for JSON archives
8f94a7f5 sago007 2020-05-10 10:26 775
  template <class T> inline
8f94a7f5 sago007 2020-05-10 10:26 776
  void prologue( JSONInputArchive &, DeferredData<T> const & )
8f94a7f5 sago007 2020-05-10 10:26 777
  { }
8f94a7f5 sago007 2020-05-10 10:26 778
8f94a7f5 sago007 2020-05-10 10:26 779
  // ######################################################################
8f94a7f5 sago007 2020-05-10 10:26 780
  //! Epilogue for deferred for JSON archives
8f94a7f5 sago007 2020-05-10 10:26 781
  /*! NVPs do not start or finish nodes - they just set up the names */
8f94a7f5 sago007 2020-05-10 10:26 782
  template <class T> inline
8f94a7f5 sago007 2020-05-10 10:26 783
  void epilogue( JSONOutputArchive &, DeferredData<T> const & )
8f94a7f5 sago007 2020-05-10 10:26 784
  { }
8f94a7f5 sago007 2020-05-10 10:26 785
8f94a7f5 sago007 2020-05-10 10:26 786
  //! Epilogue for deferred for JSON archives
8f94a7f5 sago007 2020-05-10 10:26 787
  /*! Do nothing for the defer wrapper */
8f94a7f5 sago007 2020-05-10 10:26 788
  template <class T> inline
8f94a7f5 sago007 2020-05-10 10:26 789
  void epilogue( JSONInputArchive &, DeferredData<T> const & )
8f94a7f5 sago007 2020-05-10 10:26 790
  { }
8f94a7f5 sago007 2020-05-10 10:26 791
8f94a7f5 sago007 2020-05-10 10:26 792
  // ######################################################################
7a956470 sago007 2016-02-14 17:09 793
  //! Prologue for SizeTags for JSON archives
7a956470 sago007 2016-02-14 17:09 794
  /*! SizeTags are strictly ignored for JSON, they just indicate
7a956470 sago007 2016-02-14 17:09 795
      that the current node should be made into an array */
7a956470 sago007 2016-02-14 17:09 796
  template <class T> inline
7a956470 sago007 2016-02-14 17:09 797
  void prologue( JSONOutputArchive & ar, SizeTag<T> const & )
7a956470 sago007 2016-02-14 17:09 798
  {
7a956470 sago007 2016-02-14 17:09 799
    ar.makeArray();
7a956470 sago007 2016-02-14 17:09 800
  }
7a956470 sago007 2016-02-14 17:09 801
7a956470 sago007 2016-02-14 17:09 802
  //! Prologue for SizeTags for JSON archives
7a956470 sago007 2016-02-14 17:09 803
  template <class T> inline
7a956470 sago007 2016-02-14 17:09 804
  void prologue( JSONInputArchive &, SizeTag<T> const & )
7a956470 sago007 2016-02-14 17:09 805
  { }
7a956470 sago007 2016-02-14 17:09 806
7a956470 sago007 2016-02-14 17:09 807
  // ######################################################################
7a956470 sago007 2016-02-14 17:09 808
  //! Epilogue for SizeTags for JSON archives
7a956470 sago007 2016-02-14 17:09 809
  /*! SizeTags are strictly ignored for JSON */
7a956470 sago007 2016-02-14 17:09 810
  template <class T> inline
7a956470 sago007 2016-02-14 17:09 811
  void epilogue( JSONOutputArchive &, SizeTag<T> const & )
7a956470 sago007 2016-02-14 17:09 812
  { }
7a956470 sago007 2016-02-14 17:09 813
7a956470 sago007 2016-02-14 17:09 814
  //! Epilogue for SizeTags for JSON archives
7a956470 sago007 2016-02-14 17:09 815
  template <class T> inline
7a956470 sago007 2016-02-14 17:09 816
  void epilogue( JSONInputArchive &, SizeTag<T> const & )
7a956470 sago007 2016-02-14 17:09 817
  { }
7a956470 sago007 2016-02-14 17:09 818
7a956470 sago007 2016-02-14 17:09 819
  // ######################################################################
7a956470 sago007 2016-02-14 17:09 820
  //! Prologue for all other types for JSON archives (except minimal types)
7a956470 sago007 2016-02-14 17:09 821
  /*! Starts a new node, named either automatically or by some NVP,
7a956470 sago007 2016-02-14 17:09 822
      that may be given data by the type about to be archived
7a956470 sago007 2016-02-14 17:09 823
7a956470 sago007 2016-02-14 17:09 824
      Minimal types do not start or finish nodes */
6c5f2c01 sago007 2017-03-15 17:56 825
  template <class T, traits::EnableIf<!std::is_arithmetic<T>::value,
6c5f2c01 sago007 2017-03-15 17:56 826
                                      !traits::has_minimal_base_class_serialization<T, traits::has_minimal_output_serialization, JSONOutputArchive>::value,
6c5f2c01 sago007 2017-03-15 17:56 827
                                      !traits::has_minimal_output_serialization<T, JSONOutputArchive>::value> = traits::sfinae>
7a956470 sago007 2016-02-14 17:09 828
  inline void prologue( JSONOutputArchive & ar, T const & )
7a956470 sago007 2016-02-14 17:09 829
  {
7a956470 sago007 2016-02-14 17:09 830
    ar.startNode();
7a956470 sago007 2016-02-14 17:09 831
  }
7a956470 sago007 2016-02-14 17:09 832
7a956470 sago007 2016-02-14 17:09 833
  //! Prologue for all other types for JSON archives
6c5f2c01 sago007 2017-03-15 17:56 834
  template <class T, traits::EnableIf<!std::is_arithmetic<T>::value,
6c5f2c01 sago007 2017-03-15 17:56 835
                                      !traits::has_minimal_base_class_serialization<T, traits::has_minimal_input_serialization, JSONInputArchive>::value,
6c5f2c01 sago007 2017-03-15 17:56 836
                                      !traits::has_minimal_input_serialization<T, JSONInputArchive>::value> = traits::sfinae>
7a956470 sago007 2016-02-14 17:09 837
  inline void prologue( JSONInputArchive & ar, T const & )
7a956470 sago007 2016-02-14 17:09 838
  {
7a956470 sago007 2016-02-14 17:09 839
    ar.startNode();
7a956470 sago007 2016-02-14 17:09 840
  }
7a956470 sago007 2016-02-14 17:09 841
7a956470 sago007 2016-02-14 17:09 842
  // ######################################################################
6c5f2c01 sago007 2017-03-15 17:56 843
  //! Epilogue for all other types other for JSON archives (except minimal types)
7a956470 sago007 2016-02-14 17:09 844
  /*! Finishes the node created in the prologue
7a956470 sago007 2016-02-14 17:09 845
7a956470 sago007 2016-02-14 17:09 846
      Minimal types do not start or finish nodes */
6c5f2c01 sago007 2017-03-15 17:56 847
  template <class T, traits::EnableIf<!std::is_arithmetic<T>::value,
6c5f2c01 sago007 2017-03-15 17:56 848
                                      !traits::has_minimal_base_class_serialization<T, traits::has_minimal_output_serialization, JSONOutputArchive>::value,
6c5f2c01 sago007 2017-03-15 17:56 849
                                      !traits::has_minimal_output_serialization<T, JSONOutputArchive>::value> = traits::sfinae>
7a956470 sago007 2016-02-14 17:09 850
  inline void epilogue( JSONOutputArchive & ar, T const & )
7a956470 sago007 2016-02-14 17:09 851
  {
7a956470 sago007 2016-02-14 17:09 852
    ar.finishNode();
7a956470 sago007 2016-02-14 17:09 853
  }
7a956470 sago007 2016-02-14 17:09 854
7a956470 sago007 2016-02-14 17:09 855
  //! Epilogue for all other types other for JSON archives
6c5f2c01 sago007 2017-03-15 17:56 856
  template <class T, traits::EnableIf<!std::is_arithmetic<T>::value,
6c5f2c01 sago007 2017-03-15 17:56 857
                                      !traits::has_minimal_base_class_serialization<T, traits::has_minimal_input_serialization, JSONInputArchive>::value,
6c5f2c01 sago007 2017-03-15 17:56 858
                                      !traits::has_minimal_input_serialization<T, JSONInputArchive>::value> = traits::sfinae>
7a956470 sago007 2016-02-14 17:09 859
  inline void epilogue( JSONInputArchive & ar, T const & )
7a956470 sago007 2016-02-14 17:09 860
  {
7a956470 sago007 2016-02-14 17:09 861
    ar.finishNode();
7a956470 sago007 2016-02-14 17:09 862
  }
7a956470 sago007 2016-02-14 17:09 863
7a956470 sago007 2016-02-14 17:09 864
  // ######################################################################
7a956470 sago007 2016-02-14 17:09 865
  //! Prologue for arithmetic types for JSON archives
6c5f2c01 sago007 2017-03-15 17:56 866
  inline
6c5f2c01 sago007 2017-03-15 17:56 867
  void prologue( JSONOutputArchive & ar, std::nullptr_t const & )
6c5f2c01 sago007 2017-03-15 17:56 868
  {
6c5f2c01 sago007 2017-03-15 17:56 869
    ar.writeName();
6c5f2c01 sago007 2017-03-15 17:56 870
  }
6c5f2c01 sago007 2017-03-15 17:56 871
6c5f2c01 sago007 2017-03-15 17:56 872
  //! Prologue for arithmetic types for JSON archives
6c5f2c01 sago007 2017-03-15 17:56 873
  inline
6c5f2c01 sago007 2017-03-15 17:56 874
  void prologue( JSONInputArchive &, std::nullptr_t const & )
6c5f2c01 sago007 2017-03-15 17:56 875
  { }
6c5f2c01 sago007 2017-03-15 17:56 876
6c5f2c01 sago007 2017-03-15 17:56 877
  // ######################################################################
6c5f2c01 sago007 2017-03-15 17:56 878
  //! Epilogue for arithmetic types for JSON archives
6c5f2c01 sago007 2017-03-15 17:56 879
  inline
6c5f2c01 sago007 2017-03-15 17:56 880
  void epilogue( JSONOutputArchive &, std::nullptr_t const & )
6c5f2c01 sago007 2017-03-15 17:56 881
  { }
6c5f2c01 sago007 2017-03-15 17:56 882
6c5f2c01 sago007 2017-03-15 17:56 883
  //! Epilogue for arithmetic types for JSON archives
6c5f2c01 sago007 2017-03-15 17:56 884
  inline
6c5f2c01 sago007 2017-03-15 17:56 885
  void epilogue( JSONInputArchive &, std::nullptr_t const & )
6c5f2c01 sago007 2017-03-15 17:56 886
  { }
6c5f2c01 sago007 2017-03-15 17:56 887
6c5f2c01 sago007 2017-03-15 17:56 888
  // ######################################################################
6c5f2c01 sago007 2017-03-15 17:56 889
  //! Prologue for arithmetic types for JSON archives
7a956470 sago007 2016-02-14 17:09 890
  template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
7a956470 sago007 2016-02-14 17:09 891
  void prologue( JSONOutputArchive & ar, T const & )
7a956470 sago007 2016-02-14 17:09 892
  {
7a956470 sago007 2016-02-14 17:09 893
    ar.writeName();
7a956470 sago007 2016-02-14 17:09 894
  }
7a956470 sago007 2016-02-14 17:09 895
7a956470 sago007 2016-02-14 17:09 896
  //! Prologue for arithmetic types for JSON archives
7a956470 sago007 2016-02-14 17:09 897
  template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
7a956470 sago007 2016-02-14 17:09 898
  void prologue( JSONInputArchive &, T const & )
7a956470 sago007 2016-02-14 17:09 899
  { }
7a956470 sago007 2016-02-14 17:09 900
7a956470 sago007 2016-02-14 17:09 901
  // ######################################################################
7a956470 sago007 2016-02-14 17:09 902
  //! Epilogue for arithmetic types for JSON archives
7a956470 sago007 2016-02-14 17:09 903
  template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
7a956470 sago007 2016-02-14 17:09 904
  void epilogue( JSONOutputArchive &, T const & )
7a956470 sago007 2016-02-14 17:09 905
  { }
7a956470 sago007 2016-02-14 17:09 906
7a956470 sago007 2016-02-14 17:09 907
  //! Epilogue for arithmetic types for JSON archives
7a956470 sago007 2016-02-14 17:09 908
  template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
7a956470 sago007 2016-02-14 17:09 909
  void epilogue( JSONInputArchive &, T const & )
7a956470 sago007 2016-02-14 17:09 910
  { }
7a956470 sago007 2016-02-14 17:09 911
7a956470 sago007 2016-02-14 17:09 912
  // ######################################################################
7a956470 sago007 2016-02-14 17:09 913
  //! Prologue for strings for JSON archives
7a956470 sago007 2016-02-14 17:09 914
  template<class CharT, class Traits, class Alloc> inline
7a956470 sago007 2016-02-14 17:09 915
  void prologue(JSONOutputArchive & ar, std::basic_string<CharT, Traits, Alloc> const &)
7a956470 sago007 2016-02-14 17:09 916
  {
7a956470 sago007 2016-02-14 17:09 917
    ar.writeName();
7a956470 sago007 2016-02-14 17:09 918
  }
7a956470 sago007 2016-02-14 17:09 919
7a956470 sago007 2016-02-14 17:09 920
  //! Prologue for strings for JSON archives
7a956470 sago007 2016-02-14 17:09 921
  template<class CharT, class Traits, class Alloc> inline
7a956470 sago007 2016-02-14 17:09 922
  void prologue(JSONInputArchive &, std::basic_string<CharT, Traits, Alloc> const &)
7a956470 sago007 2016-02-14 17:09 923
  { }
7a956470 sago007 2016-02-14 17:09 924
7a956470 sago007 2016-02-14 17:09 925
  // ######################################################################
7a956470 sago007 2016-02-14 17:09 926
  //! Epilogue for strings for JSON archives
7a956470 sago007 2016-02-14 17:09 927
  template<class CharT, class Traits, class Alloc> inline
7a956470 sago007 2016-02-14 17:09 928
  void epilogue(JSONOutputArchive &, std::basic_string<CharT, Traits, Alloc> const &)
7a956470 sago007 2016-02-14 17:09 929
  { }
7a956470 sago007 2016-02-14 17:09 930
7a956470 sago007 2016-02-14 17:09 931
  //! Epilogue for strings for JSON archives
7a956470 sago007 2016-02-14 17:09 932
  template<class CharT, class Traits, class Alloc> inline
7a956470 sago007 2016-02-14 17:09 933
  void epilogue(JSONInputArchive &, std::basic_string<CharT, Traits, Alloc> const &)
7a956470 sago007 2016-02-14 17:09 934
  { }
7a956470 sago007 2016-02-14 17:09 935
7a956470 sago007 2016-02-14 17:09 936
  // ######################################################################
7a956470 sago007 2016-02-14 17:09 937
  // Common JSONArchive serialization functions
7a956470 sago007 2016-02-14 17:09 938
  // ######################################################################
7a956470 sago007 2016-02-14 17:09 939
  //! Serializing NVP types to JSON
7a956470 sago007 2016-02-14 17:09 940
  template <class T> inline
7a956470 sago007 2016-02-14 17:09 941
  void CEREAL_SAVE_FUNCTION_NAME( JSONOutputArchive & ar, NameValuePair<T> const & t )
7a956470 sago007 2016-02-14 17:09 942
  {
7a956470 sago007 2016-02-14 17:09 943
    ar.setNextName( t.name );
7a956470 sago007 2016-02-14 17:09 944
    ar( t.value );
7a956470 sago007 2016-02-14 17:09 945
  }
7a956470 sago007 2016-02-14 17:09 946
7a956470 sago007 2016-02-14 17:09 947
  template <class T> inline
7a956470 sago007 2016-02-14 17:09 948
  void CEREAL_LOAD_FUNCTION_NAME( JSONInputArchive & ar, NameValuePair<T> & t )
7a956470 sago007 2016-02-14 17:09 949
  {
7a956470 sago007 2016-02-14 17:09 950
    ar.setNextName( t.name );
7a956470 sago007 2016-02-14 17:09 951
    ar( t.value );
7a956470 sago007 2016-02-14 17:09 952
  }
7a956470 sago007 2016-02-14 17:09 953
6c5f2c01 sago007 2017-03-15 17:56 954
  //! Saving for nullptr to JSON
6c5f2c01 sago007 2017-03-15 17:56 955
  inline
6c5f2c01 sago007 2017-03-15 17:56 956
  void CEREAL_SAVE_FUNCTION_NAME(JSONOutputArchive & ar, std::nullptr_t const & t)
6c5f2c01 sago007 2017-03-15 17:56 957
  {
6c5f2c01 sago007 2017-03-15 17:56 958
    ar.saveValue( t );
6c5f2c01 sago007 2017-03-15 17:56 959
  }
6c5f2c01 sago007 2017-03-15 17:56 960
6c5f2c01 sago007 2017-03-15 17:56 961
  //! Loading arithmetic from JSON
6c5f2c01 sago007 2017-03-15 17:56 962
  inline
6c5f2c01 sago007 2017-03-15 17:56 963
  void CEREAL_LOAD_FUNCTION_NAME(JSONInputArchive & ar, std::nullptr_t & t)
6c5f2c01 sago007 2017-03-15 17:56 964
  {
6c5f2c01 sago007 2017-03-15 17:56 965
    ar.loadValue( t );
6c5f2c01 sago007 2017-03-15 17:56 966
  }
6c5f2c01 sago007 2017-03-15 17:56 967
7a956470 sago007 2016-02-14 17:09 968
  //! Saving for arithmetic to JSON
7a956470 sago007 2016-02-14 17:09 969
  template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
7a956470 sago007 2016-02-14 17:09 970
  void CEREAL_SAVE_FUNCTION_NAME(JSONOutputArchive & ar, T const & t)
7a956470 sago007 2016-02-14 17:09 971
  {
7a956470 sago007 2016-02-14 17:09 972
    ar.saveValue( t );
7a956470 sago007 2016-02-14 17:09 973
  }
7a956470 sago007 2016-02-14 17:09 974
7a956470 sago007 2016-02-14 17:09 975
  //! Loading arithmetic from JSON
7a956470 sago007 2016-02-14 17:09 976
  template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
7a956470 sago007 2016-02-14 17:09 977
  void CEREAL_LOAD_FUNCTION_NAME(JSONInputArchive & ar, T & t)
7a956470 sago007 2016-02-14 17:09 978
  {
7a956470 sago007 2016-02-14 17:09 979
    ar.loadValue( t );
7a956470 sago007 2016-02-14 17:09 980
  }
7a956470 sago007 2016-02-14 17:09 981
7a956470 sago007 2016-02-14 17:09 982
  //! saving string to JSON
7a956470 sago007 2016-02-14 17:09 983
  template<class CharT, class Traits, class Alloc> inline
7a956470 sago007 2016-02-14 17:09 984
  void CEREAL_SAVE_FUNCTION_NAME(JSONOutputArchive & ar, std::basic_string<CharT, Traits, Alloc> const & str)
7a956470 sago007 2016-02-14 17:09 985
  {
7a956470 sago007 2016-02-14 17:09 986
    ar.saveValue( str );
7a956470 sago007 2016-02-14 17:09 987
  }
7a956470 sago007 2016-02-14 17:09 988
7a956470 sago007 2016-02-14 17:09 989
  //! loading string from JSON
7a956470 sago007 2016-02-14 17:09 990
  template<class CharT, class Traits, class Alloc> inline
7a956470 sago007 2016-02-14 17:09 991
  void CEREAL_LOAD_FUNCTION_NAME(JSONInputArchive & ar, std::basic_string<CharT, Traits, Alloc> & str)
7a956470 sago007 2016-02-14 17:09 992
  {
7a956470 sago007 2016-02-14 17:09 993
    ar.loadValue( str );
7a956470 sago007 2016-02-14 17:09 994
  }
7a956470 sago007 2016-02-14 17:09 995
7a956470 sago007 2016-02-14 17:09 996
  // ######################################################################
7a956470 sago007 2016-02-14 17:09 997
  //! Saving SizeTags to JSON
7a956470 sago007 2016-02-14 17:09 998
  template <class T> inline
7a956470 sago007 2016-02-14 17:09 999
  void CEREAL_SAVE_FUNCTION_NAME( JSONOutputArchive &, SizeTag<T> const & )
7a956470 sago007 2016-02-14 17:09 1000
  {
7a956470 sago007 2016-02-14 17:09 1001
    // nothing to do here, we don't explicitly save the size
7a956470 sago007 2016-02-14 17:09 1002
  }
7a956470 sago007 2016-02-14 17:09 1003
7a956470 sago007 2016-02-14 17:09 1004
  //! Loading SizeTags from JSON
7a956470 sago007 2016-02-14 17:09 1005
  template <class T> inline
7a956470 sago007 2016-02-14 17:09 1006
  void CEREAL_LOAD_FUNCTION_NAME( JSONInputArchive & ar, SizeTag<T> & st )
7a956470 sago007 2016-02-14 17:09 1007
  {
7a956470 sago007 2016-02-14 17:09 1008
    ar.loadSize( st.size );
7a956470 sago007 2016-02-14 17:09 1009
  }
7a956470 sago007 2016-02-14 17:09 1010
} // namespace cereal
7a956470 sago007 2016-02-14 17:09 1011
7a956470 sago007 2016-02-14 17:09 1012
// register archives for polymorphic support
7a956470 sago007 2016-02-14 17:09 1013
CEREAL_REGISTER_ARCHIVE(cereal::JSONInputArchive)
7a956470 sago007 2016-02-14 17:09 1014
CEREAL_REGISTER_ARCHIVE(cereal::JSONOutputArchive)
7a956470 sago007 2016-02-14 17:09 1015
7a956470 sago007 2016-02-14 17:09 1016
// tie input and output archives together
7a956470 sago007 2016-02-14 17:09 1017
CEREAL_SETUP_ARCHIVE_TRAITS(cereal::JSONInputArchive, cereal::JSONOutputArchive)
7a956470 sago007 2016-02-14 17:09 1018
7a956470 sago007 2016-02-14 17:09 1019
#endif // CEREAL_ARCHIVES_JSON_HPP_
1970-01-01 00:00 1020