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