Merge pull request #36 from nlohmann/template
template version with re2c scanner
This commit is contained in:
commit
118ec996fd
22 changed files with 19746 additions and 19558 deletions
50
.gitignore
vendored
50
.gitignore
vendored
|
@ -1,50 +1,2 @@
|
|||
.DS_Store
|
||||
src/.DS_Store
|
||||
|
||||
aclocal.m4
|
||||
|
||||
autom4te.cache/*
|
||||
|
||||
config.log
|
||||
|
||||
config.status
|
||||
|
||||
configure
|
||||
|
||||
depcomp
|
||||
|
||||
html
|
||||
|
||||
*.o
|
||||
|
||||
*.Po
|
||||
|
||||
install-sh
|
||||
|
||||
json_unit
|
||||
|
||||
Makefile
|
||||
|
||||
missing
|
||||
|
||||
.dirstamp
|
||||
|
||||
test-driver
|
||||
|
||||
Makefile.in
|
||||
|
||||
*.plist
|
||||
|
||||
json_parser
|
||||
|
||||
CMakeCache.txt
|
||||
|
||||
*.cmake
|
||||
|
||||
CMakeFiles
|
||||
|
||||
libjson.a
|
||||
|
||||
Testing
|
||||
|
||||
.idea
|
||||
html
|
||||
|
|
13
.travis.yml
13
.travis.yml
|
@ -6,15 +6,11 @@ compiler:
|
|||
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
|
||||
- if [ "$CXX" = "g++" ]; then sudo apt-get install -qq g++-4.9; fi
|
||||
- if [ "$CXX" = "g++" ]; then export CXX="g++-4.9" CC="gcc-4.9"; fi
|
||||
- sudo pip install cpp-coveralls pyyaml
|
||||
- sudo apt-get install valgrind
|
||||
|
||||
before_script:
|
||||
- autoreconf -iv
|
||||
- ./configure
|
||||
|
||||
script:
|
||||
- make
|
||||
- ./json_unit
|
||||
|
@ -22,6 +18,7 @@ script:
|
|||
|
||||
after_success:
|
||||
- make clean
|
||||
- make json_unit CXXFLAGS="-fprofile-arcs -ftest-coverage"
|
||||
- touch src/json.hpp
|
||||
- make json_unit CXXFLAGS="-fprofile-arcs -ftest-coverage -std=c++11"
|
||||
- ./json_unit
|
||||
- coveralls --exclude benchmark --exclude test --exclude header_only --gcov-options '\-lp' --gcov 'gcov-4.8'
|
||||
- coveralls --exclude test/catch.hpp --exclude test/unit.cpp --include src/json.hpp --gcov-options '\-lp' --gcov 'gcov-4.9'
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
cmake_minimum_required(VERSION 2.8.4)
|
||||
project(json)
|
||||
|
||||
# Enable C++11 and set flags for coverage testing
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -g -O0 --coverage -fprofile-arcs -ftest-coverage")
|
||||
|
||||
# Make everything public for testing purposes
|
||||
add_definitions(-Dprivate=public)
|
||||
|
||||
# If not specified, use Debug as build type (necessary for coverage testing)
|
||||
if( NOT CMAKE_BUILD_TYPE )
|
||||
set( CMAKE_BUILD_TYPE Debug CACHE STRING
|
||||
""
|
||||
FORCE )
|
||||
endif()
|
||||
|
||||
# CMake addons for lcov
|
||||
# Only possible with g++ at the moment. We run otherwise just the test
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 --coverage -fprofile-arcs -ftest-coverage")
|
||||
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeModules)
|
||||
include(CodeCoverage)
|
||||
|
||||
setup_coverage(coverage)
|
||||
endif()
|
||||
|
||||
# Normal sources
|
||||
include_directories(src/)
|
||||
aux_source_directory(src/ json_list)
|
||||
add_library(json ${json_list})
|
||||
|
||||
# Testing
|
||||
enable_testing()
|
||||
|
||||
# Search all test files in the test directory with a .cc suffix
|
||||
file(GLOB TEST_FILES "test/*.cc")
|
||||
foreach(TEST_FILE ${TEST_FILES})
|
||||
# We use the basename to identify the test. E.g "json_unit" for "json_unit.cc"
|
||||
get_filename_component(BASENAME ${TEST_FILE} NAME_WE)
|
||||
# Create a test executable
|
||||
add_executable(${BASENAME} ${TEST_FILE})
|
||||
# Link it with our main json file
|
||||
target_link_libraries(${BASENAME} json)
|
||||
|
||||
# Add test if people want to use ctest
|
||||
add_test(${BASENAME} ${BASENAME})
|
||||
|
||||
# If we are using g++, we also need to setup the commands for coverage
|
||||
# testing
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
# Add a run_XXX target that runs the executable and produces the
|
||||
# coverage data automatically
|
||||
add_custom_target(run_${BASENAME} COMMAND ./${BASENAME})
|
||||
# Make sure that running requires the executable to be build
|
||||
add_dependencies (run_${BASENAME} ${BASENAME})
|
||||
# To create a valid coverage report, the executable has to be
|
||||
# executed first
|
||||
add_dependencies (coverage run_${BASENAME})
|
||||
endif()
|
||||
endforeach()
|
||||
|
|
@ -1,116 +0,0 @@
|
|||
#
|
||||
#
|
||||
# 2012-01-31, Lars Bilke
|
||||
# - Enable Code Coverage
|
||||
#
|
||||
# 2013-09-17, Joakim Söderberg
|
||||
# - Added support for Clang.
|
||||
# - Some additional usage instructions.
|
||||
#
|
||||
# USAGE:
|
||||
|
||||
# 0. (Mac only) If you use Xcode 5.1 make sure to patch geninfo as described here:
|
||||
# http://stackoverflow.com/a/22404544/80480
|
||||
#
|
||||
# 1. Copy this file into your cmake modules path.
|
||||
#
|
||||
# 2. Add the following line to your CMakeLists.txt:
|
||||
# INCLUDE(CodeCoverage)
|
||||
#
|
||||
# 3. Set compiler flags to turn off optimization and enable coverage:
|
||||
# SET(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
|
||||
# SET(CMAKE_C_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
|
||||
#
|
||||
# 3. Use the function SETUP_TARGET_FOR_COVERAGE to create a custom make target
|
||||
# which runs your test executable and produces a lcov code coverage report:
|
||||
# Example:
|
||||
# SETUP_TARGET_FOR_COVERAGE(
|
||||
# my_coverage_target # Name for custom target.
|
||||
# test_driver # Name of the test driver executable that runs the tests.
|
||||
# # NOTE! This should always have a ZERO as exit code
|
||||
# # otherwise the coverage generation will not complete.
|
||||
# coverage # Name of output directory.
|
||||
# )
|
||||
#
|
||||
# 4. Build a Debug build:
|
||||
# cmake -DCMAKE_BUILD_TYPE=Debug ..
|
||||
# make
|
||||
# make my_coverage_target
|
||||
#
|
||||
#
|
||||
|
||||
# Check prereqs
|
||||
FIND_PROGRAM( GCOV_PATH gcov )
|
||||
FIND_PROGRAM( LCOV_PATH lcov )
|
||||
FIND_PROGRAM( GENHTML_PATH genhtml )
|
||||
FIND_PROGRAM( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/tests)
|
||||
|
||||
IF(NOT GCOV_PATH)
|
||||
MESSAGE(FATAL_ERROR "gcov not found! Aborting...")
|
||||
ENDIF() # NOT GCOV_PATH
|
||||
|
||||
IF(NOT CMAKE_COMPILER_IS_GNUCXX)
|
||||
# Clang version 3.0.0 and greater now supports gcov as well.
|
||||
MESSAGE(WARNING "Compiler is not GNU gcc! Clang Version 3.0.0 and greater supports gcov as well, but older versions don't.")
|
||||
|
||||
IF(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
MESSAGE(FATAL_ERROR "Compiler is not GNU gcc! Aborting...")
|
||||
ENDIF()
|
||||
ENDIF() # NOT CMAKE_COMPILER_IS_GNUCXX
|
||||
|
||||
SET(CMAKE_CXX_FLAGS_COVERAGE
|
||||
"-g -O0 --coverage -fprofile-arcs -ftest-coverage"
|
||||
CACHE STRING "Flags used by the C++ compiler during coverage builds."
|
||||
FORCE )
|
||||
SET(CMAKE_C_FLAGS_COVERAGE
|
||||
"-g -O0 --coverage -fprofile-arcs -ftest-coverage"
|
||||
CACHE STRING "Flags used by the C compiler during coverage builds."
|
||||
FORCE )
|
||||
SET(CMAKE_EXE_LINKER_FLAGS_COVERAGE
|
||||
""
|
||||
CACHE STRING "Flags used for linking binaries during coverage builds."
|
||||
FORCE )
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
|
||||
""
|
||||
CACHE STRING "Flags used by the shared libraries linker during coverage builds."
|
||||
FORCE )
|
||||
MARK_AS_ADVANCED(
|
||||
CMAKE_CXX_FLAGS_COVERAGE
|
||||
CMAKE_C_FLAGS_COVERAGE
|
||||
CMAKE_EXE_LINKER_FLAGS_COVERAGE
|
||||
CMAKE_SHARED_LINKER_FLAGS_COVERAGE )
|
||||
|
||||
IF ( NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "Coverage"))
|
||||
MESSAGE( WARNING "Code coverage results with an optimized (non-Debug) build may be misleading" )
|
||||
ENDIF() # NOT CMAKE_BUILD_TYPE STREQUAL "Debug"
|
||||
|
||||
|
||||
# Param _outputname lcov output is generated as _outputname.info
|
||||
# HTML report is generated in _outputname/index.html
|
||||
FUNCTION(SETUP_COVERAGE _outputname)
|
||||
|
||||
IF(NOT LCOV_PATH)
|
||||
MESSAGE(FATAL_ERROR "lcov not found! Aborting...")
|
||||
ENDIF() # NOT LCOV_PATH
|
||||
|
||||
IF(NOT GENHTML_PATH)
|
||||
MESSAGE(FATAL_ERROR "genhtml not found! Aborting...")
|
||||
ENDIF() # NOT GENHTML_PATH
|
||||
|
||||
# Setup target
|
||||
ADD_CUSTOM_TARGET(coverage
|
||||
|
||||
|
||||
# Capturing lcov counters and generating report
|
||||
COMMAND ${LCOV_PATH} --rc lcov_branch_coverage=1 --directory . --capture --output-file ${_outputname}.info
|
||||
COMMAND ${LCOV_PATH} --rc lcov_branch_coverage=1 --remove ${_outputname}.info 'tests/*' '/usr/*' --output-file ${_outputname}.info.cleaned
|
||||
COMMAND ${GENHTML_PATH} --branch-coverage --rc lcov_branch_coverage=1 -o ${_outputname} ${_outputname}.info.cleaned
|
||||
COMMAND ${CMAKE_COMMAND} -E remove ${_outputname}.info ${_outputname}.info.cleaned
|
||||
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report."
|
||||
# Cleanup lcov
|
||||
${LCOV_PATH} --directory . --zerocounters
|
||||
)
|
||||
|
||||
ENDFUNCTION() # SETUP_TARGET_FOR_COVERAGE
|
314
Doxyfile
Normal file
314
Doxyfile
Normal file
|
@ -0,0 +1,314 @@
|
|||
# Doxyfile 1.8.9.1
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Project related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = "JSON for Modern C++"
|
||||
PROJECT_NUMBER = 3.0
|
||||
PROJECT_BRIEF =
|
||||
PROJECT_LOGO =
|
||||
OUTPUT_DIRECTORY = .
|
||||
CREATE_SUBDIRS = NO
|
||||
ALLOW_UNICODE_NAMES = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
REPEAT_BRIEF = NO
|
||||
ABBREVIATE_BRIEF =
|
||||
ALWAYS_DETAILED_SEC = YES
|
||||
INLINE_INHERITED_MEMB = NO
|
||||
FULL_PATH_NAMES = YES
|
||||
STRIP_FROM_PATH =
|
||||
STRIP_FROM_INC_PATH =
|
||||
SHORT_NAMES = NO
|
||||
JAVADOC_AUTOBRIEF = NO
|
||||
QT_AUTOBRIEF = NO
|
||||
MULTILINE_CPP_IS_BRIEF = NO
|
||||
INHERIT_DOCS = YES
|
||||
SEPARATE_MEMBER_PAGES = NO
|
||||
TAB_SIZE = 4
|
||||
ALIASES =
|
||||
TCL_SUBST =
|
||||
OPTIMIZE_OUTPUT_FOR_C = NO
|
||||
OPTIMIZE_OUTPUT_JAVA = NO
|
||||
OPTIMIZE_FOR_FORTRAN = NO
|
||||
OPTIMIZE_OUTPUT_VHDL = NO
|
||||
EXTENSION_MAPPING =
|
||||
MARKDOWN_SUPPORT = YES
|
||||
AUTOLINK_SUPPORT = YES
|
||||
BUILTIN_STL_SUPPORT = YES
|
||||
CPP_CLI_SUPPORT = NO
|
||||
SIP_SUPPORT = NO
|
||||
IDL_PROPERTY_SUPPORT = YES
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
SUBGROUPING = YES
|
||||
INLINE_GROUPED_CLASSES = NO
|
||||
INLINE_SIMPLE_STRUCTS = NO
|
||||
TYPEDEF_HIDES_STRUCT = NO
|
||||
LOOKUP_CACHE_SIZE = 0
|
||||
#---------------------------------------------------------------------------
|
||||
# Build related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
EXTRACT_ALL = YES
|
||||
EXTRACT_PRIVATE = YES
|
||||
EXTRACT_PACKAGE = YES
|
||||
EXTRACT_STATIC = YES
|
||||
EXTRACT_LOCAL_CLASSES = YES
|
||||
EXTRACT_LOCAL_METHODS = YES
|
||||
EXTRACT_ANON_NSPACES = YES
|
||||
HIDE_UNDOC_MEMBERS = NO
|
||||
HIDE_UNDOC_CLASSES = NO
|
||||
HIDE_FRIEND_COMPOUNDS = NO
|
||||
HIDE_IN_BODY_DOCS = NO
|
||||
INTERNAL_DOCS = NO
|
||||
CASE_SENSE_NAMES = NO
|
||||
HIDE_SCOPE_NAMES = NO
|
||||
HIDE_COMPOUND_REFERENCE= NO
|
||||
SHOW_INCLUDE_FILES = YES
|
||||
SHOW_GROUPED_MEMB_INC = NO
|
||||
FORCE_LOCAL_INCLUDES = NO
|
||||
INLINE_INFO = YES
|
||||
SORT_MEMBER_DOCS = YES
|
||||
SORT_BRIEF_DOCS = NO
|
||||
SORT_MEMBERS_CTORS_1ST = YES
|
||||
SORT_GROUP_NAMES = NO
|
||||
SORT_BY_SCOPE_NAME = NO
|
||||
STRICT_PROTO_MATCHING = NO
|
||||
GENERATE_TODOLIST = YES
|
||||
GENERATE_TESTLIST = YES
|
||||
GENERATE_BUGLIST = YES
|
||||
GENERATE_DEPRECATEDLIST= YES
|
||||
ENABLED_SECTIONS =
|
||||
MAX_INITIALIZER_LINES = 30
|
||||
SHOW_USED_FILES = YES
|
||||
SHOW_FILES = YES
|
||||
SHOW_NAMESPACES = YES
|
||||
FILE_VERSION_FILTER =
|
||||
LAYOUT_FILE =
|
||||
CITE_BIB_FILES =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to warning and progress messages
|
||||
#---------------------------------------------------------------------------
|
||||
QUIET = YES
|
||||
WARNINGS = YES
|
||||
WARN_IF_UNDOCUMENTED = YES
|
||||
WARN_IF_DOC_ERROR = YES
|
||||
WARN_NO_PARAMDOC = NO
|
||||
WARN_FORMAT = "$file:$line: $text"
|
||||
WARN_LOGFILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
INPUT = src/json.hpp
|
||||
INPUT_ENCODING = UTF-8
|
||||
FILE_PATTERNS =
|
||||
RECURSIVE = NO
|
||||
EXCLUDE =
|
||||
EXCLUDE_SYMLINKS = NO
|
||||
EXCLUDE_PATTERNS =
|
||||
EXCLUDE_SYMBOLS =
|
||||
EXAMPLE_PATH =
|
||||
EXAMPLE_PATTERNS =
|
||||
EXAMPLE_RECURSIVE = NO
|
||||
IMAGE_PATH =
|
||||
INPUT_FILTER =
|
||||
FILTER_PATTERNS =
|
||||
FILTER_SOURCE_FILES = NO
|
||||
FILTER_SOURCE_PATTERNS =
|
||||
USE_MDFILE_AS_MAINPAGE =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to source browsing
|
||||
#---------------------------------------------------------------------------
|
||||
SOURCE_BROWSER = YES
|
||||
INLINE_SOURCES = YES
|
||||
STRIP_CODE_COMMENTS = YES
|
||||
REFERENCED_BY_RELATION = YES
|
||||
REFERENCES_RELATION = YES
|
||||
REFERENCES_LINK_SOURCE = YES
|
||||
SOURCE_TOOLTIPS = YES
|
||||
USE_HTAGS = NO
|
||||
VERBATIM_HEADERS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the alphabetical class index
|
||||
#---------------------------------------------------------------------------
|
||||
ALPHABETICAL_INDEX = YES
|
||||
COLS_IN_ALPHA_INDEX = 5
|
||||
IGNORE_PREFIX =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the HTML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_HTML = YES
|
||||
HTML_OUTPUT = html
|
||||
HTML_FILE_EXTENSION = .html
|
||||
HTML_HEADER =
|
||||
HTML_FOOTER =
|
||||
HTML_STYLESHEET =
|
||||
HTML_EXTRA_STYLESHEET =
|
||||
HTML_EXTRA_FILES =
|
||||
HTML_COLORSTYLE_HUE = 220
|
||||
HTML_COLORSTYLE_SAT = 100
|
||||
HTML_COLORSTYLE_GAMMA = 80
|
||||
HTML_TIMESTAMP = YES
|
||||
HTML_DYNAMIC_SECTIONS = NO
|
||||
HTML_INDEX_NUM_ENTRIES = 100
|
||||
GENERATE_DOCSET = NO
|
||||
DOCSET_FEEDNAME = "Doxygen generated docs"
|
||||
DOCSET_BUNDLE_ID = org.doxygen.Project
|
||||
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
|
||||
DOCSET_PUBLISHER_NAME = Publisher
|
||||
GENERATE_HTMLHELP = NO
|
||||
CHM_FILE =
|
||||
HHC_LOCATION =
|
||||
GENERATE_CHI = NO
|
||||
CHM_INDEX_ENCODING =
|
||||
BINARY_TOC = NO
|
||||
TOC_EXPAND = NO
|
||||
GENERATE_QHP = NO
|
||||
QCH_FILE =
|
||||
QHP_NAMESPACE = org.doxygen.Project
|
||||
QHP_VIRTUAL_FOLDER = doc
|
||||
QHP_CUST_FILTER_NAME =
|
||||
QHP_CUST_FILTER_ATTRS =
|
||||
QHP_SECT_FILTER_ATTRS =
|
||||
QHG_LOCATION =
|
||||
GENERATE_ECLIPSEHELP = NO
|
||||
ECLIPSE_DOC_ID = org.doxygen.Project
|
||||
DISABLE_INDEX = NO
|
||||
GENERATE_TREEVIEW = YES
|
||||
ENUM_VALUES_PER_LINE = 4
|
||||
TREEVIEW_WIDTH = 250
|
||||
EXT_LINKS_IN_WINDOW = NO
|
||||
FORMULA_FONTSIZE = 10
|
||||
FORMULA_TRANSPARENT = YES
|
||||
USE_MATHJAX = NO
|
||||
MATHJAX_FORMAT = HTML-CSS
|
||||
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
|
||||
MATHJAX_EXTENSIONS =
|
||||
MATHJAX_CODEFILE =
|
||||
SEARCHENGINE = YES
|
||||
SERVER_BASED_SEARCH = NO
|
||||
EXTERNAL_SEARCH = NO
|
||||
SEARCHENGINE_URL =
|
||||
SEARCHDATA_FILE = searchdata.xml
|
||||
EXTERNAL_SEARCH_ID =
|
||||
EXTRA_SEARCH_MAPPINGS =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the LaTeX output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_LATEX = NO
|
||||
LATEX_OUTPUT = latex
|
||||
LATEX_CMD_NAME = latex
|
||||
MAKEINDEX_CMD_NAME = makeindex
|
||||
COMPACT_LATEX = NO
|
||||
PAPER_TYPE = a4
|
||||
EXTRA_PACKAGES =
|
||||
LATEX_HEADER =
|
||||
LATEX_FOOTER =
|
||||
LATEX_EXTRA_STYLESHEET =
|
||||
LATEX_EXTRA_FILES =
|
||||
PDF_HYPERLINKS = YES
|
||||
USE_PDFLATEX = YES
|
||||
LATEX_BATCHMODE = NO
|
||||
LATEX_HIDE_INDICES = NO
|
||||
LATEX_SOURCE_CODE = NO
|
||||
LATEX_BIB_STYLE = plain
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the RTF output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_RTF = NO
|
||||
RTF_OUTPUT = rtf
|
||||
COMPACT_RTF = NO
|
||||
RTF_HYPERLINKS = NO
|
||||
RTF_STYLESHEET_FILE =
|
||||
RTF_EXTENSIONS_FILE =
|
||||
RTF_SOURCE_CODE = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the man page output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_MAN = NO
|
||||
MAN_OUTPUT = man
|
||||
MAN_EXTENSION = .3
|
||||
MAN_SUBDIR =
|
||||
MAN_LINKS = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the XML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_XML = NO
|
||||
XML_OUTPUT = xml
|
||||
XML_PROGRAMLISTING = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the DOCBOOK output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_DOCBOOK = NO
|
||||
DOCBOOK_OUTPUT = docbook
|
||||
DOCBOOK_PROGRAMLISTING = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options for the AutoGen Definitions output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_AUTOGEN_DEF = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the Perl module output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_PERLMOD = NO
|
||||
PERLMOD_LATEX = NO
|
||||
PERLMOD_PRETTY = YES
|
||||
PERLMOD_MAKEVAR_PREFIX =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the preprocessor
|
||||
#---------------------------------------------------------------------------
|
||||
ENABLE_PREPROCESSING = YES
|
||||
MACRO_EXPANSION = NO
|
||||
EXPAND_ONLY_PREDEF = NO
|
||||
SEARCH_INCLUDES = YES
|
||||
INCLUDE_PATH =
|
||||
INCLUDE_FILE_PATTERNS =
|
||||
PREDEFINED =
|
||||
EXPAND_AS_DEFINED =
|
||||
SKIP_FUNCTION_MACROS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to external references
|
||||
#---------------------------------------------------------------------------
|
||||
TAGFILES =
|
||||
GENERATE_TAGFILE =
|
||||
ALLEXTERNALS = NO
|
||||
EXTERNAL_GROUPS = YES
|
||||
EXTERNAL_PAGES = YES
|
||||
PERL_PATH = /usr/bin/perl
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
CLASS_DIAGRAMS = YES
|
||||
MSCGEN_PATH =
|
||||
DIA_PATH =
|
||||
HIDE_UNDOC_RELATIONS = YES
|
||||
HAVE_DOT = YES
|
||||
DOT_NUM_THREADS = 0
|
||||
DOT_FONTNAME = Helvetica
|
||||
DOT_FONTSIZE = 10
|
||||
DOT_FONTPATH =
|
||||
CLASS_GRAPH = YES
|
||||
COLLABORATION_GRAPH = YES
|
||||
GROUP_GRAPHS = YES
|
||||
UML_LOOK = YES
|
||||
UML_LIMIT_NUM_FIELDS = 10
|
||||
TEMPLATE_RELATIONS = YES
|
||||
INCLUDE_GRAPH = YES
|
||||
INCLUDED_BY_GRAPH = YES
|
||||
CALL_GRAPH = YES
|
||||
CALLER_GRAPH = YES
|
||||
GRAPHICAL_HIERARCHY = YES
|
||||
DIRECTORY_GRAPH = YES
|
||||
DOT_IMAGE_FORMAT = svg
|
||||
INTERACTIVE_SVG = YES
|
||||
DOT_PATH =
|
||||
DOTFILE_DIRS =
|
||||
MSCFILE_DIRS =
|
||||
DIAFILE_DIRS =
|
||||
PLANTUML_JAR_PATH =
|
||||
PLANTUML_INCLUDE_PATH =
|
||||
DOT_GRAPH_MAX_NODES = 50
|
||||
MAX_DOT_GRAPH_DEPTH = 0
|
||||
DOT_TRANSPARENT = NO
|
||||
DOT_MULTI_TARGETS = NO
|
||||
GENERATE_LEGEND = YES
|
||||
DOT_CLEANUP = YES
|
|
@ -1,7 +1,7 @@
|
|||
The library is licensed under the MIT License
|
||||
<http://opensource.org/licenses/MIT>:
|
||||
|
||||
Copyright (c) 2013-2014 Niels Lohmann
|
||||
Copyright (c) 2013-2015 Niels Lohmann
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
|
|
33
Makefile
Normal file
33
Makefile
Normal file
|
@ -0,0 +1,33 @@
|
|||
# used programs
|
||||
RE2C = re2c
|
||||
SED = gsed
|
||||
|
||||
# additional flags
|
||||
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
|
||||
|
||||
all: json_unit
|
||||
|
||||
# clean up
|
||||
clean:
|
||||
rm -f json_unit
|
||||
|
||||
# build unit tests
|
||||
json_unit: test/unit.cpp src/json.hpp test/catch.hpp
|
||||
$(CXX) -std=c++11 $(CXXFLAGS) $(FLAGS) $(CPPFLAGS) -I src -I test -Dprivate=public $< $(LDFLAGS) -o $@
|
||||
|
||||
# create scanner with re2c
|
||||
re2c: src/json.hpp.re2c
|
||||
$(RE2C) -b -s -i --no-generation-date $< | $(SED) '1d' > src/json.hpp
|
||||
|
||||
# static analyser
|
||||
cppcheck:
|
||||
cppcheck --enable=all --inconclusive --std=c++11 src/json.hpp
|
||||
|
||||
# pretty printer
|
||||
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 \
|
||||
src/json.hpp src/json.hpp.re2c test/unit.cpp
|
41
Makefile.am
41
Makefile.am
|
@ -1,41 +0,0 @@
|
|||
.PHONY: header_only
|
||||
|
||||
# the order is important: header before other sources
|
||||
CORE_SOURCES = src/json.h src/json.cc
|
||||
|
||||
noinst_PROGRAMS = json_unit json_parser
|
||||
|
||||
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_unit_SOURCES = $(CORE_SOURCES) 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
|
||||
|
||||
json_parser_SOURCES = $(CORE_SOURCES) benchmark/parse.cc
|
||||
json_parser_CXXFLAGS = -O3 -std=c++11 -flto
|
||||
json_parser_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/benchmark
|
||||
|
||||
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
|
||||
for DIR in $(DIST_SUBDIRS) .; do rm -f $$DIR/Makefile.in; done
|
||||
|
||||
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)
|
||||
|
||||
parser:
|
||||
make CXXFLAGS="" json_parser
|
||||
|
||||
header_only/json.h: $(CORE_SOURCES)
|
||||
$(AM_V_GEN)
|
||||
$(AM_V_at)mkdir -p header_only
|
||||
$(AM_V_at)cat $(CORE_SOURCES) | $(SED) 's/#include "json.h"//' > header_only/json.h
|
||||
|
||||
BUILT_SOURCES = header_only/json.h
|
71
README.md
71
README.md
|
@ -10,34 +10,45 @@
|
|||
|
||||
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:
|
||||
|
||||
- **Intuitive syntax**. In languages such as Python, JSON feels like a first class data type. We used all the operator magic of modern C++ to achieve the same feeling in your code. Check out the [examples below](#examples) and the [reference](https://github.com/nlohmann/json/blob/master/doc/Reference.md), 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 modern C++ to achieve the same feeling in your code. Check out the [examples below](#examples) and you know, what I mean.
|
||||
|
||||
- **Trivial integration**. Our whole code consists of a class in 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, everything should require no adjustment of your compiler flags or project settings.
|
||||
- **Trivial integration**. Our whole code consists of a single header file `json.hpp`. That's it. No library, no subproject, no dependencies, no complex build system. The class is written in vanilla C++11. All in all, everything should require no adjustment of your compiler flags or project settings.
|
||||
|
||||
- **Serious testing**. Our class is heavily [unit-tested](https://github.com/nlohmann/json/blob/master/test/json_unit.cc) and covers [100%](https://coveralls.io/r/nlohmann/json) of the code, including all exceptional behavior. Furthermore, we checked with [Valgrind](http://valgrind.org) that there are no memory leaks.
|
||||
|
||||
Other aspects were not so important to us:
|
||||
|
||||
- **Memory efficiency**. Each JSON object has an overhead of one pointer (the maximal size of a union) and one enumeration element (1 byte). We use the following C++ data types: `std::string` for strings, `int64_t` or `double` for numbers, `std::map` for objects, `std::vector` for arrays, and `bool` for Booleans. We know that there are more efficient ways to store the values, but we are happy enough right now.
|
||||
- **Memory efficiency**. Each JSON object has an overhead of one pointer (the maximal size of a union) and one enumeration element (1 byte). The default generalization uses the following C++ data types: `std::string` for strings, `int64_t` or `double` for numbers, `std::map` for objects, `std::vector` for arrays, and `bool` for Booleans. However, you can template the generalized class `basic_json` to your needs.
|
||||
|
||||
- **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).
|
||||
|
||||
- **Rigorous standard compliance**. Any [compliant](http://json.org) JSON file can be read by our class, and any output of the class is standard-compliant. However, we do not check for some details in the format of numbers and strings. For instance, `-0` will be treated as `0` whereas the standard forbids this. Furthermore, we allow for more escape symbols in strings as the JSON specification. While this may not be a problem in reality, we are aware of it, but as long as we have a hand-written parser, we won't invest too much to be fully compliant.
|
||||
- **Rigorous Unicode compliance**. We did our best to implement some robust Unicode support. There are still some issues with escaping, and if you run into a problem, please [tell me](https://github.com/nlohmann/json/issues).
|
||||
|
||||
## Updates since last version
|
||||
|
||||
As of February 2015, the following updates were made to the library
|
||||
|
||||
- *Changed:* In the generic class `basic_json`, all JSON value types (array, object, string, bool, integer number, and floating-point) are now **templated**. That is, you can choose whether you like a `std::list` for your arrays or an `std::unordered_map` for your objects. The specialization `json` sets some reasonable defaults.
|
||||
- *Changed:* The library now consists of a single header, called `json.hpp`. Consequently, build systems such as Automake or CMake are not any longer required.
|
||||
- *Changed:* The **deserialization** is now supported by a lexer generated with [re2c](http://re2c.org) from file [`src/json.hpp.re2c`](https://github.com/nlohmann/json/blob/master/src/json.hpp.re2c). As a result, we follow the JSON specification more strictly. Note neither the tool re2c nor its input are required to use the class.
|
||||
- *Added:* The library now satisfies the [**ReversibleContainer**](http://en.cppreference.com/w/cpp/concept/ReversibleContainer) requirement. It hence provides four different iterators (`iterator`, `const_iterator`, `reverse_iterator`, and `const_reverse_iterator`), comparison functions, `swap()`, `size()`, `max_size()`, and `empty()` member functions.
|
||||
- *Added*: The class uses **user-defined allocators** which default to `std::allocator`, but can be templated via parameter `Allocator`.
|
||||
- *Added:* To simplify pretty-printing, the `std::setw` **stream manipulator** has been overloaded to set the desired indentation. Pretty-printing a JSON object `j` is as simple as `std::cout << std::setw(4) << j << '\n'.
|
||||
- *Changed*: The type `json::value_t::number` is now called `json::value_t::number_integer` to be more symmetric compared to `json::value_t::number_float`.
|
||||
- *Removed:* The `key()` and `value()` member functions for object iterators were nonstandard and yielded more problems than benefits. They were removed from the library.
|
||||
|
||||
## Integration
|
||||
|
||||
The two required source files are in the `src` directory. All you need to do is add
|
||||
The single required source, `json.hpp` file is in the `src` directory. All you need to do is add
|
||||
|
||||
```cpp
|
||||
#include "json.h"
|
||||
#include "json.hpp"
|
||||
|
||||
// for convenience
|
||||
using json = nlohmann::json;
|
||||
```
|
||||
|
||||
to the files you want to use JSON objects. Furthermore, you need to compile the file `json.cc` and link it to your binaries. Do not forget to set the necessary switches to enable C++11 (e.g., `-std=c++11` for GCC and Clang).
|
||||
|
||||
If you want a single header file, use the `json.h` file from the `header_only` directory.
|
||||
to the files you want to use JSON objects. That's it. Do not forget to set the necessary switches to enable C++11 (e.g., `-std=c++11` for GCC and Clang).
|
||||
|
||||
## Examples
|
||||
|
||||
|
@ -164,6 +175,9 @@ j << std::cin;
|
|||
|
||||
// serialize to standard output
|
||||
std::cout << j;
|
||||
|
||||
// the setw manipulator was overloaded to set the indentation for pretty printing
|
||||
std::cout << std::setw(4) << j << std::endl;
|
||||
```
|
||||
|
||||
These operators work for any subclasses of `std::istream` or `std::ostream`.
|
||||
|
@ -213,11 +227,6 @@ o["baz"] = 3.141;
|
|||
if (o.find("foo") != o.end()) {
|
||||
// there is an entry with key "foo"
|
||||
}
|
||||
|
||||
// iterate the object
|
||||
for (json::iterator it = o.begin(); it != o.end(); ++it) {
|
||||
std::cout << it.key() << ':' << it.value() << '\n';
|
||||
}
|
||||
```
|
||||
|
||||
### Conversion from STL containers
|
||||
|
@ -321,7 +330,7 @@ int vi = jn.get<int>();
|
|||
|
||||
The class is licensed under the [MIT License](http://opensource.org/licenses/MIT):
|
||||
|
||||
Copyright © 2013-2014 [Niels Lohmann](http://nlohmann.me)
|
||||
Copyright © 2013-2015 [Niels Lohmann](http://nlohmann.me)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
@ -341,44 +350,16 @@ I deeply appreciate the help of the following people.
|
|||
|
||||
Thanks a lot for helping out!
|
||||
|
||||
## Execute unit tests with CMake
|
||||
## Execute unit tests
|
||||
|
||||
To compile and run the tests, you need to execute
|
||||
|
||||
```sh
|
||||
$ cmake .
|
||||
$ make
|
||||
$ ctest
|
||||
```
|
||||
|
||||
If you want to generate a coverage report with the lcov/genhtml tools, execute this instead:
|
||||
|
||||
```sh
|
||||
$ cmake .
|
||||
$ make coverage
|
||||
```
|
||||
|
||||
**Note: You need to use GCC for now as otherwise the target coverage doesn't exist!**
|
||||
|
||||
The report is now in the subfolder coverage/index.html
|
||||
|
||||
## Execute unit tests with automake
|
||||
|
||||
To compile the unit tests, you need to execute
|
||||
|
||||
```sh
|
||||
$ autoreconf -i
|
||||
$ ./configure
|
||||
$ make
|
||||
```
|
||||
|
||||
The unit tests can then be executed with
|
||||
|
||||
```sh
|
||||
$ ./json_unit
|
||||
|
||||
===============================================================================
|
||||
All tests passed (887 assertions in 10 test cases)
|
||||
All tests passed (4280 assertions in 16 test cases)
|
||||
```
|
||||
|
||||
For more information, have a look at the file [.travis.yml](https://github.com/nlohmann/json/blob/master/.travis.yml).
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
import json
|
||||
|
||||
j = json.load(sys.stdin)
|
|
@ -1,8 +0,0 @@
|
|||
#include "json.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
nlohmann::json j;
|
||||
j << std::cin;
|
||||
return 0;
|
||||
}
|
11
configure.ac
11
configure.ac
|
@ -1,11 +0,0 @@
|
|||
AC_INIT([JSON], [2.0], [mail@nlohmann.me])
|
||||
AC_CONFIG_SRCDIR([src/json.h])
|
||||
|
||||
AM_INIT_AUTOMAKE([foreign subdir-objects])
|
||||
AM_SILENT_RULES([yes])
|
||||
|
||||
AC_PROG_CXX
|
||||
AC_PROG_SED
|
||||
|
||||
AC_CONFIG_FILES(Makefile)
|
||||
AC_OUTPUT
|
2331
doc/Doxyfile
2331
doc/Doxyfile
File diff suppressed because it is too large
Load diff
|
@ -1,53 +0,0 @@
|
|||
# Reference
|
||||
|
||||
## Nomenclature
|
||||
|
||||
We use the term "JSON" when we mean the [JavaScript Object Notation](http://json.org); that is, the file format. When we talk about the class implementing our library, we use "`json`" (typewriter font). Instances of this class are called "`json` values" to differentiate them from "JSON objects"; that is, unordered mappings, hashes, and whatnot.
|
||||
|
||||
## Types and default values
|
||||
|
||||
This table describes how JSON values are mapped to C++ types.
|
||||
|
||||
| JSON type | value_type | C++ type | type alias | default value |
|
||||
| ----------------------- | -------------------------- | ----------------------------- | ---------------------- | --------------
|
||||
| null | `value_type::null` | `nullptr_t` | - | `nullptr` |
|
||||
| string | `value_type::string` | `std::string` | `json::string_t` | `""` |
|
||||
| number (integer) | `value_type::number` | `int` | `json::number_t` | `0` |
|
||||
| number (floating point) | `value_type::number_float` | `double` | `json::number_float_t` | `0.0` |
|
||||
| array | `value_type::array ` | `std::array<json>` | `json::array_t` | `{}` |
|
||||
| object | `value_type::object` | `std::map<std::string, json>` | `json::object_t` | `{}` |
|
||||
|
||||
The second column list entries of an enumeration `value_type` which can be queried by calling `type()` on a `json` value. The column "C++ types" list the internal type that is used to represent the respective JSON value. The "type alias" column furthermore lists type aliases that are used in the `json` class to allow for more flexibility. The last column list the default value; that is, the value that is set if none is passed to the constructor or that is set if `clear()` is called.
|
||||
|
||||
## Type conversions
|
||||
|
||||
There are only a few type conversions possible:
|
||||
|
||||
- An integer number can be translated to a floating point number.
|
||||
- A floating point number can be translated to an integer number. Note the number is truncated and not rounded, ceiled or floored.
|
||||
- Any value (i.e., boolean, string, number, null) but JSON objects can be translated into an array. The result is a singleton array that consists of the value before.
|
||||
- Any other conversion will throw a `std::logic_error` exception.
|
||||
|
||||
When compatible, `json` values **implicitly convert** to `std::string`, `int`, `double`, `json::array_t`, and `json::object_t`. Furthermore, **explicit type conversion** is possible using the `get<>()` function with the aforementioned types.
|
||||
|
||||
## Initialization
|
||||
|
||||
`json` values can be created from many literals and variable types:
|
||||
|
||||
| JSON type | literal/variable types | examples |
|
||||
| --------- | ---------------------- | -------- |
|
||||
| none | null pointer literal, `nullptr_t` type, no value | `nullptr` |
|
||||
| boolean | boolean literals, `bool` type, `json::boolean_t` type | `true`, `false` |
|
||||
| string | string literal, `char*` type, `std::string` type, `std::string&&` rvalue reference, `json::string_t` type | `"Hello"` |
|
||||
| number (integer) | integer literal, `short int` type, `int` type, `json_number_t` type | `42` |
|
||||
| number (floating point) | floating point literal, `float` type, `double` type, `json::number_float_t` type | `3.141529`
|
||||
| array | initializer list whose elements are `json` values (or can be translated into `json` values using the rules above), `std::vector<json>` type, `json::array_t` type, `json::array_t&&` rvalue reference | `{1, 2, 3, true, "foo"}` |
|
||||
| object | initializer list whose elements are pairs of a string literal and a `json` value (or can be translated into `json` values using the rules above), `std::map<std::string, json>` type, `json::object_t` type, `json::object_t&&` rvalue reference | `{ {"key1", 42}, {"key2", false} }` |
|
||||
|
||||
## Number types
|
||||
|
||||
[![JSON number format](http://json.org/number.gif)](http://json.org)
|
||||
|
||||
The JSON specification explicitly does not define an internal number representation, but only the syntax of how numbers can be written down. Consequently, we would need to use the largest possible floating point number format (e.g., `long double`) to internally store JSON numbers.
|
||||
|
||||
However, this would be a waste of space, so we let the JSON parser decide which format to use: If the number can be precisely stored in an `int`, we use an `int` to store it. However, if it is a floating point number, we use `double` to store it.
|
3174
header_only/json.h
3174
header_only/json.h
File diff suppressed because it is too large
Load diff
2598
src/json.cc
2598
src/json.cc
File diff suppressed because it is too large
Load diff
576
src/json.h
576
src/json.h
|
@ -1,576 +0,0 @@
|
|||
/*!
|
||||
@file
|
||||
@copyright The code is licensed under the MIT License
|
||||
<http://opensource.org/licenses/MIT>,
|
||||
Copyright (c) 2013-2015 Niels Lohmann.
|
||||
|
||||
@author Niels Lohmann <http://nlohmann.me>
|
||||
|
||||
@see https://github.com/nlohmann/json
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <initializer_list> // std::initializer_list
|
||||
#include <iostream> // std::istream, std::ostream
|
||||
#include <map> // std::map
|
||||
#include <string> // std::string
|
||||
#include <vector> // std::vector
|
||||
#include <iterator> // std::iterator
|
||||
#include <limits> // std::numeric_limits
|
||||
#include <functional> // std::hash
|
||||
|
||||
namespace nlohmann
|
||||
{
|
||||
|
||||
/*!
|
||||
@brief JSON for Modern C++
|
||||
|
||||
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.
|
||||
|
||||
@see http://stackoverflow.com/questions/7758580/writing-your-own-stl-container/7759622#7759622
|
||||
|
||||
@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::insert(), json::emplace(), json::emplace_back, json::erase
|
||||
*/
|
||||
class json
|
||||
{
|
||||
public:
|
||||
// forward declaration to friend this class
|
||||
class iterator;
|
||||
class const_iterator;
|
||||
|
||||
public:
|
||||
// container types
|
||||
/// the type of elements in a JSON class
|
||||
using value_type = json;
|
||||
/// the type of element references
|
||||
using reference = json&;
|
||||
/// the type of const element references
|
||||
using const_reference = const json&;
|
||||
/// the type of pointers to elements
|
||||
using pointer = json*;
|
||||
/// the type of const pointers to elements
|
||||
using const_pointer = const json*;
|
||||
/// a type to represent differences between iterators
|
||||
using difference_type = std::ptrdiff_t;
|
||||
/// a type to represent container sizes
|
||||
using size_type = std::size_t;
|
||||
/// an iterator for a JSON container
|
||||
using iterator = json::iterator;
|
||||
/// a const iterator for a JSON container
|
||||
using const_iterator = json::const_iterator;
|
||||
/// a reverse iterator for a JSON container
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
/// a const reverse iterator for a JSON container
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
|
||||
/// a type for an object
|
||||
using object_t = std::map<std::string, json>;
|
||||
/// a type for an array
|
||||
using array_t = std::vector<json>;
|
||||
/// a type for a string
|
||||
using string_t = std::string;
|
||||
/// a type for a Boolean
|
||||
using boolean_t = bool;
|
||||
/// a type for an integer number
|
||||
using number_t = int64_t;
|
||||
/// a type for a floating point number
|
||||
using number_float_t = double;
|
||||
/// a type for list initialization
|
||||
using list_init_t = std::initializer_list<json>;
|
||||
|
||||
/// a JSON value
|
||||
union value
|
||||
{
|
||||
/// array as pointer to array_t
|
||||
array_t* array;
|
||||
/// object as pointer to object_t
|
||||
object_t* object;
|
||||
/// string as pointer to string_t
|
||||
string_t* string;
|
||||
/// Boolean
|
||||
boolean_t boolean;
|
||||
/// number (integer)
|
||||
number_t number;
|
||||
/// number (float)
|
||||
number_float_t number_float;
|
||||
|
||||
/// default constructor
|
||||
value() = default;
|
||||
/// constructor for arrays
|
||||
value(array_t*);
|
||||
/// constructor for objects
|
||||
value(object_t*);
|
||||
/// constructor for strings
|
||||
value(string_t*);
|
||||
/// constructor for Booleans
|
||||
value(boolean_t);
|
||||
/// constructor for numbers (integer)
|
||||
value(number_t);
|
||||
/// constructor for numbers (float)
|
||||
value(number_float_t);
|
||||
};
|
||||
|
||||
/// possible types of a JSON object
|
||||
enum class value_t : 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:
|
||||
/// create an object according to given type
|
||||
json(const value_t);
|
||||
/// create a null object
|
||||
json() noexcept;
|
||||
/// create a null object
|
||||
json(std::nullptr_t) noexcept;
|
||||
/// create a string object from a C++ string
|
||||
json(const std::string&);
|
||||
/// create a string object from a C++ string (move)
|
||||
json(std::string&&);
|
||||
/// create a string object from a C string
|
||||
json(const char*);
|
||||
/// create a Boolean object
|
||||
json(const bool) noexcept;
|
||||
/// create an array
|
||||
json(const array_t&);
|
||||
/// create an array (move)
|
||||
json(array_t&&);
|
||||
/// create an object
|
||||
json(const object_t&);
|
||||
/// create an object (move)
|
||||
json(object_t&&);
|
||||
/// create from an initializer list (to an array or object)
|
||||
json(list_init_t, bool = true, value_t = value_t::array);
|
||||
|
||||
/*!
|
||||
@brief create a number object (integer)
|
||||
@param n an integer number to wrap in a JSON object
|
||||
*/
|
||||
template<typename T, typename
|
||||
std::enable_if<
|
||||
std::numeric_limits<T>::is_integer, T>::type
|
||||
= 0>
|
||||
json(const T n) noexcept
|
||||
: final_type_(0), type_(value_t::number),
|
||||
value_(static_cast<number_t>(n))
|
||||
{}
|
||||
|
||||
/*!
|
||||
@brief create a number object (float)
|
||||
@param n a floating point number to wrap in a JSON object
|
||||
*/
|
||||
template<typename T, typename = typename
|
||||
std::enable_if<
|
||||
std::is_floating_point<T>::value>::type
|
||||
>
|
||||
json(const T n) noexcept
|
||||
: final_type_(0), type_(value_t::number_float),
|
||||
value_(static_cast<number_float_t>(n))
|
||||
{}
|
||||
|
||||
/*!
|
||||
@brief create an array object
|
||||
@param v any type of container whose elements can be use to construct
|
||||
JSON objects (e.g., std::vector, std::set, std::array)
|
||||
@note For some reason, we need to explicitly forbid JSON iterator types.
|
||||
*/
|
||||
template <class V, typename
|
||||
std::enable_if<
|
||||
not std::is_same<V, json::iterator>::value and
|
||||
not std::is_same<V, json::const_iterator>::value and
|
||||
not std::is_same<V, json::reverse_iterator>::value and
|
||||
not std::is_same<V, json::const_reverse_iterator>::value and
|
||||
std::is_constructible<json, typename V::value_type>::value, int>::type
|
||||
= 0>
|
||||
json(const V& v) : json(array_t(v.begin(), v.end()))
|
||||
{}
|
||||
|
||||
/*!
|
||||
@brief create a JSON object
|
||||
@param v any type of associative container whose elements can be use to
|
||||
construct JSON objects (e.g., std::map<std::string, *>)
|
||||
*/
|
||||
template <class V, typename
|
||||
std::enable_if<
|
||||
std::is_constructible<std::string, typename V::key_type>::value and
|
||||
std::is_constructible<json, typename V::mapped_type>::value, int>::type
|
||||
= 0>
|
||||
json(const V& v) : json(object_t(v.begin(), v.end()))
|
||||
{}
|
||||
|
||||
/// copy constructor
|
||||
json(const json&);
|
||||
/// move constructor
|
||||
json(json&&) noexcept;
|
||||
|
||||
/// copy assignment
|
||||
json& operator=(json) noexcept;
|
||||
|
||||
/// destructor
|
||||
~json() noexcept;
|
||||
|
||||
/// explicit keyword to force array creation
|
||||
static json array(list_init_t = list_init_t());
|
||||
/// explicit keyword to force object creation
|
||||
static json object(list_init_t = list_init_t());
|
||||
|
||||
/// create from string representation
|
||||
static json parse(const std::string&);
|
||||
/// create from string representation
|
||||
static json parse(const char*);
|
||||
|
||||
private:
|
||||
/// return the type as string
|
||||
std::string type_name() const noexcept;
|
||||
|
||||
/// dump the object (with pretty printer)
|
||||
std::string dump(const bool, const unsigned int, unsigned int = 0) const noexcept;
|
||||
/// replaced a character in a string with another string
|
||||
void replaceChar(std::string& str, char c, const std::string& replacement) const;
|
||||
/// escapes special characters to safely dump the string
|
||||
std::string escapeString(const std::string&) const;
|
||||
|
||||
public:
|
||||
/// explicit value conversion
|
||||
template<typename T>
|
||||
T get() const;
|
||||
|
||||
/// implicit conversion to string representation
|
||||
operator std::string() const;
|
||||
/// implicit conversion to integer (only for numbers)
|
||||
operator int() const;
|
||||
/// implicit conversion to integer (only for numbers)
|
||||
operator int64_t() const;
|
||||
/// implicit conversion to double (only for numbers)
|
||||
operator double() const;
|
||||
/// implicit conversion to Boolean (only for Booleans)
|
||||
operator bool() const;
|
||||
/// implicit conversion to JSON vector (not for objects)
|
||||
operator array_t() const;
|
||||
/// implicit conversion to JSON map (only for objects)
|
||||
operator object_t() const;
|
||||
|
||||
/// serialize to stream
|
||||
friend std::ostream& operator<<(std::ostream& o, const json& j)
|
||||
{
|
||||
o << j.dump();
|
||||
return o;
|
||||
}
|
||||
/// serialize to stream
|
||||
friend std::ostream& operator>>(const json& j, std::ostream& o)
|
||||
{
|
||||
o << j.dump();
|
||||
return o;
|
||||
}
|
||||
|
||||
/// deserialize from stream
|
||||
friend std::istream& operator>>(std::istream& i, json& j)
|
||||
{
|
||||
j = parser(i).parse();
|
||||
return i;
|
||||
}
|
||||
/// deserialize from stream
|
||||
friend std::istream& operator<<(json& j, std::istream& i)
|
||||
{
|
||||
j = parser(i).parse();
|
||||
return i;
|
||||
}
|
||||
|
||||
/// explicit serialization
|
||||
std::string dump(int = -1) const noexcept;
|
||||
|
||||
/// add constructible objects to an array
|
||||
template<class T, typename std::enable_if<std::is_constructible<json, T>::value>::type = 0>
|
||||
json & operator+=(const T& o)
|
||||
{
|
||||
push_back(json(o));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// add an object/array to an array
|
||||
json& operator+=(const json&);
|
||||
|
||||
/// 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 constructible objects to an array
|
||||
template<class T, typename std::enable_if<std::is_constructible<json, T>::value>::type = 0>
|
||||
void push_back(const T& o)
|
||||
{
|
||||
push_back(json(o));
|
||||
}
|
||||
|
||||
/// 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 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
|
||||
reference operator[](const int);
|
||||
/// operator to get an element in an array
|
||||
const_reference operator[](const int) const;
|
||||
/// operator to get an element in an array
|
||||
reference at(const int);
|
||||
/// operator to get an element in an array
|
||||
const_reference at(const int) const;
|
||||
|
||||
/// operator to set an element in an object
|
||||
reference operator[](const std::string&);
|
||||
/// operator to set an element in an object
|
||||
reference operator[](const char*);
|
||||
/// operator to get an element in an object
|
||||
const_reference operator[](const std::string&) const;
|
||||
/// operator to get an element in an object
|
||||
const_reference operator[](const char*) const;
|
||||
/// operator to set an element in an object
|
||||
reference at(const std::string&);
|
||||
/// operator to set an element in an object
|
||||
reference at(const char*);
|
||||
/// operator to get an element in an object
|
||||
const_reference at(const std::string&) const;
|
||||
/// operator to get an element in an object
|
||||
const_reference at(const char*) const;
|
||||
|
||||
/// return the number of stored values
|
||||
size_type size() const noexcept;
|
||||
/// return the maximal number of values that can be stored
|
||||
size_type max_size() const noexcept;
|
||||
/// checks whether object is empty
|
||||
bool empty() const noexcept;
|
||||
/// removes all elements from compounds and resets values to default
|
||||
void clear() noexcept;
|
||||
|
||||
/// swaps content with other object
|
||||
void swap(json&) noexcept;
|
||||
|
||||
/// return the type of the object
|
||||
value_t type() const noexcept;
|
||||
|
||||
/// find an element in an object (returns end() iterator otherwise)
|
||||
iterator find(const std::string&);
|
||||
/// find an element in an object (returns end() iterator otherwise)
|
||||
const_iterator find(const std::string&) const;
|
||||
/// find an element in an object (returns end() iterator otherwise)
|
||||
iterator find(const char*);
|
||||
/// find an element in an object (returns end() iterator otherwise)
|
||||
const_iterator find(const char*) const;
|
||||
|
||||
/// lexicographically compares the values
|
||||
bool operator==(const json&) const noexcept;
|
||||
/// lexicographically compares the values
|
||||
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;
|
||||
/// returns a reverse iterator to the beginning
|
||||
reverse_iterator rbegin() noexcept;
|
||||
/// returns a reverse iterator to the end
|
||||
reverse_iterator rend() noexcept;
|
||||
/// returns a reverse iterator to the beginning
|
||||
const_reverse_iterator crbegin() const noexcept;
|
||||
/// returns a reverse iterator to the end
|
||||
const_reverse_iterator crend() const noexcept;
|
||||
|
||||
private:
|
||||
/// whether the type is final
|
||||
unsigned final_type_ : 1;
|
||||
/// the type of this object
|
||||
value_t type_ = value_t::null;
|
||||
/// the payload
|
||||
value value_ {};
|
||||
|
||||
public:
|
||||
/// an iterator
|
||||
class iterator : public std::iterator<std::bidirectional_iterator_tag, json>
|
||||
{
|
||||
friend class json;
|
||||
friend class json::const_iterator;
|
||||
|
||||
public:
|
||||
iterator() = default;
|
||||
iterator(json*, bool);
|
||||
iterator(const iterator&);
|
||||
~iterator();
|
||||
|
||||
iterator& operator=(iterator);
|
||||
bool operator==(const iterator&) const;
|
||||
bool operator!=(const iterator&) const;
|
||||
iterator& operator++();
|
||||
iterator& operator--();
|
||||
json& operator*() const;
|
||||
json* operator->() const;
|
||||
|
||||
/// getter for the key (in case of objects)
|
||||
std::string key() const;
|
||||
/// getter for the value
|
||||
json& value() const;
|
||||
|
||||
private:
|
||||
/// a JSON value
|
||||
json* object_ = nullptr;
|
||||
/// an iterator for JSON arrays
|
||||
array_t::iterator* vi_ = nullptr;
|
||||
/// an iterator for JSON objects
|
||||
object_t::iterator* oi_ = nullptr;
|
||||
/// whether iterator points to a valid object
|
||||
bool invalid = true;
|
||||
};
|
||||
|
||||
/// a const iterator
|
||||
class const_iterator : public std::iterator<std::bidirectional_iterator_tag, const json>
|
||||
{
|
||||
friend class json;
|
||||
|
||||
public:
|
||||
const_iterator() = default;
|
||||
const_iterator(const json*, bool);
|
||||
const_iterator(const const_iterator&);
|
||||
const_iterator(const json::iterator&);
|
||||
~const_iterator();
|
||||
|
||||
const_iterator& operator=(const_iterator);
|
||||
bool operator==(const const_iterator&) const;
|
||||
bool operator!=(const const_iterator&) const;
|
||||
const_iterator& operator++();
|
||||
const_iterator& operator--();
|
||||
const json& operator*() const;
|
||||
const json* operator->() const;
|
||||
|
||||
/// getter for the key (in case of objects)
|
||||
std::string key() const;
|
||||
/// getter for the value
|
||||
const json& value() const;
|
||||
|
||||
private:
|
||||
/// a JSON value
|
||||
const json* object_ = nullptr;
|
||||
/// an iterator for JSON arrays
|
||||
array_t::const_iterator* vi_ = nullptr;
|
||||
/// an iterator for JSON objects
|
||||
object_t::const_iterator* oi_ = nullptr;
|
||||
/// whether iterator reached past the end
|
||||
bool invalid = true;
|
||||
};
|
||||
|
||||
private:
|
||||
/// a helper class to parse a JSON object
|
||||
class parser
|
||||
{
|
||||
public:
|
||||
/// a parser reading from a C string
|
||||
parser(const char*);
|
||||
/// a parser reading from a C++ string
|
||||
parser(const std::string&);
|
||||
/// a parser reading from an input stream
|
||||
parser(std::istream&);
|
||||
/// destructor of the parser
|
||||
~parser() = default;
|
||||
|
||||
// no copy constructor
|
||||
parser(const parser&) = delete;
|
||||
// no copy assignment
|
||||
parser& operator=(parser) = delete;
|
||||
|
||||
/// parse and return a JSON object
|
||||
json parse();
|
||||
|
||||
private:
|
||||
/// read the next character, stripping whitespace
|
||||
bool next();
|
||||
/// raise an exception with an error message
|
||||
[[noreturn]] inline void error(const std::string&) const;
|
||||
/// parse a quoted string
|
||||
inline std::string parseString();
|
||||
/// transforms a unicode codepoint to it's UTF-8 presentation
|
||||
std::string codePointToUTF8(unsigned int codePoint) const;
|
||||
/// parses 4 hex characters that represent a unicode code point
|
||||
inline unsigned int parse4HexCodePoint();
|
||||
/// parses \uXXXX[\uXXXX] unicode escape characters
|
||||
inline std::string parseUnicodeEscape();
|
||||
/// parse a Boolean "true"
|
||||
inline void parseTrue();
|
||||
/// parse a Boolean "false"
|
||||
inline void parseFalse();
|
||||
/// parse a null object
|
||||
inline void parseNull();
|
||||
/// a helper function to expect a certain character
|
||||
inline void expect(const char);
|
||||
|
||||
private:
|
||||
/// a buffer of the input
|
||||
std::string buffer_ {};
|
||||
/// the current character
|
||||
char current_ {};
|
||||
/// the position inside the input buffer
|
||||
std::size_t pos_ = 0;
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/// user-defined literal operator to create JSON objects from strings
|
||||
nlohmann::json operator "" _json(const char*, std::size_t);
|
||||
|
||||
// specialization of std::swap, and std::hash
|
||||
namespace std
|
||||
{
|
||||
template <>
|
||||
/// swaps the values of two JSON objects
|
||||
inline void swap(nlohmann::json& j1,
|
||||
nlohmann::json& j2) noexcept(
|
||||
is_nothrow_move_constructible<nlohmann::json>::value and
|
||||
is_nothrow_move_assignable<nlohmann::json>::value
|
||||
)
|
||||
{
|
||||
j1.swap(j2);
|
||||
}
|
||||
|
||||
template <>
|
||||
/// hash value for JSON objects
|
||||
struct hash<nlohmann::json>
|
||||
{
|
||||
size_t operator()(const nlohmann::json& j) const
|
||||
{
|
||||
// a naive hashing via the string representation
|
||||
return hash<std::string>()(j.dump());
|
||||
}
|
||||
};
|
||||
|
||||
}
|
3844
src/json.hpp
Normal file
3844
src/json.hpp
Normal file
File diff suppressed because it is too large
Load diff
3193
src/json.hpp.re2c
Normal file
3193
src/json.hpp.re2c
Normal file
File diff suppressed because it is too large
Load diff
4578
test/catch.hpp
4578
test/catch.hpp
File diff suppressed because it is too large
Load diff
2258
test/json_unit.cc
2258
test/json_unit.cc
File diff suppressed because it is too large
Load diff
6135
test/unit.cpp
Normal file
6135
test/unit.cpp
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue