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