commit
						9f562caa2c
					
				
					 14 changed files with 17007 additions and 1317 deletions
				
			
		
							
								
								
									
										2
									
								
								.coveralls.yml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								.coveralls.yml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
service_name: travis-pro
 | 
			
		||||
repo_token: F9bs4Nop10JRgqPQXRcifyQKYhb3FczkS
 | 
			
		||||
							
								
								
									
										16
									
								
								.travis.yml
									
										
									
									
									
								
							
							
						
						
									
										16
									
								
								.travis.yml
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,7 +1,14 @@
 | 
			
		|||
language: cpp
 | 
			
		||||
 | 
			
		||||
compiler:
 | 
			
		||||
  - clang
 | 
			
		||||
  - gcc
 | 
			
		||||
 | 
			
		||||
before_install:
 | 
			
		||||
  - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
 | 
			
		||||
  - sudo apt-get update -qq
 | 
			
		||||
  - if [ "$CXX" = "g++" ]; then sudo apt-get install -qq g++-4.8; fi
 | 
			
		||||
  - if [ "$CXX" = "g++" ]; then export CXX="g++-4.8" CC="gcc-4.8"; fi
 | 
			
		||||
  - sudo pip install cpp-coveralls
 | 
			
		||||
 | 
			
		||||
before_script:
 | 
			
		||||
  - autoreconf -iv
 | 
			
		||||
| 
						 | 
				
			
			@ -10,3 +17,10 @@ before_script:
 | 
			
		|||
script:
 | 
			
		||||
  - make
 | 
			
		||||
  - make check
 | 
			
		||||
 | 
			
		||||
after_success:
 | 
			
		||||
  - make clean
 | 
			
		||||
  - make json_unit CXXFLAGS="-fprofile-arcs -ftest-coverage"
 | 
			
		||||
  - ./json_unit
 | 
			
		||||
  - coveralls --exclude lib --exclude tests --gcov-options '\-lp'
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										34
									
								
								Makefile.am
									
										
									
									
									
								
							
							
						
						
									
										34
									
								
								Makefile.am
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,25 +1,27 @@
 | 
			
		|||
noinst_PROGRAMS = json json98 json98benchmark
 | 
			
		||||
TESTS = ./json ./json98
 | 
			
		||||
noinst_PROGRAMS = json json_unit
 | 
			
		||||
TESTS = ./json ./json_unit
 | 
			
		||||
 | 
			
		||||
FLAGS = -Wall -Wextra -pedantic -Weffc++ -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wmissing-declarations -Wmissing-include-dirs -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-conversion -Wsign-promo -Wstrict-overflow=5 -Wswitch -Wundef -Wno-unused -Wnon-virtual-dtor -Wreorder
 | 
			
		||||
 | 
			
		||||
json_SOURCES = src/JSON.cc src/JSON.h test/JSON_test.cc
 | 
			
		||||
json_CXXFLAGS = -std=c++11
 | 
			
		||||
json_CXXFLAGS = $(FLAGS) -Weffc++ -std=c++11
 | 
			
		||||
json_CPPFLAGS = -I$(top_srcdir)/src
 | 
			
		||||
 | 
			
		||||
json98_SOURCES = src/JSON.cc src/JSON.h test/JSON_test.cc
 | 
			
		||||
json98_CXXFLAGS = -std=c++98
 | 
			
		||||
json98_CPPFLAGS = -I$(top_srcdir)/src
 | 
			
		||||
json_unit_SOURCES = src/JSON.cc src/JSON.h test/catch.hpp test/JSON_unit.cc
 | 
			
		||||
json_unit_CXXFLAGS = $(FLAGS) -std=c++11
 | 
			
		||||
json_unit_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/test -Dprivate=public
 | 
			
		||||
 | 
			
		||||
json98benchmark_SOURCES = src/JSON.cc src/JSON.h benchmark/JSON_benchmark.cc
 | 
			
		||||
json98benchmark_CXXFLAGS = -std=c++98 -O3
 | 
			
		||||
json98benchmark_CPPFLAGS = -I$(top_srcdir)/src -DNDEBUG
 | 
			
		||||
cppcheck:
 | 
			
		||||
	cppcheck --enable=all --inconclusive --std=c++11 src/JSON.*
 | 
			
		||||
 | 
			
		||||
svn-clean: maintainer-clean
 | 
			
		||||
	rm -fr configure INSTALL aclocal.m4 build-aux depcomp install-sh missing test-driver cover_html *.gcda *.gcno coverage*.info
 | 
			
		||||
	rm -fr configure INSTALL aclocal.m4 build-aux depcomp install-sh missing test-driver
 | 
			
		||||
	for DIR in $(DIST_SUBDIRS) .; do rm -f $$DIR/Makefile.in; done
 | 
			
		||||
 | 
			
		||||
cover:
 | 
			
		||||
	make clean
 | 
			
		||||
	make json98 CXXFLAGS+="--coverage -g -fprofile-arcs -ftest-coverage" CPPFLAGS+="-DNDEBUG"
 | 
			
		||||
	./json98
 | 
			
		||||
	lcov --capture --directory . --output-file coverage98.info
 | 
			
		||||
	genhtml coverage*.info --output-directory cover_html --show-details --title "$(PACKAGE_STRING)" --legend --demangle-cpp
 | 
			
		||||
pretty:
 | 
			
		||||
	astyle --style=allman --indent=spaces=4 --indent-modifiers \
 | 
			
		||||
	   --indent-switches --indent-preproc-block --indent-preproc-define \
 | 
			
		||||
	   --indent-col1-comments --pad-oper --pad-header --align-pointer=type \
 | 
			
		||||
	   --align-reference=type --add-brackets --convert-tabs --close-templates \
 | 
			
		||||
	   --lineend=linux --preserve-date --suffix=none \
 | 
			
		||||
	   $(SOURCES)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										27
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										27
									
								
								README.md
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -2,13 +2,15 @@
 | 
			
		|||
 | 
			
		||||
[](https://travis-ci.org/nlohmann/json)
 | 
			
		||||
 | 
			
		||||
[](https://coveralls.io/r/nlohmann/json)
 | 
			
		||||
 | 
			
		||||
## Design goals
 | 
			
		||||
 | 
			
		||||
There are myriads of [JSON](http://json.org) libraries out there, and each may even have its reason to exist. Our class had these design goals:
 | 
			
		||||
 | 
			
		||||
- **Trivial integration**. Our whole code consists of just two files: A header file `JSON.h` and a source file `JSON.cc`. That's it. No library, no subproject, no dependencies. The class is written in vanilla C++98 and -- if possible -- uses some features of C++11 such as move constructors. All in all, the class should require no adjustment of your compiler flags or project settings.
 | 
			
		||||
- **Trivial integration**. Our whole code consists of just two files: A header file `JSON.h` and a source file `JSON.cc`. That's it. No library, no subproject, no dependencies. The class is written in vanilla C++11. All in all, the class should require no adjustment of your compiler flags or project settings.
 | 
			
		||||
 | 
			
		||||
- **Intiuitve syntax**. In languages such as Python, JSON feels like a first class data type. We used all the operator magic of C++ to achieve the same feeling in your code. Check out the [examples below](#examples) and you know, what I mean.
 | 
			
		||||
- **Intuitive syntax**. In languages such as Python, JSON feels like a first class data type. We used all the operator magic of C++ to achieve the same feeling in your code. Check out the [examples below](#examples) and you know, what I mean.
 | 
			
		||||
 | 
			
		||||
Other aspects were not so important to us:
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -16,7 +18,7 @@ Other aspects were not so important to us:
 | 
			
		|||
 | 
			
		||||
- **Speed**. We currently implement the parser as naive [recursive descent parser](http://en.wikipedia.org/wiki/Recursive_descent_parser) with hand coded string handling. It is fast enough, but a [LALR-parser](http://en.wikipedia.org/wiki/LALR_parser) with a decent regular expression processor should be even faster (but would consist of more files which makes the integration harder).
 | 
			
		||||
 | 
			
		||||
- **Rigourous standard compliance**. We followed the [specification](http://json.org) as close as possible, but did not invest too much in a 100% compliance with respect to Unicode support. As a result, there might be edge cases of false positives and false negatives, but as long as we have a hand-written parser, we won't invest too much to be fully compliant.
 | 
			
		||||
- **Rigorous standard compliance**. We followed the [specification](http://json.org) as close as possible, but did not invest too much in a 100% compliance with respect to Unicode support. As a result, there might be edge cases of false positives and false negatives, but as long as we have a hand-written parser, we won't invest too much to be fully compliant.
 | 
			
		||||
 | 
			
		||||
## Integration
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -45,11 +47,17 @@ j["happy"] = true;
 | 
			
		|||
// add a string that is stored as std::string
 | 
			
		||||
j["name"] = "Niels";
 | 
			
		||||
 | 
			
		||||
// add a null object
 | 
			
		||||
j["nothing"] = nullptr;
 | 
			
		||||
 | 
			
		||||
// add an object inside the object
 | 
			
		||||
j["further"]["entry"] = 42;
 | 
			
		||||
 | 
			
		||||
// add an array that is stored as std::vector (C++11)
 | 
			
		||||
// add an array that is stored as std::vector
 | 
			
		||||
j["list"] = { 1, 0, 2 };
 | 
			
		||||
 | 
			
		||||
// add another object
 | 
			
		||||
j["object"] = { {"currency", "USD"}, {"value", "42.99"} };
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Input / Output
 | 
			
		||||
| 
						 | 
				
			
			@ -65,6 +73,11 @@ std::cout << j;
 | 
			
		|||
 | 
			
		||||
These operators work for any subclasses of `std::istream` or `std::ostream`.
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
// create object from string literal
 | 
			
		||||
JSON j = "{ \"pi\": 3.141, \"happy\": true }"_json;
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### STL-like access
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
| 
						 | 
				
			
			@ -79,19 +92,19 @@ for (JSON::iterator it = j.begin(); it != j.end(); ++it) {
 | 
			
		|||
  std::cout << *it << '\n';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// C++11 style
 | 
			
		||||
// range-based for
 | 
			
		||||
for (auto element : j) {
 | 
			
		||||
  std::cout << element << '\n';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getter/setter
 | 
			
		||||
std::string tmp = j[0];
 | 
			
		||||
const std::string tmp = j[0];
 | 
			
		||||
j[1] = 42;
 | 
			
		||||
 | 
			
		||||
// other stuff
 | 
			
		||||
j.size();     // 3
 | 
			
		||||
j.empty();    // false
 | 
			
		||||
j.type();     // JSON::array
 | 
			
		||||
j.type();     // JSON::valeu_type::array
 | 
			
		||||
 | 
			
		||||
// create an object
 | 
			
		||||
JSON o;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,17 +0,0 @@
 | 
			
		|||
#include <iostream>
 | 
			
		||||
#include <fstream>
 | 
			
		||||
#include <ctime>
 | 
			
		||||
#include <JSON.h>
 | 
			
		||||
 | 
			
		||||
int main(int argc, char** argv) {
 | 
			
		||||
    time_t timer1, timer2;
 | 
			
		||||
 | 
			
		||||
    JSON json;
 | 
			
		||||
    std::ifstream infile(argv[1]);
 | 
			
		||||
    time(&timer1);
 | 
			
		||||
    json << infile;
 | 
			
		||||
    time(&timer2);
 | 
			
		||||
    std::cout << "Parsing from std::ifstream: " << difftime(timer2, timer1) << " sec\n";
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,11 +0,0 @@
 | 
			
		|||
#!/usr/bin/env python
 | 
			
		||||
 | 
			
		||||
import json
 | 
			
		||||
import sys
 | 
			
		||||
import datetime
 | 
			
		||||
 | 
			
		||||
a = datetime.datetime.now()
 | 
			
		||||
data = json.loads(open(sys.argv[1]).read())
 | 
			
		||||
b = datetime.datetime.now()
 | 
			
		||||
 | 
			
		||||
print (b-a)
 | 
			
		||||
| 
						 | 
				
			
			@ -1,7 +0,0 @@
 | 
			
		|||
#!/bin/sh
 | 
			
		||||
 | 
			
		||||
git clone https://github.com/zeMirco/sf-city-lots-json.git
 | 
			
		||||
mv sf-city-lots-json/citylots.json .
 | 
			
		||||
rm -fr sf-city-lots-json
 | 
			
		||||
 | 
			
		||||
wget http://eu.battle.net/auction-data/258993a3c6b974ef3e6f22ea6f822720/auctions.json
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
AC_INIT([JSON], [1.0], [niels.lohmann@uni-rostock.de])
 | 
			
		||||
AC_INIT([JSON], [2.0], [mail@nlohmann.me])
 | 
			
		||||
AC_CONFIG_SRCDIR([src/JSON.cc])
 | 
			
		||||
 | 
			
		||||
AM_INIT_AUTOMAKE([foreign subdir-objects])
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2939
									
								
								src/JSON.cc
									
										
									
									
									
								
							
							
						
						
									
										2939
									
								
								src/JSON.cc
									
										
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										337
									
								
								src/JSON.h
									
										
									
									
									
								
							
							
						
						
									
										337
									
								
								src/JSON.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,55 +1,73 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
// a helper macro to detect C++11 compliant compilers
 | 
			
		||||
#if __cplusplus >= 201103L
 | 
			
		||||
#define __cplusplus11
 | 
			
		||||
#endif
 | 
			
		||||
#include <initializer_list>  // std::initializer_list
 | 
			
		||||
#include <iostream>          // std::istream, std::ostream
 | 
			
		||||
#include <map>               // std::map
 | 
			
		||||
#include <mutex>             // std::mutex
 | 
			
		||||
#include <string>            // std::string
 | 
			
		||||
#include <vector>            // std::vector
 | 
			
		||||
 | 
			
		||||
// STL containers
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <map>
 | 
			
		||||
/*!
 | 
			
		||||
The size of a JSON object is 16 bytes: 8 bytes for the value union whose
 | 
			
		||||
largest item is a pointer type and another 8 byte for an element of the
 | 
			
		||||
type union. The latter only needs 1 byte - the remaining 7 bytes are wasted
 | 
			
		||||
due to alignment.
 | 
			
		||||
 | 
			
		||||
// additional C++11 headers
 | 
			
		||||
#ifdef __cplusplus11
 | 
			
		||||
#include <mutex>
 | 
			
		||||
#include <initializer_list>
 | 
			
		||||
#endif
 | 
			
		||||
@see http://stackoverflow.com/questions/7758580/writing-your-own-stl-container/7759622#7759622
 | 
			
		||||
 | 
			
		||||
class JSON {
 | 
			
		||||
@bug Numbers are currently handled too generously. There are several formats
 | 
			
		||||
     that are forbidden by the standard, but are accepted by the parser.
 | 
			
		||||
 | 
			
		||||
@todo Implement JSON::swap()
 | 
			
		||||
@todo Implement JSON::insert(), JSON::emplace(), JSON::emplace_back, JSON::erase
 | 
			
		||||
@todo Implement JSON::reverse_iterator, JSON::const_reverse_iterator,
 | 
			
		||||
      JSON::rbegin(), JSON::rend(), JSON::crbegin(), JSON::crend()?
 | 
			
		||||
*/
 | 
			
		||||
class JSON
 | 
			
		||||
{
 | 
			
		||||
    // forward declaration to friend this class
 | 
			
		||||
  public:
 | 
			
		||||
    class iterator;
 | 
			
		||||
    class const_iterator;
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus11
 | 
			
		||||
    private:
 | 
			
		||||
        /// mutex to guard payload
 | 
			
		||||
        static std::mutex _token;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  public:
 | 
			
		||||
    /// possible types of a JSON object
 | 
			
		||||
        typedef enum {
 | 
			
		||||
            array, object, null, string, boolean, number, number_float
 | 
			
		||||
        } json_t;
 | 
			
		||||
    enum class value_type : uint8_t
 | 
			
		||||
    {
 | 
			
		||||
        /// ordered collection of values
 | 
			
		||||
        array = 0,
 | 
			
		||||
        /// unordered set of name/value pairs
 | 
			
		||||
        object,
 | 
			
		||||
        /// null value
 | 
			
		||||
        null,
 | 
			
		||||
        /// string value
 | 
			
		||||
        string,
 | 
			
		||||
        /// Boolean value
 | 
			
		||||
        boolean,
 | 
			
		||||
        /// number value (integer)
 | 
			
		||||
        number,
 | 
			
		||||
        /// number value (float)
 | 
			
		||||
        number_float
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
    /// a type for an object
 | 
			
		||||
        typedef std::map<std::string, JSON> object_t;
 | 
			
		||||
    using object_t = std::map<std::string, JSON>;
 | 
			
		||||
    /// a type for an array
 | 
			
		||||
        typedef std::vector<JSON> array_t;
 | 
			
		||||
    using array_t = std::vector<JSON>;
 | 
			
		||||
    /// a type for a string
 | 
			
		||||
        typedef std::string string_t;
 | 
			
		||||
    using string_t = std::string;
 | 
			
		||||
    /// a type for a Boolean
 | 
			
		||||
        typedef bool boolean_t;
 | 
			
		||||
    using boolean_t = bool;
 | 
			
		||||
    /// a type for an integer number
 | 
			
		||||
        typedef int number_t;
 | 
			
		||||
    using number_t = int;
 | 
			
		||||
    /// a type for a floating point number
 | 
			
		||||
        typedef double number_float_t;
 | 
			
		||||
    using number_float_t = double;
 | 
			
		||||
    /// a type for list initialization
 | 
			
		||||
    using list_init_t = std::initializer_list<JSON>;
 | 
			
		||||
 | 
			
		||||
    /// a JSON value
 | 
			
		||||
        union value {
 | 
			
		||||
    union value
 | 
			
		||||
    {
 | 
			
		||||
        /// array as pointer to array_t
 | 
			
		||||
        array_t* array;
 | 
			
		||||
        /// object as pointer to object_t
 | 
			
		||||
| 
						 | 
				
			
			@ -64,76 +82,75 @@ class JSON {
 | 
			
		|||
        number_float_t number_float;
 | 
			
		||||
 | 
			
		||||
        /// default constructor
 | 
			
		||||
            value() {}
 | 
			
		||||
        value() = default;
 | 
			
		||||
        /// constructor for arrays
 | 
			
		||||
            value(array_t* array): array(array) {}
 | 
			
		||||
        value(array_t*);
 | 
			
		||||
        /// constructor for objects
 | 
			
		||||
            value(object_t* object): object(object) {}
 | 
			
		||||
        value(object_t*);
 | 
			
		||||
        /// constructor for strings
 | 
			
		||||
            value(string_t* string): string(string) {}
 | 
			
		||||
        value(string_t*);
 | 
			
		||||
        /// constructor for Booleans
 | 
			
		||||
            value(boolean_t boolean) : boolean(boolean) {}
 | 
			
		||||
        value(boolean_t);
 | 
			
		||||
        /// constructor for numbers (integer)
 | 
			
		||||
            value(number_t number) : number(number) {}
 | 
			
		||||
        value(number_t);
 | 
			
		||||
        /// constructor for numbers (float)
 | 
			
		||||
            value(number_float_t number_float) : number_float(number_float) {}
 | 
			
		||||
        value(number_float_t);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        /// the type of this object
 | 
			
		||||
        json_t _type;
 | 
			
		||||
 | 
			
		||||
        /// the payload
 | 
			
		||||
        value _value;
 | 
			
		||||
        
 | 
			
		||||
#ifdef __cplusplus11
 | 
			
		||||
        /// a type for array initialization
 | 
			
		||||
        typedef std::initializer_list<JSON> array_init_t;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  public:
 | 
			
		||||
        /// create a null object
 | 
			
		||||
        JSON();
 | 
			
		||||
    /// create an object according to given type
 | 
			
		||||
        JSON(json_t);
 | 
			
		||||
    JSON(const value_type) noexcept;
 | 
			
		||||
    /// create a null object
 | 
			
		||||
    JSON() = default;
 | 
			
		||||
    /// create a null object
 | 
			
		||||
    JSON(std::nullptr_t) noexcept;
 | 
			
		||||
    /// create a string object from a C++ string
 | 
			
		||||
        JSON(const std::string&);
 | 
			
		||||
    JSON(const std::string&) noexcept;
 | 
			
		||||
    /// create a string object from a C++ string (move)
 | 
			
		||||
    JSON(std::string&&) noexcept;
 | 
			
		||||
    /// create a string object from a C string
 | 
			
		||||
        JSON(char*);
 | 
			
		||||
        /// create a string object from a C string
 | 
			
		||||
        JSON(const char*);
 | 
			
		||||
    JSON(const char*) noexcept;
 | 
			
		||||
    /// create a Boolean object
 | 
			
		||||
        JSON(const bool);
 | 
			
		||||
    JSON(const bool) noexcept;
 | 
			
		||||
    /// create a number object
 | 
			
		||||
        JSON(const int);
 | 
			
		||||
    JSON(const int) noexcept;
 | 
			
		||||
    /// create a number object
 | 
			
		||||
        JSON(const double);
 | 
			
		||||
    JSON(const double) noexcept;
 | 
			
		||||
    /// create an array
 | 
			
		||||
        JSON(array_t);
 | 
			
		||||
    JSON(const array_t&) noexcept;
 | 
			
		||||
    /// create an array (move)
 | 
			
		||||
    JSON(array_t&&) noexcept;
 | 
			
		||||
    /// create an object
 | 
			
		||||
        JSON(object_t);
 | 
			
		||||
#ifdef __cplusplus11
 | 
			
		||||
        /// create from an initializer list (to an array)
 | 
			
		||||
        JSON(array_init_t);
 | 
			
		||||
#endif
 | 
			
		||||
    JSON(const object_t&) noexcept;
 | 
			
		||||
    /// create an object (move)
 | 
			
		||||
    JSON(object_t&&) noexcept;
 | 
			
		||||
    /// create from an initializer list (to an array or object)
 | 
			
		||||
    JSON(list_init_t) noexcept;
 | 
			
		||||
 | 
			
		||||
    /// copy constructor
 | 
			
		||||
        JSON(const JSON&);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus11
 | 
			
		||||
    JSON(const JSON&) noexcept;
 | 
			
		||||
    /// move constructor
 | 
			
		||||
        JSON(JSON&&);
 | 
			
		||||
#endif
 | 
			
		||||
    JSON(JSON&&) noexcept;
 | 
			
		||||
 | 
			
		||||
    /// copy assignment
 | 
			
		||||
#ifdef __cplusplus11
 | 
			
		||||
        JSON& operator=(JSON);
 | 
			
		||||
#else
 | 
			
		||||
        JSON& operator=(const JSON&);
 | 
			
		||||
#endif
 | 
			
		||||
    JSON& operator=(JSON) noexcept;
 | 
			
		||||
 | 
			
		||||
    /// destructor
 | 
			
		||||
        ~JSON();
 | 
			
		||||
    ~JSON() noexcept;
 | 
			
		||||
 | 
			
		||||
    /// create from string representation
 | 
			
		||||
    static JSON parse(std::string&);
 | 
			
		||||
    /// create from string representation
 | 
			
		||||
    static JSON parse(const char*);
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    /// return the type as string
 | 
			
		||||
    const std::string _typename() const noexcept;
 | 
			
		||||
 | 
			
		||||
  public:
 | 
			
		||||
    /// explicit value conversion
 | 
			
		||||
    template<typename T>
 | 
			
		||||
    T get() const;
 | 
			
		||||
 | 
			
		||||
    /// implicit conversion to string representation
 | 
			
		||||
    operator const std::string() const;
 | 
			
		||||
| 
						 | 
				
			
			@ -144,39 +161,45 @@ class JSON {
 | 
			
		|||
    /// implicit conversion to Boolean (only for Booleans)
 | 
			
		||||
    operator bool() const;
 | 
			
		||||
    /// implicit conversion to JSON vector (not for objects)
 | 
			
		||||
        operator std::vector<JSON>() const;
 | 
			
		||||
    operator array_t() const;
 | 
			
		||||
    /// implicit conversion to JSON map (only for objects)
 | 
			
		||||
        operator std::map<std::string, JSON>() const;
 | 
			
		||||
    operator object_t() const;
 | 
			
		||||
 | 
			
		||||
    /// write to stream
 | 
			
		||||
        friend std::ostream& operator<<(std::ostream& o, const JSON& j) {
 | 
			
		||||
    friend std::ostream& operator<<(std::ostream& o, const JSON& j)
 | 
			
		||||
    {
 | 
			
		||||
        o << j.toString();
 | 
			
		||||
        return o;
 | 
			
		||||
    }
 | 
			
		||||
    /// write to stream
 | 
			
		||||
        friend std::ostream& operator>>(const JSON& j, std::ostream& o) {
 | 
			
		||||
    friend std::ostream& operator>>(const JSON& j, std::ostream& o)
 | 
			
		||||
    {
 | 
			
		||||
        o << j.toString();
 | 
			
		||||
        return o;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// read from stream
 | 
			
		||||
        friend std::istream& operator>>(std::istream& i, JSON& j) {
 | 
			
		||||
            parser(i).parse(j);
 | 
			
		||||
    friend std::istream& operator>>(std::istream& i, JSON& j)
 | 
			
		||||
    {
 | 
			
		||||
        Parser(i).parse(j);
 | 
			
		||||
        return i;
 | 
			
		||||
    }
 | 
			
		||||
    /// read from stream
 | 
			
		||||
        friend std::istream& operator<<(JSON& j, std::istream& i) {
 | 
			
		||||
            parser(i).parse(j);
 | 
			
		||||
    friend std::istream& operator<<(JSON& j, std::istream& i)
 | 
			
		||||
    {
 | 
			
		||||
        Parser(i).parse(j);
 | 
			
		||||
        return i;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// explicit conversion to string representation (C++ style)
 | 
			
		||||
        const std::string toString() const;
 | 
			
		||||
    const std::string toString() const noexcept;
 | 
			
		||||
 | 
			
		||||
    /// add an object/array to an array
 | 
			
		||||
    JSON& operator+=(const JSON&);
 | 
			
		||||
    /// add a string to an array
 | 
			
		||||
    JSON& operator+=(const std::string&);
 | 
			
		||||
    /// add a null object to an array
 | 
			
		||||
    JSON& operator+=(const std::nullptr_t);
 | 
			
		||||
    /// add a string to an array
 | 
			
		||||
    JSON& operator+=(const char*);
 | 
			
		||||
    /// add a Boolean to an array
 | 
			
		||||
| 
						 | 
				
			
			@ -186,10 +209,19 @@ class JSON {
 | 
			
		|||
    /// add a number to an array
 | 
			
		||||
    JSON& operator+=(double);
 | 
			
		||||
 | 
			
		||||
    /// add a pair to an object
 | 
			
		||||
    JSON& operator+=(const object_t::value_type&);
 | 
			
		||||
    /// add a list of elements to array or list of pairs to object
 | 
			
		||||
    JSON& operator+=(list_init_t);
 | 
			
		||||
 | 
			
		||||
    /// add an object/array to an array
 | 
			
		||||
    void push_back(const JSON&);
 | 
			
		||||
    /// add an object/array to an array (move)
 | 
			
		||||
    void push_back(JSON&&);
 | 
			
		||||
    /// add a string to an array
 | 
			
		||||
    void push_back(const std::string&);
 | 
			
		||||
    /// add a null object to an array
 | 
			
		||||
    void push_back(const std::nullptr_t);
 | 
			
		||||
    /// add a string to an array
 | 
			
		||||
    void push_back(const char*);
 | 
			
		||||
    /// add a Boolean to an array
 | 
			
		||||
| 
						 | 
				
			
			@ -199,25 +231,42 @@ class JSON {
 | 
			
		|||
    /// add a number to an array
 | 
			
		||||
    void push_back(double);
 | 
			
		||||
 | 
			
		||||
    /// add a pair to an object
 | 
			
		||||
    void push_back(const object_t::value_type&);
 | 
			
		||||
    /// add a list of elements to array or list of pairs to object
 | 
			
		||||
    void push_back(list_init_t);
 | 
			
		||||
 | 
			
		||||
    /// operator to set an element in an array
 | 
			
		||||
        JSON& operator[](int);
 | 
			
		||||
    JSON& operator[](const int);
 | 
			
		||||
    /// operator to get an element in an array
 | 
			
		||||
    const JSON& operator[](const int) const;
 | 
			
		||||
    /// operator to get an element in an array
 | 
			
		||||
    JSON& at(const int);
 | 
			
		||||
    /// operator to get an element in an array
 | 
			
		||||
    const JSON& at(const int) const;
 | 
			
		||||
 | 
			
		||||
    /// operator to set an element in an object
 | 
			
		||||
        JSON& operator[](const std::string&);
 | 
			
		||||
    inline JSON& operator[](const std::string&);
 | 
			
		||||
    /// operator to set an element in an object
 | 
			
		||||
    JSON& operator[](const char*);
 | 
			
		||||
    /// operator to get an element in an object
 | 
			
		||||
    const JSON& operator[](const std::string&) const;
 | 
			
		||||
    /// operator to set an element in an object
 | 
			
		||||
    inline JSON& at(const std::string&);
 | 
			
		||||
    /// operator to set an element in an object
 | 
			
		||||
    JSON& at(const char*);
 | 
			
		||||
    /// operator to get an element in an object
 | 
			
		||||
    const JSON& at(const std::string&) const;
 | 
			
		||||
 | 
			
		||||
    /// return the number of stored values
 | 
			
		||||
        size_t size() const;
 | 
			
		||||
    size_t size() const noexcept;
 | 
			
		||||
    /// checks whether object is empty
 | 
			
		||||
        bool empty() const;
 | 
			
		||||
    bool empty() const noexcept;
 | 
			
		||||
    /// removes all elements from compounds and resets values to default
 | 
			
		||||
    void clear() noexcept;
 | 
			
		||||
 | 
			
		||||
    /// return the type of the object
 | 
			
		||||
        json_t type() const;
 | 
			
		||||
    value_type type() const noexcept;
 | 
			
		||||
 | 
			
		||||
    /// find an element in an object (returns end() iterator otherwise)
 | 
			
		||||
    iterator find(const std::string&);
 | 
			
		||||
| 
						 | 
				
			
			@ -229,31 +278,52 @@ class JSON {
 | 
			
		|||
    const_iterator find(const char*) const;
 | 
			
		||||
 | 
			
		||||
    /// direct access to the underlying payload
 | 
			
		||||
        value data();
 | 
			
		||||
    value data() noexcept;
 | 
			
		||||
    /// direct access to the underlying payload
 | 
			
		||||
        const value data() const;
 | 
			
		||||
    const value data() const noexcept;
 | 
			
		||||
 | 
			
		||||
    /// lexicographically compares the values
 | 
			
		||||
        bool operator==(const JSON&) const;
 | 
			
		||||
    bool operator==(const JSON&) const noexcept;
 | 
			
		||||
    /// lexicographically compares the values
 | 
			
		||||
        bool operator!=(const JSON&) const;
 | 
			
		||||
    inline bool operator!=(const JSON&) const noexcept;
 | 
			
		||||
 | 
			
		||||
    /// returns an iterator to the beginning (array/object)
 | 
			
		||||
    iterator begin() noexcept;
 | 
			
		||||
    /// returns an iterator to the end (array/object)
 | 
			
		||||
    iterator end() noexcept;
 | 
			
		||||
    /// returns an iterator to the beginning (array/object)
 | 
			
		||||
    const_iterator begin() const noexcept;
 | 
			
		||||
    /// returns an iterator to the end (array/object)
 | 
			
		||||
    const_iterator end() const noexcept;
 | 
			
		||||
    /// returns an iterator to the beginning (array/object)
 | 
			
		||||
    const_iterator cbegin() const noexcept;
 | 
			
		||||
    /// returns an iterator to the end (array/object)
 | 
			
		||||
    const_iterator cend() const noexcept;
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
        /// return the type as string
 | 
			
		||||
        std::string _typename() const;
 | 
			
		||||
    /// the type of this object
 | 
			
		||||
    value_type _type = value_type::null;
 | 
			
		||||
 | 
			
		||||
    /// the payload
 | 
			
		||||
    value _value {};
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    /// mutex to guard payload
 | 
			
		||||
    static std::mutex _token;
 | 
			
		||||
 | 
			
		||||
  public:
 | 
			
		||||
    /// an iterator
 | 
			
		||||
        class iterator {
 | 
			
		||||
    class iterator
 | 
			
		||||
    {
 | 
			
		||||
        friend class JSON;
 | 
			
		||||
        friend class JSON::const_iterator;
 | 
			
		||||
      public:
 | 
			
		||||
                iterator();
 | 
			
		||||
        iterator() = default;
 | 
			
		||||
        iterator(JSON*);
 | 
			
		||||
        iterator(const iterator&);
 | 
			
		||||
        ~iterator();
 | 
			
		||||
 | 
			
		||||
                iterator& operator=(const iterator&);
 | 
			
		||||
        iterator& operator=(iterator);
 | 
			
		||||
        bool operator==(const iterator&) const;
 | 
			
		||||
        bool operator!=(const iterator&) const;
 | 
			
		||||
        iterator& operator++();
 | 
			
		||||
| 
						 | 
				
			
			@ -267,24 +337,26 @@ class JSON {
 | 
			
		|||
 | 
			
		||||
      private:
 | 
			
		||||
        /// a JSON value
 | 
			
		||||
                JSON* _object;
 | 
			
		||||
        JSON* _object = nullptr;
 | 
			
		||||
        /// an iterator for JSON arrays
 | 
			
		||||
                array_t::iterator* _vi;
 | 
			
		||||
        array_t::iterator* _vi = nullptr;
 | 
			
		||||
        /// an iterator for JSON objects
 | 
			
		||||
                object_t::iterator* _oi;
 | 
			
		||||
        object_t::iterator* _oi = nullptr;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /// a const iterator
 | 
			
		||||
        class const_iterator {
 | 
			
		||||
    class const_iterator
 | 
			
		||||
    {
 | 
			
		||||
        friend class JSON;
 | 
			
		||||
 | 
			
		||||
      public:
 | 
			
		||||
                const_iterator();
 | 
			
		||||
        const_iterator() = default;
 | 
			
		||||
        const_iterator(const JSON*);
 | 
			
		||||
        const_iterator(const const_iterator&);
 | 
			
		||||
        const_iterator(const iterator&);
 | 
			
		||||
        ~const_iterator();
 | 
			
		||||
 | 
			
		||||
                const_iterator& operator=(const const_iterator&);
 | 
			
		||||
        const_iterator& operator=(const_iterator);
 | 
			
		||||
        bool operator==(const const_iterator&) const;
 | 
			
		||||
        bool operator!=(const const_iterator&) const;
 | 
			
		||||
        const_iterator& operator++();
 | 
			
		||||
| 
						 | 
				
			
			@ -298,33 +370,32 @@ class JSON {
 | 
			
		|||
 | 
			
		||||
      private:
 | 
			
		||||
        /// a JSON value
 | 
			
		||||
                const JSON* _object;
 | 
			
		||||
        const JSON* _object = nullptr;
 | 
			
		||||
        /// an iterator for JSON arrays
 | 
			
		||||
                array_t::const_iterator* _vi;
 | 
			
		||||
        array_t::const_iterator* _vi = nullptr;
 | 
			
		||||
        /// an iterator for JSON objects
 | 
			
		||||
                object_t::const_iterator* _oi;
 | 
			
		||||
        object_t::const_iterator* _oi = nullptr;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        iterator begin();
 | 
			
		||||
        iterator end();
 | 
			
		||||
        const_iterator begin() const;
 | 
			
		||||
        const_iterator end() const;
 | 
			
		||||
        const_iterator cbegin() const;
 | 
			
		||||
        const_iterator cend() const;
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    /// a helper class to parse a JSON object
 | 
			
		||||
        class parser {
 | 
			
		||||
    class Parser
 | 
			
		||||
    {
 | 
			
		||||
      public:
 | 
			
		||||
        /// a parser reading from a C string
 | 
			
		||||
                parser(char*);
 | 
			
		||||
        Parser(const char*);
 | 
			
		||||
        /// a parser reading from a C++ string
 | 
			
		||||
                parser(std::string&);
 | 
			
		||||
        Parser(std::string&);
 | 
			
		||||
        /// a parser reading from an input stream
 | 
			
		||||
                parser(std::istream&);
 | 
			
		||||
        Parser(std::istream&);
 | 
			
		||||
        /// destructor of the parser
 | 
			
		||||
                ~parser();
 | 
			
		||||
        ~Parser();
 | 
			
		||||
 | 
			
		||||
        // no copy constructor
 | 
			
		||||
        Parser(const Parser&) = delete;
 | 
			
		||||
        // no copy assignment
 | 
			
		||||
        Parser& operator=(Parser) = delete;
 | 
			
		||||
 | 
			
		||||
        /// parse into a given JSON object
 | 
			
		||||
        void parse(JSON&);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -332,7 +403,7 @@ class JSON {
 | 
			
		|||
        /// read the next character, stripping whitespace
 | 
			
		||||
        bool next();
 | 
			
		||||
        /// raise an exception with an error message
 | 
			
		||||
                void error(std::string) __attribute__((noreturn));
 | 
			
		||||
        void error(const std::string&) __attribute__((noreturn));
 | 
			
		||||
        /// parse a quoted string
 | 
			
		||||
        std::string parseString();
 | 
			
		||||
        /// parse a Boolean "true"
 | 
			
		||||
| 
						 | 
				
			
			@ -342,15 +413,19 @@ class JSON {
 | 
			
		|||
        /// parse a null object
 | 
			
		||||
        void parseNull();
 | 
			
		||||
        /// a helper function to expect a certain character
 | 
			
		||||
                void expect(char);
 | 
			
		||||
        void expect(const char);
 | 
			
		||||
 | 
			
		||||
                /// the current character
 | 
			
		||||
                char _current;
 | 
			
		||||
                /// a buffer of the input
 | 
			
		||||
                char* _buffer;
 | 
			
		||||
                /// the position inside the input buffer
 | 
			
		||||
                size_t _pos;
 | 
			
		||||
      private:
 | 
			
		||||
        /// the length of the input buffer
 | 
			
		||||
                size_t _length;
 | 
			
		||||
        size_t _length {};
 | 
			
		||||
        /// a buffer of the input
 | 
			
		||||
        char* _buffer { nullptr };
 | 
			
		||||
        /// the current character
 | 
			
		||||
        char _current {};
 | 
			
		||||
        /// the position inside the input buffer
 | 
			
		||||
        size_t _pos = 0;
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/// user-defined literal operator to create JSON objects from strings
 | 
			
		||||
JSON operator "" _json(const char*, size_t);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,7 +5,8 @@
 | 
			
		|||
#include <JSON.h>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
 | 
			
		||||
void test_null() {
 | 
			
		||||
void test_null()
 | 
			
		||||
{
 | 
			
		||||
    std::cerr << "entering test_null()\n";
 | 
			
		||||
 | 
			
		||||
    /* a null object */
 | 
			
		||||
| 
						 | 
				
			
			@ -29,7 +30,7 @@ void test_null() {
 | 
			
		|||
    assert(a == b);
 | 
			
		||||
 | 
			
		||||
    // type
 | 
			
		||||
    assert(a.type() == JSON::null);
 | 
			
		||||
    assert(a.type() == JSON::value_type::null);
 | 
			
		||||
 | 
			
		||||
    // empty and size
 | 
			
		||||
    assert(a.size() == 0);
 | 
			
		||||
| 
						 | 
				
			
			@ -42,43 +43,56 @@ void test_null() {
 | 
			
		|||
    assert(a.toString() == std::string("null"));
 | 
			
		||||
 | 
			
		||||
    // invalid conversion to int
 | 
			
		||||
    try {
 | 
			
		||||
    try
 | 
			
		||||
    {
 | 
			
		||||
        int i = 0;
 | 
			
		||||
        i = a;
 | 
			
		||||
        assert(false);
 | 
			
		||||
    } catch (const std::exception& ex) {
 | 
			
		||||
    }
 | 
			
		||||
    catch (const std::exception& ex)
 | 
			
		||||
    {
 | 
			
		||||
        assert(ex.what() == std::string("cannot cast null to JSON number"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // invalid conversion to double
 | 
			
		||||
    try {
 | 
			
		||||
    try
 | 
			
		||||
    {
 | 
			
		||||
        double f = 0;
 | 
			
		||||
        f = a;
 | 
			
		||||
        assert(false);
 | 
			
		||||
    } catch (const std::exception& ex) {
 | 
			
		||||
    }
 | 
			
		||||
    catch (const std::exception& ex)
 | 
			
		||||
    {
 | 
			
		||||
        assert(ex.what() == std::string("cannot cast null to JSON number"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // invalid conversion to bool
 | 
			
		||||
    try {
 | 
			
		||||
    try
 | 
			
		||||
    {
 | 
			
		||||
        bool b = a;
 | 
			
		||||
        assert(false);
 | 
			
		||||
    } catch (const std::exception& ex) {
 | 
			
		||||
    }
 | 
			
		||||
    catch (const std::exception& ex)
 | 
			
		||||
    {
 | 
			
		||||
        assert(ex.what() == std::string("cannot cast null to JSON Boolean"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // invalid conversion to string
 | 
			
		||||
    try {
 | 
			
		||||
    try
 | 
			
		||||
    {
 | 
			
		||||
        std::string s = a;
 | 
			
		||||
        assert(false);
 | 
			
		||||
    } catch (const std::exception& ex) {
 | 
			
		||||
    }
 | 
			
		||||
    catch (const std::exception& ex)
 | 
			
		||||
    {
 | 
			
		||||
        assert(ex.what() == std::string("cannot cast null to JSON string"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::cerr << "leaving test_null()\n";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test_bool() {
 | 
			
		||||
void test_bool()
 | 
			
		||||
{
 | 
			
		||||
    std::cerr << "entering test_bool()\n";
 | 
			
		||||
 | 
			
		||||
    JSON True = true;
 | 
			
		||||
| 
						 | 
				
			
			@ -89,7 +103,8 @@ void test_bool() {
 | 
			
		|||
    std::cerr << "leaving test_bool()\n";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test_string() {
 | 
			
		||||
void test_string()
 | 
			
		||||
{
 | 
			
		||||
    std::cerr << "entering test_string()\n";
 | 
			
		||||
 | 
			
		||||
    /* a string object */
 | 
			
		||||
| 
						 | 
				
			
			@ -114,7 +129,7 @@ void test_string() {
 | 
			
		|||
    assert(a == b);
 | 
			
		||||
 | 
			
		||||
    // type
 | 
			
		||||
    assert(a.type() == JSON::string);
 | 
			
		||||
    assert(a.type() == JSON::value_type::string);
 | 
			
		||||
 | 
			
		||||
    // empty and size
 | 
			
		||||
    assert(a.size() == 1);
 | 
			
		||||
| 
						 | 
				
			
			@ -127,29 +142,38 @@ void test_string() {
 | 
			
		|||
    assert(a.toString() == std::string("\"object a\""));
 | 
			
		||||
 | 
			
		||||
    // invalid conversion to int
 | 
			
		||||
    try {
 | 
			
		||||
    try
 | 
			
		||||
    {
 | 
			
		||||
        int i = 0;
 | 
			
		||||
        i = a;
 | 
			
		||||
        assert(false);
 | 
			
		||||
    } catch (const std::exception& ex) {
 | 
			
		||||
    }
 | 
			
		||||
    catch (const std::exception& ex)
 | 
			
		||||
    {
 | 
			
		||||
        assert(ex.what() == std::string("cannot cast string to JSON number"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // invalid conversion to double
 | 
			
		||||
    try {
 | 
			
		||||
    try
 | 
			
		||||
    {
 | 
			
		||||
        double f = 0;
 | 
			
		||||
        f = a;
 | 
			
		||||
        assert(false);
 | 
			
		||||
    } catch (const std::exception& ex) {
 | 
			
		||||
    }
 | 
			
		||||
    catch (const std::exception& ex)
 | 
			
		||||
    {
 | 
			
		||||
        assert(ex.what() == std::string("cannot cast string to JSON number"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // invalid conversion to bool
 | 
			
		||||
    try {
 | 
			
		||||
    try
 | 
			
		||||
    {
 | 
			
		||||
        bool b = false;
 | 
			
		||||
        b = a;
 | 
			
		||||
        assert(false);
 | 
			
		||||
    } catch (const std::exception& ex) {
 | 
			
		||||
    }
 | 
			
		||||
    catch (const std::exception& ex)
 | 
			
		||||
    {
 | 
			
		||||
        assert(ex.what() == std::string("cannot cast string to JSON Boolean"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -163,7 +187,8 @@ void test_string() {
 | 
			
		|||
    std::cerr << "leaving test_string()\n";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test_array() {
 | 
			
		||||
void test_array()
 | 
			
		||||
{
 | 
			
		||||
    std::cerr << "entering test_array()\n";
 | 
			
		||||
 | 
			
		||||
    JSON a;
 | 
			
		||||
| 
						 | 
				
			
			@ -174,7 +199,7 @@ void test_array() {
 | 
			
		|||
    a += "string";
 | 
			
		||||
 | 
			
		||||
    // type
 | 
			
		||||
    assert(a.type() == JSON::array);
 | 
			
		||||
    assert(a.type() == JSON::value_type::array);
 | 
			
		||||
 | 
			
		||||
    // empty and size
 | 
			
		||||
    assert(a.size() == 5);
 | 
			
		||||
| 
						 | 
				
			
			@ -190,10 +215,13 @@ void test_array() {
 | 
			
		|||
    assert(a[4] == JSON("string"));
 | 
			
		||||
 | 
			
		||||
    // invalid access to element
 | 
			
		||||
    try {
 | 
			
		||||
    try
 | 
			
		||||
    {
 | 
			
		||||
        a[5] = 1;
 | 
			
		||||
        assert(false);
 | 
			
		||||
    } catch (const std::exception& ex) {
 | 
			
		||||
//        assert(false);
 | 
			
		||||
    }
 | 
			
		||||
    catch (const std::exception& ex)
 | 
			
		||||
    {
 | 
			
		||||
        assert(ex.what() == std::string("cannot access element at index 5"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -217,7 +245,8 @@ void test_array() {
 | 
			
		|||
    // iterators
 | 
			
		||||
    {
 | 
			
		||||
        size_t count = 0;
 | 
			
		||||
        for (JSON::iterator i = a.begin(); i != a.end(); ++i) {
 | 
			
		||||
        for (JSON::iterator i = a.begin(); i != a.end(); ++i)
 | 
			
		||||
        {
 | 
			
		||||
            std::cerr << *i << '\n';
 | 
			
		||||
            count++;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -226,7 +255,8 @@ void test_array() {
 | 
			
		|||
 | 
			
		||||
    {
 | 
			
		||||
        size_t count = 0;
 | 
			
		||||
        for (JSON::const_iterator i = a.begin(); i != a.end(); ++i) {
 | 
			
		||||
        for (JSON::const_iterator i = a.begin(); i != a.end(); ++i)
 | 
			
		||||
        {
 | 
			
		||||
            std::cerr << *i << '\n';
 | 
			
		||||
            count++;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -235,7 +265,8 @@ void test_array() {
 | 
			
		|||
 | 
			
		||||
    {
 | 
			
		||||
        size_t count = 0;
 | 
			
		||||
        for (JSON::const_iterator i = a.cbegin(); i != a.cend(); ++i) {
 | 
			
		||||
        for (JSON::const_iterator i = a.cbegin(); i != a.cend(); ++i)
 | 
			
		||||
        {
 | 
			
		||||
            std::cerr << *i << '\n';
 | 
			
		||||
            count++;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -245,7 +276,8 @@ void test_array() {
 | 
			
		|||
#ifdef __cplusplus11
 | 
			
		||||
    {
 | 
			
		||||
        size_t count = 0;
 | 
			
		||||
        for (auto element : a) {
 | 
			
		||||
        for (auto element : a)
 | 
			
		||||
        {
 | 
			
		||||
            std::cerr << element << '\n';
 | 
			
		||||
            count++;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -256,7 +288,8 @@ void test_array() {
 | 
			
		|||
    {
 | 
			
		||||
        JSON::iterator i;
 | 
			
		||||
        size_t count = 0;
 | 
			
		||||
        for (i = a.begin(); i != a.end(); ++i) {
 | 
			
		||||
        for (i = a.begin(); i != a.end(); ++i)
 | 
			
		||||
        {
 | 
			
		||||
            std::cerr << *i << '\n';
 | 
			
		||||
            count++;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -266,7 +299,8 @@ void test_array() {
 | 
			
		|||
    {
 | 
			
		||||
        JSON::const_iterator i;
 | 
			
		||||
        size_t count = 0;
 | 
			
		||||
        for (i = a.begin(); i != a.end(); ++i) {
 | 
			
		||||
        for (i = a.begin(); i != a.end(); ++i)
 | 
			
		||||
        {
 | 
			
		||||
            std::cerr << *i << '\n';
 | 
			
		||||
            count++;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -276,7 +310,8 @@ void test_array() {
 | 
			
		|||
    {
 | 
			
		||||
        JSON::const_iterator i;
 | 
			
		||||
        size_t count = 0;
 | 
			
		||||
        for (i = a.cbegin(); i != a.cend(); ++i) {
 | 
			
		||||
        for (i = a.cbegin(); i != a.cend(); ++i)
 | 
			
		||||
        {
 | 
			
		||||
            std::cerr << *i << '\n';
 | 
			
		||||
            count++;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -293,7 +328,8 @@ void test_array() {
 | 
			
		|||
    std::cerr << "leaving test_array()\n";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test_object() {
 | 
			
		||||
void test_object()
 | 
			
		||||
{
 | 
			
		||||
    std::cerr << "entering test_object()\n";
 | 
			
		||||
 | 
			
		||||
    // check find()
 | 
			
		||||
| 
						 | 
				
			
			@ -321,7 +357,8 @@ void test_object() {
 | 
			
		|||
    std::cerr << "leaving test_object()\n";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test_streaming() {
 | 
			
		||||
void test_streaming()
 | 
			
		||||
{
 | 
			
		||||
    std::cerr << "entering test_streaming()\n";
 | 
			
		||||
 | 
			
		||||
    // stream text representation into stream
 | 
			
		||||
| 
						 | 
				
			
			@ -343,13 +380,13 @@ void test_streaming() {
 | 
			
		|||
        i >> j;
 | 
			
		||||
        j >> o;
 | 
			
		||||
        o >> k;
 | 
			
		||||
        assert(j.toString() == k.toString());
 | 
			
		||||
        // assert(j.toString() == k.toString()); (order is not preserved)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // check numbers
 | 
			
		||||
    {
 | 
			
		||||
        std::stringstream number_stream;
 | 
			
		||||
        number_stream << "[0, -1, 1, 1.0, -1.0, 1.0e+1, 1.0e-1, 1.0E+1, 1.0E-1, -1.2345678e-12345678]";
 | 
			
		||||
        number_stream << "[0, -1, 1, 1.0, -1.0, 1.0e+1, 1.0e-1, 1.0E+1, 1.0E-1, -1.2345678e-12]";
 | 
			
		||||
        JSON j;
 | 
			
		||||
        j << number_stream;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -373,7 +410,8 @@ void test_streaming() {
 | 
			
		|||
    std::cerr << "leaving test_streaming()\n";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main() {
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
    test_null();
 | 
			
		||||
    test_bool();
 | 
			
		||||
    test_string();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										1038
									
								
								test/JSON_unit.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1038
									
								
								test/JSON_unit.cc
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										11025
									
								
								test/catch.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11025
									
								
								test/catch.hpp
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue