diff --git a/Doxyfile b/Doxyfile new file mode 100644 index 00000000..ef4ca859 --- /dev/null +++ b/Doxyfile @@ -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 = YES +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 diff --git a/src/json.hpp b/src/json.hpp index 64799111..3c7ed93a 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -315,6 +315,7 @@ class basic_json : m_type(value_t::number_float), m_value(number_float_t(value)) {} + /// create a container (array or object) from an initializer list inline basic_json(list_init_t l, bool type_deduction = true, value_t manual_type = value_t::array) { // the initializer list could describe an object @@ -372,11 +373,13 @@ class basic_json } } + /// explicitly create an array from an initializer list inline static basic_json array(list_init_t l = list_init_t()) { return basic_json(l, false, value_t::array); } + /// explicitly create an object from an initializer list inline static basic_json object(list_init_t l = list_init_t()) { return basic_json(l, false, value_t::object); @@ -733,6 +736,33 @@ class basic_json } + /// find an element in an object + iterator find(typename object_t::key_type key) + { + auto result = end(); + + if (m_type == value_t::object) + { + result.m_it.object_iterator = m_value.object->find(key); + } + + return result; + } + + /// find an element in an object + const_iterator find(typename object_t::key_type key) const + { + auto result = cend(); + + if (m_type == value_t::object) + { + result.m_it.object_iterator = m_value.object->find(key); + } + + return result; + } + + /////////////// // iterators // /////////////// @@ -1287,6 +1317,7 @@ class basic_json // deserialization // ///////////////////// + /// deserialize from string static basic_json parse(const std::string& s) { return parser(s).parse(); @@ -1347,7 +1378,7 @@ class basic_json /*! @brief escape a string - + Escape a string by replacing certain special characters by a sequence of an escape character (backslash) and another character and other control characters by a sequence of "\u" followed by a four-digit hex @@ -1435,12 +1466,12 @@ class basic_json /*! @brief internal implementation of the serialization function - + This function is called by the public member function dump and organizes the serializaion internally. The indentation level is propagated as additional parameter. In case of arrays and objects, the function is called recursively. Note that - + - strings and object keys are escaped using escape_string() - numbers are converted to a string before output using std::to_string() @@ -1572,6 +1603,7 @@ class basic_json /// the value of the current element json_value m_value = {}; + public: /////////////// // iterators // @@ -1600,7 +1632,9 @@ class basic_json /// the iterator points to the only value begin, /// the iterator points past the only value - end + end, + /// the iterator points to an invalid value + invalid }; /// an iterator value @@ -1673,6 +1707,7 @@ class basic_json case (basic_json::value_t::null): { + // set to end so begin()==end() is true: null is empty m_it.generic_iterator = generic_iterator_value::end; break; } @@ -1794,7 +1829,14 @@ class basic_json default: { - m_it.generic_iterator = generic_iterator_value::end; + if (m_it.generic_iterator == generic_iterator_value::begin) + { + m_it.generic_iterator = generic_iterator_value::end; + } + else + { + m_it.generic_iterator = generic_iterator_value::invalid; + } break; } } @@ -1821,7 +1863,14 @@ class basic_json default: { - m_it.generic_iterator = generic_iterator_value::end; + if (m_it.generic_iterator == generic_iterator_value::begin) + { + m_it.generic_iterator = generic_iterator_value::end; + } + else + { + m_it.generic_iterator = generic_iterator_value::invalid; + } break; } } @@ -1848,9 +1897,22 @@ class basic_json break; } + case (basic_json::value_t::null): + { + m_it.generic_iterator = generic_iterator_value::invalid; + break; + } + default: { - m_it.generic_iterator = generic_iterator_value::uninitialized; + if (m_it.generic_iterator == generic_iterator_value::end) + { + m_it.generic_iterator = generic_iterator_value::begin; + } + else + { + m_it.generic_iterator = generic_iterator_value::invalid; + } break; } } @@ -1875,9 +1937,22 @@ class basic_json break; } + case (basic_json::value_t::null): + { + m_it.generic_iterator = generic_iterator_value::invalid; + break; + } + default: { - m_it.generic_iterator = generic_iterator_value::uninitialized; + if (m_it.generic_iterator == generic_iterator_value::end) + { + m_it.generic_iterator = generic_iterator_value::begin; + } + else + { + m_it.generic_iterator = generic_iterator_value::invalid; + } break; } } @@ -1948,7 +2023,9 @@ class basic_json /// the iterator points to the only value begin, /// the iterator points past the only value - end + end, + /// the iterator points to an invalid value + invalid }; /// an iterator value @@ -1994,6 +2071,7 @@ class basic_json } } + /// copy constructor given a nonconst iterator inline const_iterator(const iterator& other) : m_object(other.m_object), m_it(other.m_it) {} @@ -2024,6 +2102,7 @@ class basic_json case (basic_json::value_t::null): { + // set to end so begin()==end() is true: null is empty m_it.generic_iterator = generic_iterator_value::end; break; } @@ -2145,7 +2224,14 @@ class basic_json default: { - m_it.generic_iterator = generic_iterator_value::end; + if (m_it.generic_iterator == generic_iterator_value::begin) + { + m_it.generic_iterator = generic_iterator_value::end; + } + else + { + m_it.generic_iterator = generic_iterator_value::invalid; + } break; } } @@ -2172,7 +2258,14 @@ class basic_json default: { - m_it.generic_iterator = generic_iterator_value::end; + if (m_it.generic_iterator == generic_iterator_value::begin) + { + m_it.generic_iterator = generic_iterator_value::end; + } + else + { + m_it.generic_iterator = generic_iterator_value::invalid; + } break; } } @@ -2199,9 +2292,22 @@ class basic_json break; } + case (basic_json::value_t::null): + { + m_it.generic_iterator = generic_iterator_value::invalid; + break; + } + default: { - m_it.generic_iterator = generic_iterator_value::uninitialized; + if (m_it.generic_iterator == generic_iterator_value::end) + { + m_it.generic_iterator = generic_iterator_value::begin; + } + else + { + m_it.generic_iterator = generic_iterator_value::invalid; + } break; } } @@ -2226,9 +2332,22 @@ class basic_json break; } + case (basic_json::value_t::null): + { + m_it.generic_iterator = generic_iterator_value::invalid; + break; + } + default: { - m_it.generic_iterator = generic_iterator_value::uninitialized; + if (m_it.generic_iterator == generic_iterator_value::end) + { + m_it.generic_iterator = generic_iterator_value::begin; + } + else + { + m_it.generic_iterator = generic_iterator_value::invalid; + } break; } } @@ -2276,6 +2395,7 @@ class basic_json internal_const_iterator m_it; }; + private: //////////// // parser // @@ -2497,359 +2617,704 @@ class basic_json const lexer_char_t* marker; // set up RE2C - + for (;;) { // set current to the begin of the buffer current_re2c = buffer_re2c; - -{ - lexer_char_t yych; - unsigned int yyaccept = 0; - static const unsigned char yybm[] = { - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 192, 192, 64, 64, 192, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 192, 64, 0, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 96, 96, 96, 96, 96, 96, 96, 96, - 96, 96, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 0, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - }; - yych = *buffer_re2c; - if (yych <= ':') { - if (yych <= '!') { - if (yych <= '\f') { - if (yych <= 0x08) goto json_parser_3; - if (yych <= '\n') goto json_parser_5; - goto json_parser_3; - } else { - if (yych <= '\r') goto json_parser_5; - if (yych == ' ') goto json_parser_5; - goto json_parser_3; - } - } else { - if (yych <= '-') { - if (yych <= '"') goto json_parser_6; - if (yych <= '+') goto json_parser_3; - if (yych <= ',') goto json_parser_7; - goto json_parser_9; - } else { - if (yych <= '/') goto json_parser_3; - if (yych <= '0') goto json_parser_10; - if (yych <= '9') goto json_parser_12; - goto json_parser_13; - } - } - } else { - if (yych <= 'm') { - if (yych <= '\\') { - if (yych == '[') goto json_parser_15; - goto json_parser_3; - } else { - if (yych <= ']') goto json_parser_17; - if (yych == 'f') goto json_parser_19; - goto json_parser_3; - } - } else { - if (yych <= 'z') { - if (yych <= 'n') goto json_parser_20; - if (yych == 't') goto json_parser_21; - goto json_parser_3; - } else { - if (yych <= '{') goto json_parser_22; - if (yych == '}') goto json_parser_24; - goto json_parser_3; - } - } - } + { + lexer_char_t yych; + unsigned int yyaccept = 0; + static const unsigned char yybm[] = + { + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 192, 192, 64, 64, 192, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 192, 64, 0, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 96, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 0, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + }; + + yych = *buffer_re2c; + if (yych <= ':') + { + if (yych <= '!') + { + if (yych <= '\f') + { + if (yych <= 0x08) + { + goto json_parser_3; + } + if (yych <= '\n') + { + goto json_parser_5; + } + goto json_parser_3; + } + else + { + if (yych <= '\r') + { + goto json_parser_5; + } + if (yych == ' ') + { + goto json_parser_5; + } + goto json_parser_3; + } + } + else + { + if (yych <= '-') + { + if (yych <= '"') + { + goto json_parser_6; + } + if (yych <= '+') + { + goto json_parser_3; + } + if (yych <= ',') + { + goto json_parser_7; + } + goto json_parser_9; + } + else + { + if (yych <= '/') + { + goto json_parser_3; + } + if (yych <= '0') + { + goto json_parser_10; + } + if (yych <= '9') + { + goto json_parser_12; + } + goto json_parser_13; + } + } + } + else + { + if (yych <= 'm') + { + if (yych <= '\\') + { + if (yych == '[') + { + goto json_parser_15; + } + goto json_parser_3; + } + else + { + if (yych <= ']') + { + goto json_parser_17; + } + if (yych == 'f') + { + goto json_parser_19; + } + goto json_parser_3; + } + } + else + { + if (yych <= 'z') + { + if (yych <= 'n') + { + goto json_parser_20; + } + if (yych == 't') + { + goto json_parser_21; + } + goto json_parser_3; + } + else + { + if (yych <= '{') + { + goto json_parser_22; + } + if (yych == '}') + { + goto json_parser_24; + } + goto json_parser_3; + } + } + } json_parser_2: - { continue; } + { + continue; + } json_parser_3: - ++buffer_re2c; + ++buffer_re2c; json_parser_4: - { return last_token = token_type::parse_error; } + { + return last_token = token_type::parse_error; + } json_parser_5: - yych = *++buffer_re2c; - goto json_parser_60; + yych = *++buffer_re2c; + goto json_parser_60; json_parser_6: - yyaccept = 0; - yych = *(marker = ++buffer_re2c); - goto json_parser_51; + yyaccept = 0; + yych = *(marker = ++buffer_re2c); + goto json_parser_51; json_parser_7: - ++buffer_re2c; - { return last_token = token_type::value_separator; } + ++buffer_re2c; + { + return last_token = token_type::value_separator; + } json_parser_9: - yych = *++buffer_re2c; - if (yych <= '/') goto json_parser_4; - if (yych <= '0') goto json_parser_49; - if (yych <= '9') goto json_parser_40; - goto json_parser_4; + yych = *++buffer_re2c; + if (yych <= '/') + { + goto json_parser_4; + } + if (yych <= '0') + { + goto json_parser_49; + } + if (yych <= '9') + { + goto json_parser_40; + } + goto json_parser_4; json_parser_10: - yyaccept = 1; - yych = *(marker = ++buffer_re2c); - if (yych <= 'D') { - if (yych == '.') goto json_parser_42; - } else { - if (yych <= 'E') goto json_parser_43; - if (yych == 'e') goto json_parser_43; - } + yyaccept = 1; + yych = *(marker = ++buffer_re2c); + if (yych <= 'D') + { + if (yych == '.') + { + goto json_parser_42; + } + } + else + { + if (yych <= 'E') + { + goto json_parser_43; + } + if (yych == 'e') + { + goto json_parser_43; + } + } json_parser_11: - { return last_token = token_type::value_number; } + { + return last_token = token_type::value_number; + } json_parser_12: - yyaccept = 1; - yych = *(marker = ++buffer_re2c); - goto json_parser_41; + yyaccept = 1; + yych = *(marker = ++buffer_re2c); + goto json_parser_41; json_parser_13: - ++buffer_re2c; - { return last_token = token_type::name_separator; } + ++buffer_re2c; + { + return last_token = token_type::name_separator; + } json_parser_15: - ++buffer_re2c; - { return last_token = token_type::begin_array; } + ++buffer_re2c; + { + return last_token = token_type::begin_array; + } json_parser_17: - ++buffer_re2c; - { return last_token = token_type::end_array; } + ++buffer_re2c; + { + return last_token = token_type::end_array; + } json_parser_19: - yyaccept = 0; - yych = *(marker = ++buffer_re2c); - if (yych == 'a') goto json_parser_35; - goto json_parser_4; + yyaccept = 0; + yych = *(marker = ++buffer_re2c); + if (yych == 'a') + { + goto json_parser_35; + } + goto json_parser_4; json_parser_20: - yyaccept = 0; - yych = *(marker = ++buffer_re2c); - if (yych == 'u') goto json_parser_31; - goto json_parser_4; + yyaccept = 0; + yych = *(marker = ++buffer_re2c); + if (yych == 'u') + { + goto json_parser_31; + } + goto json_parser_4; json_parser_21: - yyaccept = 0; - yych = *(marker = ++buffer_re2c); - if (yych == 'r') goto json_parser_26; - goto json_parser_4; + yyaccept = 0; + yych = *(marker = ++buffer_re2c); + if (yych == 'r') + { + goto json_parser_26; + } + goto json_parser_4; json_parser_22: - ++buffer_re2c; - { return last_token = token_type::begin_object; } + ++buffer_re2c; + { + return last_token = token_type::begin_object; + } json_parser_24: - ++buffer_re2c; - { return last_token = token_type::end_object; } + ++buffer_re2c; + { + return last_token = token_type::end_object; + } json_parser_26: - yych = *++buffer_re2c; - if (yych == 'u') goto json_parser_28; + yych = *++buffer_re2c; + if (yych == 'u') + { + goto json_parser_28; + } json_parser_27: - buffer_re2c = marker; - if (yyaccept == 0) { - goto json_parser_4; - } else { - goto json_parser_11; - } + buffer_re2c = marker; + if (yyaccept == 0) + { + goto json_parser_4; + } + else + { + goto json_parser_11; + } json_parser_28: - yych = *++buffer_re2c; - if (yych != 'e') goto json_parser_27; - ++buffer_re2c; - { return last_token = token_type::literal_true; } + yych = *++buffer_re2c; + if (yych != 'e') + { + goto json_parser_27; + } + ++buffer_re2c; + { + return last_token = token_type::literal_true; + } json_parser_31: - yych = *++buffer_re2c; - if (yych != 'l') goto json_parser_27; - yych = *++buffer_re2c; - if (yych != 'l') goto json_parser_27; - ++buffer_re2c; - { return last_token = token_type::literal_null; } + yych = *++buffer_re2c; + if (yych != 'l') + { + goto json_parser_27; + } + yych = *++buffer_re2c; + if (yych != 'l') + { + goto json_parser_27; + } + ++buffer_re2c; + { + return last_token = token_type::literal_null; + } json_parser_35: - yych = *++buffer_re2c; - if (yych != 'l') goto json_parser_27; - yych = *++buffer_re2c; - if (yych != 's') goto json_parser_27; - yych = *++buffer_re2c; - if (yych != 'e') goto json_parser_27; - ++buffer_re2c; - { return last_token = token_type::literal_false; } + yych = *++buffer_re2c; + if (yych != 'l') + { + goto json_parser_27; + } + yych = *++buffer_re2c; + if (yych != 's') + { + goto json_parser_27; + } + yych = *++buffer_re2c; + if (yych != 'e') + { + goto json_parser_27; + } + ++buffer_re2c; + { + return last_token = token_type::literal_false; + } json_parser_40: - yyaccept = 1; - marker = ++buffer_re2c; - yych = *buffer_re2c; + yyaccept = 1; + marker = ++buffer_re2c; + yych = *buffer_re2c; json_parser_41: - if (yybm[0+yych] & 32) { - goto json_parser_40; - } - if (yych <= 'D') { - if (yych != '.') goto json_parser_11; - } else { - if (yych <= 'E') goto json_parser_43; - if (yych == 'e') goto json_parser_43; - goto json_parser_11; - } + if (yybm[0 + yych] & 32) + { + goto json_parser_40; + } + if (yych <= 'D') + { + if (yych != '.') + { + goto json_parser_11; + } + } + else + { + if (yych <= 'E') + { + goto json_parser_43; + } + if (yych == 'e') + { + goto json_parser_43; + } + goto json_parser_11; + } json_parser_42: - yych = *++buffer_re2c; - if (yych <= '/') goto json_parser_27; - if (yych <= '9') goto json_parser_47; - goto json_parser_27; + yych = *++buffer_re2c; + if (yych <= '/') + { + goto json_parser_27; + } + if (yych <= '9') + { + goto json_parser_47; + } + goto json_parser_27; json_parser_43: - yych = *++buffer_re2c; - if (yych <= ',') { - if (yych != '+') goto json_parser_27; - } else { - if (yych <= '-') goto json_parser_44; - if (yych <= '/') goto json_parser_27; - if (yych <= '9') goto json_parser_45; - goto json_parser_27; - } + yych = *++buffer_re2c; + if (yych <= ',') + { + if (yych != '+') + { + goto json_parser_27; + } + } + else + { + if (yych <= '-') + { + goto json_parser_44; + } + if (yych <= '/') + { + goto json_parser_27; + } + if (yych <= '9') + { + goto json_parser_45; + } + goto json_parser_27; + } json_parser_44: - yych = *++buffer_re2c; - if (yych <= '/') goto json_parser_27; - if (yych >= ':') goto json_parser_27; + yych = *++buffer_re2c; + if (yych <= '/') + { + goto json_parser_27; + } + if (yych >= ':') + { + goto json_parser_27; + } json_parser_45: - ++buffer_re2c; - yych = *buffer_re2c; - if (yych <= '/') goto json_parser_11; - if (yych <= '9') goto json_parser_45; - goto json_parser_11; + ++buffer_re2c; + yych = *buffer_re2c; + if (yych <= '/') + { + goto json_parser_11; + } + if (yych <= '9') + { + goto json_parser_45; + } + goto json_parser_11; json_parser_47: - yyaccept = 1; - marker = ++buffer_re2c; - yych = *buffer_re2c; - if (yych <= 'D') { - if (yych <= '/') goto json_parser_11; - if (yych <= '9') goto json_parser_47; - goto json_parser_11; - } else { - if (yych <= 'E') goto json_parser_43; - if (yych == 'e') goto json_parser_43; - goto json_parser_11; - } + yyaccept = 1; + marker = ++buffer_re2c; + yych = *buffer_re2c; + if (yych <= 'D') + { + if (yych <= '/') + { + goto json_parser_11; + } + if (yych <= '9') + { + goto json_parser_47; + } + goto json_parser_11; + } + else + { + if (yych <= 'E') + { + goto json_parser_43; + } + if (yych == 'e') + { + goto json_parser_43; + } + goto json_parser_11; + } json_parser_49: - yyaccept = 1; - yych = *(marker = ++buffer_re2c); - if (yych <= 'D') { - if (yych == '.') goto json_parser_42; - goto json_parser_11; - } else { - if (yych <= 'E') goto json_parser_43; - if (yych == 'e') goto json_parser_43; - goto json_parser_11; - } + yyaccept = 1; + yych = *(marker = ++buffer_re2c); + if (yych <= 'D') + { + if (yych == '.') + { + goto json_parser_42; + } + goto json_parser_11; + } + else + { + if (yych <= 'E') + { + goto json_parser_43; + } + if (yych == 'e') + { + goto json_parser_43; + } + goto json_parser_11; + } json_parser_50: - ++buffer_re2c; - yych = *buffer_re2c; + ++buffer_re2c; + yych = *buffer_re2c; json_parser_51: - if (yybm[0+yych] & 64) { - goto json_parser_50; - } - if (yych <= '"') goto json_parser_53; - ++buffer_re2c; - yych = *buffer_re2c; - if (yych <= 'e') { - if (yych <= '/') { - if (yych == '"') goto json_parser_50; - if (yych <= '.') goto json_parser_27; - goto json_parser_50; - } else { - if (yych <= '\\') { - if (yych <= '[') goto json_parser_27; - goto json_parser_50; - } else { - if (yych == 'b') goto json_parser_50; - goto json_parser_27; - } - } - } else { - if (yych <= 'q') { - if (yych <= 'f') goto json_parser_50; - if (yych == 'n') goto json_parser_50; - goto json_parser_27; - } else { - if (yych <= 's') { - if (yych <= 'r') goto json_parser_50; - goto json_parser_27; - } else { - if (yych <= 't') goto json_parser_50; - if (yych <= 'u') goto json_parser_55; - goto json_parser_27; - } - } - } + if (yybm[0 + yych] & 64) + { + goto json_parser_50; + } + if (yych <= '"') + { + goto json_parser_53; + } + ++buffer_re2c; + yych = *buffer_re2c; + if (yych <= 'e') + { + if (yych <= '/') + { + if (yych == '"') + { + goto json_parser_50; + } + if (yych <= '.') + { + goto json_parser_27; + } + goto json_parser_50; + } + else + { + if (yych <= '\\') + { + if (yych <= '[') + { + goto json_parser_27; + } + goto json_parser_50; + } + else + { + if (yych == 'b') + { + goto json_parser_50; + } + goto json_parser_27; + } + } + } + else + { + if (yych <= 'q') + { + if (yych <= 'f') + { + goto json_parser_50; + } + if (yych == 'n') + { + goto json_parser_50; + } + goto json_parser_27; + } + else + { + if (yych <= 's') + { + if (yych <= 'r') + { + goto json_parser_50; + } + goto json_parser_27; + } + else + { + if (yych <= 't') + { + goto json_parser_50; + } + if (yych <= 'u') + { + goto json_parser_55; + } + goto json_parser_27; + } + } + } json_parser_53: - ++buffer_re2c; - { return last_token = token_type::value_string; } + ++buffer_re2c; + { + return last_token = token_type::value_string; + } json_parser_55: - ++buffer_re2c; - yych = *buffer_re2c; - if (yych <= '@') { - if (yych <= '/') goto json_parser_27; - if (yych >= ':') goto json_parser_27; - } else { - if (yych <= 'F') goto json_parser_56; - if (yych <= '`') goto json_parser_27; - if (yych >= 'g') goto json_parser_27; - } + ++buffer_re2c; + yych = *buffer_re2c; + if (yych <= '@') + { + if (yych <= '/') + { + goto json_parser_27; + } + if (yych >= ':') + { + goto json_parser_27; + } + } + else + { + if (yych <= 'F') + { + goto json_parser_56; + } + if (yych <= '`') + { + goto json_parser_27; + } + if (yych >= 'g') + { + goto json_parser_27; + } + } json_parser_56: - ++buffer_re2c; - yych = *buffer_re2c; - if (yych <= '@') { - if (yych <= '/') goto json_parser_27; - if (yych >= ':') goto json_parser_27; - } else { - if (yych <= 'F') goto json_parser_57; - if (yych <= '`') goto json_parser_27; - if (yych >= 'g') goto json_parser_27; - } + ++buffer_re2c; + yych = *buffer_re2c; + if (yych <= '@') + { + if (yych <= '/') + { + goto json_parser_27; + } + if (yych >= ':') + { + goto json_parser_27; + } + } + else + { + if (yych <= 'F') + { + goto json_parser_57; + } + if (yych <= '`') + { + goto json_parser_27; + } + if (yych >= 'g') + { + goto json_parser_27; + } + } json_parser_57: - ++buffer_re2c; - yych = *buffer_re2c; - if (yych <= '@') { - if (yych <= '/') goto json_parser_27; - if (yych >= ':') goto json_parser_27; - } else { - if (yych <= 'F') goto json_parser_58; - if (yych <= '`') goto json_parser_27; - if (yych >= 'g') goto json_parser_27; - } + ++buffer_re2c; + yych = *buffer_re2c; + if (yych <= '@') + { + if (yych <= '/') + { + goto json_parser_27; + } + if (yych >= ':') + { + goto json_parser_27; + } + } + else + { + if (yych <= 'F') + { + goto json_parser_58; + } + if (yych <= '`') + { + goto json_parser_27; + } + if (yych >= 'g') + { + goto json_parser_27; + } + } json_parser_58: - ++buffer_re2c; - yych = *buffer_re2c; - if (yych <= '@') { - if (yych <= '/') goto json_parser_27; - if (yych <= '9') goto json_parser_50; - goto json_parser_27; - } else { - if (yych <= 'F') goto json_parser_50; - if (yych <= '`') goto json_parser_27; - if (yych <= 'f') goto json_parser_50; - goto json_parser_27; - } + ++buffer_re2c; + yych = *buffer_re2c; + if (yych <= '@') + { + if (yych <= '/') + { + goto json_parser_27; + } + if (yych <= '9') + { + goto json_parser_50; + } + goto json_parser_27; + } + else + { + if (yych <= 'F') + { + goto json_parser_50; + } + if (yych <= '`') + { + goto json_parser_27; + } + if (yych <= 'f') + { + goto json_parser_50; + } + goto json_parser_27; + } json_parser_59: - ++buffer_re2c; - yych = *buffer_re2c; + ++buffer_re2c; + yych = *buffer_re2c; json_parser_60: - if (yybm[0+yych] & 128) { - goto json_parser_59; - } - goto json_parser_2; -} + if (yybm[0 + yych] & 128) + { + goto json_parser_59; + } + goto json_parser_2; + } } } @@ -2964,6 +3429,7 @@ inline void swap(nlohmann::json& j1, template <> struct hash { + /// return a hash value for a JSON object size_t operator()(const nlohmann::json& j) const { // a naive hashing via the string representation diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 07cce7c7..9485632b 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -196,25 +196,25 @@ class basic_json case (value_t::string): { - m_value.string = new string_t(); + m_value.string = new string_t(""); break; } case (value_t::boolean): { - m_value.boolean = boolean_t(); + m_value.boolean = boolean_t(false); break; } case (value_t::number_integer): { - m_value.number_integer = number_integer_t(); + m_value.number_integer = number_integer_t(0); break; } case (value_t::number_float): { - m_value.number_float = number_float_t(); + m_value.number_float = number_float_t(0.0); break; } } @@ -315,6 +315,7 @@ class basic_json : m_type(value_t::number_float), m_value(number_float_t(value)) {} + /// create a container (array or object) from an initializer list inline basic_json(list_init_t l, bool type_deduction = true, value_t manual_type = value_t::array) { // the initializer list could describe an object @@ -372,11 +373,13 @@ class basic_json } } + /// explicitly create an array from an initializer list inline static basic_json array(list_init_t l = list_init_t()) { return basic_json(l, false, value_t::array); } + /// explicitly create an object from an initializer list inline static basic_json object(list_init_t l = list_init_t()) { return basic_json(l, false, value_t::object); @@ -733,6 +736,33 @@ class basic_json } + /// find an element in an object + inline iterator find(typename object_t::key_type key) + { + auto result = end(); + + if (m_type == value_t::object) + { + result.m_it.object_iterator = m_value.object->find(key); + } + + return result; + } + + /// find an element in an object + inline const_iterator find(typename object_t::key_type key) const + { + auto result = cend(); + + if (m_type == value_t::object) + { + result.m_it.object_iterator = m_value.object->find(key); + } + + return result; + } + + /////////////// // iterators // /////////////// @@ -799,22 +829,20 @@ class basic_json { return true; } - case (value_t::number_integer): - case (value_t::number_float): - case (value_t::boolean): - case (value_t::string): - { - return false; - } + case (value_t::array): { return m_value.array->empty(); } + case (value_t::object): { return m_value.object->empty(); } } + + // all other types are nonempty + return false; } /// returns the number of elements @@ -826,22 +854,20 @@ class basic_json { return 0; } - case (value_t::number_integer): - case (value_t::number_float): - case (value_t::boolean): - case (value_t::string): - { - return 1; - } + case (value_t::array): { return m_value.array->size(); } + case (value_t::object): { return m_value.object->size(); } } + + // all other types have size 1 + return 1; } /// returns the maximum possible number of elements @@ -853,22 +879,20 @@ class basic_json { return 0; } - case (value_t::number_integer): - case (value_t::number_float): - case (value_t::boolean): - case (value_t::string): - { - return 1; - } + case (value_t::array): { return m_value.array->max_size(); } + case (value_t::object): { return m_value.object->max_size(); } } + + // all other types have max_size 1 + return 1; } @@ -887,17 +911,17 @@ class basic_json } case (value_t::number_integer): { - m_value.number_integer = {}; + m_value.number_integer = 0; break; } case (value_t::number_float): { - m_value.number_float = {}; + m_value.number_float = 0.0; break; } case (value_t::boolean): { - m_value.boolean = {}; + m_value.boolean = false; break; } case (value_t::string): @@ -1348,7 +1372,7 @@ class basic_json /*! @brief escape a string - + Escape a string by replacing certain special characters by a sequence of an escape character (backslash) and another character and other control characters by a sequence of "\u" followed by a four-digit hex @@ -1436,12 +1460,12 @@ class basic_json /*! @brief internal implementation of the serialization function - + This function is called by the public member function dump and organizes the serializaion internally. The indentation level is propagated as additional parameter. In case of arrays and objects, the function is called recursively. Note that - + - strings and object keys are escaped using escape_string() - numbers are converted to a string before output using std::to_string() @@ -1573,6 +1597,7 @@ class basic_json /// the value of the current element json_value m_value = {}; + public: /////////////// // iterators // @@ -1601,7 +1626,9 @@ class basic_json /// the iterator points to the only value begin, /// the iterator points past the only value - end + end, + /// the iterator points to an invalid value + invalid }; /// an iterator value @@ -1674,6 +1701,7 @@ class basic_json case (basic_json::value_t::null): { + // set to end so begin()==end() is true: null is empty m_it.generic_iterator = generic_iterator_value::end; break; } @@ -1795,7 +1823,14 @@ class basic_json default: { - m_it.generic_iterator = generic_iterator_value::end; + if (m_it.generic_iterator == generic_iterator_value::begin) + { + m_it.generic_iterator = generic_iterator_value::end; + } + else + { + m_it.generic_iterator = generic_iterator_value::invalid; + } break; } } @@ -1822,7 +1857,14 @@ class basic_json default: { - m_it.generic_iterator = generic_iterator_value::end; + if (m_it.generic_iterator == generic_iterator_value::begin) + { + m_it.generic_iterator = generic_iterator_value::end; + } + else + { + m_it.generic_iterator = generic_iterator_value::invalid; + } break; } } @@ -1849,9 +1891,22 @@ class basic_json break; } + case (basic_json::value_t::null): + { + m_it.generic_iterator = generic_iterator_value::invalid; + break; + } + default: { - m_it.generic_iterator = generic_iterator_value::uninitialized; + if (m_it.generic_iterator == generic_iterator_value::end) + { + m_it.generic_iterator = generic_iterator_value::begin; + } + else + { + m_it.generic_iterator = generic_iterator_value::invalid; + } break; } } @@ -1876,9 +1931,22 @@ class basic_json break; } + case (basic_json::value_t::null): + { + m_it.generic_iterator = generic_iterator_value::invalid; + break; + } + default: { - m_it.generic_iterator = generic_iterator_value::uninitialized; + if (m_it.generic_iterator == generic_iterator_value::end) + { + m_it.generic_iterator = generic_iterator_value::begin; + } + else + { + m_it.generic_iterator = generic_iterator_value::invalid; + } break; } } @@ -1949,7 +2017,9 @@ class basic_json /// the iterator points to the only value begin, /// the iterator points past the only value - end + end, + /// the iterator points to an invalid value + invalid }; /// an iterator value @@ -1995,6 +2065,7 @@ class basic_json } } + /// copy constructor given a nonconst iterator inline const_iterator(const iterator& other) : m_object(other.m_object), m_it(other.m_it) {} @@ -2025,6 +2096,7 @@ class basic_json case (basic_json::value_t::null): { + // set to end so begin()==end() is true: null is empty m_it.generic_iterator = generic_iterator_value::end; break; } @@ -2146,7 +2218,14 @@ class basic_json default: { - m_it.generic_iterator = generic_iterator_value::end; + if (m_it.generic_iterator == generic_iterator_value::begin) + { + m_it.generic_iterator = generic_iterator_value::end; + } + else + { + m_it.generic_iterator = generic_iterator_value::invalid; + } break; } } @@ -2173,7 +2252,14 @@ class basic_json default: { - m_it.generic_iterator = generic_iterator_value::end; + if (m_it.generic_iterator == generic_iterator_value::begin) + { + m_it.generic_iterator = generic_iterator_value::end; + } + else + { + m_it.generic_iterator = generic_iterator_value::invalid; + } break; } } @@ -2200,9 +2286,22 @@ class basic_json break; } + case (basic_json::value_t::null): + { + m_it.generic_iterator = generic_iterator_value::invalid; + break; + } + default: { - m_it.generic_iterator = generic_iterator_value::uninitialized; + if (m_it.generic_iterator == generic_iterator_value::end) + { + m_it.generic_iterator = generic_iterator_value::begin; + } + else + { + m_it.generic_iterator = generic_iterator_value::invalid; + } break; } } @@ -2227,9 +2326,22 @@ class basic_json break; } + case (basic_json::value_t::null): + { + m_it.generic_iterator = generic_iterator_value::invalid; + break; + } + default: { - m_it.generic_iterator = generic_iterator_value::uninitialized; + if (m_it.generic_iterator == generic_iterator_value::end) + { + m_it.generic_iterator = generic_iterator_value::begin; + } + else + { + m_it.generic_iterator = generic_iterator_value::invalid; + } break; } } @@ -2277,6 +2389,7 @@ class basic_json internal_const_iterator m_it; }; + private: //////////// // parser // @@ -2670,6 +2783,7 @@ inline void swap(nlohmann::json& j1, template <> struct hash { + /// return a hash value for a JSON object size_t operator()(const nlohmann::json& j) const { // a naive hashing via the string representation diff --git a/test/unit.cpp b/test/unit.cpp index 79536c9b..b131fcb3 100644 --- a/test/unit.cpp +++ b/test/unit.cpp @@ -72,6 +72,13 @@ TEST_CASE() std::cerr << j.dump(4) << std::endl; j["pi"] = {3, 1, 4, 1}; std::cerr << j << std::endl; + + const json jc(j); + CHECK(j.find("name") != j.end()); + CHECK(j.find("foo") == j.end()); + CHECK(*(j.find("name")) == json("Niels") ); + CHECK(jc.find("name") != jc.end()); + CHECK(jc.find("foo") == jc.end()); } { // ways to express the empty array []