From 5acfb7f926f9aa1f0ce2fe573117d63d3dee5802 Mon Sep 17 00:00:00 2001 From: Joao Paulo Magalhaes Date: Fri, 31 Jul 2026 20:06:33 +0100 Subject: [PATCH 1/2] Move EmitType_e to emit_options.hpp --- src/c4/yml/emit_options.hpp | 8 +++++++ src/c4/yml/emitter.def.hpp | 45 ------------------------------------- src/c4/yml/emitter.hpp | 5 ----- 3 files changed, 8 insertions(+), 50 deletions(-) diff --git a/src/c4/yml/emit_options.hpp b/src/c4/yml/emit_options.hpp index d35aa6a26..1e46b4271 100644 --- a/src/c4/yml/emit_options.hpp +++ b/src/c4/yml/emit_options.hpp @@ -8,6 +8,14 @@ namespace c4 { namespace yml { + +/** Specifies the type of content to emit */ +typedef enum { // NOLINT + EMIT_YAML = 0, ///< emit YAML + EMIT_JSON = 1, ///< emit JSON +} EmitType_e; + + /** A lightweight object containing options to be used when emitting. * @ingroup doc_emit */ diff --git a/src/c4/yml/emitter.def.hpp b/src/c4/yml/emitter.def.hpp index 04138092b..1e3d75842 100644 --- a/src/c4/yml/emitter.def.hpp +++ b/src/c4/yml/emitter.def.hpp @@ -1227,7 +1227,6 @@ void Emitter::write_scalar_dquo_(csubstr s, id_type ilevel) pos = i+1; break; } -#ifndef prefer_writing_newlines_as_double_newlines case '\n': { csubstr sub = s.range(pos, i); @@ -1237,50 +1236,6 @@ void Emitter::write_scalar_dquo_(csubstr s, id_type ilevel) (void)ilevel; break; } -#else - case '\n': - { - // write everything up to (excluding) this newline - //_c4dbgpf("nl@i={} rem=[{}]~~~{}~~~", i, s.sub(i).len, s.sub(i)); - _write(s.range(pos, i)); - i = _write_escaped_newlines(s, i); - ++i; - pos = i; - // as for the next line... - if(i < s.len) - { - _indent(ilevel + 1); // indent the next line - // escape leading whitespace, and flush it - size_t first = s.first_not_of(" \t", i); - //_c4dbgpf("@i={} first={} rem=[{}]~~~{}~~~", i, first, s.sub(i).len, s.sub(i)); - if(first > i) - { - if(first == npos) - first = s.len; - _write('\\'); - _write(s.range(i, first)); - _write('\\'); - i = first-1; - pos = first; - } - } - break; - } - // escape trailing whitespace before a newline - case ' ': - case '\t': - { - const size_t next = s.first_not_of(" \t\r", i); - if(next != npos && s.str[next] == '\n') - { - csubstr sub = s.range(pos, i); - _write(sub); // write everything up to (excluding) this char - _write('\\'); // escape the whitespace - pos = i; - } - break; - } -#endif case '\r': { csubstr sub = s.range(pos, i); diff --git a/src/c4/yml/emitter.hpp b/src/c4/yml/emitter.hpp index 8a5b7a277..e22906390 100644 --- a/src/c4/yml/emitter.hpp +++ b/src/c4/yml/emitter.hpp @@ -18,11 +18,6 @@ namespace yml { /** @cond dev */ // fwd declarations class Tree; -/** Specifies the type of content to emit */ -typedef enum { // NOLINT - EMIT_YAML = 0, ///< emit YAML - EMIT_JSON = 1, ///< emit JSON -} EmitType_e; /** @endcond */ From c5d85cfc77da98a6adfafc7f0f62b5e4c3ba1f43 Mon Sep 17 00:00:00 2001 From: Joao Paulo Magalhaes Date: Fri, 31 Jul 2026 16:25:28 +0100 Subject: [PATCH 2/2] wip --- CMakeLists.txt | 8 +- bm/CMakeLists.txt | 1 - bm/bm_common.hpp | 67 +- bm/bm_emit.cpp | 3 + bm/bm_parse.cpp | 302 +- samples/ints_only/CMakeLists.txt | 9 +- samples/quickstart-ints.cpp | 450 ++- samples/quickstart.cpp | 14 +- src/c4/yml/common.cpp | 32 + src/c4/yml/common.hpp | 23 + src/c4/yml/detail/dbgprint.hpp | 6 +- src/c4/yml/detail/emit_scalar.hpp | 483 +++ src/c4/yml/emit_container.hpp | 12 +- src/c4/yml/emitter.def.hpp | 545 +-- src/c4/yml/emitter.hpp | 16 +- src/c4/yml/parse_engine.def.hpp | 159 +- src/c4/yml/scalar_style.cpp | 2 + src_extra/c4/yml/extra/emitter_ints.def.hpp | 1644 ++++++++ src_extra/c4/yml/extra/emitter_ints.hpp | 251 ++ src_extra/c4/yml/extra/event_handler_ints.cpp | 103 - src_extra/c4/yml/extra/event_handler_ints.hpp | 1010 +++-- .../extra/event_handler_ints_no_resize.cpp | 15 + .../yml/extra/event_handler_ints_resize.cpp | 15 + src_extra/c4/yml/extra/event_ints.cpp | 338 ++ src_extra/c4/yml/extra/event_ints.hpp | 461 +++ src_extra/c4/yml/extra/ints_to_testsuite.cpp | 12 +- src_extra/c4/yml/extra/ints_to_testsuite.hpp | 14 +- src_extra/c4/yml/extra/ints_utils.cpp | 60 +- src_extra/c4/yml/extra/ints_utils.hpp | 40 +- test/CMakeLists.txt | 46 +- test/test_anchor.cpp | 6 +- test/test_doc.cpp | 92 +- test/test_emit.cpp | 3504 +++++++++++++---- test/test_engine_1_doc_1.cpp | 734 ---- test/test_engine_1_doc_3.cpp | 764 ++++ test/test_engine_3_map_block_1.cpp | 5 +- test/test_engine_3_map_block_2.cpp | 115 +- test/test_engine_3_map_flow_1.cpp | 12 +- test/test_engine_4_anchor.cpp | 51 +- test/test_engine_5_tag_1.cpp | 56 +- test/test_engine_5_tag_2.cpp | 2 + test/test_engine_6_qmrk_1.cpp | 143 +- test/test_engine_6_qmrk_2.cpp | 187 +- test/test_engine_6_qmrk_3.cpp | 75 +- test/test_engine_6_qmrk_4.cpp | 945 +---- test/test_engine_6_qmrk_5.cpp | 967 +++++ test/test_engine_7_seqimap.cpp | 10 +- test/test_extra_ints.cpp | 220 +- test/test_fuzz/test_fuzz_common.hpp | 82 +- .../test_fuzz_json_ints_noresize.cpp | 9 + ...nts.cpp => test_fuzz_json_ints_resize.cpp} | 2 +- .../test_fuzz_yaml_ints_noresize.cpp | 9 + ...nts.cpp => test_fuzz_yaml_ints_resize.cpp} | 2 +- test/test_github_issues.cpp | 4 +- test/test_json.cpp | 101 +- test/test_lib/string.hpp | 425 -- test/test_lib/test_case.cpp | 105 +- test/test_lib/test_case.hpp | 201 +- test/test_lib/test_case_node.cpp | 19 +- test/test_lib/test_case_node.hpp | 3 +- test/test_lib/test_compare_events.cpp | 164 + test/test_lib/test_compare_events.hpp | 37 + test/test_lib/test_engine.cpp | 710 ++-- test/test_lib/test_engine.hpp | 232 +- test/test_lib/test_events_ints_helpers.cpp | 797 ++-- test/test_lib/test_events_ints_helpers.hpp | 258 +- test/test_lib/test_group.cpp | 887 ++--- test/test_lib/test_group.def.hpp | 206 +- test/test_lib/test_group.hpp | 98 +- test/test_lib/tree_and_ints.hpp | 259 ++ test/test_map.cpp | 10 +- test/test_map_set.cpp | 14 +- test/test_qmrk.cpp | 10 +- test/test_scalar_dquoted.cpp | 2 +- test/test_scalar_null.cpp | 28 +- test/test_scalar_plain.cpp | 18 +- test/test_scalar_squoted.cpp | 2 +- test/test_seq.cpp | 8 +- test/test_seq_of_map.cpp | 4 +- test/test_style.cpp | 1666 +++++--- test/test_tag.cpp | 12 +- test/test_tree.cpp | 23 +- test/testsuite.cpp | 694 +++- test/testsuite/testsuite_events.cpp | 6 +- tools/amalgamate.py | 22 +- tools/parse_emit.cpp | 46 +- 86 files changed, 14317 insertions(+), 6887 deletions(-) create mode 100644 src/c4/yml/detail/emit_scalar.hpp create mode 100644 src_extra/c4/yml/extra/emitter_ints.def.hpp create mode 100644 src_extra/c4/yml/extra/emitter_ints.hpp delete mode 100644 src_extra/c4/yml/extra/event_handler_ints.cpp create mode 100644 src_extra/c4/yml/extra/event_handler_ints_no_resize.cpp create mode 100644 src_extra/c4/yml/extra/event_handler_ints_resize.cpp create mode 100644 src_extra/c4/yml/extra/event_ints.cpp create mode 100644 src_extra/c4/yml/extra/event_ints.hpp create mode 100644 test/test_engine_1_doc_3.cpp create mode 100644 test/test_engine_6_qmrk_5.cpp create mode 100644 test/test_fuzz/test_fuzz_json_ints_noresize.cpp rename test/test_fuzz/{test_fuzz_json_ints.cpp => test_fuzz_json_ints_resize.cpp} (78%) create mode 100644 test/test_fuzz/test_fuzz_yaml_ints_noresize.cpp rename test/test_fuzz/{test_fuzz_yaml_ints.cpp => test_fuzz_yaml_ints_resize.cpp} (78%) delete mode 100644 test/test_lib/string.hpp create mode 100644 test/test_lib/test_compare_events.cpp create mode 100644 test/test_lib/test_compare_events.hpp create mode 100644 test/test_lib/tree_and_ints.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index b482a75ea..4f340e581 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,6 +38,7 @@ c4_add_library(ryml ryml.natvis c4/yml/detail/checks.hpp c4/yml/detail/dbgprint.hpp + c4/yml/detail/emit_scalar.hpp c4/yml/detail/print.hpp c4/yml/detail/stack.hpp c4/yml/common.hpp @@ -169,8 +170,13 @@ if(RYML_EXTRA_ALL # test the extra facilities as well if(RYML_EXTRA_INTS OR RYML_EXTRA_ALL) list(APPEND RYML_EXTRA_SRC - "${CMAKE_CURRENT_LIST_DIR}/src_extra/c4/yml/extra/event_handler_ints.cpp" + "${CMAKE_CURRENT_LIST_DIR}/src_extra/c4/yml/extra/event_ints.cpp" + "${CMAKE_CURRENT_LIST_DIR}/src_extra/c4/yml/extra/event_ints.hpp" + "${CMAKE_CURRENT_LIST_DIR}/src_extra/c4/yml/extra/event_handler_ints_resize.cpp" + "${CMAKE_CURRENT_LIST_DIR}/src_extra/c4/yml/extra/event_handler_ints_no_resize.cpp" "${CMAKE_CURRENT_LIST_DIR}/src_extra/c4/yml/extra/event_handler_ints.hpp" + "${CMAKE_CURRENT_LIST_DIR}/src_extra/c4/yml/extra/emitter_ints.hpp" + "${CMAKE_CURRENT_LIST_DIR}/src_extra/c4/yml/extra/emitter_ints.def.hpp" ) endif() if(RYML_EXTRA_INTS_UTILS OR RYML_EXTRA_ALL) diff --git a/bm/CMakeLists.txt b/bm/CMakeLists.txt index 726f8b31c..e2c20991c 100644 --- a/bm/CMakeLists.txt +++ b/bm/CMakeLists.txt @@ -145,7 +145,6 @@ function(ryml_add_bm_comparison_exe name) c4_add_executable(ryml-bm-${name} SOURCES bm_common.hpp ${ARGN} ../src_extra/c4/yml/extra/event_handler_ints.hpp - ../src_extra/c4/yml/extra/event_handler_ints.cpp LIBS ryml yaml yaml-cpp benchmark jsoncpp_static nlohmann_json c4fs INC_DIRS ${RYML_RAPIDJSON_INC_DIR} diff --git a/bm/bm_common.hpp b/bm/bm_common.hpp index a71b2d20a..1641b2009 100644 --- a/bm/bm_common.hpp +++ b/bm/bm_common.hpp @@ -111,39 +111,41 @@ namespace bm = benchmark; //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -using IntHandler = ryml::extra::EventHandlerInts; -using IntParser = ryml::ParseEngine; -struct IntData +using IntHandlerResize = ryml::extra::ievt::EventHandlerInts; +using IntHandlerNoResize = ryml::extra::ievt::EventHandlerInts; +using IntParserResize = ryml::ParseEngine; +using IntParserNoResize = ryml::ParseEngine; +struct IntDataNoResize { std::vector events; std::vector arena; - void resize(ryml::extra::EventHandlerInts const& handler) + void resize(IntHandlerNoResize const& handler) { resize((size_t)handler.required_size_events(), handler.required_size_arena()); } - void resize(ryml::substr src) + void resize(ryml::csubstr src) { - resize((size_t)ryml::extra::estimate_events_ints_size(src), + resize((size_t)ryml::extra::ievt::estimate_events_size(src), src.len); } void resize(size_t evt_sz, size_t arn_sz) { events.resize(evt_sz); - events.resize(arn_sz); + arena.resize(arn_sz); } }; -struct IntObjects +struct IntObjectsNoResize { - IntObjects(ryml::ParserOptions opts={}) + IntObjectsNoResize(ryml::ParserOptions opts={}) : handler() , parser(&handler, opts) , data() { } - IntHandler handler; - IntParser parser; - IntData data; + IntHandlerNoResize handler; + IntParserNoResize parser; + IntDataNoResize data; bool again() { if(!handler.fits_buffers()) @@ -154,7 +156,7 @@ struct IntObjects return false; } }; -inline void parse_yaml_inplace(ryml::csubstr filename, ryml::substr src, IntParser &parser, IntData *dst) +inline void parse_yaml_ints_noresize_inplace(ryml::csubstr filename, ryml::substr src, IntParserNoResize &parser, IntDataNoResize *dst) { parser.m_evt_handler->reset(src, ryml::to_substr(dst->arena), @@ -162,7 +164,7 @@ inline void parse_yaml_inplace(ryml::csubstr filename, ryml::substr src, IntPars (int)dst->events.size()); parser.parse_in_place_ev(filename, src); } -inline void parse_json_inplace(ryml::csubstr filename, ryml::substr src, IntParser &parser, IntData *dst) +inline void parse_json_ints_noresize_inplace(ryml::csubstr filename, ryml::substr src, IntParserNoResize &parser, IntDataNoResize *dst) { parser.m_evt_handler->reset(src, ryml::to_substr(dst->arena), @@ -171,6 +173,36 @@ inline void parse_json_inplace(ryml::csubstr filename, ryml::substr src, IntPars parser.parse_json_in_place_ev(filename, src); } +struct IntObjectsResize +{ + IntObjectsResize(ryml::ParserOptions opts={}) + : handler() + , parser(&handler, opts) + , data() + { + } + IntHandlerResize handler; + IntParserResize parser; + ryml::extra::ievt::Buffers data; + void reserve(ryml::csubstr src) + { + handler.reserve_evts(ryml::extra::ievt::estimate_events_size(src)); + handler.reserve_arena(src.len); + } +}; +inline void parse_yaml_ints_resize_inplace(ryml::csubstr filename, ryml::substr src, IntParserResize &parser, ryml::extra::ievt::Buffers *dst) +{ + parser.m_evt_handler->reset(src); + parser.parse_in_place_ev(filename, src); + *dst = parser.m_evt_handler->get_buffers(); +} +inline void parse_json_ints_resize_inplace(ryml::csubstr filename, ryml::substr src, IntParserResize &parser, ryml::extra::ievt::Buffers *dst) +{ + parser.m_evt_handler->reset(src); + parser.parse_json_in_place_ev(filename, src); + *dst = parser.m_evt_handler->get_buffers(); +} + //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- @@ -200,8 +232,11 @@ struct BmCase rapidjson::Document rapidjson_doc; ryml::Tree libyaml_tree; - IntObjects int_obj; - IntObjects int_obj_nofilter{ryml::ParserOptions().scalar_filtering(false)}; + IntObjectsNoResize int_obj_noresize; + IntObjectsNoResize int_obj_noresize_nofilter{ryml::ParserOptions().scalar_filtering(false)}; + + IntObjectsResize int_obj_resize; + IntObjectsResize int_obj_resize_nofilter{ryml::ParserOptions().scalar_filtering(false)}; void run(std::string name, int argc, char **argv) { diff --git a/bm/bm_emit.cpp b/bm/bm_emit.cpp index 866390459..30340827c 100644 --- a/bm/bm_emit.cpp +++ b/bm/bm_emit.cpp @@ -200,6 +200,9 @@ void bm_yamlcpp(bm::State& st) s_bm_case->report(st); } + +//----------------------------------------------------------------------------- + void bm_ryml_yaml_ostream(bm::State& st) { c4::csubstr src = c4::to_csubstr(s_bm_case->src).trimr('\0'); diff --git a/bm/bm_parse.cpp b/bm/bm_parse.cpp index 003914af2..7964068f9 100644 --- a/bm/bm_parse.cpp +++ b/bm/bm_parse.cpp @@ -294,69 +294,129 @@ void bm_rymlints_estimate(bm::State& st) } -void bm_rymlints_yaml_inplace(bm::State& st) +void bm_rymlints_yaml_noresize_inplace(bm::State& st) { c4::substr src = c4::to_substr(s_bm_case->in_place).trimr('\0'); for(auto _ : st) { - IntObjects obj; + IntObjectsNoResize obj; s_bm_case->prepare(st, kResetInPlace); - parse_yaml_inplace(s_bm_case->filename, src, obj.parser, &obj.data); + parse_yaml_ints_noresize_inplace(s_bm_case->filename, src, obj.parser, &obj.data); if(obj.again()) { s_bm_case->prepare(st, kResetInPlace); - parse_yaml_inplace(s_bm_case->filename, src, obj.parser, &obj.data); + parse_yaml_ints_noresize_inplace(s_bm_case->filename, src, obj.parser, &obj.data); } bm::DoNotOptimize(obj); } s_bm_case->report(st); } +void bm_rymlints_yaml_resize_inplace(bm::State& st) +{ + c4::substr src = c4::to_substr(s_bm_case->in_place).trimr('\0'); + for(auto _ : st) + { + st.PauseTiming(); + IntObjectsResize obj; + s_bm_case->prepare(st, kResetInPlace); + st.ResumeTiming(); + parse_yaml_ints_resize_inplace(s_bm_case->filename, src, obj.parser, &obj.data); + bm::DoNotOptimize(obj); + } + s_bm_case->report(st); +} -void bm_rymlints_yaml_inplace_reserve(bm::State& st) +void bm_rymlints_yaml_noresize_inplace_reserve(bm::State& st) { c4::substr src = c4::to_substr(s_bm_case->in_place).trimr('\0'); for(auto _ : st) { st.PauseTiming(); s_bm_case->prepare(kResetInPlace); - IntObjects obj; + IntObjectsNoResize obj; obj.data.resize(src); st.ResumeTiming(); - parse_yaml_inplace(s_bm_case->filename, src, obj.parser, &obj.data); + parse_yaml_ints_noresize_inplace(s_bm_case->filename, src, obj.parser, &obj.data); + bm::DoNotOptimize(obj); + } + s_bm_case->report(st); +} +void bm_rymlints_yaml_resize_inplace_reserve(bm::State& st) +{ + c4::substr src = c4::to_substr(s_bm_case->in_place).trimr('\0'); + IntObjectsResize obj; + obj.reserve(src); + for(auto _ : st) + { + st.PauseTiming(); + s_bm_case->prepare(kResetInPlace); + st.ResumeTiming(); + parse_yaml_ints_resize_inplace(s_bm_case->filename, src, obj.parser, &obj.data); bm::DoNotOptimize(obj); } s_bm_case->report(st); } -void bm_rymlints_yaml_inplace_nofilter(bm::State& st) +void bm_rymlints_yaml_noresize_inplace_nofilter(bm::State& st) { c4::substr src = c4::to_substr(s_bm_case->in_place).trimr('\0'); for(auto _ : st) { - IntObjects obj(ryml::ParserOptions().scalar_filtering(false)); + st.PauseTiming(); + IntObjectsNoResize obj(ryml::ParserOptions().scalar_filtering(false)); s_bm_case->prepare(st, kResetInPlace); - parse_yaml_inplace(s_bm_case->filename, src, obj.parser, &obj.data); + st.ResumeTiming(); + parse_yaml_ints_noresize_inplace(s_bm_case->filename, src, obj.parser, &obj.data); if(obj.again()) { s_bm_case->prepare(st, kResetInPlace); - parse_yaml_inplace(s_bm_case->filename, src, obj.parser, &obj.data); + parse_yaml_ints_noresize_inplace(s_bm_case->filename, src, obj.parser, &obj.data); } bm::DoNotOptimize(obj); } s_bm_case->report(st); } +void bm_rymlints_yaml_resize_inplace_nofilter(bm::State& st) +{ + c4::substr src = c4::to_substr(s_bm_case->in_place).trimr('\0'); + for(auto _ : st) + { + st.PauseTiming(); + IntObjectsResize obj(ryml::ParserOptions().scalar_filtering(false)); + s_bm_case->prepare(st, kResetInPlace); + st.ResumeTiming(); + parse_yaml_ints_resize_inplace(s_bm_case->filename, src, obj.parser, &obj.data); + bm::DoNotOptimize(obj); + } + s_bm_case->report(st); +} -void bm_rymlints_yaml_inplace_nofilter_reserve(bm::State& st) +void bm_rymlints_yaml_noresize_inplace_nofilter_reserve(bm::State& st) { c4::substr src = c4::to_substr(s_bm_case->in_place).trimr('\0'); for(auto _ : st) { st.PauseTiming(); s_bm_case->prepare(kResetInPlace); - IntObjects obj(ryml::ParserOptions().scalar_filtering(false)); + IntObjectsNoResize obj(ryml::ParserOptions().scalar_filtering(false)); obj.data.resize(src); st.ResumeTiming(); - parse_yaml_inplace(s_bm_case->filename, src, obj.parser, &obj.data); + parse_yaml_ints_noresize_inplace(s_bm_case->filename, src, obj.parser, &obj.data); + bm::DoNotOptimize(obj); + } + s_bm_case->report(st); +} +void bm_rymlints_yaml_resize_inplace_nofilter_reserve(bm::State& st) +{ + c4::substr src = c4::to_substr(s_bm_case->in_place).trimr('\0'); + IntObjectsResize obj(ryml::ParserOptions().scalar_filtering(false)); + obj.reserve(src); + for(auto _ : st) + { + st.PauseTiming(); + s_bm_case->prepare(kResetInPlace); + st.ResumeTiming(); + parse_yaml_ints_resize_inplace(s_bm_case->filename, src, obj.parser, &obj.data); bm::DoNotOptimize(obj); } s_bm_case->report(st); @@ -365,26 +425,41 @@ void bm_rymlints_yaml_inplace_nofilter_reserve(bm::State& st) //----------------------------------------------------------------------------- -void bm_rymlints_json_inplace(bm::State& st) +void bm_rymlints_json_noresize_inplace(bm::State& st) { c4::substr src = c4::to_substr(s_bm_case->in_place).trimr('\0'); for(auto _ : st) { ONLY_FOR_JSON; - IntObjects obj; + IntObjectsNoResize obj; s_bm_case->prepare(st, kResetInPlace); - parse_json_inplace(s_bm_case->filename, src, obj.parser, &obj.data); + parse_json_ints_noresize_inplace(s_bm_case->filename, src, obj.parser, &obj.data); if(obj.again()) { s_bm_case->prepare(st, kResetInPlace); - parse_json_inplace(s_bm_case->filename, src, obj.parser, &obj.data); + parse_json_ints_noresize_inplace(s_bm_case->filename, src, obj.parser, &obj.data); } bm::DoNotOptimize(obj); } s_bm_case->report(st); } +void bm_rymlints_json_resize_inplace(bm::State& st) +{ + c4::substr src = c4::to_substr(s_bm_case->in_place).trimr('\0'); + for(auto _ : st) + { + ONLY_FOR_JSON; + st.PauseTiming(); + IntObjectsResize obj; + s_bm_case->prepare(st, kResetInPlace); + st.ResumeTiming(); + parse_json_ints_resize_inplace(s_bm_case->filename, src, obj.parser, &obj.data); + bm::DoNotOptimize(obj); + } + s_bm_case->report(st); +} -void bm_rymlints_json_inplace_reserve(bm::State& st) +void bm_rymlints_json_noresize_inplace_reserve(bm::State& st) { c4::substr src = c4::to_substr(s_bm_case->in_place).trimr('\0'); size_t sz = (size_t)ryml::extra::estimate_events_ints_size(src); @@ -393,35 +468,66 @@ void bm_rymlints_json_inplace_reserve(bm::State& st) ONLY_FOR_JSON; st.PauseTiming(); s_bm_case->prepare(kResetInPlace); - IntObjects obj; + IntObjectsNoResize obj; obj.data.resize(sz, src.len); st.ResumeTiming(); - parse_json_inplace(s_bm_case->filename, src, obj.parser, &obj.data); + parse_json_ints_noresize_inplace(s_bm_case->filename, src, obj.parser, &obj.data); + bm::DoNotOptimize(obj); + } + s_bm_case->report(st); +} +void bm_rymlints_json_resize_inplace_reserve(bm::State& st) +{ + c4::substr src = c4::to_substr(s_bm_case->in_place).trimr('\0'); + for(auto _ : st) + { + ONLY_FOR_JSON; + st.PauseTiming(); + IntObjectsResize obj; + obj.reserve(src); + s_bm_case->prepare(kResetInPlace); + st.ResumeTiming(); + parse_json_ints_resize_inplace(s_bm_case->filename, src, obj.parser, &obj.data); bm::DoNotOptimize(obj); } s_bm_case->report(st); } -void bm_rymlints_json_inplace_nofilter(bm::State& st) +void bm_rymlints_json_noresize_inplace_nofilter(bm::State& st) { c4::substr src = c4::to_substr(s_bm_case->in_place).trimr('\0'); for(auto _ : st) { ONLY_FOR_JSON; - IntObjects obj(ryml::ParserOptions().scalar_filtering(false)); + IntObjectsNoResize obj(ryml::ParserOptions().scalar_filtering(false)); s_bm_case->prepare(st, kResetInPlace); - parse_json_inplace(s_bm_case->filename, src, obj.parser, &obj.data); + parse_json_ints_noresize_inplace(s_bm_case->filename, src, obj.parser, &obj.data); if(obj.again()) { s_bm_case->prepare(st, kResetInPlace); - parse_json_inplace(s_bm_case->filename, src, obj.parser, &obj.data); + parse_json_ints_noresize_inplace(s_bm_case->filename, src, obj.parser, &obj.data); } bm::DoNotOptimize(obj); } s_bm_case->report(st); } +void bm_rymlints_json_resize_inplace_nofilter(bm::State& st) +{ + c4::substr src = c4::to_substr(s_bm_case->in_place).trimr('\0'); + for(auto _ : st) + { + ONLY_FOR_JSON; + st.PauseTiming(); + IntObjectsResize obj(ryml::ParserOptions().scalar_filtering(false)); + s_bm_case->prepare(st, kResetInPlace); + st.ResumeTiming(); + parse_json_ints_resize_inplace(s_bm_case->filename, src, obj.parser, &obj.data); + bm::DoNotOptimize(obj); + } + s_bm_case->report(st); +} -void bm_rymlints_json_inplace_nofilter_reserve(bm::State& st) +void bm_rymlints_json_noresize_inplace_nofilter_reserve(bm::State& st) { c4::substr src = c4::to_substr(s_bm_case->in_place).trimr('\0'); size_t sz = (size_t)ryml::extra::estimate_events_ints_size(src); @@ -430,10 +536,26 @@ void bm_rymlints_json_inplace_nofilter_reserve(bm::State& st) ONLY_FOR_JSON; st.PauseTiming(); s_bm_case->prepare(kResetInPlace); - IntObjects obj(ryml::ParserOptions().scalar_filtering(false)); + IntObjectsNoResize obj(ryml::ParserOptions().scalar_filtering(false)); obj.data.resize(sz, src.len); st.ResumeTiming(); - parse_json_inplace(s_bm_case->filename, src, obj.parser, &obj.data); + parse_json_ints_noresize_inplace(s_bm_case->filename, src, obj.parser, &obj.data); + bm::DoNotOptimize(obj); + } + s_bm_case->report(st); +} +void bm_rymlints_json_resize_inplace_nofilter_reserve(bm::State& st) +{ + c4::substr src = c4::to_substr(s_bm_case->in_place).trimr('\0'); + for(auto _ : st) + { + ONLY_FOR_JSON; + st.PauseTiming(); + IntObjectsResize obj(ryml::ParserOptions().scalar_filtering(false)); + obj.reserve(src); + s_bm_case->prepare(kResetInPlace); + st.ResumeTiming(); + parse_json_ints_resize_inplace(s_bm_case->filename, src, obj.parser, &obj.data); bm::DoNotOptimize(obj); } s_bm_case->report(st); @@ -676,28 +798,52 @@ void bm_ryml_json_arena_reuse_nofilter_reserve(bm::State& st) //----------------------------------------------------------------------------- -void bm_rymlints_yaml_inplace_reuse(bm::State& st) +void bm_rymlints_yaml_noresize_inplace_reuse(bm::State& st) { c4::substr src = c4::to_substr(s_bm_case->in_place).trimr('\0'); - s_bm_case->int_obj.data.resize(src); + s_bm_case->int_obj_noresize.data.resize(src); for(auto _ : st) { s_bm_case->prepare(st, kResetInPlace); - parse_yaml_inplace(s_bm_case->filename, src, s_bm_case->int_obj.parser, &s_bm_case->int_obj.data); - bm::DoNotOptimize(s_bm_case->int_obj); + parse_yaml_ints_noresize_inplace(s_bm_case->filename, src, s_bm_case->int_obj_noresize.parser, &s_bm_case->int_obj_noresize.data); + bm::DoNotOptimize(s_bm_case->int_obj_noresize); + } + s_bm_case->report(st); +} +void bm_rymlints_yaml_resize_inplace_reuse(bm::State& st) +{ + c4::substr src = c4::to_substr(s_bm_case->in_place).trimr('\0'); + s_bm_case->int_obj_resize.reserve(src); + for(auto _ : st) + { + s_bm_case->prepare(st, kResetInPlace); + parse_yaml_ints_resize_inplace(s_bm_case->filename, src, s_bm_case->int_obj_resize.parser, &s_bm_case->int_obj_resize.data); + bm::DoNotOptimize(s_bm_case->int_obj_resize); } s_bm_case->report(st); } -void bm_rymlints_yaml_inplace_reuse_nofilter(bm::State& st) +void bm_rymlints_yaml_noresize_inplace_reuse_nofilter(bm::State& st) +{ + c4::substr src = c4::to_substr(s_bm_case->in_place).trimr('\0'); + s_bm_case->int_obj_noresize_nofilter.data.resize(src); + for(auto _ : st) + { + s_bm_case->prepare(st, kResetInPlace); + parse_yaml_ints_noresize_inplace(s_bm_case->filename, src, s_bm_case->int_obj_noresize_nofilter.parser, &s_bm_case->int_obj_noresize_nofilter.data); + bm::DoNotOptimize(s_bm_case->int_obj_noresize_nofilter); + } + s_bm_case->report(st); +} +void bm_rymlints_yaml_resize_inplace_reuse_nofilter(bm::State& st) { c4::substr src = c4::to_substr(s_bm_case->in_place).trimr('\0'); - s_bm_case->int_obj_nofilter.data.resize(src); + s_bm_case->int_obj_resize_nofilter.reserve(src); for(auto _ : st) { s_bm_case->prepare(st, kResetInPlace); - parse_yaml_inplace(s_bm_case->filename, src, s_bm_case->int_obj_nofilter.parser, &s_bm_case->int_obj_nofilter.data); - bm::DoNotOptimize(s_bm_case->int_obj_nofilter); + parse_yaml_ints_resize_inplace(s_bm_case->filename, src, s_bm_case->int_obj_resize_nofilter.parser, &s_bm_case->int_obj_resize_nofilter.data); + bm::DoNotOptimize(s_bm_case->int_obj_resize_nofilter); } s_bm_case->report(st); } @@ -705,30 +851,56 @@ void bm_rymlints_yaml_inplace_reuse_nofilter(bm::State& st) //----------------------------------------------------------------------------- -void bm_rymlints_json_inplace_reuse(bm::State& st) +void bm_rymlints_json_noresize_inplace_reuse(bm::State& st) { c4::substr src = c4::to_substr(s_bm_case->in_place).trimr('\0'); - s_bm_case->int_obj.data.resize(src); + s_bm_case->int_obj_noresize.data.resize(src); for(auto _ : st) { ONLY_FOR_JSON; s_bm_case->prepare(st, kResetInPlace); - parse_json_inplace(s_bm_case->filename, src, s_bm_case->int_obj.parser, &s_bm_case->int_obj.data); - bm::DoNotOptimize(s_bm_case->int_obj); + parse_json_ints_noresize_inplace(s_bm_case->filename, src, s_bm_case->int_obj_noresize.parser, &s_bm_case->int_obj_noresize.data); + bm::DoNotOptimize(s_bm_case->int_obj_noresize); + } + s_bm_case->report(st); +} +void bm_rymlints_json_resize_inplace_reuse(bm::State& st) +{ + c4::substr src = c4::to_substr(s_bm_case->in_place).trimr('\0'); + s_bm_case->int_obj_resize.reserve(src); + for(auto _ : st) + { + ONLY_FOR_JSON; + s_bm_case->prepare(st, kResetInPlace); + parse_json_ints_resize_inplace(s_bm_case->filename, src, s_bm_case->int_obj_resize.parser, &s_bm_case->int_obj_resize.data); + bm::DoNotOptimize(s_bm_case->int_obj_resize); } s_bm_case->report(st); } -void bm_rymlints_json_inplace_reuse_nofilter(bm::State& st) +void bm_rymlints_json_noresize_inplace_reuse_nofilter(bm::State& st) +{ + c4::substr src = c4::to_substr(s_bm_case->in_place).trimr('\0'); + s_bm_case->int_obj_noresize_nofilter.data.resize(src); + for(auto _ : st) + { + ONLY_FOR_JSON; + s_bm_case->prepare(st, kResetInPlace); + parse_json_ints_noresize_inplace(s_bm_case->filename, src, s_bm_case->int_obj_noresize_nofilter.parser, &s_bm_case->int_obj_noresize_nofilter.data); + bm::DoNotOptimize(s_bm_case->int_obj_noresize_nofilter); + } + s_bm_case->report(st); +} +void bm_rymlints_json_resize_inplace_reuse_nofilter(bm::State& st) { c4::substr src = c4::to_substr(s_bm_case->in_place).trimr('\0'); - s_bm_case->int_obj_nofilter.data.resize(src); + s_bm_case->int_obj_resize_nofilter.reserve(src); for(auto _ : st) { ONLY_FOR_JSON; s_bm_case->prepare(st, kResetInPlace); - parse_json_inplace(s_bm_case->filename, src, s_bm_case->int_obj_nofilter.parser, &s_bm_case->int_obj_nofilter.data); - bm::DoNotOptimize(s_bm_case->int_obj_nofilter); + parse_json_ints_resize_inplace(s_bm_case->filename, src, s_bm_case->int_obj_resize_nofilter.parser, &s_bm_case->int_obj_resize_nofilter.data); + bm::DoNotOptimize(s_bm_case->int_obj_resize_nofilter); } s_bm_case->report(st); } @@ -841,22 +1013,40 @@ void bm_ryml_json_inplace_reuse_nofilter_reserve(bm::State& st) BENCHMARK(bm_rymlints_estimate); -BENCHMARK(bm_rymlints_json_inplace_reuse_nofilter); -BENCHMARK(bm_rymlints_json_inplace_reuse); +BENCHMARK(bm_rymlints_json_noresize_inplace_reuse_nofilter); +BENCHMARK(bm_rymlints_json_noresize_inplace_reuse); + +BENCHMARK(bm_rymlints_json_noresize_inplace_nofilter_reserve); +BENCHMARK(bm_rymlints_json_noresize_inplace_nofilter); +BENCHMARK(bm_rymlints_json_noresize_inplace_reserve); +BENCHMARK(bm_rymlints_json_noresize_inplace); + + +BENCHMARK(bm_rymlints_json_resize_inplace_reuse_nofilter); +BENCHMARK(bm_rymlints_json_resize_inplace_reuse); + +BENCHMARK(bm_rymlints_json_resize_inplace_nofilter_reserve); +BENCHMARK(bm_rymlints_json_resize_inplace_nofilter); +BENCHMARK(bm_rymlints_json_resize_inplace_reserve); +BENCHMARK(bm_rymlints_json_resize_inplace); + + +BENCHMARK(bm_rymlints_yaml_noresize_inplace_reuse_nofilter); +BENCHMARK(bm_rymlints_yaml_noresize_inplace_reuse); -BENCHMARK(bm_rymlints_json_inplace_nofilter_reserve); -BENCHMARK(bm_rymlints_json_inplace_nofilter); -BENCHMARK(bm_rymlints_json_inplace_reserve); -BENCHMARK(bm_rymlints_json_inplace); +BENCHMARK(bm_rymlints_yaml_noresize_inplace_nofilter_reserve); +BENCHMARK(bm_rymlints_yaml_noresize_inplace_nofilter); +BENCHMARK(bm_rymlints_yaml_noresize_inplace_reserve); +BENCHMARK(bm_rymlints_yaml_noresize_inplace); -BENCHMARK(bm_rymlints_yaml_inplace_reuse_nofilter); -BENCHMARK(bm_rymlints_yaml_inplace_reuse); +BENCHMARK(bm_rymlints_yaml_resize_inplace_reuse_nofilter); +BENCHMARK(bm_rymlints_yaml_resize_inplace_reuse); -BENCHMARK(bm_rymlints_yaml_inplace_nofilter_reserve); -BENCHMARK(bm_rymlints_yaml_inplace_nofilter); -BENCHMARK(bm_rymlints_yaml_inplace_reserve); -BENCHMARK(bm_rymlints_yaml_inplace); +BENCHMARK(bm_rymlints_yaml_resize_inplace_nofilter_reserve); +BENCHMARK(bm_rymlints_yaml_resize_inplace_nofilter); +BENCHMARK(bm_rymlints_yaml_resize_inplace_reserve); +BENCHMARK(bm_rymlints_yaml_resize_inplace); BENCHMARK(bm_ryml_json_inplace_reuse_nofilter_reserve); diff --git a/samples/ints_only/CMakeLists.txt b/samples/ints_only/CMakeLists.txt index f5efe8022..ebcec5de1 100644 --- a/samples/ints_only/CMakeLists.txt +++ b/samples/ints_only/CMakeLists.txt @@ -24,10 +24,17 @@ add_library(ryml-ints ${RAPIDYAML_DIR}/src/c4/yml/node_type.cpp ${RAPIDYAML_DIR}/src/c4/yml/parse_engine.hpp ${RAPIDYAML_DIR}/src/c4/yml/parse_engine.def.hpp + ${RAPIDYAML_DIR}/src/c4/yml/scalar_style.hpp + ${RAPIDYAML_DIR}/src/c4/yml/scalar_style.cpp ${RAPIDYAML_DIR}/src/c4/yml/tag.hpp ${RAPIDYAML_DIR}/src/c4/yml/tag.cpp + ${RAPIDYAML_DIR}/src_extra/c4/yml/extra/event_ints.hpp + ${RAPIDYAML_DIR}/src_extra/c4/yml/extra/event_ints.cpp ${RAPIDYAML_DIR}/src_extra/c4/yml/extra/event_handler_ints.hpp - ${RAPIDYAML_DIR}/src_extra/c4/yml/extra/event_handler_ints.cpp + ${RAPIDYAML_DIR}/src_extra/c4/yml/extra/event_handler_ints_no_resize.cpp + ${RAPIDYAML_DIR}/src_extra/c4/yml/extra/event_handler_ints_resize.cpp + ${RAPIDYAML_DIR}/src_extra/c4/yml/extra/emitter_ints.hpp + ${RAPIDYAML_DIR}/src_extra/c4/yml/extra/emitter_ints.def.hpp # # files required from c4core ${C4CORE_DIR}/c4/charconv.hpp diff --git a/samples/quickstart-ints.cpp b/samples/quickstart-ints.cpp index ed8f97833..2fa774c6c 100644 --- a/samples/quickstart-ints.cpp +++ b/samples/quickstart-ints.cpp @@ -16,80 +16,122 @@ #include // estimate size, print #include #include +#include +#include +#include +#include #endif #include -using namespace c4::yml::extra::ievt; +constexpr const bool dynamic_buffers = true; +constexpr const bool fixed_buffers = false; +namespace ievt = c4::yml::extra::ievt; +namespace ryml = c4::yml; +struct IntsParserDynamicBuffers; +struct IntsParserFixedBuffers; -// holds the buffers necessary for getting the int events -struct IntsResult + +//----------------------------------------------------------------------------- + +// a helper to parse the YAML +struct IntsParserDynamicBuffers { - std::vector yaml = {}; ///< source buffer - std::vector arena = {}; ///< arena to place out-of-source filtered scalars or tags - std::vector events = {}; ///< result buffer with events - void reset_yaml(c4::csubstr yaml_) - { - yaml.assign(yaml_.begin(), yaml_.end()); - } - void resize_buffers(c4::yml::extra::evt_size esz, size_t arena_size) - { - events.resize(static_cast(esz)); - arena.resize(arena_size); - } - void resize_buffers(c4::yml::extra::EventHandlerInts const& handler) + using handler_type = ievt::EventHandlerInts; + using parser_type = c4::yml::ParseEngine; + using Result = ievt::Buffers; + +public: + + handler_type handler; + parser_type parser; + +public: + + IntsParserDynamicBuffers() noexcept : handler(), parser(&handler) {} + + void parse_in_place(const char *filename, c4::substr yaml, Result *result, bool transfer_ownership=false) { - resize_buffers(handler.required_size_events(), handler.required_size_arena()); + handler.reset(yaml); + parser.parse_in_place_ev(filename, yaml); // we're parsing in place on the original YAML + handler.get_buffers(result, transfer_ownership); } }; +//----------------------------------------------------------------------------- + // a helper to parse the YAML -struct IntsParser +struct IntsParserFixedBuffers { - c4::yml::extra::EventHandlerInts handler; - c4::yml::ParseEngine parser; + using handler_type = ievt::EventHandlerInts; + using parser_type = c4::yml::ParseEngine; + // holds the buffers necessary for getting the int events + struct Result + { + std::vector yaml = {}; ///< source buffer + std::vector arena = {}; ///< arena to place out-of-source filtered scalars or tags + std::vector events = {}; ///< result buffer with events + void reset_yaml(c4::csubstr yaml_) + { + yaml.assign(yaml_.begin(), yaml_.end()); + } + void resize_buffers(ievt::evt_size esz, size_t arena_size) + { + events.resize(static_cast(esz)); + arena.resize(arena_size); + } + void resize_buffers(handler_type const& handler_) + { + resize_buffers(handler_.required_size_events(), handler_.required_size_arena()); + } + }; + +public: // members + + handler_type handler; + parser_type parser; + +public: // methods - IntsParser() noexcept: handler(), parser(&handler) {} + IntsParserFixedBuffers() noexcept : handler(), parser(&handler) {} - bool parse_in_place(const char *filename, c4::substr yaml, IntsResult *result) + bool parse_in_place(const char *filename, c4::csubstr yaml, Result *result) { - handler.reset(yaml, c4::to_substr(result->arena), - result->events.data(), static_cast(result->events.size())); - parser.parse_in_place_ev(filename, yaml); // we're parsing in place on the original YAML - // the YAML was successfully parsed, but it may happen that it - // requires more events than may fit in the buffers. so we - // need to check that it actually fits (this is mandatory): - if(handler.fits_buffers()) - result->resize_buffers(handler); // trim the events buffer to the required size - return handler.fits_buffers(); + result->reset_yaml(yaml); // copy to enable retries + handler.reset(c4::to_substr(result->yaml), + c4::to_substr(result->arena), + result->events.data(), + static_cast(result->events.size())); + parser.parse_in_place_ev(filename, c4::to_substr(result->yaml)); + // parse was successful, but it may happen that it requires + // more events than may fit in the buffers. so we need to + // check that it actually fits (this is mandatory): + bool success = handler.fits_buffers(); + result->resize_buffers(handler); // trim (or expand) the events buffer to the required size + return success; } - bool parse_or_resize_and_then_parse(const char *filename, c4::csubstr yaml, IntsResult *result) + bool parse_or_resize_and_then_parse(const char *filename, c4::csubstr yaml, Result *result) { - // the buffer is not mutable. we'll need to parse a copy - result->reset_yaml(yaml); // attempt the parse - if(this->parse_in_place(filename, c4::to_substr(result->yaml), result)) + if(this->parse_in_place(filename, yaml, result)) return true; - // events or arena buffers were too small. need to resize and parse again. - result->resize_buffers(handler); - // copy the source again! we need to do this because the - // buffer was parsed in place, and may have been modified - // during the parse. - result->reset_yaml(yaml); // parse again! - return this->parse_in_place(filename, c4::to_substr(result->yaml), result); + return this->parse_in_place(filename, yaml, result); } }; +//----------------------------------------------------------------------------- + struct Args { const char *filename = nullptr; int events_size = -1; int arena_size = -1; + bool fixed_size = false; bool retry = true; bool quiet = false; }; @@ -102,16 +144,21 @@ void print_usage(c4::csubstr basename) options: - -e ,--events-size set size of events buffer. -1 means + -f,--fixed-size use fixed size output buffers, and retry parsing + if their size was small. otherwise, use dynamic size + buffers, growing as required during the parse. + default=%s + -e ,--events-size [fixed size] set size of events buffer. -1 means estimate size. default=%d - -a ,--arena-size set size of arena buffer. -1 means + -a ,--arena-size [fixed size] set size of arena buffer. -1 means take the source size as the arena size. default=%d - -n,--no-retry do not retry parsing if any buffer size + -n,--no-retry [fixed size] do not retry parsing if any buffer size was insufficient. default=%s -q,--quiet do not print events. default=%s )", static_cast(basename.len), basename.str, + defaults.fixed_size ? "fixed size" : "dynamic size", defaults.events_size, defaults.arena_size, defaults.retry ? "retry" : "do not retry", @@ -159,6 +206,11 @@ bool parse_args(int argc, const char **argv, Args *args, int &status) { parse_arg("--arena-size", &args->arena_size); } + else if(arg == "-f" || arg == "--fixed-size") + { + args->fixed_size = true; + advance(1); + } else if(arg == "-n" || arg == "--no-retry") { args->retry = false; @@ -191,8 +243,177 @@ bool parse_args(int argc, const char **argv, Args *args, int &status) // NOLINTBEGIN(hicpp-signed-bitwise) +int compare_to_expected(c4::csubstr src, + c4::csubstr arena, + ievt::evt_bits const* actual, ievt::evt_size actual_sz, + ievt::evt_bits const* expected, ievt::evt_size expected_sz, + bool quiet) +{ + bool success = actual_sz == expected_sz; + // example iterating through the events array: compare and print + // the result + char flags[256]; // buffer for converting event flags to string + for (ievt::evt_size pos = 0, evt = 0, sz = actual_sz < expected_sz ? actual_sz : expected_sz; + pos < sz; + ++pos, ++evt) + { + bool ok = (actual[pos] == expected[pos]); + // print the event + if( ! quiet) + { + // let's format the event flags to print them as string. + size_t len = ievt::to_str(flags, actual[pos]); + printf("pos=%d\tevent[%d]:\t%.*s = 0x%08x", pos, evt, static_cast(len), flags, actual[pos]); + } + if(actual[pos] & ievt::WSTR) // the event has a string following it + { + int offset = actual[pos + 1]; + int length = actual[pos + 2]; + bool in_arena = (actual[pos] & ievt::AREN); + // WATCHOUT! the string is NOT ZERO TERMINATED! + const char *region = in_arena ? arena.str : src.str; + const char *str = region + offset; + if( ! quiet) + printf("\tstr=(%d,%d)\t'%.*s'", offset, length, length, str); + ok = ok && (offset == expected[pos + 1]); + ok = ok && (length == expected[pos + 2]); + } + if(!ok) + { + if( ! quiet) // LCOV_EXCL_LINE + printf(" ... fail!"); // LCOV_EXCL_LINE + success = false; // LCOV_EXCL_LINE + } + if( ! quiet) // LCOV_EXCL_LINE + printf("\n"); + } + + return success ? 0 : 1; +} + + +//----------------------------------------------------------------------------- + + +size_t emit_yaml(c4::substr yaml, + c4::csubstr src, + c4::csubstr arena, + ievt::evtbuf evts, + c4::yml::EmitOptions const& opts={}) +{ + ievt::EmitterInts emitter(opts, yaml); + emitter.emit_as(c4::yml::EMIT_YAML, evts.ptr, evts.len, src, arena); + return emitter.get_result(/*error_on_excess*/false).len; +} + +template +void emit_yaml(CharContainer *cont, + c4::csubstr src, + c4::csubstr arena, + ievt::evtbuf evts, + c4::yml::EmitOptions const& opts={}) +{ + const size_t cap = cont->capacity(); + cont->resize(cap); + const size_t len = emit_yaml(c4::to_substr(*cont), src, arena, evts, opts); + cont->resize(len); + if(len > cap) + emit_yaml(c4::to_substr(*cont), src, arena, evts, opts); +} + +template +CharContainer emit_yaml(c4::csubstr src, + c4::csubstr arena, + ievt::evtbuf evts, + c4::yml::EmitOptions const& opts={}) +{ + CharContainer c; + emit_yaml(&c, src, arena, evts, opts); + return c; +} // LCOV_EXCL_LINE + + + +//----------------------------------------------------------------------------- +// methods to provide default callbacks (needed when +// RYML_NO_DEFAULT_CALLBACKS is defined) + +#ifndef RYML_NO_DEFAULT_CALLBACKS +void ensure_callbacks() {} +#else +// optional header, definitions for error utilities to implement +// user-defined error callbacks: +#include +namespace { +// LCOV_EXCL_START +/** dump (part of an) error message to terminal + * @ingroup doc_quickstart_helpers */ +void errdump(c4::csubstr s) +{ + if(s.len) + fwrite(s.str, 1, s.len, stderr); // NOLINT +} +/** finish printing an error message, and flush + * @ingroup doc_quickstart_helpers */ +void errend() +{ + fputc('\n', stderr); // NOLINT + fflush(NULL); // NOLINT +} +// LCOV_EXCL_STOP +} // namespace + +/** set up a bare-bones implementation of the callbacks + * @ingroup doc_quickstart_helpers */ +c4::yml::Callbacks default_callbacks() +{ + return c4::yml::Callbacks{} + .set_allocate([](size_t len, void* , void *){ + return malloc(len); // NOLINT + }) + .set_free([](void* mem, size_t, void *){ + free(mem); // NOLINT + }) + /// + /// The default error callbacks won't be called in this + /// quickstart, because no errors are expected. But we + /// implement them here to show how a bare-bones implementation + /// looks like, and also because they are needed when + /// @ref RYML_NO_DEFAULT_CALLBACKS is defined. + /// + // LCOV_EXCL_START + .set_error_basic([](c4::csubstr msg, c4::yml::ErrorDataBasic const& errdata, void *){ + c4::yml::err_basic_format(errdump, msg, errdata); // format the message, printing to stderr + errend(); // print newline and flush + abort(); // abort (must never return: abort, or exception or setjmp) + }) + .set_error_parse([](c4::csubstr msg, c4::yml::ErrorDataParse const& errdata, void *){ + c4::yml::err_parse_format(errdump, msg, errdata); // format the message, printing to out + errend(); // print newline and flush + abort(); // abort (must never return: abort, or exception or setjmp) + }) + .set_error_visit([](c4::csubstr msg, c4::yml::ErrorDataVisit const& errdata, void *){ + c4::yml::err_visit_format(errdump, msg, errdata); // format the message, printing to out + errend(); // print newline and flush + abort(); // abort (must never return: abort, or exception or setjmp) + }); + // LCOV_EXCL_STOP +} + +/** set up default callbacks when ryml does not provide them + * (ie when @ref RYML_NO_DEFAULT_CALLBACKS is defined) */ +void ensure_callbacks() +{ + c4::yml::set_callbacks(default_callbacks()); +} +#endif + + +//----------------------------------------------------------------------------- + int main(int argc, const char *argv[]) { + ensure_callbacks(); Args args = {}; int status = 0; if(!parse_args(argc, argv, &args, status)) @@ -212,6 +433,7 @@ int main(int argc, const char *argv[]) // these are the events we expect from parsing the demo YAML auto STR = c4::yml::extra::ievt::PSTR; // PSTR does not work in windows + using namespace ievt; const int demo_expected[] = { BSTR, BDOC, @@ -247,9 +469,6 @@ int main(int argc, const char *argv[]) * pos=29 event[13]: ESTR = 0x00000002 */ - IntsParser parser; - IntsResult result; - const char *filename = args.filename; std::vector yaml_file; c4::substr yaml; @@ -269,82 +488,95 @@ int main(int argc, const char *argv[]) yaml = c4::to_substr(yaml_file); } - if(args.events_size == -1) - args.events_size = c4::yml::extra::estimate_events_ints_size(yaml); - if(args.arena_size == -1) - args.arena_size = static_cast(yaml.size()); - - result.resize_buffers(args.events_size, static_cast(args.arena_size)); - - // parse now. since we did not set up the error callbacks, if - // there is a parse error, we will get the default behavior, which - // is abort on error - if( ! args.retry) - { - if( ! parser.parse_in_place(filename, yaml, &result)) - return 1; - } - else - { - if( ! parser.parse_or_resize_and_then_parse(filename, yaml, &result)) - return 1; // this is really not expected LCOV_EXCL_LINE - } - - if( ! is_demo) + int stat = 0; + if(!args.fixed_size) { + IntsParserDynamicBuffers parser; + IntsParserDynamicBuffers::Result result; + parser.parse_in_place(filename, yaml, &result); + if( ! is_demo) + { + if( ! args.quiet) + { + ievt::events_ints_print(result.src, + result.arena, + result.evts.ptr, result.evts.len); + } + } + else + { + // it's the demo data: + stat = compare_to_expected(c4::to_csubstr(result.src), + c4::to_csubstr(result.arena), + result.evts.ptr, result.evts.len, + demo_expected, static_cast(C4_COUNTOF(demo_expected)), + args.quiet); + } if( ! args.quiet) { - c4::csubstr actual_buffer = args.retry ? yaml : c4::to_csubstr(result.yaml); - c4::yml::extra::events_ints_print(actual_buffer, c4::to_csubstr(result.arena), - result.events.data(), - static_cast(result.events.size())); + std::string emitted = emit_yaml(result.src, result.arena, result.evts); + printf("%s", emitted.c_str()); } - return 0; } + else + { + if(args.events_size == -1) + args.events_size = ievt::estimate_events_size(yaml); + if(args.arena_size == -1) + args.arena_size = static_cast(yaml.size()); - // we have the demo. ensure the result is as expected - bool success = true; + IntsParserFixedBuffers parser; + IntsParserFixedBuffers::Result result; - // example iterating through the events array: compare and print - // the result - char flags[100]; // buffer for converting event flags to string - for (size_t pos = 0, evt = 0, sz = static_cast(parser.handler.required_size_events()); - pos < sz; - ++pos, ++evt) - { - bool ok = (result.events[pos] == demo_expected[pos]); - // print the event - if( ! args.quiet) + result.resize_buffers(args.events_size, static_cast(args.arena_size)); + + // parse now. since we did not set up the error callbacks, if + // there is a parse error, we will get the default behavior, which + // is abort on error + if( ! args.retry) { - // let's format the event flags to print them as string. - size_t len = c4::yml::extra::ievt::to_str(flags, result.events[pos]); - printf("pos=%zu\tevent[%zu]:\t%.*s = 0x%08x", pos, evt, static_cast(len), flags, result.events[pos]); + if( ! parser.parse_in_place(filename, yaml, &result)) + return 1; } - if(result.events[pos] & WSTR) // the event has a string following it + else + { + if( ! parser.parse_or_resize_and_then_parse(filename, yaml, &result)) + return 1; // this is really not expected LCOV_EXCL_LINE + } + + if( ! is_demo) { - int offset = result.events[pos + 1]; - int length = result.events[pos + 2]; - bool in_arena = (result.events[pos] & AREN); - // WATCHOUT! the string is NOT ZERO TERMINATED! - const char *ptr = in_arena ? result.arena.data() : yaml.str; - const char *str = ptr + offset; if( ! args.quiet) - printf("\tstr=(%d,%d)\t'%.*s'", offset, length, length, str); - ok = ok && (offset == demo_expected[pos + 1]); - ok = ok && (length == demo_expected[pos + 2]); - pos += 2; // advance the two ints from the string + { + c4::csubstr actual_buffer = args.retry ? yaml : c4::to_csubstr(result.yaml); + ievt::events_ints_print(actual_buffer, c4::to_csubstr(result.arena), + result.events.data(), + static_cast(result.events.size())); + } } - if(!ok) + else { - if( ! args.quiet) // LCOV_EXCL_LINE - printf(" ... fail!"); // LCOV_EXCL_LINE - success = false; // LCOV_EXCL_LINE + // it's the demo data: + stat = compare_to_expected(c4::to_csubstr(result.yaml), + c4::to_csubstr(result.arena), + result.events.data(), static_cast(result.events.size()), + demo_expected, static_cast(C4_COUNTOF(demo_expected)), + args.quiet); } - if( ! args.quiet) // LCOV_EXCL_LINE - printf("\n"); - } - return success ? 0 : 1; + if( ! args.quiet) + { + ievt::evtbuf evts; + evts.ptr = result.events.data(); + evts.len = static_cast(result.events.size()); + evts.cap = static_cast(result.events.capacity()); + std::string emitted = emit_yaml(c4::to_csubstr(result.yaml), + c4::to_csubstr(result.arena), + evts); + printf("%s", emitted.c_str()); + } + } + return stat; } // NOLINTEND(hicpp-signed-bitwise) diff --git a/samples/quickstart.cpp b/samples/quickstart.cpp index 1be04a78d..d7bc5e350 100644 --- a/samples/quickstart.cpp +++ b/samples/quickstart.cpp @@ -902,7 +902,7 @@ void sample_quick_overview() CHECK(!root.has_child("I am not nothing")); ryml::NodeRef nothing; CHECK(nothing.invalid()); // invalid because it points at nothing - nothing = wroot["I am nothing"]; + nothing = wroot["I am nothing"]; // LCOV_EXCL_LINE workaround for lcov fail CHECK(!nothing.invalid()); // points at the tree, and a specific place in the tree CHECK(nothing.is_seed()); // ... but nothing is there yet. CHECK(!root.has_child("I am nothing")); // same as above @@ -947,7 +947,7 @@ void sample_quick_overview() // met. If you are not sure about the structure of your data, // write your code defensively to signify your full intent: // - ryml::NodeRef wbar = wroot["bar"]; + ryml::NodeRef wbar = wroot["bar"]; // LCOV_EXCL_LINE workaround for lcov fail if(wbar.readable() && wbar.is_seq()) // .is_seq() requires .readable() { CHECK(wbar[0].readable() && wbar[0].val() == "20"); @@ -2659,7 +2659,7 @@ void sample_create_tree() ryml::Tree tree; ryml::NodeRef root = tree.rootref(); root.set_map(); // mark root as a map - doe = root["doe"]; + doe = root["doe"]; // LCOV_EXCL_LINE workaround for lcov fail CHECK(!doe.invalid()); // it's now pointing at the tree CHECK(doe.is_seed()); // but the tree has nothing there, so this is only a seed @@ -2688,13 +2688,13 @@ void sample_create_tree() root["pi"].set_serialized(ryml::fmt::real(3.141592654, 5)); root["xmas"].set_serialized(ryml::fmt::boolalpha(true)); root["french-hens"].set_serialized(3); - ryml::NodeRef calling_birds = root["calling-birds"]; + ryml::NodeRef calling_birds = root["calling-birds"]; // LCOV_EXCL_LINE workaround for lcov fail calling_birds.set_seq(); calling_birds.append_child().set_val("huey"); calling_birds.append_child().set_val("dewey"); calling_birds.append_child().set_val("louie"); calling_birds.append_child().set_val("fred"); - ryml::NodeRef xmas5 = root["xmas-fifth-day"]; + ryml::NodeRef xmas5 = root["xmas-fifth-day"]; // LCOV_EXCL_LINE workaround for lcov fail xmas5.set_map(); xmas5["calling-birds"].set_val("four"); xmas5["french-hens"].set_serialized(3); @@ -6390,7 +6390,7 @@ void sample_docs() // in which case, you can avoid the error by emitting the // documents one-by-one: const std::string expected_json[] = { - "{" "\n" + "{" "\n" // LCOV_EXCL_LINE workaround for lcov fail " \"a\": 0," "\n" " \"b\": 1" "\n" "}" "\n" @@ -6766,7 +6766,7 @@ void sample_error_visit_location() auto cause_visit_error = [&]{ int intval = 0; tree["float"].load(&intval); // cannot deserialize 123.456 to int - }; + }; // LCOV_EXCL_LINE workaround for lcov fail // Like with the parse error, we will use our error handler to // catch that visit error, and save the error info: CHECK(evt_handler.callbacks() == errh.callbacks()); diff --git a/src/c4/yml/common.cpp b/src/c4/yml/common.cpp index 0e2fc52de..38817837b 100644 --- a/src/c4/yml/common.cpp +++ b/src/c4/yml/common.cpp @@ -280,6 +280,38 @@ ExceptionVisit::ExceptionVisit(csubstr msg_, ErrorDataVisit const& errdata_) noe namespace detail { + +// resize a buffer with length only +RYML_EXPORT C4_NODISCARD void* grow_buf_raw(void* buf, size_t len, size_t next_len, Callbacks const& cb) +{ + RYML_ASSERT_BASIC_CB_(cb, next_len > len); + void *ptr = cb.m_allocate(next_len, buf, cb.m_user_data); + if C4_UNLIKELY(!ptr) + RYML_ERR_BASIC_CB_(cb, "out of memory"); // LCOV_EXCL_LINE + if(len) + { + memcpy(ptr, buf, len); + cb.m_free(buf, len, cb.m_user_data); + } + return ptr; +} + +// resize a buffer with length+capacity +RYML_EXPORT C4_NODISCARD void* grow_buf_raw(void* buf, size_t len, size_t cap, size_t next_cap, Callbacks const& cb) +{ + RYML_ASSERT_BASIC_CB_(cb, next_cap > cap);(void)cap; + RYML_ASSERT_BASIC_CB_(cb, len <= cap); + void *ptr = cb.m_allocate(next_cap, buf, cb.m_user_data); + if C4_UNLIKELY(!ptr) + RYML_ERR_BASIC_CB_(cb, "out of memory"); // LCOV_EXCL_LINE + if(len) + { + memcpy(ptr, buf, len); + cb.m_free(buf, len, cb.m_user_data); + } + return ptr; +} + RYML_EXPORT csubstr _get_text_region(csubstr text, size_t pos, size_t num_lines_before, size_t num_lines_after) { if(pos > text.len) diff --git a/src/c4/yml/common.hpp b/src/c4/yml/common.hpp index efcbf6478..1f8b6fa96 100644 --- a/src/c4/yml/common.hpp +++ b/src/c4/yml/common.hpp @@ -484,6 +484,28 @@ C4_SUPPRESS_WARNING_POP (buf) = nullptr; \ } while(false) + +namespace detail { +// resize a buffer with length only +RYML_EXPORT C4_NODISCARD void* grow_buf_raw(void* buf, size_t len, size_t next_len, Callbacks const& cb); +template +C4_NODISCARD T* grow_buf(T* buf, size_t len, size_t next_len, Callbacks const& cb) +{ + size_t s = sizeof(T); + return reinterpret_cast(grow_buf_raw(buf, s * len, s * next_len, cb)); // NOLINT +} + +// resize a buffer with length+capacity +RYML_EXPORT C4_NODISCARD void* grow_buf_raw(void* buf, size_t len, size_t cap, size_t next_cap, Callbacks const& cb); +template +C4_NODISCARD T* grow_buf(T* buf, size_t len, size_t cap, size_t next_cap, Callbacks const& cb) +{ + size_t s = sizeof(T); + return reinterpret_cast(grow_buf_raw(buf, s * len, s * cap, s * next_cap, cb)); // NOLINT +} +} // detail + + namespace detail { template struct _charconstant_t // is there a better way to do this? @@ -516,6 +538,7 @@ inline csubstr _c4prc(const char &C4_RESTRICT c) // pass by reference! #define RYML_HAS_DEPRECATED_ENUMS_ #endif + /// @endcond C4_SUPPRESS_WARNING_GCC_POP diff --git a/src/c4/yml/detail/dbgprint.hpp b/src/c4/yml/detail/dbgprint.hpp index 14478cff6..b709a92f5 100644 --- a/src/c4/yml/detail/dbgprint.hpp +++ b/src/c4/yml/detail/dbgprint.hpp @@ -91,7 +91,7 @@ C4_NO_INLINE void dbg_dump_(DumpFn &&dumpfn, csubstr fmt, Args&& ...args) // // results.bufsize is set to the size of the largest element // serialized. Eg int(1) will require 1 byte. - if(C4_UNLIKELY(results.bufsize > RYML_LOGBUF_SIZE)) + if C4_UNLIKELY (results.bufsize > RYML_LOGBUF_SIZE) { const size_t bufsize = results.bufsize <= RYML_LOGBUF_SIZE_MAX ? results.bufsize : RYML_LOGBUF_SIZE_MAX; #ifdef C4_MSVC @@ -169,7 +169,7 @@ struct prs_ inline C4_NO_INLINE size_t to_chars(substr buf, prs_ const& v) { csubstr s = v.subject; - if(C4_LIKELY(s.str != nullptr)) + if C4_LIKELY(s.str != nullptr) { csubstr ellipsis = ""; if(v.maxsize < s.len) @@ -192,7 +192,7 @@ C4_NO_INLINE size_t dump(SinkPfn &&sinkfn, substr buf, prs_ const& v) size_t sz = to_chars(buf, s.len); if(sz <= buf.len) { - if(C4_LIKELY(s.str != nullptr)) + if C4_LIKELY(s.str != nullptr) { csubstr ellipsis = ""; if(v.maxsize < s.len) diff --git a/src/c4/yml/detail/emit_scalar.hpp b/src/c4/yml/detail/emit_scalar.hpp new file mode 100644 index 000000000..0b1b5e828 --- /dev/null +++ b/src/c4/yml/detail/emit_scalar.hpp @@ -0,0 +1,483 @@ +#ifndef C4_YML_DETAIL_EMIT_SCALAR_HPP_ +#define C4_YML_DETAIL_EMIT_SCALAR_HPP_ + +#ifndef C4_YML_ERROR_HPP_ +#include "c4/yml/error.hpp" +#endif +#ifndef C4_YML_SCALAR_CHARCONV_HPP_ +#include "c4/yml/scalar_charconv.hpp" +#endif + +namespace c4 { +namespace yml { +namespace detail { + + +template +C4_NODISCARD size_t emit_escaped_newlines_(Emitter *em, csubstr s, size_t i) +{ + RYML_ASSERT_BASIC_(s.len > i); + RYML_ASSERT_BASIC_(s.str[i] == '\n'); + //_c4dbgpf("nl@i={} rem=[{}]~~~{}~~~", i, s.sub(i).len, s.sub(i)); + // add an extra newline for each sequence of consecutive + // newline/whitespace + em->newl_(); + do + { + em->newl_(); // write the newline again + ++i; // increase the outer loop counter! + } while(i < s.len && s.str[i] == '\n'); + RYML_ASSERT_BASIC_(i > 0); + --i; + RYML_ASSERT_BASIC_(s.str[i] == '\n'); + return i; +} + + +template +void emit_scalar_plain_(Emitter *em, csubstr s, typename Emitter::indent_type ilevel) +{ + if C4_UNLIKELY(ilevel == 0 && (s.begins_with("...") || s.begins_with("---"))) + { + em->indent_(ilevel + 1); // indent the next line + ++ilevel; + } + size_t pos = 0; // tracks the last character that was already written + for(size_t i = 0; i < s.len; ++i) + { + const char curr = s.str[i]; + if(curr == '\n') + { + csubstr sub = s.range(pos, i); + em->write_(sub); // write everything up to (including) this newline + i = detail::emit_escaped_newlines_(em, s, i); + pos = i+1; + if(pos < s.len) + em->indent_(ilevel + 1); // indent the next line + } + } + // write remaining characters at the end of the string + if(pos < s.len) + em->write_(s.sub(pos)); +} + + +template +void emit_scalar_dquo_(Emitter *em, csubstr s) +{ + size_t pos = 0; // tracks the last character that was already written + em->write_('"'); + for(size_t i = 0; i < s.len; ++i) + { + const char curr = s.str[i]; + switch(curr) // NOLINT + { + case '"': + case '\\': + { + csubstr sub = s.range(pos, i); + em->write_(sub); // write everything up to (excluding) this char + em->write_('\\'); // write the escape + em->write_(curr); // write the char + pos = i+1; + break; + } + case '\n': + { + csubstr sub = s.range(pos, i); + em->write_(sub); // write everything up to (excluding) this char + em->write_("\\n"); // write the escape + pos = i+1; + break; + } + case '\r': + { + csubstr sub = s.range(pos, i); + em->write_(sub); // write everything up to (excluding) this char + em->write_("\\r"); // write the escaped char + pos = i+1; + break; + } + case '\b': + { + csubstr sub = s.range(pos, i); + em->write_(sub); // write everything up to (excluding) this char + em->write_("\\b"); // write the escaped char + pos = i+1; + break; + } + } + } + // write remaining characters at the end of the string + if(pos < s.len) + em->write_(s.sub(pos)); + em->write_('"'); +} + + +template +void emit_scalar_squo_(Emitter *em, csubstr s, typename Emitter::indent_type ilevel) +{ + size_t pos = 0; // tracks the last character that was already written + em->write_('\''); + for(size_t i = 0; i < s.len; ++i) + { + if(s[i] == '\n') + { + em->write_(s.range(pos, i)); // write everything up to (excluding) this char + //_c4dbgpf("newline at {}. writing ~~~{}~~~", i, s.range(pos, i)); + i = detail::emit_escaped_newlines_(em, s, i); + //_c4dbgpf("newline --> {}", i); + if(i < s.len) + em->indent_(ilevel + 1); + pos = i+1; + } + else if(s[i] == '\'') + { + csubstr sub = s.range(pos, i+1); + //_c4dbgpf("squote at {}. writing ~~~{}~~~", i, sub); + em->write_(sub); // write everything up to (including) this squote + em->write_('\''); // write the squote again + pos = i+1; + } + } + // write remaining characters at the end of the string + if(pos < s.len) + em->write_(s.sub(pos)); + em->write_('\''); +} + + + +inline C4_NODISCARD bool _is_indented_block(csubstr s, size_t prev, size_t i) noexcept +{ + if(prev == 0 && s.begins_with_any(" \t")) + return true; + const size_t pos = s.first_not_of('\n', i); + return (pos != npos) && (s.str[pos] == ' ' || s.str[pos] == '\t'); +} + + +template +C4_NODISCARD size_t emit_indented_block_(Emitter *em, csubstr s, size_t i, typename Emitter::indent_type ilevel) +{ + //_c4dbgpf("indblock@i={} rem=[{}]~~~\n{}~~~", i, s.sub(i).len, s.sub(i)); + RYML_ASSERT_BASIC_(i > 0); + RYML_ASSERT_BASIC_(s.str[i-1] == '\n'); + RYML_ASSERT_BASIC_(i < s.len); + RYML_ASSERT_BASIC_(s.str[i] == ' ' || s.str[i] == '\t' || s.str[i] == '\n'); +again: + size_t pos = s.find("\n ", i); + if(pos == npos) + pos = s.find("\n\t", i); + if(pos != npos) + { + ++pos; + //_c4dbgpf("indblock line@i={} rem=[{}]~~~\n{}~~~", i, s.range(i, pos).len, s.range(i, pos)); + em->indent_(ilevel + 1); + em->write_(s.range(i, pos)); + i = pos; + goto again; // NOLINT + } + // consume the newlines after the indented block + // to prevent them from being escaped + pos = s.find('\n', i); + if(pos != npos) + { + const size_t pos2 = s.first_not_of('\n', pos); + pos = (pos2 != npos) ? pos2 : pos; + //_c4dbgpf("indblock line@i={} rem=[{}]~~~\n{}~~~", i, s.range(i, pos).len, s.range(i, pos)); + em->indent_(ilevel + 1); + em->write_(s.range(i, pos)); + i = pos; + } + return i; +} + + +template +void emit_scalar_literal_(Emitter *em, csubstr s, typename Emitter::indent_type ilevel) +{ + RYML_ASSERT_BASIC_(s.find("\r") == csubstr::npos); + csubstr trimmed = s.trimr('\n'); + const size_t numnewlines_at_end = s.len - trimmed.len; + const bool is_newline_only = (trimmed.len == 0 && (s.len > 0)); + const bool explicit_indentation = s.triml("\n\r").begins_with_any(" \t"); + // + em->write_('|'); + if(explicit_indentation) + em->write_('2'); + // + if(numnewlines_at_end > 1 || is_newline_only) + em->write_('+'); + else if(numnewlines_at_end == 0) + em->write_('-'); + // + if(trimmed.len) + { + em->newl_(); + size_t pos = 0; // tracks the last character that was already written + for(size_t i = 0; i < trimmed.len; ++i) + { + if(trimmed[i] != '\n') + continue; + // write everything up to this point + csubstr since_pos = trimmed.range(pos, i+1); // include the newline + em->indent_(ilevel + 1); + em->write_(since_pos); + pos = i+1; // already written + } + if(pos < trimmed.len) + { + em->indent_(ilevel + 1); + em->write_(trimmed.sub(pos)); + } + } + for(size_t i = !is_newline_only; i < numnewlines_at_end; ++i) + em->newl_(); +} + + +template +void emit_scalar_folded_(Emitter *em, csubstr s, typename Emitter::indent_type ilevel) +{ + RYML_ASSERT_BASIC_(s.find("\r") == csubstr::npos); + csubstr trimmed = s.trimr('\n'); + const size_t numnewlines_at_end = s.len - trimmed.len; + const bool is_newline_only = (trimmed.len == 0 && (s.len > 0)); + const bool explicit_indentation = s.triml("\n\r").begins_with_any(" \t"); + // + em->write_('>'); + if(explicit_indentation) + em->write_('2'); + // + if(numnewlines_at_end == 0) + em->write_('-'); + else if(numnewlines_at_end > 1 || is_newline_only) + em->write_('+'); + // + if(trimmed.len) + { + em->newl_(); + size_t pos = 0; // tracks the last character that was already written + for(size_t i = 0; i < trimmed.len; ++i) + { + if(trimmed[i] != '\n') + continue; + // escape newline sequences + if( ! detail::_is_indented_block(s, pos, i)) + { + if(pos < i) + { + em->indent_(ilevel + 1); + em->write_(s.range(pos, i)); + i = detail::emit_escaped_newlines_(em, s, i); + pos = i + 1; + } + else + { + if(i+1 < s.len) + { + if(s.str[i+1] == '\n') + { + ++i; + i = detail::emit_escaped_newlines_(em, s, i); + pos = i+1; + } + else + { + em->newl_(); + pos = i+1; + } + } + } + } + else // do not escape newlines in indented blocks + { + ++i; + em->indent_(ilevel + 1); + em->write_(s.range(pos, i)); + if(pos > 0 || !s.begins_with_any(" \t")) + i = detail::emit_indented_block_(em, s, i, ilevel); + pos = i; + } + } + if(pos < trimmed.len) + { + em->indent_(ilevel + 1); + em->write_(trimmed.sub(pos)); + } + } + for(size_t i = !is_newline_only; i < numnewlines_at_end; ++i) + em->newl_(); +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +template +C4_NODISCARD bool emit_json_maybe_write_naninf_(Emitter *em, csubstr s) +{ + switch(s.len) + { + case 3: case 4: case 5: // inf, nan, .nan, -.inf + case 8: case 9: // infinity, -infinity + break; + default: + return false; + } + const char first = s.str[0]; + csubstr rest = s.sub(1); + if(s.len == 4 && first == '.') + { + if(scalar_is_inf3(rest.str)) + goto write_inf_positive; // NOLINT + else if(scalar_is_nan3(rest.str)) + goto write_nan; // NOLINT + } + else if(first == '-' || first == '+') // begins with sign: must be inf + { + // match [-+].inf + if((rest.len == 4 && rest.str[0] == '.' && scalar_is_inf3(rest.str + 1)) + // match [-+]inf + || (rest.len == 3 && scalar_is_inf3(rest.str)) + // match [-+]infinity + || (rest.len == 8 && (0 == memcmp(rest.str, "infinity", 8)))) + { + if(first == '-') + goto write_inf_negative; // NOLINT + else + goto write_inf_positive; // NOLINT + } + } + else if(s.len == 8 && (0 == memcmp(s.str, "infinity", 8))) + { + goto write_inf_positive; // NOLINT + } + else if(s.len == 3) + { + if(scalar_is_inf3(s.str)) + goto write_inf_positive; // NOLINT + else if(scalar_is_nan3(s.str)) + goto write_nan; // NOLINT + } + return false; +write_inf_positive: + em->write_("\".inf\""); + return true; +write_inf_negative: + em->write_("\"-.inf\""); + return true; +write_nan: + em->write_("\".nan\""); + return true; +} + + +template +void emit_json_write_scalar_dquo_(Emitter *em, csubstr s) +{ + size_t pos = 0; + em->write_('"'); + for(size_t i = 0; i < s.len; ++i) + { + switch(s.str[i]) + { + case '"': + em->write_(s.range(pos, i)); + em->write_("\\\""); + pos = i + 1; + break; + case '\n': + em->write_(s.range(pos, i)); + em->write_("\\n"); + pos = i + 1; + break; + case '\t': + em->write_(s.range(pos, i)); + em->write_("\\t"); + pos = i + 1; + break; + case '\\': + em->write_(s.range(pos, i)); + em->write_("\\\\"); + pos = i + 1; + break; + case '\r': + em->write_(s.range(pos, i)); + em->write_("\\r"); + pos = i + 1; + break; + case '\b': + em->write_(s.range(pos, i)); + em->write_("\\b"); + pos = i + 1; + break; + case '\f': + em->write_(s.range(pos, i)); + em->write_("\\f"); + pos = i + 1; + break; + } + } + if(pos < s.len) + { + csubstr sub = s.sub(pos); + em->write_(sub); + } + em->write_('"'); +} + + +template +void emit_json_write_number_(Emitter *em, csubstr s) +{ + if(s.is_integer()) + { + em->write_(s); + } + else + { + if(s.begins_with('-') && s.len > 1) + { + csubstr rest = s.sub(1); + if(rest.begins_with('.')) + { + em->write_("-0"); + em->write_(rest); + } + else if(rest.ends_with('.')) + { + em->write_(s); + em->write_('0'); + } + else + { + em->write_(s); + } + } + else if(s.begins_with('.')) + { + em->write_('0'); + em->write_(s); + } + else if(s.ends_with('.')) + { + em->write_(s); + em->write_('0'); + } + else + { + em->write_(s); + } + } +} + + +} // namespace detail +} // namespace yml +} // namespace c4 + +#endif /* C4_YML_DETAIL_EMIT_SCALAR_HPP_ */ diff --git a/src/c4/yml/emit_container.hpp b/src/c4/yml/emit_container.hpp index 284a2b377..7d8b04ad0 100644 --- a/src/c4/yml/emit_container.hpp +++ b/src/c4/yml/emit_container.hpp @@ -175,7 +175,7 @@ CharOwningContainer emitrs_json(Tree const& t, EmitOptions const& opts={}) template substr emitrs_yaml(ConstNodeRef const& n, EmitOptions const& opts, CharOwningContainer * cont, bool append=false) { - if(!n.readable()) + if(!n.tree()) return {}; return emitrs_yaml(*n.tree(), n.id(), opts, cont, append); } @@ -183,7 +183,7 @@ substr emitrs_yaml(ConstNodeRef const& n, EmitOptions const& opts, CharOwningCon template substr emitrs_yaml(ConstNodeRef const& n, CharOwningContainer * cont, bool append=false) { - if(!n.readable()) + if(!n.tree()) return {}; return emitrs_yaml(*n.tree(), n.id(), EmitOptions{}, cont, append); } @@ -195,7 +195,7 @@ substr emitrs_yaml(ConstNodeRef const& n, CharOwningContainer * cont, bool appen template substr emitrs_json(ConstNodeRef const& n, EmitOptions const& opts, CharOwningContainer * cont, bool append=false) { - if(!n.readable()) + if(!n.tree()) return {}; return emitrs_json(*n.tree(), n.id(), opts, cont, append); } @@ -203,7 +203,7 @@ substr emitrs_json(ConstNodeRef const& n, EmitOptions const& opts, CharOwningCon template substr emitrs_json(ConstNodeRef const& n, CharOwningContainer * cont, bool append=false) { - if(!n.readable()) + if(!n.tree()) return {}; return emitrs_json(*n.tree(), n.id(), EmitOptions{}, cont, append); } @@ -214,7 +214,7 @@ template CharOwningContainer emitrs_yaml(ConstNodeRef const& n, EmitOptions const& opts={}) { CharOwningContainer c; - if(n.readable()) + if(n.tree()) emitrs_yaml(*n.tree(), n.id(), opts, &c); return c; } @@ -223,7 +223,7 @@ template CharOwningContainer emitrs_json(ConstNodeRef const& n, EmitOptions const& opts={}) { CharOwningContainer c; - if(n.readable()) + if(n.tree()) emitrs_json(*n.tree(), n.id(), opts, &c); return c; } diff --git a/src/c4/yml/emitter.def.hpp b/src/c4/yml/emitter.def.hpp index 1e3d75842..abb956da8 100644 --- a/src/c4/yml/emitter.def.hpp +++ b/src/c4/yml/emitter.def.hpp @@ -18,6 +18,10 @@ #ifndef C4_YML_ERROR_HPP_ #include "c4/yml/error.hpp" #endif +#ifndef C4_YML_DETAIL_EMIT_SCALAR_HPP_ +#include "c4/yml/detail/emit_scalar.hpp" +#endif + C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wold-style-cast") @@ -81,7 +85,7 @@ void Emitter::emit_as(EmitType_e type, Tree const* tree, id_type id) // This function kickstarts the tree descent by handling all the // initial and final logic at the top-level scope, thus avoiding // top-level kickstart branches in the recursive descending code -// (which should be oblivious of such logic). This makes the recursive +// (which should be oblivious to such logic). This makes the recursive // descending code a lot simpler. template void Emitter::emit_yaml_(id_type id) @@ -152,8 +156,7 @@ void Emitter::emit_yaml_(id_type id) } else if(m_tree->is_root(id) || emit_dash || emit_key - || !ty.is_val() - || !ty.is_val_plain()) + || !ty.is_val()) { write_pws_and_pend_(PWS_NONE_); } @@ -352,7 +355,7 @@ template void Emitter::top_close_entry_(id_type node) { NodeType ty = m_tree->type(node); - if(ty.is_val() && !(ty.m_bits & VALNIL)) + if(ty.is_val() && (!(ty.m_bits & VALNIL) || (ty.m_bits & (VALTAG|VALANCH)))) { pend_newl_(); } @@ -956,15 +959,15 @@ void Emitter::flow_write_scalar_(csubstr str, type_bits ty) RYML_ASSERT_BASIC_CB_(m_tree->callbacks(), !(ty & detail::styles_block_)); if((ty & detail::styles_plain_) || !(ty & SCALAR_STYLE)) { - write_scalar_plain_(str, m_ilevel); + detail::emit_scalar_plain_(this, str, m_ilevel); } else if(ty & detail::styles_squo_) { - write_scalar_squo_(str, m_ilevel); + detail::emit_scalar_squo_(this, str, m_ilevel); } else // if(ty & detail::styles_dquo_) { - write_scalar_dquo_(str, m_ilevel); + detail::emit_scalar_dquo_(this, str); } } @@ -973,318 +976,24 @@ void Emitter::blck_write_scalar_(csubstr str, type_bits ty) { if((ty & detail::styles_plain_) || !(ty & SCALAR_STYLE)) { - write_scalar_plain_(str, m_ilevel); + detail::emit_scalar_plain_(this, str, m_ilevel); } else if(ty & detail::styles_squo_) { - write_scalar_squo_(str, m_ilevel); + detail::emit_scalar_squo_(this, str, m_ilevel); } else if(ty & detail::styles_dquo_) { - write_scalar_dquo_(str, m_ilevel); + detail::emit_scalar_dquo_(this, str); } else if(ty & detail::styles_literal_) { - write_scalar_literal_(str, m_ilevel); + detail::emit_scalar_literal_(this, str, m_ilevel); } else // if(ty & detail::styles_folded_) { - write_scalar_folded_(str, m_ilevel); - } -} - -template -size_t Emitter::write_escaped_newlines_(csubstr s, size_t i) -{ - RYML_ASSERT_BASIC_CB_(m_tree->callbacks(), s.len > i); - RYML_ASSERT_BASIC_CB_(m_tree->callbacks(), s.str[i] == '\n'); - //_c4dbgpf("nl@i={} rem=[{}]~~~{}~~~", i, s.sub(i).len, s.sub(i)); - // add an extra newline for each sequence of consecutive - // newline/whitespace - newl_(); - do - { - newl_(); // write the newline again - ++i; // increase the outer loop counter! - } while(i < s.len && s.str[i] == '\n'); - RYML_ASSERT_BASIC_CB_(m_tree->callbacks(), i > 0); - --i; - RYML_ASSERT_BASIC_CB_(m_tree->callbacks(), s.str[i] == '\n'); - return i; -} - - -inline bool _is_indented_block(csubstr s, size_t prev, size_t i) noexcept -{ - if(prev == 0 && s.begins_with_any(" \t")) - return true; - const size_t pos = s.first_not_of('\n', i); - return (pos != npos) && (s.str[pos] == ' ' || s.str[pos] == '\t'); -} - - -template -size_t Emitter::write_indented_block_(csubstr s, size_t i, id_type ilevel) -{ - //_c4dbgpf("indblock@i={} rem=[{}]~~~\n{}~~~", i, s.sub(i).len, s.sub(i)); - RYML_ASSERT_BASIC_CB_(m_tree->callbacks(), i > 0); - RYML_ASSERT_BASIC_CB_(m_tree->callbacks(), s.str[i-1] == '\n'); - RYML_ASSERT_BASIC_CB_(m_tree->callbacks(), i < s.len); - RYML_ASSERT_BASIC_CB_(m_tree->callbacks(), s.str[i] == ' ' || s.str[i] == '\t' || s.str[i] == '\n'); -again: - size_t pos = s.find("\n ", i); - if(pos == npos) - pos = s.find("\n\t", i); - if(pos != npos) - { - ++pos; - //_c4dbgpf("indblock line@i={} rem=[{}]~~~\n{}~~~", i, s.range(i, pos).len, s.range(i, pos)); - indent_(ilevel + 1); - write_(s.range(i, pos)); - i = pos; - goto again; // NOLINT - } - // consume the newlines after the indented block - // to prevent them from being escaped - pos = s.find('\n', i); - if(pos != npos) - { - const size_t pos2 = s.first_not_of('\n', pos); - pos = (pos2 != npos) ? pos2 : pos; - //_c4dbgpf("indblock line@i={} rem=[{}]~~~\n{}~~~", i, s.range(i, pos).len, s.range(i, pos)); - indent_(ilevel + 1); - write_(s.range(i, pos)); - i = pos; - } - return i; -} - -template -void Emitter::write_scalar_literal_(csubstr s, id_type ilevel) -{ - RYML_ASSERT_BASIC_CB_(m_tree->callbacks(), s.find("\r") == csubstr::npos); - csubstr trimmed = s.trimr('\n'); - const size_t numnewlines_at_end = s.len - trimmed.len; - const bool is_newline_only = (trimmed.len == 0 && (s.len > 0)); - const bool explicit_indentation = s.triml("\n\r").begins_with_any(" \t"); - // - write_('|'); - if(explicit_indentation) - write_('2'); - // - if(numnewlines_at_end > 1 || is_newline_only) - write_('+'); - else if(numnewlines_at_end == 0) - write_('-'); - // - if(trimmed.len) - { - newl_(); - size_t pos = 0; // tracks the last character that was already written - for(size_t i = 0; i < trimmed.len; ++i) - { - if(trimmed[i] != '\n') - continue; - // write everything up to this point - csubstr since_pos = trimmed.range(pos, i+1); // include the newline - indent_(ilevel + 1); - write_(since_pos); - pos = i+1; // already written - } - if(pos < trimmed.len) - { - indent_(ilevel + 1); - write_(trimmed.sub(pos)); - } - } - for(size_t i = !is_newline_only; i < numnewlines_at_end; ++i) - newl_(); -} - -template -void Emitter::write_scalar_folded_(csubstr s, id_type ilevel) -{ - RYML_ASSERT_BASIC_CB_(m_tree->callbacks(), s.find("\r") == csubstr::npos); - csubstr trimmed = s.trimr('\n'); - const size_t numnewlines_at_end = s.len - trimmed.len; - const bool is_newline_only = (trimmed.len == 0 && (s.len > 0)); - const bool explicit_indentation = s.triml("\n\r").begins_with_any(" \t"); - // - write_('>'); - if(explicit_indentation) - write_('2'); - // - if(numnewlines_at_end == 0) - write_('-'); - else if(numnewlines_at_end > 1 || is_newline_only) - write_('+'); - // - if(trimmed.len) - { - newl_(); - size_t pos = 0; // tracks the last character that was already written - for(size_t i = 0; i < trimmed.len; ++i) - { - if(trimmed[i] != '\n') - continue; - // escape newline sequences - if( ! _is_indented_block(s, pos, i)) - { - if(pos < i) - { - indent_(ilevel + 1); - write_(s.range(pos, i)); - i = write_escaped_newlines_(s, i); - pos = i + 1; - } - else - { - if(i+1 < s.len) - { - if(s.str[i+1] == '\n') - { - ++i; - i = write_escaped_newlines_(s, i); - pos = i+1; - } - else - { - newl_(); - pos = i+1; - } - } - } - } - else // do not escape newlines in indented blocks - { - ++i; - indent_(ilevel + 1); - write_(s.range(pos, i)); - if(pos > 0 || !s.begins_with_any(" \t")) - i = write_indented_block_(s, i, ilevel); - pos = i; - } - } - if(pos < trimmed.len) - { - indent_(ilevel + 1); - write_(trimmed.sub(pos)); - } - } - for(size_t i = !is_newline_only; i < numnewlines_at_end; ++i) - newl_(); -} - -template -void Emitter::write_scalar_squo_(csubstr s, id_type ilevel) -{ - size_t pos = 0; // tracks the last character that was already written - write_('\''); - for(size_t i = 0; i < s.len; ++i) - { - if(s[i] == '\n') - { - write_(s.range(pos, i)); // write everything up to (excluding) this char - //_c4dbgpf("newline at {}. writing ~~~{}~~~", i, s.range(pos, i)); - i = write_escaped_newlines_(s, i); - //_c4dbgpf("newline --> {}", i); - if(i < s.len) - indent_(ilevel + 1); - pos = i+1; - } - else if(s[i] == '\'') - { - csubstr sub = s.range(pos, i+1); - //_c4dbgpf("squote at {}. writing ~~~{}~~~", i, sub); - write_(sub); // write everything up to (including) this squote - write_('\''); // write the squote again - pos = i+1; - } + detail::emit_scalar_folded_(this, str, m_ilevel); } - // write remaining characters at the end of the string - if(pos < s.len) - write_(s.sub(pos)); - write_('\''); -} - -template -void Emitter::write_scalar_dquo_(csubstr s, id_type ilevel) -{ - size_t pos = 0; // tracks the last character that was already written - write_('"'); - for(size_t i = 0; i < s.len; ++i) - { - const char curr = s.str[i]; - switch(curr) // NOLINT - { - case '"': - case '\\': - { - csubstr sub = s.range(pos, i); - write_(sub); // write everything up to (excluding) this char - write_('\\'); // write the escape - write_(curr); // write the char - pos = i+1; - break; - } - case '\n': - { - csubstr sub = s.range(pos, i); - write_(sub); // write everything up to (excluding) this char - write_("\\n"); // write the escape - pos = i+1; - (void)ilevel; - break; - } - case '\r': - { - csubstr sub = s.range(pos, i); - write_(sub); // write everything up to (excluding) this char - write_("\\r"); // write the escaped char - pos = i+1; - break; - } - case '\b': - { - csubstr sub = s.range(pos, i); - write_(sub); // write everything up to (excluding) this char - write_("\\b"); // write the escaped char - pos = i+1; - break; - } - } - } - // write remaining characters at the end of the string - if(pos < s.len) - write_(s.sub(pos)); - write_('"'); -} - -template -void Emitter::write_scalar_plain_(csubstr s, id_type ilevel) -{ - if C4_UNLIKELY(ilevel == 0 && (s.begins_with("...") || s.begins_with("---"))) - { - indent_(ilevel + 1); // indent the next line - ++ilevel; - } - size_t pos = 0; // tracks the last character that was already written - for(size_t i = 0; i < s.len; ++i) - { - const char curr = s.str[i]; - if(curr == '\n') - { - csubstr sub = s.range(pos, i); - write_(sub); // write everything up to (including) this newline - i = write_escaped_newlines_(s, i); - pos = i+1; - if(pos < s.len) - indent_(ilevel + 1); // indent the next line - } - } - // write remaining characters at the end of the string - if(pos < s.len) - write_(s.sub(pos)); } @@ -1319,6 +1028,8 @@ void Emitter::json_emit_(id_type id) if C4_UNLIKELY(ty.is_stream() && m_opts.json_err_on_stream()) RYML_ERR_VISIT_CB_(m_tree->callbacks(), m_tree, id, "found stream node"); static_assert(STREAM & SEQ, "STREAM must be a SEQ"); + if(!m_tree->is_root(id) && !m_opts.emit_nonroot_key()) + ty &= ~(KEY|KEY_STYLE); ty = detail::json_type_(ty); if(ty.is_flow_mlx()) { @@ -1328,6 +1039,8 @@ void Emitter::json_emit_(id_type id) else { json_visit_sl_(id, ty, 0); + if(ty.has_key()) + newl_(); } } @@ -1336,24 +1049,21 @@ void Emitter::json_visit_sl_(id_type id, NodeType ty, id_type depth) { if C4_UNLIKELY(depth > m_opts.max_depth()) RYML_ERR_VISIT_CB_(m_tree->callbacks(), m_tree, id, "max depth exceeded"); - if(ty.is_val()) - { - json_writev_(id, ty); - } - else if(ty.is_keyval()) + if C4_UNLIKELY(m_opts.json_err_on_anchor() && (ty.m_bits & (VALREF|KEYREF))) + RYML_ERR_VISIT_CB_(m_tree->callbacks(), m_tree, id, "JSON does not have anchors"); + if(ty.m_bits & KEY) { json_writek_(id, ty); write_(": "); + } + // no else! + if(ty.m_bits & VAL) + { json_writev_(id, ty); } else if(ty.is_container()) { ty = detail::json_type_(ty); - if(ty.has_key()) - { - json_writek_(id, ty); - write_(": "); - } if(ty.is_seq()) write_('['); else if(ty.is_map()) @@ -1383,24 +1093,21 @@ void Emitter::json_visit_ml_(id_type id, NodeType ty, id_type depth) { if C4_UNLIKELY(depth > m_opts.max_depth()) RYML_ERR_VISIT_CB_(m_tree->callbacks(), m_tree, id, "max depth exceeded"); - if(ty.is_val()) - { - json_writev_(id, ty); - } - else if(ty.is_keyval()) + if C4_UNLIKELY(m_opts.json_err_on_anchor() && (ty.m_bits & (VALREF|KEYREF))) + RYML_ERR_VISIT_CB_(m_tree->callbacks(), m_tree, id, "JSON does not have anchors"); + if(ty.m_bits & KEY) { json_writek_(id, ty); write_(": "); + } + // no else! + if(ty.m_bits & VAL) + { json_writev_(id, ty); } else if(ty.is_container()) { ty = detail::json_type_(ty); - if(ty.has_key()) - { - json_writek_(id, ty); - write_(": "); - } if(ty.is_seq()) write_('['); else if(ty.is_map()) @@ -1442,6 +1149,11 @@ void Emitter::json_visit_ml_(id_type id, NodeType ty, id_type depth) newl_(); indent_(m_ilevel); } + else if(ty.m_bits & FLOW_ML1) + { + newl_(); + indent_(m_ilevel); + } if(ty.is_seq()) write_(']'); @@ -1450,78 +1162,21 @@ void Emitter::json_visit_ml_(id_type id, NodeType ty, id_type depth) } } -template -bool Emitter::json_maybe_write_naninf_(csubstr s) -{ - switch(s.len) - { - case 3: case 4: case 5: // inf, nan, .nan, -.inf - case 8: case 9: // infinity, -infinity - break; - default: - return false; - } - const char first = s.str[0]; - csubstr rest = s.sub(1); - if(s.len == 4 && first == '.') - { - if(scalar_is_inf3(rest.str)) - goto write_inf_positive; // NOLINT - else if(scalar_is_nan3(rest.str)) - goto write_nan; // NOLINT - } - else if(first == '-' || first == '+') // begins with sign: must be inf - { - // match [-+].inf - if((rest.len == 4 && rest.str[0] == '.' && scalar_is_inf3(rest.str + 1)) - // match [-+]inf - || (rest.len == 3 && scalar_is_inf3(rest.str)) - // match [-+]infinity - || (rest.len == 8 && (0 == memcmp(rest.str, "infinity", 8)))) - { - if(first == '-') - goto write_inf_negative; // NOLINT - else - goto write_inf_positive; // NOLINT - } - } - else if(s.len == 8 && (0 == memcmp(s.str, "infinity", 8))) - { - goto write_inf_positive; // NOLINT - } - else if(s.len == 3) - { - if(scalar_is_inf3(s.str)) - goto write_inf_positive; // NOLINT - else if(scalar_is_nan3(s.str)) - goto write_nan; // NOLINT - } - return false; -write_inf_positive: - write_("\".inf\""); - return true; -write_inf_negative: - write_("\"-.inf\""); - return true; -write_nan: - write_("\".nan\""); - return true; -} template void Emitter::json_writek_(id_type id, NodeType ty) { - if C4_UNLIKELY(ty.has_key_tag() && m_opts.json_err_on_tag()) - RYML_ERR_VISIT_CB_(m_tree->callbacks(), m_tree, id, "JSON does not have tags"); - if C4_UNLIKELY(ty.has_key_anchor() && m_opts.json_err_on_anchor()) - RYML_ERR_VISIT_CB_(m_tree->callbacks(), m_tree, id, "JSON does not have anchors"); + if C4_UNLIKELY((m_opts.json_err_on_tag() && ty.has_key_tag()) + || + (m_opts.json_err_on_anchor() && ty.has_key_anchor())) + RYML_ERR_VISIT_CB_(m_tree->callbacks(), m_tree, id, "feature not supported in JSON"); csubstr key = m_tree->key(id); if(key.len) { - if(json_maybe_write_naninf_(key)) + if(detail::emit_json_maybe_write_naninf_(this, key)) ; else - json_write_scalar_dquo_(key); + detail::emit_json_write_scalar_dquo_(this, key); } else { @@ -1532,10 +1187,10 @@ void Emitter::json_writek_(id_type id, NodeType ty) template void Emitter::json_writev_(id_type id, NodeType ty) { - if C4_UNLIKELY(ty.has_val_tag() && m_opts.json_err_on_tag()) - RYML_ERR_VISIT_CB_(m_tree->callbacks(), m_tree, id, "JSON does not have tags"); - if C4_UNLIKELY(ty.has_val_anchor() && m_opts.json_err_on_anchor()) - RYML_ERR_VISIT_CB_(m_tree->callbacks(), m_tree, id, "JSON does not have anchors"); + if C4_UNLIKELY((m_opts.json_err_on_tag() && ty.has_val_tag()) + || + (m_opts.json_err_on_anchor() && ty.has_val_anchor())) + RYML_ERR_VISIT_CB_(m_tree->callbacks(), m_tree, id, "feature not supported in JSON"); csubstr val = m_tree->val(id); if(val.len) { @@ -1543,11 +1198,11 @@ void Emitter::json_writev_(id_type id, NodeType ty) bool dquoted = ((ty.m_bits & VALQUO) || (scalar_style_choose_json(val).m_bits & SCALAR_DQUO)); // choose the style if(dquoted) - json_write_scalar_dquo_(val); - else if(json_maybe_write_naninf_(val)) + detail::emit_json_write_scalar_dquo_(this, val); + else if(detail::emit_json_maybe_write_naninf_(this, val)) ; else if(val.is_number()) - json_write_number_(val); + detail::emit_json_write_number_(this, val); else write_(val); } @@ -1561,104 +1216,6 @@ void Emitter::json_writev_(id_type id, NodeType ty) } -template -void Emitter::json_write_scalar_dquo_(csubstr s) -{ - size_t pos = 0; - write_('"'); - for(size_t i = 0; i < s.len; ++i) - { - switch(s.str[i]) - { - case '"': - write_(s.range(pos, i)); - write_("\\\""); - pos = i + 1; - break; - case '\n': - write_(s.range(pos, i)); - write_("\\n"); - pos = i + 1; - break; - case '\t': - write_(s.range(pos, i)); - write_("\\t"); - pos = i + 1; - break; - case '\\': - write_(s.range(pos, i)); - write_("\\\\"); - pos = i + 1; - break; - case '\r': - write_(s.range(pos, i)); - write_("\\r"); - pos = i + 1; - break; - case '\b': - write_(s.range(pos, i)); - write_("\\b"); - pos = i + 1; - break; - case '\f': - write_(s.range(pos, i)); - write_("\\f"); - pos = i + 1; - break; - } - } - if(pos < s.len) - { - csubstr sub = s.sub(pos); - write_(sub); - } - write_('"'); -} - -template -void Emitter::json_write_number_(csubstr s) -{ - if(s.is_integer()) - { - write_(s); - } - else - { - if(s.begins_with('-') && s.len > 1) - { - csubstr rest = s.sub(1); - if(rest.begins_with('.')) - { - write_("-0"); - write_(rest); - } - else if(rest.ends_with('.')) - { - write_(s); - write_('0'); - } - else - { - write_(s); - } - } - else if(s.begins_with('.')) - { - write_('0'); - write_(s); - } - else if(s.ends_with('.')) - { - write_(s); - write_('0'); - } - else - { - write_(s); - } - } -} - /** @endcond */ } // namespace yml diff --git a/src/c4/yml/emitter.hpp b/src/c4/yml/emitter.hpp index e22906390..e3a269f92 100644 --- a/src/c4/yml/emitter.hpp +++ b/src/c4/yml/emitter.hpp @@ -152,24 +152,14 @@ class Emitter : public Writer private: void json_emit_(id_type id); - void write_scalar_literal_(csubstr s, id_type level); - void write_scalar_folded_(csubstr s, id_type level); - void write_scalar_squo_(csubstr s, id_type level); - void write_scalar_dquo_(csubstr s, id_type level); - void write_scalar_plain_(csubstr s, id_type level); - - size_t write_escaped_newlines_(csubstr s, size_t i); - size_t write_indented_block_(csubstr s, size_t i, id_type level); private: void json_visit_ml_(id_type id, NodeType ty, id_type depth); void json_visit_sl_(id_type id, NodeType ty, id_type depth); - bool json_maybe_write_naninf_(csubstr s); + void json_writek_(id_type id, NodeType ty); void json_writev_(id_type id, NodeType ty); - void json_write_scalar_dquo_(csubstr s); - void json_write_number_(csubstr s); private: @@ -189,7 +179,9 @@ class Emitter : public Writer } } -private: +public: + + using indent_type = id_type; template C4_ALWAYS_INLINE void write_(const char (&a)[N]) // LCOV_EXCL_LINE diff --git a/src/c4/yml/parse_engine.def.hpp b/src/c4/yml/parse_engine.def.hpp index 97650afba..3111b2352 100644 --- a/src/c4/yml/parse_engine.def.hpp +++ b/src/c4/yml/parse_engine.def.hpp @@ -4361,19 +4361,6 @@ bool ParseEngine::_handle_annotations_before_unexpected_flow_token if(!(m_pending_tags.num_entries | m_pending_anchors.num_entries)) return false; _c4dbgpf("handle_annotations_before_unexpected_flow_comma_rkey, node={}", m_evt_handler->m_curr->node_id); - if(m_pending_tags.num_entries) - { - _c4dbgpf("handle_annotations_before_unexpected_flow_comma_rkey, #tags={}", m_pending_tags.num_entries); - if C4_LIKELY(m_pending_tags.num_entries == 1) - { - m_evt_handler->set_key_tag(m_pending_tags.annotations[0].str); - _clear_annotations(&m_pending_tags); - } - else - { - _c4err("too many tags"); - } - } if(m_pending_anchors.num_entries) { _c4dbgpf("handle_annotations_before_unexpected_flow_comma, #anchors={}", m_pending_tags.num_entries); @@ -4387,18 +4374,9 @@ bool ParseEngine::_handle_annotations_before_unexpected_flow_token _c4err("too many anchors"); } } - m_evt_handler->set_key_scalar_plain_empty(); - m_evt_handler->set_val_scalar_plain_empty(); - return true; -} - -template -void ParseEngine::_handle_annotations_before_blck_key_scalar() -{ - _c4dbgpf("annotations_before_blck_key_scalar, node={}", m_evt_handler->m_curr->node_id); if(m_pending_tags.num_entries) { - _c4dbgpf("annotations_before_blck_key_scalar, #tags={}", m_pending_tags.num_entries); + _c4dbgpf("handle_annotations_before_unexpected_flow_comma_rkey, #tags={}", m_pending_tags.num_entries); if C4_LIKELY(m_pending_tags.num_entries == 1) { m_evt_handler->set_key_tag(m_pending_tags.annotations[0].str); @@ -4406,9 +4384,18 @@ void ParseEngine::_handle_annotations_before_blck_key_scalar() } else { - _c4err("too many tags"); // LCOV_EXCL_LINE + _c4err("too many tags"); } } + m_evt_handler->set_key_scalar_plain_empty(); + m_evt_handler->set_val_scalar_plain_empty(); + return true; +} + +template +void ParseEngine::_handle_annotations_before_blck_key_scalar() +{ + _c4dbgpf("annotations_before_blck_key_scalar, node={}", m_evt_handler->m_curr->node_id); if(m_pending_anchors.num_entries) { _c4dbgpf("annotations_before_blck_key_scalar, #anchors={}", m_pending_anchors.num_entries); @@ -4422,25 +4409,25 @@ void ParseEngine::_handle_annotations_before_blck_key_scalar() _c4err("too many anchors"); // LCOV_EXCL_LINE } } -} - -template -void ParseEngine::_handle_annotations_before_blck_val_scalar() -{ - _c4dbgpf("annotations_before_blck_val_scalar, node={}", m_evt_handler->m_curr->node_id); if(m_pending_tags.num_entries) { - _c4dbgpf("annotations_before_blck_val_scalar, #tags={}", m_pending_tags.num_entries); + _c4dbgpf("annotations_before_blck_key_scalar, #tags={}", m_pending_tags.num_entries); if C4_LIKELY(m_pending_tags.num_entries == 1) { - m_evt_handler->set_val_tag(m_pending_tags.annotations[0].str); + m_evt_handler->set_key_tag(m_pending_tags.annotations[0].str); _clear_annotations(&m_pending_tags); } else { - _c4err("too many tags"); + _c4err("too many tags"); // LCOV_EXCL_LINE } } +} + +template +void ParseEngine::_handle_annotations_before_blck_val_scalar() +{ + _c4dbgpf("annotations_before_blck_val_scalar, node={}", m_evt_handler->m_curr->node_id); if(m_pending_anchors.num_entries) { _c4dbgpf("annotations_before_blck_val_scalar, #anchors={}", m_pending_anchors.num_entries); @@ -4454,28 +4441,25 @@ void ParseEngine::_handle_annotations_before_blck_val_scalar() _c4err("too many anchors"); } } -} - -template -void ParseEngine::_handle_annotations_before_start_mapblck(size_t current_line) -{ - _c4dbgpf("annotations_before_start_mapblck, current_line={}", current_line); - if(m_pending_tags.num_entries == 2) - { - _c4dbgp("2 tags, setting entry 0"); - m_evt_handler->set_val_tag(m_pending_tags.annotations[0].str); - } - else if(m_pending_tags.num_entries == 1) + if(m_pending_tags.num_entries) { - _c4dbgpf("1 tag. line={}, curr={}", m_pending_tags.annotations[0].line, current_line); - if(m_pending_tags.annotations[0].line < current_line) + _c4dbgpf("annotations_before_blck_val_scalar, #tags={}", m_pending_tags.num_entries); + if C4_LIKELY(m_pending_tags.num_entries == 1) { - _c4dbgp("...tag is for the map. setting it."); m_evt_handler->set_val_tag(m_pending_tags.annotations[0].str); _clear_annotations(&m_pending_tags); } + else + { + _c4err("too many tags"); + } } - // +} + +template +void ParseEngine::_handle_annotations_before_start_mapblck(size_t current_line) +{ + _c4dbgpf("annotations_before_start_mapblck, current_line={}", current_line); if(m_pending_anchors.num_entries == 2) { _c4dbgp("2 anchors, setting entry 0"); @@ -4491,28 +4475,28 @@ void ParseEngine::_handle_annotations_before_start_mapblck(size_t _clear_annotations(&m_pending_anchors); } } + // + if(m_pending_tags.num_entries == 2) + { + _c4dbgp("2 tags, setting entry 0"); + m_evt_handler->set_val_tag(m_pending_tags.annotations[0].str); + } + else if(m_pending_tags.num_entries == 1) + { + _c4dbgpf("1 tag. line={}, curr={}", m_pending_tags.annotations[0].line, current_line); + if(m_pending_tags.annotations[0].line < current_line) + { + _c4dbgp("...tag is for the map. setting it."); + m_evt_handler->set_val_tag(m_pending_tags.annotations[0].str); + _clear_annotations(&m_pending_tags); + } + } } template void ParseEngine::_handle_annotations_before_start_mapblck_as_key() { _c4dbgp("annotations_before_start_mapblck_as_key"); - switch(m_pending_tags.num_entries) - { - case 1u: - _c4dbgpf("annotations_after_start_mapblck_as_key: 1 tag={} line={} currline=", prs_(m_pending_tags.annotations[0].str), m_pending_tags.annotations[0].line, m_evt_handler->m_curr->pos.line); - if(m_pending_tags.annotations[0].line != m_evt_handler->m_curr->pos.line) - { - _c4dbgp("annotations_after_start_mapblck_as_key: is map tag"); - m_evt_handler->set_key_tag(m_pending_tags.annotations[0].str); - _clear_annotations(&m_pending_tags); - } - break; - case 2u: - _c4dbgpf("annotations_after_start_mapblck_as_key: 2 tags: {} -> {}", prs_(m_pending_tags.annotations[0].str), prs_(m_pending_tags.annotations[1].str)); - m_evt_handler->set_key_tag(m_pending_tags.annotations[0].str); - break; - } switch(m_pending_anchors.num_entries) { case 1u: @@ -4529,6 +4513,22 @@ void ParseEngine::_handle_annotations_before_start_mapblck_as_key( m_evt_handler->set_key_anchor(m_pending_anchors.annotations[0].str); break; } + switch(m_pending_tags.num_entries) + { + case 1u: + _c4dbgpf("annotations_after_start_mapblck_as_key: 1 tag={} line={} currline=", prs_(m_pending_tags.annotations[0].str), m_pending_tags.annotations[0].line, m_evt_handler->m_curr->pos.line); + if(m_pending_tags.annotations[0].line != m_evt_handler->m_curr->pos.line) + { + _c4dbgp("annotations_after_start_mapblck_as_key: is map tag"); + m_evt_handler->set_key_tag(m_pending_tags.annotations[0].str); + _clear_annotations(&m_pending_tags); + } + break; + case 2u: + _c4dbgpf("annotations_after_start_mapblck_as_key: 2 tags: {} -> {}", prs_(m_pending_tags.annotations[0].str), prs_(m_pending_tags.annotations[1].str)); + m_evt_handler->set_key_tag(m_pending_tags.annotations[0].str); + break; + } } template @@ -4540,19 +4540,6 @@ void ParseEngine::_handle_annotations_and_indentation_after_start_ if(m_pending_anchors.num_entries || m_pending_tags.num_entries) { key_indentation = _select_indentation_from_annotations(key_indentation, key_line); - switch(m_pending_tags.num_entries) - { - case 1u: - _c4dbgpf("annotations_after_start_mapblck: 1 tag: {}", prs_(m_pending_tags.annotations[0].str)); - m_evt_handler->set_key_tag(m_pending_tags.annotations[0].str); - _clear_annotations(&m_pending_tags); - break; - case 2u: - _c4dbgpf("annotations_after_start_mapblck: 2 tags: {} -> {}", prs_(m_pending_tags.annotations[0].str), prs_(m_pending_tags.annotations[1].str)); - m_evt_handler->set_key_tag(m_pending_tags.annotations[1].str); - _clear_annotations(&m_pending_tags); - break; - } switch(m_pending_anchors.num_entries) { case 1u: @@ -4566,6 +4553,19 @@ void ParseEngine::_handle_annotations_and_indentation_after_start_ _clear_annotations(&m_pending_anchors); break; } + switch(m_pending_tags.num_entries) + { + case 1u: + _c4dbgpf("annotations_after_start_mapblck: 1 tag: {}", prs_(m_pending_tags.annotations[0].str)); + m_evt_handler->set_key_tag(m_pending_tags.annotations[0].str); + _clear_annotations(&m_pending_tags); + break; + case 2u: + _c4dbgpf("annotations_after_start_mapblck: 2 tags: {} -> {}", prs_(m_pending_tags.annotations[0].str), prs_(m_pending_tags.annotations[1].str)); + m_evt_handler->set_key_tag(m_pending_tags.annotations[1].str); + _clear_annotations(&m_pending_tags); + break; + } } _set_indentation(key_indentation); } @@ -6793,6 +6793,9 @@ void ParseEngine::_handle_map_block() _c4dbgp("mapblck[RKEY]: end doc"); _end_doc_suddenly(); _line_progressed(3); + #if defined(__GNUC__) && (__GNUC__ == 13) && (C4_WORDSIZE == 4) && (C4_CPP >= 20) + C4_DONT_OPTIMIZE(m_evt_handler->m_curr->line_contents.rem); + #endif _maybe_skip_whitespace_tokens(); _check_doc_end_tokens(); goto mapblck_finish; diff --git a/src/c4/yml/scalar_style.cpp b/src/c4/yml/scalar_style.cpp index cd605b11b..b5a1f6b63 100644 --- a/src/c4/yml/scalar_style.cpp +++ b/src/c4/yml/scalar_style.cpp @@ -143,6 +143,7 @@ bool scalar_style_query_plain_block(csubstr scalar) noexcept } +// see also ievt implementation in emitter_ints NodeType scalar_style_choose_block(csubstr scalar) noexcept { if(scalar.len) @@ -157,6 +158,7 @@ NodeType scalar_style_choose_block(csubstr scalar) noexcept } +// see also ievt implementation in emitter_ints NodeType scalar_style_choose_json(csubstr scalar) noexcept { // do not quote numbers or special scalars diff --git a/src_extra/c4/yml/extra/emitter_ints.def.hpp b/src_extra/c4/yml/extra/emitter_ints.def.hpp new file mode 100644 index 000000000..91d0c9225 --- /dev/null +++ b/src_extra/c4/yml/extra/emitter_ints.def.hpp @@ -0,0 +1,1644 @@ +#ifndef C4_YML_EXTRA_EMITTER_INTS_DEF_HPP_ +#define C4_YML_EXTRA_EMITTER_INTS_DEF_HPP_ + +/** @file emitter.def.hpp */ + +#ifndef C4_YML_EXTRA_EMITTER_INTS_HPP_ +#include "c4/yml/extra/emitter_ints.hpp" +#endif +#ifndef C4_YML_ERROR_HPP_ +#include "c4/yml/error.hpp" +#endif +#ifndef C4_YML_DETAIL_EMIT_SCALAR_HPP_ +#include "c4/yml/detail/emit_scalar.hpp" +#endif + + +C4_SUPPRESS_WARNING_PUSH +C4_SUPPRESS_WARNING_GCC_CLANG("-Wold-style-cast") +C4_SUPPRESS_WARNING_GCC("-Wuseless-cast") +C4_SUPPRESS_WARNING_MSVC(5054) // '|': deprecated between enumerations of different types +#if defined(__GNUC__) && (__GNUC__ > 8) +C4_SUPPRESS_WARNING_GCC("-Wdeprecated-enum-enum-conversion") +#endif +#if defined(__clang__) && (__clang_major__ >= 10) +C4_SUPPRESS_WARNING_CLANG("-Wdeprecated-anon-enum-enum-conversion") +#endif +// NOLINTBEGIN(hicpp-signed-bitwise,*avoid-c-style-cast) + +namespace c4 { +namespace yml { +namespace extra { +namespace ievt { + +/** @cond dev */ + +namespace detail { +enum : evt_bits { // NOLINT + styles_ievt_quot = ievt::SQUO|ievt::DQUO|ievt::LITL|ievt::FOLD, + styles_ievt_sclr = ievt::PLAI|styles_ievt_quot, + styles_ievt_cont = ievt::BLCK|ievt::FLOW|ievt::FSL_|ievt::FML1|ievt::FMLN, +}; +inline bool query_blck_cont_(evt_bits evt) noexcept +{ + return (evt & ievt::BLCK) || (!(evt & detail::styles_ievt_cont)); +} +inline bool key_requires_qmark_block(evt_bits const* C4_RESTRICT evts, evt_size evts_size, evt_size pos) RYML_NOEXCEPT +{ + return get_all_bits_key(evts, evts_size, pos) & (detail::mask_seqmap|ievt::LITL|ievt::FOLD); // NOLINT +} +inline bool key_requires_qmark_flow(evt_bits const* C4_RESTRICT evts, evt_size evts_size, evt_size pos) RYML_NOEXCEPT +{ + return get_all_bits_key(evts, evts_size, pos) & (detail::mask_seqmap); +} +} // namespace detail + + +//----------------------------------------------------------------------------- + +template +void EmitterInts::emit_as(EmitType_e type, + evt_bits const* evts, + evt_size evts_size, + evt_size pos, + csubstr src, + csubstr arena) +{ + RYML_ASSERT_BASIC_(evts || !evts_size); + RYML_ASSERT_BASIC_(pos <= evts_size); + if(!evts || !evts_size) + return; + m_evts = evts; + m_evts_size = evts_size; + m_src = src; + m_arena = arena; + m_col = 0; + m_depth = 0; + m_ilevel = 0; + m_pws = PWS_NONE_; + m_flow_pws = {}; + if(type == EMIT_YAML) + emit_yaml_(pos); + else if(type == EMIT_JSON) + emit_json_(pos); + else + RYML_ERR_BASIC_("unknown emit type"); // LCOV_EXCL_LINE + m_evts = nullptr; + m_evts_size = 0; + m_src = {}; + m_arena = {}; +} + + +//----------------------------------------------------------------------------- + +// The startup logic is made complicated from it having to accept +// initial non-root nodes, and having to deal with tricky tokens like +// doc separators, anchors, tags, optional keys or dashes, and +// comments. +// +// This function kickstarts the tree descent by handling all the +// initial and final logic at the top-level scope, thus avoiding +// top-level kickstart branches in the recursive descending code +// (which should be oblivious of such logic). This makes the recursive +// descending code a lot simpler. + +template +void EmitterInts::emit_yaml_(evt_size pos) +{ + const detail::EmitKickoff ek = detail::kickoff_emit(m_evts, m_evts_size, pos, m_opts); + + evt_bits evt = m_evts[ek.valpos]; + if(ek.emit_dash) + { + ++m_ilevel; + write_("- "); + } + else if(ek.emit_key) + { + pos = kickoff_key(pos, ek.keypos); + if(detail::seqormap(evt) && detail::query_blck_cont_(evt)) + pend_newl_(); + } + + bool flushpws = false; + + // emit the payload + if(detail::hasall(evt, ievt::BSTR)) + { + RYML_ASSERT_BASIC_(m_ilevel == 0); + pos = visit_stream_(pos); + } + else if(detail::hasall(evt, ievt::BDOC)) + { + RYML_ASSERT_BASIC_(m_ilevel == 0); + bool expl = evt & ievt::EXPL; + if(expl) + { + write_("---"); + pend_space_(); + } + pos = visit_doc_(pos, expl); + } + else if(detail::seqormap(evt)) + { + { + evt_size nextpos = write_tag_or_anchor(pos, ek.valpos); + if(nextpos > pos && detail::seqormap(evt) && detail::query_blck_cont_(evt)) + pend_newl_(); + pos = nextpos; + } + pos = visit_blck_container_(pos); + if(evt & ievt::FMLX) + { + pend_newl_(); + flushpws = true; + } + } + else if(evt & (ievt::SCLR|ievt::ALIA)) + { + pos = write_tag_or_anchor(pos, ek.valpos); + pos = visit_doc_val_(pos); + } + + // emit closing tokens + if(ek.emit_dash || ek.emit_key) + { + --m_ilevel; + pend_newl_(); + flushpws = true; + } + + if(!ek.parent + || flushpws + || !(evt & ievt::SCLR) + || !(evt & ievt::PLAI)) + { + write_pws_and_pend_(PWS_NONE_); + } +} + +template +evt_size EmitterInts::write_tag_or_anchor(evt_size pos, evt_size dst) +{ + RYML_ASSERT_BASIC_(pos < m_evts_size); + RYML_ASSERT_BASIC_(dst < m_evts_size); + while(pos < dst) + { + const evt_bits evt = m_evts[pos]; + if(evt & ievt::ANCH) + { + write_pws_and_pend_(PWS_SPACE_); + write_('&'); + write_(getstr_(pos)); + pos += 3; + } + else if(evt & ievt::TAG_) + { + write_pws_and_pend_(PWS_SPACE_); + write_tag_(getstr_(pos)); + pos += 3; + } + else + { + pos += ievt::nextstep(evt); // LCOV_EXCL_LINE + } + } + return pos; +} + +template +evt_size EmitterInts::kickoff_key(evt_size pos, evt_size keypos) +{ + RYML_ASSERT_BASIC_(pos < m_evts_size); + evt_bits evt = m_evts[keypos]; + if(evt & (ievt::SCLR|ievt::ALIA)) + { + csubstr key = getstr_(keypos); + evt_bits keystyle = (evt & detail::styles_ievt_sclr); + if(!keystyle) + keystyle = detail::scalar_style_choose_block_ievt(key); + if(keystyle & (ievt::FOLD|ievt::LITL)) + { + write_('?'); + pend_space_(); + pos = write_tag_or_anchor(pos, keypos); + write_pws_and_pend_(PWS_NEWL_); + blck_write_scalar_(key, keystyle); + } + else + { + pos = write_tag_or_anchor(pos, keypos); + write_pws_and_pend_(PWS_NONE_); + blck_write_scalar_(key, keystyle); + } + write_pws_and_pend_(PWS_SPACE_); + write_(':'); + ++m_ilevel; + } + else + { + RYML_ASSERT_BASIC_(detail::seqormap(m_evts[keypos])); + evt_bits keystyle = (m_evts[keypos] & detail::styles_ievt_cont); + if(!keystyle) + keystyle = ievt::BLCK; + write_('?'); + pend_space_(); + pos = write_tag_or_anchor(pos, keypos); + ++m_ilevel; + if(keystyle & ievt::BLCK) + pend_newl_(); + pos = visit_blck_container_(pos); + --m_ilevel; + pend_newl_(); + write_pws_and_pend_(PWS_SPACE_); + write_(':'); + ++m_ilevel; + } + return pos; +} + + +//----------------------------------------------------------------------------- + +template +evt_size EmitterInts::visit_stream_(evt_size pos) +{ + m_ilevel = 0; + uint32_t doc_count = 0; + while(pos < m_evts_size) + { + evt_bits evt = m_evts[pos]; + if(detail::hasall(evt, ievt::BDOC)) + { + bool expl = doc_count || (evt & ievt::EXPL); + if(expl) + { + if(doc_count) + pend_newl_(); + write_pws_and_pend_(PWS_SPACE_); + write_("---"); + } + ++doc_count; + RYML_ASSERT_BASIC_(pos + 1 < m_evts_size); + if(detail::hasnone(m_evts[pos + 1], ievt::EDOC)) + { + pos = visit_doc_(pos, expl); + } + } + else if(evt & ievt::YAML) + { + write_pws_and_pend_(PWS_NEWL_); + write_("%YAML "); + write_(getstr_(pos)); + pos += 3; + } + else if(evt & ievt::TAGH) + { + RYML_ASSERT_BASIC_(m_evts[pos + 3] & ievt::TAGP); + write_pws_and_pend_(PWS_NEWL_); + write_("%TAG "); + write_(getstr_(pos)); + write_(' '); + pos += 3; + write_(getstr_(pos)); + pos += 3; + } + else + { + pos += ievt::nextstep(evt); // LCOV_EXCL_LINE + } + } + return pos; +} + + +//----------------------------------------------------------------------------- + +template +evt_size EmitterInts::visit_doc_val_(evt_size pos) +{ + // some plain scalars such as '...' and '---' must not + // appear at 0-indentation + evt_bits evt = m_evts[pos]; + RYML_ASSERT_BASIC_(evt & (ievt::SCLR|ievt::ALIA)); + RYML_ASSERT_BASIC_(evt & (ievt::VAL_|ievt::KEY_)); + const csubstr val = getstr_(pos); + if(!(evt & ievt::ALIA)) + { + evt_bits valstyle = evt & detail::styles_ievt_sclr; + const bool is_ambiguous = ((evt & ievt::PLAI) || !valstyle) + && (val.begins_with("...") || val.begins_with("---")); + if(!valstyle) + valstyle = detail::scalar_style_choose_block_ievt(val); + if(is_ambiguous) + { + ++m_ilevel; + if(m_pws != PWS_NONE_) + pend_newl_(); + else + indent_(m_ilevel); + } + else if(val.empty() && (valstyle & ievt::PLAI)) + { + pend_none_(); + } + write_pws_and_pend_(PWS_NONE_); + blck_write_scalar_(val, valstyle); + if(is_ambiguous) + --m_ilevel; + } + else + { + write_('*'); + write_(val); + } + return pos; +} + + +//----------------------------------------------------------------------------- + +template +evt_size EmitterInts::visit_doc_(evt_size pos, bool begin_expl) +{ + RYML_ASSERT_BASIC_(detail::hasall(m_evts[pos], ievt::BDOC)); + ++pos; + bool anchor_or_tag = false; + bool was_flow_container = false; + while(pos < m_evts_size) + { + evt_bits evt = m_evts[pos]; + if(detail::seqormap(evt)) + { + if(evt & ievt::FLOW) + { + was_flow_container = true; + pos = visit_flow_container_(pos); + if(evt & ievt::FMLX) + pend_newl_(); + } + else + { + if(begin_expl || anchor_or_tag) + pend_newl_(); + pos = visit_blck_container_(pos); + } + anchor_or_tag = false; + } + else if(evt & ievt::SCLR) + { + RYML_ASSERT_BASIC_(evt & ievt::VAL_); + pos = visit_doc_val_(pos); + pend_newl_(); + pos += 3; + } + else if(evt & ievt::ANCH) + { + anchor_or_tag = true; + write_pws_and_pend_(PWS_SPACE_); + write_('&'); + write_(getstr_(pos)); + pos += 3; + } + else if(evt & ievt::TAG_) + { + anchor_or_tag = true; + write_pws_and_pend_(PWS_SPACE_); + write_tag_(getstr_(pos)); + pos += 3; + } + else if(evt & ievt::ALIA) + { + write_pws_and_pend_(PWS_NEWL_); + write_ref_(getstr_(pos)); + pos += 3; + } + else if(detail::hasall(evt, ievt::EDOC)) + { + if(was_flow_container) + { + // is there a better way? + if(begin_expl || (evt & ievt::EXPL) || detail::has_next_doc_and_is_expl_(m_evts, m_evts_size, pos)) + pend_newl_(); + } + if(evt & ievt::EXPL) + { + write_pws_and_pend_(PWS_NEWL_); + write_("..."); + } + ++pos; + break; + } + else + { + pos += ievt::nextstep(evt); // LCOV_EXCL_LINE + } + } + return pos; +} + + +//----------------------------------------------------------------------------- + +template +evt_size EmitterInts::visit_blck_container_(evt_size pos) +{ + evt_bits evt = m_evts[pos]; + RYML_ASSERT_BASIC_(detail::seqormap(evt)); + RYML_ASSERT_BASIC_(pos + 1 < m_evts_size); + if(!(evt & (ievt::FLOW|ievt::BLCK))) + evt |= (m_evts[pos + 1] & ievt::END_) ? ievt::FSL_ : ievt::BLCK; + write_pws_and_pend_(PWS_NONE_); + if(evt & ievt::FSL_) + pos = visit_flow_sl_(pos); + else if(evt & ievt::FMLX) + pos = visit_flow_ml_(pos); + else + pos = visit_blck_(pos); + RYML_ASSERT_BASIC_(!(evt & ievt::END_)); + return pos; +} + +template +evt_size EmitterInts::visit_flow_container_(evt_size pos) +{ + evt_bits evt = m_evts[pos]; + RYML_ASSERT_BASIC_(detail::seqormap(evt)); + RYML_ASSERT_BASIC_(pos + 1 < m_evts_size); + if(!(evt & ievt::FLOW)) + evt |= ievt::FLOW|ievt::FSL_; + write_pws_and_pend_(PWS_NONE_); + if(evt & ievt::FMLX) + pos = visit_flow_ml_(pos); + else + pos = visit_flow_sl_(pos); + RYML_ASSERT_BASIC_(!(evt & ievt::END_)); + return pos; +} + + +//----------------------------------------------------------------------------- + +template +evt_size EmitterInts::visit_blck_(evt_size pos) +{ + evt_bits evt = m_evts[pos]; + RYML_ASSERT_BASIC_(!(evt & ievt::STRM)); + RYML_ASSERT_BASIC_(detail::seqormap(evt) || detail::hasall(evt, ievt::BDOC)); + if C4_UNLIKELY(m_depth > (evt_size)m_opts.max_depth()) + RYML_ERR_BASIC_("max depth exceeded"); + if(detail::hasall(evt, ievt::BSEQ)) + { + pos = visit_blck_seq_(pos); + } + else + { + RYML_ASSERT_BASIC_(detail::hasall(evt, ievt::BMAP)); + pos = visit_blck_map_(pos); + } + return pos; +} + + +//----------------------------------------------------------------------------- + +template +evt_size EmitterInts::visit_flow_sl_(evt_size pos) +{ + evt_bits evt = m_evts[pos]; + RYML_ASSERT_BASIC_(!(evt & ievt::STRM)); + RYML_ASSERT_BASIC_(detail::seqormap(evt) || detail::hasall(evt, ievt::BDOC)); + if C4_UNLIKELY(m_depth > (evt_size)m_opts.max_depth()) + RYML_ERR_BASIC_("max depth exceeded"); + if(evt & ievt::SEQ_) + { + pos = visit_flow_sl_seq_(pos); + } + else + { + RYML_ASSERT_BASIC_(evt & ievt::MAP_); + pos = visit_flow_sl_map_(pos); + } + return pos; +} + + +//----------------------------------------------------------------------------- + +template +evt_size EmitterInts::visit_flow_ml_(evt_size pos) +{ + evt_bits evt = m_evts[pos]; + RYML_ASSERT_BASIC_(!(evt & ievt::STRM)); + RYML_ASSERT_BASIC_(detail::seqormap(evt) || detail::hasall(evt, ievt::BDOC)); + if C4_UNLIKELY(m_depth > (evt_size)m_opts.max_depth()) + RYML_ERR_BASIC_("max depth exceeded"); + if(evt & ievt::SEQ_) + { + pos = visit_flow_ml_seq_(pos); + } + else + { + RYML_ASSERT_BASIC_(evt & ievt::MAP_); + pos = visit_flow_ml_map_(pos); + } + return pos; +} + + +//----------------------------------------------------------------------------- + +template +evt_size EmitterInts::visit_blck_seq_(evt_size pos) +{ + RYML_ASSERT_BASIC_(detail::hasall(m_evts[pos], ievt::BSEQ)); + RYML_ASSERT_BASIC_(pos + 1 < m_evts_size); + ++pos; + bool newval = true; + bool has_tag_or_anchor = false; + evt_bits evt = {}; + while(pos < m_evts_size) + { + evt = m_evts[pos]; + if(detail::hasall(evt, ievt::ESEQ)) + { + ++pos; + break; + } + if(newval) + { + write_pws_and_pend_(PWS_SPACE_); // pend the space after the following dash + write_('-'); + newval = false; + } + if(evt & ievt::SCLR) + { + write_pws_and_pend_(PWS_NEWL_); + const csubstr val = getstr_(pos); + if(!(evt & detail::styles_ievt_sclr)) + evt |= detail::scalar_style_choose_block_ievt(val); + blck_write_scalar_(val, evt); + pos += 3; + goto nextval; // NOLINT + } + else if(detail::seqormap(evt)) + { + if(has_tag_or_anchor) + { + if(detail::hasnone(evt, detail::styles_ievt_cont)) + evt |= ievt::BLCK; + bool empty = (m_evts[pos + 1] & ievt::END_); + if(!empty && (evt & ievt::BLCK)) + pend_newl_(); + } + ++m_depth; + ++m_ilevel; + pos = visit_blck_container_(pos); + --m_depth; + --m_ilevel; + pend_newl_(); + goto nextval; // NOLINT + } + else if(evt & ievt::ALIA) + { + write_pws_and_pend_(PWS_NEWL_); + write_ref_(getstr_(pos)); + pos += 3; + goto nextval; // NOLINT + } + else if(evt & ievt::ANCH) + { + has_tag_or_anchor = true; + write_pws_and_pend_(PWS_SPACE_); + write_('&'); + write_(getstr_(pos)); + pos += 3; + } + else if(evt & ievt::TAG_) + { + has_tag_or_anchor = true; + write_pws_and_pend_(PWS_SPACE_); + write_tag_(getstr_(pos)); + pos += 3; + } + else + { + pos += ievt::nextstep(evt); // LCOV_EXCL_LINE + } + continue; + nextval: + newval = true; + has_tag_or_anchor = false; + } + return pos; +} + + +//----------------------------------------------------------------------------- + + +template +evt_size EmitterInts::visit_blck_map_(evt_size pos) +{ + RYML_ASSERT_BASIC_(pos + 1 < m_evts_size); + RYML_ASSERT_BASIC_(detail::hasall(m_evts[pos], ievt::BMAP)); + bool statenew = true; + bool statekey = true; + ++pos; + evt_bits evt = {}; + while(pos < m_evts_size) + { + evt = m_evts[pos]; + if(detail::hasall(evt, ievt::EMAP)) + { + ++pos; + break; + } + if(statenew) + { + if(statekey) + { + if(!detail::key_requires_qmark_block(m_evts, m_evts_size, pos)) + { + write_pws_and_pend_(PWS_NONE_); + } + else + { + write_pws_and_pend_(PWS_SPACE_); + write_('?'); + } + } + else + { + write_pws_and_pend_(PWS_SPACE_); + write_(':'); + } + statenew = false; + } + if(evt & ievt::SCLR) + { + write_pws_and_pend_(statekey ? PWS_NONE_ : PWS_NEWL_); + const csubstr val = getstr_(pos); + if(!(evt & detail::styles_ievt_sclr)) + { + evt |= detail::scalar_style_choose_block_ievt(val); + RYML_ASSERT_BASIC_(!(evt & (ievt::LITL|ievt::FOLD))); // litl/fold scalars require qmark + } + blck_write_scalar_(val, evt); + pos += 3; + if(evt & (ievt::LITL|ievt::FOLD)) + pend_newl_(); + goto statenext; // NOLINT + } + else if(detail::seqormap(evt)) + { + if(!(evt & detail::styles_ievt_cont)) + evt |= ievt::BLCK; + ++m_depth; + ++m_ilevel; + if(evt & ievt::BLCK) + pend_newl_(); + write_pws_and_pend_(PWS_NONE_); + pos = visit_blck_container_(pos); + if(evt & ievt::FLOW) + pend_newl_(); + --m_depth; + --m_ilevel; + goto statenext; // NOLINT + } + else if(evt & ievt::ALIA) + { + write_pws_and_pend_(statekey ? PWS_SPACE_ : PWS_NEWL_); + write_ref_(getstr_(pos)); + pos += 3; + goto statenext; // NOLINT + } + else if(evt & ievt::ANCH) + { + write_pws_and_pend_(PWS_SPACE_); + write_('&'); + write_(getstr_(pos)); + pos += 3; + } + else if(evt & ievt::TAG_) + { + write_pws_and_pend_(PWS_SPACE_); + write_tag_(getstr_(pos)); + pos += 3; + } + else + { + pos += ievt::nextstep(evt); // LCOV_EXCL_LINE + } + continue; + statenext: + statenew = true; + statekey = !statekey; + } + return pos; +} + + +//----------------------------------------------------------------------------- + +template +C4_NODISCARD bool EmitterInts::maybe_start_flow_pws_ml_(evt_size node) noexcept +{ + RYML_ASSERT_BASIC_((m_evts[node] & ievt::FMLX) || m_opts.force_flow_spc()); + if(m_flow_pws.active) + return false; + evt_bits evt = m_evts[node]; + if(m_opts.force_flow_spc()) + evt |= ievt::FSPC; + m_flow_pws.start(evt, m_opts.max_cols()); + return true; +} + +template +C4_NODISCARD typename EmitterInts::flow_pws EmitterInts::setup_flow_pws_sl_(evt_size node) noexcept +{ + flow_pws ret = {}; + if(m_flow_pws.active) + { + ret = m_flow_pws; + } + else + { + evt_bits evt = m_evts[node]; + if(m_opts.force_flow_spc()) + evt |= ievt::FSPC; + ret.start(evt, 0); + } + return ret; +} + +template +void EmitterInts::flow_pws::start(evt_bits evt, size_t max_cols_) noexcept +{ + max_cols = 0; + pend_after_comma = (evt & ievt::FSPC) ? PWS_SPACE_ : PWS_NONE_; + if(evt & ievt::FMLN) + { + max_cols_ = max_cols_ >= 2 ? max_cols_ : 2; + // subtract 1 for the comma, and maybe the space from pend_after_comma + max_cols = max_cols_ - 1 - pend_after_comma; + active = true; + } + else if(evt & ievt::FML1) + { + pend_after_comma = PWS_NEWL_; + } +} + +template +void EmitterInts::flow_close_entry_sl_(evt_size pos, Pws_e pend_after) +{ + RYML_ASSERT_BASIC_(pos < m_evts_size); + if(!(m_evts[pos] & ievt::END_)) + { + write_pws_and_pend_(pend_after); + write_(','); + } +} + +template +void EmitterInts::flow_close_entry_ml_(evt_size pos, Pws_e pend_after) +{ + RYML_ASSERT_BASIC_(pos < m_evts_size); + if(!(m_evts[pos] & ievt::END_)) + { + write_pws_and_pend_(pend_after); + write_(','); + } + else + { + pend_newl_(); + } +} + + +//----------------------------------------------------------------------------- + +template +evt_size EmitterInts::visit_flow_sl_seq_(evt_size pos) +{ + RYML_ASSERT_BASIC_(detail::hasall(m_evts[pos], ievt::BSEQ)); + RYML_ASSERT_BASIC_(pos + 1 < m_evts_size); + const flow_pws pws = setup_flow_pws_sl_(pos); + ++pos; + write_('['); + while(pos < m_evts_size) + { + evt_bits evt = m_evts[pos]; + if(detail::hasall(evt, ievt::ESEQ)) + { + ++pos; + break; + } + if(evt & ievt::SCLR) + { + write_pws_and_pend_(PWS_NONE_); + const csubstr val = getstr_(pos); + if(!(evt & detail::styles_ievt_sclr)) + evt |= detail::scalar_style_choose_flow_ievt(val); + flow_write_scalar_(val, evt); + pos += 3; + goto nextval; // NOLINT + } + else if(detail::seqormap(evt)) + { + ++m_depth; + pos = visit_flow_container_(pos); + --m_depth; + goto nextval; // NOLINT + } + else if(evt & ievt::ALIA) + { + write_pws_and_pend_(PWS_NONE_); + write_ref_(getstr_(pos)); + pos += 3; + goto nextval; // NOLINT + } + else if(evt & ievt::ANCH) + { + write_pws_and_pend_(PWS_SPACE_); + write_('&'); + write_(getstr_(pos)); + pos += 3; + } + else if(evt & ievt::TAG_) + { + write_pws_and_pend_(PWS_SPACE_); + write_tag_(getstr_(pos)); + pos += 3; + } + else + { + pos += ievt::nextstep(evt); // LCOV_EXCL_LINE + } + continue; + nextval: + flow_close_entry_sl_(pos, pws.next_pws(m_col)); + } + write_(']'); + return pos; +} + + +//----------------------------------------------------------------------------- + +template +evt_size EmitterInts::visit_flow_ml_seq_(evt_size pos) +{ + RYML_ASSERT_BASIC_(pos + 1 < m_evts_size); + RYML_ASSERT_BASIC_(detail::hasall(m_evts[pos], ievt::BSEQ)); + if(m_opts.indent_flow_ml()) ++m_ilevel; + write_('['); + pend_newl_(); + const bool stop_at_end = maybe_start_flow_pws_ml_(pos); + ++pos; + while(pos < m_evts_size) + { + evt_bits evt = m_evts[pos]; + if(detail::hasall(evt, ievt::ESEQ)) + { + ++pos; + break; + } + if(evt & ievt::SCLR) + { + write_pws_and_pend_(PWS_NONE_); + const csubstr val = getstr_(pos); + if(!(evt & detail::styles_ievt_sclr)) + evt |= detail::scalar_style_choose_flow_ievt(val); + flow_write_scalar_(val, evt); + pos += 3; + goto nextval; // NOLINT + } + else if(detail::seqormap(evt)) + { + write_pws_and_pend_(PWS_NONE_); + ++m_depth; + pos = visit_flow_container_(pos); + --m_depth; + goto nextval; // NOLINT + } + else if(evt & ievt::ALIA) + { + write_pws_and_pend_(PWS_NONE_); + write_ref_(getstr_(pos)); + pos += 3; + goto nextval; // NOLINT + } + else if(evt & ievt::ANCH) + { + write_pws_and_pend_(PWS_SPACE_); + write_('&'); + write_(getstr_(pos)); + pos += 3; + } + else if(evt & ievt::TAG_) + { + write_pws_and_pend_(PWS_SPACE_); + write_tag_(getstr_(pos)); + pos += 3; + } + else + { + pos += ievt::nextstep(evt); // LCOV_EXCL_LINE + } + continue; + nextval: + // pos is already at the next event + flow_close_entry_ml_(pos, m_flow_pws.next_pws(m_col)); + } + if(stop_at_end) + m_flow_pws.stop(); + if(m_opts.indent_flow_ml()) --m_ilevel; + write_pws_and_pend_(PWS_NONE_); + write_(']'); + return pos; +} + + +//----------------------------------------------------------------------------- + +template +evt_size EmitterInts::visit_flow_sl_map_(evt_size pos) +{ + RYML_ASSERT_BASIC_(pos + 1 < m_evts_size); + RYML_ASSERT_BASIC_(detail::hasall(m_evts[pos], ievt::BMAP)); + const flow_pws pws = setup_flow_pws_sl_(pos); + bool statenew = true; + bool statekey = true; + ++pos; + write_('{'); + while(pos < m_evts_size) + { + evt_bits evt = m_evts[pos]; + if(detail::hasall(evt, ievt::EMAP)) + { + ++pos; + break; + } + if(statenew) + { + if(statekey) + { + if(detail::key_requires_qmark_flow(m_evts, m_evts_size, pos)) + write_("? "); + } + else + { + write_pws_and_pend_(PWS_SPACE_); + write_(':'); + } + statenew = false; + } + if(evt & ievt::SCLR) + { + write_pws_and_pend_(PWS_NONE_); + const csubstr val = getstr_(pos); + if(!(evt & detail::styles_ievt_sclr)) + evt |= detail::scalar_style_choose_flow_ievt(val); + flow_write_scalar_(val, evt); + pos += 3; + goto statenext; // NOLINT + } + else if(detail::seqormap(evt)) + { + ++m_depth; + write_pws_and_pend_(PWS_NONE_); + pos = visit_flow_container_(pos); + --m_depth; + goto statenext; // NOLINT + } + else if(evt & ievt::ALIA) + { + write_pws_and_pend_(statekey ? PWS_SPACE_ : PWS_NONE_); + write_ref_(getstr_(pos)); + pos += 3; + goto statenext; // NOLINT + } + else if(evt & ievt::ANCH) + { + write_pws_and_pend_(PWS_SPACE_); + write_('&'); + write_(getstr_(pos)); + pos += 3; + } + else if(evt & ievt::TAG_) + { + write_pws_and_pend_(PWS_SPACE_); + write_tag_(getstr_(pos)); + pos += 3; + } + else + { + pos += ievt::nextstep(evt); // LCOV_EXCL_LINE + } + continue; + statenext: + if(!statekey) + // pos is already at the next event + flow_close_entry_sl_(pos, pws.next_pws(m_col)); + statenew = true; + statekey = !statekey; + } + write_('}'); + return pos; +} + + +//----------------------------------------------------------------------------- + +template +evt_size EmitterInts::visit_flow_ml_map_(evt_size pos) +{ + RYML_ASSERT_BASIC_(pos + 1 < m_evts_size); + RYML_ASSERT_BASIC_(detail::hasall(m_evts[pos], ievt::BMAP)); + if(m_opts.indent_flow_ml()) ++m_ilevel; + write_('{'); + pend_newl_(); + const bool stop_at_end = maybe_start_flow_pws_ml_(pos); + bool statenew = true; + bool statekey = true; + ++pos; + while(pos < m_evts_size) + { + evt_bits evt = m_evts[pos]; + if(detail::hasall(evt, ievt::EMAP)) + { + ++pos; + break; + } + if(statenew) + { + if(statekey) + { + if(detail::key_requires_qmark_flow(m_evts, m_evts_size, pos)) + { + write_pws_and_pend_(PWS_NONE_); + write_("? "); + } + } + else + { + write_pws_and_pend_(PWS_SPACE_); + write_(':'); + } + statenew = false; + } + if(evt & ievt::SCLR) + { + write_pws_and_pend_(PWS_NONE_); + const csubstr val = getstr_(pos); + if(!(evt & detail::styles_ievt_sclr)) + evt |= detail::scalar_style_choose_flow_ievt(val); + flow_write_scalar_(val, evt); + pos += 3; + goto statenext; // NOLINT + } + else if(detail::seqormap(evt)) + { + ++m_depth; + write_pws_and_pend_(PWS_NONE_); + pos = visit_flow_container_(pos); + --m_depth; + goto statenext; // NOLINT + } + else if(evt & ievt::ALIA) + { + write_pws_and_pend_(statekey ? PWS_SPACE_ : PWS_NONE_); + write_ref_(getstr_(pos)); + pos += 3; + goto statenext; // NOLINT + } + else if(evt & ievt::ANCH) + { + write_pws_and_pend_(PWS_SPACE_); + write_('&'); + write_(getstr_(pos)); + pos += 3; + } + else if(evt & ievt::TAG_) + { + write_pws_and_pend_(PWS_SPACE_); + write_tag_(getstr_(pos)); + pos += 3; + } + else + { + pos += ievt::nextstep(evt); // LCOV_EXCL_LINE + } + continue; + statenext: + if(!statekey) + // pos is already at the next event + flow_close_entry_ml_(pos, m_flow_pws.next_pws(m_col)); + statenew = true; + statekey = !statekey; + } + if(stop_at_end) + m_flow_pws.stop(); + if(m_opts.indent_flow_ml()) --m_ilevel; + write_pws_and_pend_(PWS_NONE_); + write_('}'); + return pos; +} + + +//----------------------------------------------------------------------------- + +template +void EmitterInts::flow_write_scalar_(csubstr str, evt_bits evt) +{ + RYML_ASSERT_BASIC_(!(evt & ievt::BLCK)); + if((evt & ievt::PLAI) || !(evt & detail::styles_ievt_sclr)) + { + yml::detail::emit_scalar_plain_(this, str, m_ilevel); + } + else if(evt & ievt::SQUO) + { + yml::detail::emit_scalar_squo_(this, str, m_ilevel); + } + else // if(evt & ievt::DQUO) + { + yml::detail::emit_scalar_dquo_(this, str); + } +} + +template +void EmitterInts::blck_write_scalar_(csubstr str, evt_bits evt) +{ + if((evt & ievt::PLAI) || !(evt & detail::styles_ievt_sclr)) + { + yml::detail::emit_scalar_plain_(this, str, m_ilevel); + } + else if(evt & ievt::SQUO) + { + yml::detail::emit_scalar_squo_(this, str, m_ilevel); + } + else if(evt & ievt::DQUO) + { + yml::detail::emit_scalar_dquo_(this, str); + } + else if(evt & ievt::LITL) + { + yml::detail::emit_scalar_literal_(this, str, m_ilevel); + } + else // if(ty & ievt::FOLD) + { + yml::detail::emit_scalar_folded_(this, str, m_ilevel); + } +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +template +void EmitterInts::emit_json_(evt_size pos) +{ + if(detail::hasall(m_evts[pos], ievt::BSTR)) + pos = json_visit_stream_(pos); + else + pos = json_visit_nested_(pos); + write_pws_and_pend_(PWS_NONE_); +} + +template +evt_size EmitterInts::json_visit_stream_(evt_size pos) +{ + evt_size numdocs = 0; + bool has_expl = false; + // count numdocs + for(evt_size p = pos; p < m_evts_size; p += ievt::nextstep(m_evts[p])) + { + if(detail::hasall(m_evts[p], ievt::BDOC)) + { + ++numdocs; + has_expl = has_expl || ((m_evts[p] & ievt::EXPL) != 0); + } + else if(detail::hasall(m_evts[p], ievt::ESTR)) + { + break; + } + } + const bool mldocs = (has_expl || numdocs > 1); + if(mldocs) + { + if C4_UNLIKELY(m_opts.json_err_on_stream()) + RYML_ERR_BASIC_("multiple docs"); + ++m_depth; + if(m_opts.indent_flow_ml()) ++m_ilevel; + write_('['); + newl_(); + } + ++pos; // advance past BSTR + while(pos < m_evts_size) + { + if(detail::hasall(m_evts[pos], ievt::BDOC)) + { + bool isflowml = false; + if(mldocs) + { + indent_(m_ilevel); + } + else + { + isflowml = pos + 1 < m_evts_size && (m_evts[pos+1] & (ievt::FMLX|ievt::BLCK)); + } + pos = json_visit_ml_(pos); + while(m_evts[pos] & (ievt::TAGH|ievt::TAGP)) + pos += ievt::nextstep(m_evts[pos]); // LCOV_EXCL_LINE + if(mldocs) + { + if(detail::hasall(m_evts[pos], ievt::BDOC)) + write_(','); + newl_(); + } + else + { + if(isflowml) + newl_(); + } + } + else if(detail::hasall(m_evts[pos], ievt::ESTR)) + { + break; + } + else + { + pos += ievt::nextstep(m_evts[pos]); // LCOV_EXCL_LINE + } + } + write_pws_and_pend_(PWS_NONE_); + if(mldocs) + { + if(m_opts.indent_flow_ml()) --m_ilevel; + --m_depth; + write_(']'); + newl_(); + } + return pos; +} + + +template +evt_size EmitterInts::json_visit_nested_(evt_size pos) +{ + // look for the first of BSEQ|BMAP|SCLR|ALIA + const detail::EmitKickoff ek = detail::kickoff_emit(m_evts, m_evts_size, pos, m_opts); + if(ek.emit_key) + { + if C4_LIKELY(m_evts[ek.keypos] & (ievt::SCLR|ievt::ALIA)) + { + pos = json_writek_(ek.keypos); + } + else + { + RYML_ERR_BASIC_("bad key"); + } + write_(": "); + } + while(pos < m_evts_size) + { + const evt_bits evt = m_evts[pos]; + if(detail::hasall(evt, ievt::BSEQ)) + { + write_('['); + pos = json_visit_container_(pos); + write_(']'); + if(evt & ievt::FMLX) + pend_newl_(); + break; + } + else if(detail::hasall(evt, ievt::BMAP)) + { + write_('{'); + pos = json_visit_container_(pos); + write_('}'); + if(evt & ievt::FMLX) + pend_newl_(); + break; + } + else if(evt & ievt::SCLR) + { + pos = json_writev_(pos, evt, /*has_anchor_or_tag*/false); + if(ek.emit_key) + pend_newl_(); + break; + } + else if(evt & ievt::ALIA) + { + if C4_UNLIKELY(m_opts.json_err_on_anchor()) + RYML_ERR_BASIC_("JSON does not have anchors"); + write_("\"*"); + write_(getstr_(pos)); + write_('"'); + if(ek.emit_key) + pend_newl_(); + break; + } + else + { + pos += ievt::nextstep(evt); // LCOV_EXCL_LINE + } + } + if(ek.emit_key || (m_evts[ek.valpos] & (ievt::FMLX|ievt::BLCK))) + pend_newl_(); + return pos; +} + + +template +evt_size EmitterInts::json_visit_container_(evt_size pos) +{ + if(m_evts[pos] & (ievt::BLCK|ievt::FMLX)) + { + if(m_opts.indent_flow_ml()) ++m_ilevel; + pend_newl_(); + pos = json_visit_ml_(pos); + if(m_opts.indent_flow_ml()) --m_ilevel; + write_pws_and_pend_(PWS_NONE_); + } + else + { + pos = json_visit_sl_(pos); + } + return pos; +} + + +template +evt_size EmitterInts::json_visit_sl_(evt_size pos) +{ + if C4_UNLIKELY(m_depth++ > (evt_size)m_opts.max_depth()) + RYML_ERR_BASIC_("max depth exceeded"); + RYML_ASSERT_BASIC_(m_evts[pos] & ievt::BEG_); + const evt_bits term = ((m_evts[pos] & ~ievt::BEG_) | ievt::END_) & detail::mask_open_close; + const bool with_spc = (m_evts[pos] & ievt::FSPC) || m_opts.force_flow_spc(); + bool has_anchor_or_tag = false; + ++pos; + while(pos < m_evts_size) + { + evt_bits evt = m_evts[pos]; + if(evt & ievt::SCLR) + { + if(evt & ievt::KEY_) + { + pos = json_writek_(pos); + write_(": "); + } + else + { + RYML_ASSERT_BASIC_(evt & ievt::VAL_); + pos = json_writev_(pos, evt, has_anchor_or_tag); + goto next_entry; // NOLINT + } + } + else if(detail::hasall(evt, ievt::BSEQ)) + { + if C4_UNLIKELY(evt & ievt::KEY_) + RYML_ERR_BASIC_("JSON does not accept seq keys"); + write_('['); + pos = json_visit_sl_(pos); + write_(']'); + goto next_entry; // NOLINT + } + else if(detail::hasall(evt, ievt::BMAP)) + { + if C4_UNLIKELY(evt & ievt::KEY_) + RYML_ERR_BASIC_("JSON does not accept map keys"); + write_('{'); + pos = json_visit_sl_(pos); + write_('}'); + goto next_entry; // NOLINT + } + else if(evt & ievt::ALIA) + { + if C4_UNLIKELY(m_opts.json_err_on_anchor()) + RYML_ERR_BASIC_("JSON does not have anchors"); + write_("\"*"); + write_(getstr_(pos)); + write_('"'); + pos += 3; + if(evt & ievt::KEY_) + write_(": "); + else + goto next_entry; // NOLINT + } + else if(evt & (ievt::ANCH|ievt::TAG_)) + { + if C4_UNLIKELY((evt & ievt::ANCH) && m_opts.json_err_on_anchor()) + RYML_ERR_BASIC_("JSON does not have anchors"); + if C4_UNLIKELY((evt & ievt::TAG_) && m_opts.json_err_on_tag()) + RYML_ERR_BASIC_("JSON does not have tags"); + has_anchor_or_tag = true; + pos += 3; + } + else if(detail::hasall(evt, term)) + { + ++pos; + break; + } + else + { + pos += ievt::nextstep(evt); // LCOV_EXCL_LINE + } + continue; + next_entry: + RYML_ASSERT_BASIC_(pos < m_evts_size); + if(!detail::hasall(m_evts[pos], term)) // pos changed - don't use evt here + { + if(with_spc) + write_(", "); + else + write_(','); + has_anchor_or_tag = false; + } + else + { + ++pos; + break; + } + } + --m_depth; + return pos; +} + + +template +evt_size EmitterInts::json_visit_ml_(evt_size pos) +{ + if C4_UNLIKELY(m_depth++ > (evt_size)m_opts.max_depth()) + RYML_ERR_BASIC_("max depth exceeded"); + RYML_ASSERT_BASIC_(m_evts[pos] & ievt::BEG_); + const evt_bits open = m_evts[pos]; + const evt_bits close = ((open & ~ievt::BEG_) | ievt::END_) & detail::mask_open_close; + bool has_anchor_or_tag = false; + ++pos; + while(pos < m_evts_size) + { + evt_bits evt = m_evts[pos]; + if(evt & ievt::SCLR) + { + write_pws_and_pend_(PWS_NONE_); + if(evt & ievt::KEY_) + { + pos = json_writek_(pos); + write_(": "); + } + else + { + RYML_ASSERT_BASIC_(evt & ievt::VAL_); + pos = json_writev_(pos, evt, has_anchor_or_tag); + goto next_entry; // NOLINT + } + } + else if(detail::hasall(evt, ievt::BSEQ)) + { + if C4_UNLIKELY(evt & ievt::KEY_) + RYML_ERR_BASIC_("JSON does not accept seq keys"); + write_pws_and_pend_(PWS_NONE_); + write_('['); + pos = json_visit_container_(pos); + write_(']'); + goto next_entry; // NOLINT + } + else if(detail::hasall(evt, ievt::BMAP)) + { + if C4_UNLIKELY(evt & ievt::KEY_) + RYML_ERR_BASIC_("JSON does not accept map keys"); + write_pws_and_pend_(PWS_NONE_); + write_('{'); + pos = json_visit_container_(pos); + write_('}'); + goto next_entry; // NOLINT + } + else if(evt & ievt::ALIA) + { + if C4_UNLIKELY(m_opts.json_err_on_anchor()) + RYML_ERR_BASIC_("JSON does not have anchors"); + write_pws_and_pend_(PWS_NONE_); + write_("\"*"); + write_(getstr_(pos)); + write_('"'); + pos += 3; + if(evt & ievt::KEY_) + write_(": "); + else + goto next_entry; // NOLINT + } + else if(evt & (ievt::ANCH|ievt::TAG_)) + { + if C4_UNLIKELY((evt & ievt::ANCH) && m_opts.json_err_on_anchor()) + RYML_ERR_BASIC_("JSON does not have anchors"); + if C4_UNLIKELY((evt & ievt::TAG_) && m_opts.json_err_on_tag()) + RYML_ERR_BASIC_("JSON does not have tags"); + write_pws_and_pend_(PWS_NONE_); + has_anchor_or_tag = true; + pos += 3; + } + else if(detail::hasall(evt, close)) + { + ++pos; + break; + } + else + { + pos += ievt::nextstep(evt); // LCOV_EXCL_LINE + } + continue; + next_entry: + RYML_ASSERT_BASIC_(pos < m_evts_size); + if(!detail::hasall(m_evts[pos], close)) // pos changed -- don't use evt here + { + has_anchor_or_tag = false; + write_(','); + bool at_end = (m_col+1 >= m_opts.max_cols()); + if((open & ievt::FMLN) && !at_end) + { + if((open & ievt::FSPC) || m_opts.force_flow_spc()) + write_(' '); + } + else if((open & (ievt::FML1|ievt::BLCK)) || at_end) + { + pend_newl_(); + } + } + else + { + ++pos; // advance past the close event + if(open & (ievt::FMLX|ievt::BLCK)) + pend_newl_(); + break; + } + } + --m_depth; + return pos; +} + + +template +evt_size EmitterInts::json_writek_(evt_size pos) +{ + csubstr key = getstr_(pos); + if(key.len) + { + if(yml::detail::emit_json_maybe_write_naninf_(this, key)) + ; + else + yml::detail::emit_json_write_scalar_dquo_(this, key); + } + else + { + write_("\"\""); + } + return pos + 3; +} + + +template +evt_size EmitterInts::json_writev_(evt_size pos, evt_bits ty, bool has_anchor_or_tag) +{ + csubstr val = getstr_(pos); + if(val.len) + { + // use double quoted style if the style is marked quoted + bool dquoted = ((ty & detail::styles_ievt_quot) + || (detail::scalar_style_choose_json_ievt(val) & ievt::DQUO)); // choose the style + if(dquoted) + yml::detail::emit_json_write_scalar_dquo_(this, val); + else if(yml::detail::emit_json_maybe_write_naninf_(this, val)) + ; + else if(val.is_number()) + yml::detail::emit_json_write_number_(this, val); + else + write_(val); + } + else + { + if(val.str || (ty & detail::styles_ievt_quot) || has_anchor_or_tag) + write_("\"\""); + else + write_("null"); + } + return pos + 3; +} + + +/** @endcond */ + +} // namespace ievt +} // namespace extra +} // namespace yml +} // namespace c4 + +// NOLINTEND(hicpp-signed-bitwise,*avoid-c-style-cast) +C4_SUPPRESS_WARNING_POP + +#endif /* C4_YML_EXTRA_EMITTER_INTS_DEF_HPP_ */ diff --git a/src_extra/c4/yml/extra/emitter_ints.hpp b/src_extra/c4/yml/extra/emitter_ints.hpp new file mode 100644 index 000000000..ffc845aa8 --- /dev/null +++ b/src_extra/c4/yml/extra/emitter_ints.hpp @@ -0,0 +1,251 @@ +#ifndef C4_YML_EXTRA_EMITTER_INTS_HPP_ +#define C4_YML_EXTRA_EMITTER_INTS_HPP_ + +/** @file emitter_ints.hpp */ + +#ifndef C4_YML_EMIT_OPTIONS_HPP_ +#include "c4/yml/emit_options.hpp" +#endif +#ifndef C4_YML_EXTRA_EVENT_INTS_HPP_ +#include "c4/yml/extra/event_ints.hpp" +#endif + + +namespace c4 { +namespace yml { +namespace extra { +namespace ievt { + +/** A YAML/JSON emitter, templated on a writer class such as @ref WriterBuf, + * @ref WriterFile, or @ref WriterOStream + * @ingroup doc_emit + */ +template +class EmitterInts : public Writer +{ +public: + + /** Construct the emitter and its internal Writer state. + * + * @param opts @ref EmitOptions + * @param args arguments to be forwarded to the constructor of the writer. + */ + template + EmitterInts(EmitOptions const& opts, WriterArgs &&...args) noexcept + : Writer(std::forward(args)...) + , m_evts() + , m_evts_size() + , m_src() + , m_arena() + , m_opts(opts) + , m_col() + , m_depth() + , m_ilevel() + , m_pws() + , m_flow_pws() + {} + +public: + + void emit_as(EmitType_e type, + evt_bits const* evts, + evt_size evts_size, + csubstr src, + csubstr arena) + { + emit_as(type, evts, evts_size, 0, src, arena); + } + void emit_as(EmitType_e type, + evt_bits const* evts, + evt_size evts_size, + evt_size pos, + csubstr src, + csubstr arena); + +public: + + /** get the emit options for this object */ + EmitOptions const& options() const noexcept { return m_opts; } + +private: // pending whitespace + + /// pending whitespace + typedef enum : uint32_t { PWS_NONE_ = 0u, PWS_SPACE_ = 1u, PWS_NEWL_ = 2u } Pws_e; // NOLINT + + /// set pending whitespace, ignoring pending + C4_ALWAYS_INLINE void pend_none_() noexcept // LCOV_EXCL_LINE + { + m_pws = PWS_NONE_; + } + /// set pending whitespace, ignoring pending + C4_ALWAYS_INLINE void pend_newl_() noexcept // LCOV_EXCL_LINE + { + m_pws = PWS_NEWL_; + } + /// set pending whitespace, ignoring pending + C4_ALWAYS_INLINE void pend_space_() noexcept // LCOV_EXCL_LINE + { + m_pws = PWS_SPACE_; + } + /// write pending whitespace, and then set the next pending whitespace + C4_ALWAYS_INLINE void write_pws_and_pend_(Pws_e next=PWS_NONE_) noexcept // LCOV_EXCL_LINE + { + if(m_pws == PWS_SPACE_) + { + write_(' '); + } + else if(m_pws == PWS_NEWL_) + { + newl_(); + indent_(m_ilevel); + } + m_pws = next; + } + + /// specs for obtaining pending whitespace in flow mode + struct flow_pws + { + size_t max_cols = 0; // leave this member first to avoid padding + Pws_e pend_after_comma = PWS_NONE_; + bool active = false; + C4_ALWAYS_INLINE Pws_e next_pws(size_t col) const noexcept // LCOV_EXCL_LINE + { + return (active && col >= max_cols) ? PWS_NEWL_ : pend_after_comma; + } + void start(evt_bits ty, size_t max_cols_) noexcept; + void stop() noexcept { active = false; } + }; + + C4_NODISCARD bool maybe_start_flow_pws_ml_(evt_size node) noexcept; + C4_NODISCARD flow_pws setup_flow_pws_sl_(evt_size node) noexcept; + +private: + + void emit_yaml_(evt_size pos); + + + C4_NODISCARD evt_size visit_stream_(evt_size pos); + C4_NODISCARD evt_size visit_doc_(evt_size pos, bool expl); + C4_NODISCARD evt_size visit_doc_val_(evt_size pos); + C4_NODISCARD evt_size visit_blck_container_(evt_size pos); + C4_NODISCARD evt_size visit_flow_container_(evt_size pos); + + C4_NODISCARD evt_size visit_flow_sl_(evt_size pos); + C4_NODISCARD evt_size visit_flow_sl_seq_(evt_size pos); + C4_NODISCARD evt_size visit_flow_sl_map_(evt_size pos); + + C4_NODISCARD evt_size visit_flow_ml_(evt_size pos); + C4_NODISCARD evt_size visit_flow_ml_seq_(evt_size pos); + C4_NODISCARD evt_size visit_flow_ml_map_(evt_size pos); + + C4_NODISCARD evt_size visit_blck_(evt_size pos); + C4_NODISCARD evt_size visit_blck_seq_(evt_size pos); + C4_NODISCARD evt_size visit_blck_map_(evt_size pos); + + C4_NODISCARD evt_size kickoff_key(evt_size pos, evt_size keypos); + C4_NODISCARD evt_size write_tag_or_anchor(evt_size pos, evt_size dst); + + void blck_write_scalar_(csubstr str, evt_bits type); + + void flow_close_entry_sl_(evt_size pos, Pws_e pend_after); + void flow_close_entry_ml_(evt_size pos, Pws_e pend_after); + void flow_write_scalar_(csubstr str, evt_bits type); + +private: + + void emit_json_(evt_size pos); + + C4_NODISCARD evt_size json_visit_stream_(evt_size pos); + C4_NODISCARD evt_size json_visit_nested_(evt_size pos); + C4_NODISCARD evt_size json_visit_container_(evt_size pos); + C4_NODISCARD evt_size json_visit_ml_(evt_size pos); + C4_NODISCARD evt_size json_visit_sl_(evt_size pos); + C4_NODISCARD evt_size json_writek_(evt_size pos); + C4_NODISCARD evt_size json_writev_(evt_size pos, evt_bits ty, bool has_anchor_or_tag); + +private: + + void write_tag_(csubstr tag) + { + if(!tag.begins_with('!')) + write_('!'); + write_(tag); + } + void write_ref_(csubstr ref) + { + if(ref != "<<") + { + if(!ref.begins_with('*')) + write_('*'); + write_(ref); + } + } + + C4_ALWAYS_INLINE csubstr getstr_(evt_size id) noexcept + { + RYML_ASSERT_BASIC_(id + 2 < m_evts_size); + RYML_ASSERT_BASIC_(m_evts[id] & ievt::WSTR); + csubstr region = (m_evts[id] & ievt::AREN) ? m_arena : m_src; + region.str = region.str + m_evts[id + 1]; + region.len = static_cast(m_evts[id + 2]); + return region; + } + +public: + + using indent_type = evt_size; + + template + C4_ALWAYS_INLINE void write_(const char (&a)[N]) // LCOV_EXCL_LINE + { + this->Writer::append(std::forward(a)); + m_col += N-1; + } + C4_ALWAYS_INLINE void write_(csubstr s) // LCOV_EXCL_LINE + { + this->Writer::append(s); + m_col += s.len; + } + C4_ALWAYS_INLINE void write_(char c) // LCOV_EXCL_LINE + { + this->Writer::append(c); + ++m_col; + } + + C4_ALWAYS_INLINE void indent_(indent_type level) // LCOV_EXCL_LINE + { + C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wsign-conversion") + size_t num = static_cast(2u * level); + this->Writer::append(' ', num); + m_col += num; + C4_SUPPRESS_WARNING_GCC_CLANG_POP + } + + /// write a newline and reset the column + C4_ALWAYS_INLINE void newl_() // LCOV_EXCL_LINE + { + this->Writer::append('\n'); + m_col = 0; + } + +private: + + evt_bits const* m_evts; + evt_size m_evts_size; + csubstr m_src; + csubstr m_arena; + EmitOptions m_opts; + size_t m_col; + evt_size m_depth; + evt_size m_ilevel; + Pws_e m_pws; + flow_pws m_flow_pws; + +}; + +} // namespace ievt +} // namespace extra +} // namespace yml +} // namespace c4 + +#endif /* C4_YML_EXTRA_EMITTER_INTS_HPP_ */ diff --git a/src_extra/c4/yml/extra/event_handler_ints.cpp b/src_extra/c4/yml/extra/event_handler_ints.cpp deleted file mode 100644 index 858835e23..000000000 --- a/src_extra/c4/yml/extra/event_handler_ints.cpp +++ /dev/null @@ -1,103 +0,0 @@ -#ifdef RYML_SINGLE_HEADER_INTS - #ifndef _RYML_SINGLE_HEADER_AMALGAMATED_HPP_ - #include - #endif -#elif defined(RYML_SINGLE_HEADER) - #ifndef _RYML_SINGLE_HEADER_AMALGAMATED_HPP_ - #include - #endif -#else -#include -#endif - -#ifndef C4_YML_EXTRA_EVENT_HANDLER_INTS_HPP_ -#include "c4/yml/extra/event_handler_ints.hpp" -#endif - -namespace c4 { -namespace yml { - -// instantiate the template -template class RYML_EXPORT ParseEngine; - -namespace extra { - -RYML_EXPORT evt_size estimate_events_ints_size(csubstr src) -{ - evt_size count = 7; // BSTR + BDOC + =VAL + EDOC + ESTR - for(size_t i = 0; i < src.len; ++i) - { - switch(src.str[i]) - { - case ':': // this has strings preceding/following it - case ',': // overestimate, assume map - case '%': // assume TAGD->string + TAGV->string - count += 6; - break; - // these have (or are likely to have) a string following it - case '-': - case '&': - case '*': - case '<': - case '!': - case '\'': - case '"': - case '|': - case '>': - case '\n': - count += 3; - break; - case '[': - case ']': - count += 4; - break; - case '{': - case '}': - count += 7; - break; - case '?': - count += 5; - break; - } - } - return count; -} - -// NOLINTBEGIN(hicpp-signed-bitwise) -// ensure the ievt flags work despite being signed -static_assert((ievt::MASK & ievt::BSTR) == ievt::BSTR, "overflow?"); -static_assert((ievt::MASK & ievt::ESTR) == ievt::ESTR, "overflow?"); -static_assert((ievt::MASK & ievt::BDOC) == ievt::BDOC, "overflow?"); -static_assert((ievt::MASK & ievt::EDOC) == ievt::EDOC, "overflow?"); -static_assert((ievt::MASK & ievt::BMAP) == ievt::BMAP, "overflow?"); -static_assert((ievt::MASK & ievt::EMAP) == ievt::EMAP, "overflow?"); -static_assert((ievt::MASK & ievt::BSEQ) == ievt::BSEQ, "overflow?"); -static_assert((ievt::MASK & ievt::ESEQ) == ievt::ESEQ, "overflow?"); -static_assert((ievt::MASK & ievt::ANCH) == ievt::ANCH, "overflow?"); -static_assert((ievt::MASK & ievt::ALIA) == ievt::ALIA, "overflow?"); -static_assert((ievt::MASK & ievt::TAG_) == ievt::TAG_, "overflow?"); -static_assert((ievt::MASK & ievt::PLAI) == ievt::PLAI, "overflow?"); -static_assert((ievt::MASK & ievt::SQUO) == ievt::SQUO, "overflow?"); -static_assert((ievt::MASK & ievt::DQUO) == ievt::DQUO, "overflow?"); -static_assert((ievt::MASK & ievt::LITL) == ievt::LITL, "overflow?"); -static_assert((ievt::MASK & ievt::FOLD) == ievt::FOLD, "overflow?"); -static_assert((ievt::MASK & ievt::FLOW) == ievt::FLOW, "overflow?"); -static_assert((ievt::MASK & ievt::BLCK) == ievt::BLCK, "overflow?"); -static_assert((ievt::MASK & ievt::KEY_) == ievt::KEY_, "overflow?"); -static_assert((ievt::MASK & ievt::VAL_) == ievt::VAL_, "overflow?"); -static_assert((ievt::MASK & ievt::EXPL) == ievt::EXPL, "overflow?"); -static_assert((ievt::MASK & ievt::YAML) == ievt::YAML, "overflow?"); -static_assert((ievt::MASK & ievt::TAGH) == ievt::TAGH, "overflow?"); -static_assert((ievt::MASK & ievt::TAGP) == ievt::TAGP, "overflow?"); -static_assert((ievt::MASK & ievt::AREN) == ievt::AREN, "overflow?"); -static_assert((ievt::MASK & ievt::PSTR) == ievt::PSTR, "overflow?"); -static_assert((ievt::MASK & ievt::WSTR) == ievt::WSTR, "overflow?"); -static_assert((ievt::MASK & ievt::LAST) == ievt::LAST, "overflow?"); -static_assert((ievt::MASK & ievt::JUMP) == ievt::JUMP, "overflow?"); -static_assert((ievt::MASK & ievt::PJUMP) == ievt::PJUMP, "overflow?"); -static_assert((ievt::MASK & ievt::UNFILT) == ievt::UNFILT, "overflow?"); -// NOLINTEND(hicpp-signed-bitwise) - -} // namespace extra -} // namespace yml -} // namespace c4 diff --git a/src_extra/c4/yml/extra/event_handler_ints.hpp b/src_extra/c4/yml/extra/event_handler_ints.hpp index a62cf65d6..c7995349f 100644 --- a/src_extra/c4/yml/extra/event_handler_ints.hpp +++ b/src_extra/c4/yml/extra/event_handler_ints.hpp @@ -16,348 +16,73 @@ #ifndef C4_YML_DETAIL_DBGPRINT_HPP_ #include #endif +#ifndef C4_YML_EXTRA_EVENT_INTS_HPP_ +#include "c4/yml/extra/event_ints.hpp" +#endif #endif // NOLINTBEGIN(hicpp-signed-bitwise,*avoid-c-style-cast) - -namespace c4 { -namespace yml { -namespace extra { - -/** @addtogroup doc_event_handlers_ints - * - * An event handler used by @ref ParseEngine to creates an integer - * buffer with a very compact representation of the YAML tree in a - * source buffer. This feature is an extra and is not part of the main - * rapidyaml library. - * - * This is meant for use by other programming languages, and supports - * container keys (unlike the ryml tree). It parses faster than the ryml - * tree parser, because the resulting data structure is much simpler. - * - * The resulting integer buffer is a linear array of integers - * containing encoded YAML events (as a mask of @ref ievt::EventBits), - * which in some cases (eg scalars) are followed by an encoded string - * (encoded as an offset and length to the parsed source buffer). - * - * For example, parsing `[a, bb, ccc]` results in the following event - * buffer (grouped to highlight the event sequence structure): - * - * ```c++ - * using namespace c4::yml::extra::ievt; - * const evt_bits arr[] = { // result of parsing: [a, bb, ccc] - * BSTR, // begin stream - * BDOC, // begin doc - * VAL_|BSEQ|FLOW, // begin seq as val, flow - * VAL_|SCLR|PLAI, 1, 1, // val scalar, plain style, "a" : string starts at offset 1 and has length 1 - * VAL_|SCLR|PLAI|PSTR, 4, 2, // val scalar, plain style, "bb" : string starts at offset 4 and has length 2; preceded by a string event (PSTR) - * VAL_|SCLR|PLAI|PSTR, 8, 3, // val scalar, plain style, "ccc": string starts at offset 8 and has length 3; preceded by a string event (PSTR) - * ESEQ|PSTR, // end seq; preceded by a string event (PSTR) - * EDOC, // end doc - * ESTR, // end stream - * }; - * ``` - * - * Here is a sketch clarifying the meaning of this event sequence: - * -@code -source : [a, bb, ccc] - has a string........ - | offset "a" - | | length "a" - | | | - event0 event1 event2 [ event3 "a"......|..| - | | | | | | -(start) +--------+-------+------------------+---------------+--+-----> (continued) -arr[i] : BSTR BDOC VAL_|BSEQ|FLOW VAL_|SCLR|PLAI..1..1 -i : 0 1 2 3 4 5 - - - has a string............. has a string............. - | offset "bb" | offset "ccc" - | | length "bb" | | length "ccc" - | | | | | | - event4 "bb"..........|..| event5 "ccc".........|..| - | | | | | | - (cont)--> -----+--------------------+--+--------------+--------------------+--+-----> (continued) -arr[i] : VAL_|SCLR|PLAI|PSTR..4..2 VAL_|SCLR|PLAI|PSTR..8..3 -i : 6 | 7 8 9 | 10 11 - | | - prev event has string prev event has string - (to get to prev, jump (to get to prev, jump - back 3 slots: ie 6->3) back 3 slots: ie 9->6) - - - - event6 ] event7 event8 - | | | - (cont)--> -----+-------------+--------+-----| (end) -arr[i] : ESEQ|PSTR EDOC ESTR -i : 12 | 13 14 - | - prev event has string - (to get to it, jump - back 3 slots: ie 12->9) -@endcode - * - * Note that the buffer contains both events and strings encoded as - * integer pairs. That is, events that have an associated string are - * immediately followed by two integers providing the offset and length - * of that string in the source buffer. (In the example above, this - * happens in the events for the strings `a`, `bb`, and `ccc` at - * positions 3, 6 and 9, respectively). - * - * The flag @ref ievt::PSTR and the mask @ref ievt::WSTR are provided to - * enable easier iteration over the array: you can use them to test for - * presence of a string when iterating over the array. - * - * The flag @ref ievt::PSTR announces that an event is *preceded* by a - * string. That is, the previous event has a string, so that when this - * flag is found while iterating right-to-left, a jump of -3 should be - * used to get at the bitmask of the previous event. (In the example - * above, this flag is present for the events for `bb` and `ccc`, but not - * `a` because it is not preceded by a string). - * - * Likewise, to signify that the current event is *followed* by a string, - * there is the mask @ref ievt::WSTR, which is a mask of all the flags of - * events that have a string: @ref ievt::SCLR, @ref ievt::ALIA, @ref - * ievt::ANCH and @ref ievt::TAG_. While iterating left-to-right in the - * array, presence of any of the bits in the mask @ref ievt::WSTR means - * that a jump of +3 should be employed to get at the bitmask of the next - * event. - * - * Here's another example with the result of parsing `a: bb` - * ```c++ - * const evt_bits arr[] = { // result of parsing: `a: bb` - * BSTR, // begin stream - * BDOC, // begin doc - * VAL_|BMAP|BLCK, // begin map as val, block - * KEY_|SCLR|PLAI, 0, 1, // key scalar, plain style: "a" starts at offset 0 and has length 1 - * VAL_|SCLR|PLAI|PSTR, 3, 2, // val scalar, plain style: "bb" starts at offset 3 and has length 2 - * EMAP|PSTR, // end map - * EDOC, // end doc - * ESTR, // end stream - * }; - * ``` - * - * Typical code to iterate left-to-right over the array will look like - * this: - * - * ```c++ - * // source buffer, modified in place during parsing (IMPORTANT!) - * substr src = ...; - * substr arena = ...; // arena used for scalars/tags that are extended during filtering - * // events resulting from parsing - * const int events[] = {...}; - * int events_size = ...; - * for(int i = 0; i < events_size; ++i) - * { - * if(events[i] & ievt::WSTR) // this event has a string following it - * { - * size_t offset = (size_t)events[i+1]; - * size_t length = (size_t)events[i+2]; - * csubstr region = (events[i] & ievt::AREN) ? arena : src; // is the string in the arena? - * csubstr str = region.sub(offset, length); // get the string - * ... - * i += 2; // skip the two ints of the string - * // (the jump is three places; the loop adds the other place) - * } - * else // this is a single-int event - * { - * ... - * } - * } - * ``` - * - * @{ */ - -/** data type for integer events size. This is set to an int32_t integer - * to allow compatibility with a wide range of processing languages. */ -using evt_size = int32_t; - -namespace ievt { - - -/** data type for integer events bits. This is set to an int32_t integer - * to allow compatibility with a wide range of processing languages. */ -using evt_bits = int32_t; - - -/** enumeration of integer event bits. */ -typedef enum : evt_bits { // NOLINT - - //------------------------------------------------------------------------- - // YAML flags - - // YAML structure flags - KEY_ = (1 << 0), ///< as key - VAL_ = (1 << 1), ///< as value - - // YAML event scopes - BEG_ = (1 << 2), ///< scope: begin - END_ = (1 << 3), ///< scope: end - SEQ_ = (1 << 4), ///< scope: seq - MAP_ = (1 << 5), ///< scope: map - DOC_ = (1 << 6), ///< scope: doc - EXPL = (1 << 7), ///< `---` (with BDOC) or `...` (with EDOC) - STRM = (1 << 8), ///< scope: stream - BSEQ = BEG_|SEQ_, ///< begin seq (+SEQ in test suite events) - ESEQ = END_|SEQ_, ///< end seq (-SEQ in test suite events) - BMAP = BEG_|MAP_, ///< begin map (+MAP in test suite events) - EMAP = END_|MAP_, ///< end map (-MAP in test suite events) - BSTR = BEG_|STRM, ///< begin stream (+STR in test suite events) - ESTR = END_|STRM, ///< end stream (-STR in test suite events) - BDOC = BEG_|DOC_, ///< begin doc (+DOC in test suite events) - EDOC = END_|DOC_, ///< end doc (-DOC in test suite events) - - // YAML string events - SCLR = (1 << 9), ///< scalar (=VAL in test suite events) - ALIA = (1 << 10), ///< *ref (reference) - ANCH = (1 << 11), ///< &anchor - TAG_ = (1 << 12), ///< !tag - // directives - YAML = (1 << 13), ///< yaml directive: `\%YAML ` - TAGH = (1 << 14), ///< tag directive, handle: `\%TAG ........` - TAGP = (1 << 15), ///< tag directive, prefix: `\%TAG ........ ` - - // YAML style flags - PLAI = (1 << 16), ///< scalar: plain - SQUO = (1 << 17), ///< scalar: single-quoted (') - DQUO = (1 << 18), ///< scalar: double-quoted ("") - LITL = (1 << 19), ///< scalar: block literal (|) - FOLD = (1 << 20), ///< scalar: block folded (>) - FLOW = (1 << 21), ///< container: flow: [] for seqs or {} for maps - BLCK = (1 << 22), ///< container: block - - /// Special flag to mark a scalar as unfiltered (when the parser - /// is set not to filter). - UNFILT = (1 << 23), - - //------------------------------------------------------------------------- - // NON-YAML FLAGS - - /// Special flag to mark events whose string was placed in the - /// arena. This happens when the filtered string is larger than - /// the original string in the YAML code (eg from tags that - /// resolve to a larger string, or from "\L" or "\P" in double - /// quotes, which expand from two to three bytes). Because of this - /// size expansion, the filtered string cannot be placed in the - /// original source and needs to be placed in the arena. - AREN = (1 << 24), - - /// WithSTRing: mask of all events that encode a string following - /// the event. For such events, the next two integers will provide - /// respectively the string's offset and length. See also @ref PSTR - WSTR = SCLR|ALIA|ANCH|TAG_|TAGH|TAGP|YAML, - - /// Special flag to enable look-back in the event array. It - /// signifies that the previous event has a string, meaning that - /// the jump back to that event is 3 positions. without this flag it - /// would be impossible to jump to the previous event. - /// see also @ref WSTR - PSTR = (1 << 25), - - /// unused: reserved for future use (to enable rope-like buffers) - JUMP = (1 << 26), - /// unused: reserved for future use (same purpose as @ref PSTR, - /// but for @ref JUMP) - PJUMP = (1 << 27), - - /// the last flag defined above - LAST = PJUMP, - - /// a mask of all bits in this enumeration - MASK = (LAST << 1) - 1, - -} EventBits; - -/** @cond dev */ -using DataType RYML_DEPRECATED("use evt_bits") = evt_bits; -using EventFlags RYML_DEPRECATED("use EventBits") = EventBits; -/** @endcond */ - -} // namespace ievt - -/** @} */ // doc_event_handlers_ints - -} // namespace extra -} // namespace yml -} // namespace c4 - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -namespace c4 { -namespace yml { -namespace extra { - -/** @addtogroup doc_event_handlers_ints - * @{ */ - -/** Read YAML source and, without undergoing a full parse, estimate - * the size of the integer buffer required for @ref - * EventHandlerInts. This estimation is meant to exceed the actual - * number of required events. - * - * @note This function must overpredict. It does so for every case in - * the hundreds/thousands of extensive tests of rapidyaml -- both for - * the YAML test suite and the internal cases. If you find a case - * where that does not hold, it is a bug. Please report it at - * https://github.com/biojppm/rapidyaml/issues! */ -RYML_EXPORT evt_size estimate_events_ints_size(csubstr src); - -/** @} */ - -} // namespace extra -} // namespace yml -} // namespace c4 - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -C4_SUPPRESS_WARNING_GCC_CLANG_PUSH +C4_SUPPRESS_WARNING_PUSH C4_SUPPRESS_WARNING_GCC_CLANG("-Wold-style-cast") C4_SUPPRESS_WARNING_GCC("-Wuseless-cast") +C4_SUPPRESS_WARNING_MSVC(4127) // conditional expression is constant + namespace c4 { namespace yml { namespace extra { +namespace ievt { /** @addtogroup doc_event_handlers_ints * @{ */ + /** @cond dev */ struct EventHandlerIntsState : public c4::yml::ParserState { c4::yml::type_bits evt_type; int32_t evt_id; }; +template +struct EventHandlerInts; /** @endcond */ + /** A parser event handler that creates a compact representation of * the YAML tree in a contiguous buffer of integers. The integers are * @ref ievt::EventBits containing masks (to represent events), * interleaved with offset+length (to represent strings in the source - * buffer). + * buffer). For a description of the events, see @ref + * doc_event_handlers_ints * - * For a description of the events, see @ref doc_event_handlers_ints + * This handler must be initialized with the input source buffer, the + * output arena, and the output event buffer. + * + */ +using EventHandlerIntsResize = EventHandlerInts; + + + +/** A parser event handler that creates a compact representation of + * the YAML tree in a contiguous buffer of integers. The integers are + * @ref ievt::EventBits containing masks (to represent events), + * interleaved with offset+length (to represent strings in the source + * buffer). For a description of the events, see @ref doc_event_handlers_ints * * This handler must be initialized with the input source buffer, the - * output arena, and the output event buffer. This handler will not take + * output arena, and the output event buffer. + * + * Unlike @ref EventHandlerIntsResize This handler will not take * ownership nor attempt to resize the output buffer. If the size - * required for the output buffer or arena are larger than their actual - * size, parsing goes all way to the end, determining the required buffer - * sizes without writing anything past the end of the respective - * buffer. After parsing is finished, the user must ensure that the - * buffer size was enough to accomodate all the data that needs to be - * written into it, or react accordingly (eg, throw an error, or resize - * the buffer then retry the parse). + * required for the output buffer or arena are larger than their + * actual size, parsing goes all way to the end, determining the + * required buffer sizes without writing anything past the end of the + * respective buffer. After parsing is finished, the user must ensure + * that the buffer size was enough to accomodate all the data that + * needs to be written into it, or react accordingly (eg, throw an + * error, or resize the buffer then retry the parse). * * A couple of functions will be helpful to do this. After parsing, @ref * EventHandlerInts::fits_buffers() must be used to verify that the @@ -375,8 +100,8 @@ struct EventHandlerIntsState : public c4::yml::ParserState * // estimate the size required for the events buffer, * // overpredicting it to be safe. * int estimated_size = extra::estimate_events_ints_size(src); - * extra::EventHandlerInts handler; - * ParseEngine parser(&handler); + * extra::ievt::EventHandlerIntsNoResize handler; + * ParseEngine parser(&handler); * // example with a vector * std::vector evts; * // ensure we have a fighting chance to acommodate the events @@ -433,7 +158,7 @@ struct EventHandlerIntsState : public c4::yml::ParserState * std::string parsed_src = src; // this is where we will parse (filter during parsing) * std::vector evts((size_t)estimated_size); // ensure we have a fighting change to acommodate the events * std::vector arena(src.size()); // ensure we have a fighting change to acommodate the events - * ParseEngine parser(&handler); + * ParseEngine parser(&handler); * handler.reset(to_substr(parsed_src), to_substr(arena), evts.data(), (int)evts.size()); * parser.parse_in_place_ev(filename, to_substr(parsed_src)); * if(handler.fits_buffers()) // were the buffer sizes enough? @@ -457,25 +182,30 @@ struct EventHandlerIntsState : public c4::yml::ParserState * When bringing this to other programming languages, the semantics * will be very similar to this. */ -struct EventHandlerInts : public c4::yml::EventHandlerStack +using EventHandlerIntsNoResize = EventHandlerInts; + + +//----------------------------------------------------------------------------- + +template +struct EventHandlerInts : public c4::yml::EventHandlerStack, EventHandlerIntsState> { /** @name types * @{ */ using value_type = ievt::evt_bits; + using base_type = c4::yml::EventHandlerStack, EventHandlerIntsState>; using state = EventHandlerIntsState; // our internal state must inherit from parser state - enum { requires_strings_on_buffers = true }; // NOLINT + enum { requires_strings_on_buffers = true, resize_buffers = resize_buffers_ }; // NOLINT /** @} */ public: /** @cond dev */ - ievt::evt_bits * m_evt; - evt_size m_evt_pos; + evtbuf m_evt; evt_size m_evt_prev; - evt_size m_evt_size; substr m_arena; size_t m_arena_pos; id_type m_curr_doc; @@ -494,7 +224,7 @@ struct EventHandlerInts : public c4::yml::EventHandlerStack(m_evt.cap) * sizeof(m_evt.ptr[0]), base_type::m_stack.m_callbacks.m_user_data); + //if(base_type::m_src.str) + // base_type::m_stack.m_callbacks.m_free(base_type::m_src.str, base_type::m_src.len * sizeof(base_type::m_src.str[0]), base_type::m_stack.m_callbacks.m_user_data); + if(m_arena.str) + base_type::m_stack.m_callbacks.m_free(m_arena.str, m_arena.len * sizeof(m_arena.str[0]), base_type::m_stack.m_callbacks.m_user_data); + } + } + +public: - void reset(substr str, substr arena, ievt::evt_bits *dst, evt_size dst_size) + void reset(substr str, substr arena={}, evtbuf evt={}) { - _stack_reset_root(); - m_curr->flags |= c4::yml::RUNK|c4::yml::RTOP; - m_curr->evt_type = {}; - m_curr->evt_id = 0; + base_type::_stack_reset_root(); + base_type::m_curr->flags |= c4::yml::RUNK|c4::yml::RTOP; + base_type::m_curr->evt_type = {}; + base_type::m_curr->evt_id = 0; m_arena = arena; m_arena_pos = 0; - m_src = str; - m_evt = dst; - m_evt_size = dst_size; - m_evt_pos = 0; + base_type::m_src = str; + m_evt = evt; + m_evt.len = 0; m_evt_prev = 0; m_curr_doc = 0; m_tag_directives.clear(); m_tag_cache.clear(); } + void reset(substr str, substr arena, evt_bits *dst, evt_size dst_cap) + { + evtbuf evt; + evt.ptr = dst; + evt.len = 0; + evt.cap = dst_cap; + reset(str, arena, evt); + } + void reset(ievt::Buffers const& buf) + { + reset(buf.src, buf.arena, buf.evts); + } + +public: + + ievt::Buffers get_buffers() const noexcept + { + RYML_ASSERT_BASIC_CB_(base_type::m_stack.m_callbacks, m_arena_pos <= m_arena.len); + ievt::Buffers buf = {}; + buf.owned = false; + get_buffers(&buf.src, &buf.arena, &buf.evts); + return buf; + } + + void get_buffers(ievt::Buffers *buf, bool transfer_ownership) noexcept + { + RYML_ASSERT_BASIC_CB_(base_type::m_stack.m_callbacks, m_arena_pos <= m_arena.len); + get_buffers(&buf->src, &buf->arena, &buf->evts); + buf->callbacks = base_type::m_stack.m_callbacks; + buf->owned = transfer_ownership; + if C4_IF_CONSTEXPR (resize_buffers) + { + if(transfer_ownership) + { + base_type::m_src = {}; + m_arena = {}; + m_evt = {}; + } + } + } + + void get_buffers(substr *str, substr *arena, evtbuf *buf) const noexcept + { + if C4_IF_CONSTEXPR (resize_buffers) + { + RYML_ASSERT_BASIC_CB_(base_type::m_stack.m_callbacks, m_arena_pos <= m_arena.len); + RYML_ASSERT_BASIC_CB_(base_type::m_stack.m_callbacks, m_evt.len <= m_evt.cap); + } + *str = base_type::m_src; + *arena = m_arena; + *buf = m_evt; + } + +public: /** get the size needed for the event buffer from the previous parse * @warning this is valid only until the next parse */ evt_size required_size_events() const { - return m_evt_pos; + return m_evt.len; } /** get the size needed for the arena from the previous parse @@ -535,18 +332,27 @@ struct EventHandlerInts : public c4::yml::EventHandlerStack m_arena.len) + _grow_arena(size - m_arena.len); } - void reserve_arena(int /*arena_size*/) + void reserve_evts(evt_size size) { - // does not apply here + if C4_IF_CONSTEXPR (resize_buffers) + if(size > m_evt.cap) + _grow_evts(size); } C4_ALWAYS_INLINE TagDirectives &tag_directives() { return m_tag_directives; } @@ -561,8 +367,8 @@ struct EventHandlerInts : public c4::yml::EventHandlerStack_stack_start_parse(filename, src); } @@ -573,7 +379,7 @@ struct EventHandlerInts : public c4::yml::EventHandlerStack 1) + while(base_type::m_stack.size() > 1) _pop(); } @@ -604,9 +410,9 @@ struct EventHandlerInts : public c4::yml::EventHandlerStackevt_id); + if C4_IF_CONSTEXPR(resize_buffers) + { + RYML_ASSERT_BASIC_CB_(base_type::m_stack.m_callbacks, base_type::m_curr->evt_id < m_evt.cap); + RYML_ASSERT_BASIC_CB_(base_type::m_stack.m_callbacks, (m_evt.ptr[base_type::m_curr->evt_id] & ievt::BMAP) == ievt::BMAP); + m_evt.ptr[base_type::m_curr->evt_id] |= multiline_ ? translate_flowml_(multiline_style) : ievt::FSL_; + } + else + { + if(m_evt.len < m_evt.cap) + { + RYML_ASSERT_BASIC_CB_(base_type::m_stack.m_callbacks, (m_evt.ptr[base_type::m_curr->evt_id] & ievt::BMAP) == ievt::BMAP); + m_evt.ptr[base_type::m_curr->evt_id] |= multiline_ ? translate_flowml_(multiline_style) : ievt::FSL_; + } + } _send_flag_only_(ievt::EMAP); } @@ -710,7 +531,7 @@ struct EventHandlerInts : public c4::yml::EventHandlerStackevt_id); + if C4_IF_CONSTEXPR(resize_buffers) + { + RYML_ASSERT_BASIC_CB_(base_type::m_stack.m_callbacks, base_type::m_curr->evt_id < m_evt.cap); + RYML_ASSERT_BASIC_CB_(base_type::m_stack.m_callbacks, (m_evt.ptr[base_type::m_curr->evt_id] & ievt::BSEQ) == ievt::BSEQ); + m_evt.ptr[base_type::m_curr->evt_id] |= multiline_ ? translate_flowml_(multiline_style) : ievt::FSL_; + } + else + { + if(m_evt.len < m_evt.cap) + { + RYML_ASSERT_BASIC_CB_(base_type::m_stack.m_callbacks, (m_evt.ptr[base_type::m_curr->evt_id] & ievt::BSEQ) == ievt::BSEQ); + m_evt.ptr[base_type::m_curr->evt_id] |= multiline_ ? translate_flowml_(multiline_style) : ievt::FSL_; + } + } _send_flag_only_(ievt::ESEQ); } @@ -763,8 +599,8 @@ struct EventHandlerInts : public c4::yml::EventHandlerStackevt_type = {}; + RYML_ASSERT_BASIC_CB_(base_type::m_stack.m_callbacks, base_type::m_parent); + base_type::m_curr->evt_type = {}; } /** @} */ @@ -777,13 +613,13 @@ struct EventHandlerInts : public c4::yml::EventHandlerStack{}", i, m_evt_size, m_evt[(i)+1]); \ + m_evt.ptr[i] |= ievt::AREN; \ + m_evt.ptr[(i) + 1] = (evt_bits)((scalar).str - m_arena.str); \ + _c4dbgpf("{}/{}: arena! ->{}", i, m_evt.cap, m_evt.ptr[(i)+1]); \ } \ - m_evt[(i) + 2] = (ievt::evt_bits)(scalar).len; \ - m_evt[(i) + 3] = ievt::PSTR + m_evt.ptr[(i) + 2] = (evt_bits)(scalar).len; \ + m_evt.ptr[(i) + 3] = ievt::PSTR /** @endcond */ public: @@ -903,44 +750,44 @@ struct EventHandlerInts : public c4::yml::EventHandlerStackpos); - RYML_ASSERT_PARSE_CB_(m_stack.m_callbacks, !ryml_has_any_(KEYANCH), m_curr->pos); + _c4dbgpf("{}/{}: set_key_ref: {}", m_evt.len, m_evt.cap, ref); + RYML_ASSERT_PARSE_CB_(base_type::m_stack.m_callbacks, ref.begins_with('*'), base_type::m_curr->pos); + RYML_ASSERT_PARSE_CB_(base_type::m_stack.m_callbacks, !ryml_has_any_(KEYANCH), base_type::m_curr->pos); ryml_enable_(c4::yml::KEY|c4::yml::KEYREF); _send_str_(ref.sub(1), ievt::KEY_|ievt::ALIA); // skip the leading * } void set_val_ref(csubstr ref) { - _c4dbgpf("{}/{}: set_val_ref: {}", m_evt_pos, m_evt_size, ref); - RYML_ASSERT_PARSE_CB_(m_stack.m_callbacks, ref.begins_with('*'), m_curr->pos); - RYML_ASSERT_PARSE_CB_(m_stack.m_callbacks, !ryml_has_any_(VALANCH), m_curr->pos); + _c4dbgpf("{}/{}: set_val_ref: {}", m_evt.len, m_evt.cap, ref); + RYML_ASSERT_PARSE_CB_(base_type::m_stack.m_callbacks, ref.begins_with('*'), base_type::m_curr->pos); + RYML_ASSERT_PARSE_CB_(base_type::m_stack.m_callbacks, !ryml_has_any_(VALANCH), base_type::m_curr->pos); ryml_enable_(c4::yml::VAL|c4::yml::VALREF); _send_str_(ref.sub(1), ievt::VAL_|ievt::ALIA); // skip the leading * } @@ -954,15 +801,15 @@ struct EventHandlerInts : public c4::yml::EventHandlerStackpos, "too many %TAG directives"); + RYML_ERR_PARSE_CB_(base_type::m_stack.m_callbacks, base_type::m_curr->pos, "too many %TAG directives"); _send_str_(handle, ievt::TAGH); _send_str_(prefix, ievt::TAGP); } @@ -1003,90 +850,91 @@ struct EventHandlerInts : public c4::yml::EventHandlerStack 2); - RYML_ASSERT_BASIC_CB_(m_stack.m_callbacks, m_evt_prev > 0); - // BEFORE - // ... flag start len (free) - // | | - // prev curr - // AFTER - // ... BMAP flag start len (free) - // | | - // prev curr - if(m_evt_pos < m_evt_size) + _c4dbgpf("{}/{}: prev={} actually_val_is_first_key_of_new_map_flow", m_evt.len, m_evt.cap, m_evt_prev); + RYML_ASSERT_BASIC_CB_(base_type::m_stack.m_callbacks, m_evt.len > 2); + RYML_ASSERT_BASIC_CB_(base_type::m_stack.m_callbacks, m_evt_prev > 0); + RYML_ASSERT_BASIC_CB_(base_type::m_stack.m_callbacks, m_evt.len <= m_evt.cap || !resize_buffers); + evt_size pos = m_evt_prev; + if(resize_buffers || m_evt.len < m_evt.cap) { - if(m_evt[m_evt_prev] & ievt::WSTR) + // BEFORE + // ... flag offs len (free) + // | | + // prev curr + // AFTER + // ... BMAP flag offs len (free) + // | | + // prev curr + if(m_evt.ptr[m_evt_prev] & ievt::WSTR) { - _c4dbgpf("{}/{}: WSTR", m_evt_pos, m_evt_size); - RYML_ASSERT_BASIC_CB_(m_stack.m_callbacks, m_evt_prev > 0); - evt_size pos = _extend_left_to_include_tag_and_or_anchor(m_evt_prev); - if(m_evt_pos + 1 < m_evt_size) + _c4dbgpf("{}/{}: WSTR", m_evt.len, m_evt.cap); + RYML_ASSERT_BASIC_CB_(base_type::m_stack.m_callbacks, m_evt_prev > 0); + pos = _extend_left_to_include_tag_and_or_anchor(m_evt_prev); + if C4_IF_CONSTEXPR (resize_buffers) + { + if(m_evt.len + 1 >= m_evt.cap) + _grow_evts(); + } + if(resize_buffers || m_evt.len + 1 < m_evt.cap) { for(evt_size i = pos; i <= m_evt_prev; i = _next(i)) { - m_evt[i] |= ievt::KEY_; - m_evt[i] &= ~ievt::VAL_; + m_evt.ptr[i] |= ievt::KEY_; + m_evt.ptr[i] &= ~ievt::VAL_; } - evt_size num_move = m_evt_pos + 1 - pos; - RYML_ASSERT_BASIC_CB_(m_stack.m_callbacks, num_move > 0); - memmove(m_evt + pos + 1, m_evt + pos, (size_t)num_move * sizeof(ievt::evt_bits)); + evt_size num_move = m_evt.len + 1 - pos; + RYML_ASSERT_BASIC_CB_(base_type::m_stack.m_callbacks, num_move > 0); + memmove(m_evt.ptr + pos + 1, m_evt.ptr + pos, (size_t)num_move * sizeof(evt_bits)); } - m_evt[pos] = ievt::BMAP|ievt::FLOW|ievt::VAL_; + m_evt.ptr[pos] = ievt::BMAP|ievt::FLOW|ievt::VAL_; // move PSTR to prev - if(m_evt[pos + 1] & ievt::PSTR) + if(m_evt.ptr[pos + 1] & ievt::PSTR) { - m_evt[pos ] |= ievt::PSTR; - m_evt[pos + 1] &= ~ievt::PSTR; + m_evt.ptr[pos ] |= ievt::PSTR; + m_evt.ptr[pos + 1] &= ~ievt::PSTR; } } else { - _c4dbgpf("{}/{}: container key", m_evt_pos, m_evt_size); - RYML_ASSERT_BASIC_CB_(m_stack.m_callbacks, (m_evt[m_evt_prev] & (ievt::EMAP|ievt::ESEQ))); - evt_size pos; - _c4dbgpf("{}/{}: find matching open for {}", m_evt_pos, m_evt_size, m_evt_prev); - if((m_evt[m_evt_prev] & ievt::EMAP) == ievt::EMAP) - { - pos = _find_matching_open(ievt::BMAP, ievt::EMAP, m_evt_prev); - } - else - { - RYML_ASSERT_BASIC_CB_(m_stack.m_callbacks, (m_evt[m_evt_prev] & ievt::ESEQ)); - pos = _find_matching_open(ievt::BSEQ, ievt::ESEQ, m_evt_prev); - } - _c4dbgpf("{}/{}: matching open for {}={}", m_evt_pos, m_evt_size, m_evt_prev, pos); - RYML_CHECK_BASIC_CB_(m_stack.m_callbacks, pos >= 0); // internal error - RYML_CHECK_BASIC_CB_(m_stack.m_callbacks, pos < m_evt_prev); // internal error - RYML_ASSERT_BASIC_CB_(m_stack.m_callbacks, (m_evt[pos] & ievt::ESEQ) == (m_evt[m_evt_prev] & ievt::BSEQ)); - RYML_ASSERT_BASIC_CB_(m_stack.m_callbacks, (m_evt[pos] & ievt::EMAP) == (m_evt[m_evt_prev] & ievt::BMAP)); + _c4dbgpf("{}/{}: container key. prev={}", m_evt.len, m_evt.cap, m_evt_prev); + RYML_ASSERT_BASIC_CB_(base_type::m_stack.m_callbacks, (m_evt.ptr[m_evt_prev] & (ievt::EMAP|ievt::ESEQ))); + pos = detail::find_matching_open_(m_evt.ptr, m_evt_prev); + _c4dbgpf("{}/{}: matching open for {}={}", m_evt.len, m_evt.cap, m_evt_prev, pos); + RYML_ASSERT_BASIC_CB_(base_type::m_stack.m_callbacks, (m_evt.ptr[pos] & ievt::ESEQ) == (m_evt.ptr[m_evt_prev] & ievt::BSEQ)); + RYML_ASSERT_BASIC_CB_(base_type::m_stack.m_callbacks, (m_evt.ptr[pos] & ievt::EMAP) == (m_evt.ptr[m_evt_prev] & ievt::BMAP)); // shift the array one position to the right, starting at pos evt_size posp1 = pos + 1; - if(m_evt_pos + 1 < m_evt_size) + if C4_IF_CONSTEXPR (resize_buffers) + { + if(m_evt.len + 1 >= m_evt.cap) + _grow_evts(); + } + if(resize_buffers || m_evt.len + 1 < m_evt.cap) { - evt_size num_move = m_evt_pos + 1 - pos; - RYML_ASSERT_BASIC_CB_(m_stack.m_callbacks, num_move > 0); - memmove(m_evt + posp1, m_evt + pos, (size_t)num_move * sizeof(ievt::evt_bits)); + evt_size num_move = m_evt.len + 1 - pos; + RYML_ASSERT_BASIC_CB_(base_type::m_stack.m_callbacks, num_move > 0); + memmove(m_evt.ptr + posp1, m_evt.ptr + pos, (size_t)num_move * sizeof(evt_bits)); } - RYML_ASSERT_BASIC_CB_(m_stack.m_callbacks, posp1 < m_evt_pos); + RYML_ASSERT_BASIC_CB_(base_type::m_stack.m_callbacks, posp1 < m_evt.len); // start the map - m_evt[pos] = ievt::BMAP|ievt::FLOW|ievt::VAL_; + m_evt.ptr[pos] = ievt::BMAP|ievt::FLOW|ievt::VAL_; // set next as key, not val - m_evt[posp1] |= ievt::KEY_; - m_evt[posp1] &= ~ievt::VAL_; + m_evt.ptr[posp1] |= ievt::KEY_; + m_evt.ptr[posp1] &= ~ievt::VAL_; // move PSTR to pos - if(m_evt[posp1] & ievt::PSTR) + if(m_evt.ptr[posp1] & ievt::PSTR) { - m_evt[pos] |= ievt::PSTR; - m_evt[posp1] &= ~ievt::PSTR; + m_evt.ptr[pos] |= ievt::PSTR; + m_evt.ptr[posp1] &= ~ievt::PSTR; } } } - m_curr->evt_id = m_evt_pos - 2; + base_type::m_curr->evt_id = m_evt.len - 2; ++m_evt_prev; - ++m_evt_pos; + ++m_evt.len; ryml_enable_(c4::yml::MAP|c4::yml::FLOW_SL); _push(); + base_type::m_parent->evt_id = pos; } /** like its flow counterpart, but this function can only be @@ -1097,34 +945,34 @@ struct EventHandlerInts : public c4::yml::EventHandlerStack= 0) { - RYML_ASSERT_BASIC_CB_(m_stack.m_callbacks, pos < m_evt_size); - RYML_ASSERT_BASIC_CB_(m_stack.m_callbacks, pos < m_evt_pos); - RYML_ASSERT_BASIC_CB_(m_stack.m_callbacks, (m_evt[pos] & ievt::BDOC) == ievt::BDOC); - if(m_evt_pos < m_evt_size) - { - ++pos; // add 1 to write after BDOC - evt_size num_move = m_evt_pos - pos; - evt_size posp1 = pos + 1; - RYML_ASSERT_BASIC_CB_(m_stack.m_callbacks, ((m_evt[pos] & ievt::BSEQ) == ievt::BSEQ) || ((m_evt[pos] & ievt::BMAP) == ievt::BMAP)); - RYML_ASSERT_BASIC_CB_(m_stack.m_callbacks, num_move > 0); - RYML_ASSERT_BASIC_CB_(m_stack.m_callbacks, 0 == (m_evt[posp1] & ievt::PSTR)); - memmove(m_evt + posp1, m_evt + pos, (size_t)num_move * sizeof(ievt::evt_bits)); - m_evt[pos] = ievt::VAL_|ievt::BMAP|ievt::BLCK; - m_evt[posp1] &= ~ievt::VAL_; - m_evt[posp1] |= ievt::KEY_; - } + RYML_ASSERT_BASIC_CB_(base_type::m_stack.m_callbacks, pos < m_evt.cap); + RYML_ASSERT_BASIC_CB_(base_type::m_stack.m_callbacks, pos < m_evt.len); + RYML_ASSERT_BASIC_CB_(base_type::m_stack.m_callbacks, (m_evt.ptr[pos] & ievt::BDOC) == ievt::BDOC); + RYML_ASSERT_BASIC_CB_(base_type::m_stack.m_callbacks, m_evt.len < m_evt.cap); + ++pos; // add 1 to write after BDOC + evt_size num_move = m_evt.len - pos; + evt_size posp1 = pos + 1; + RYML_ASSERT_BASIC_CB_(base_type::m_stack.m_callbacks, posp1 < m_evt.cap); + RYML_ASSERT_BASIC_CB_(base_type::m_stack.m_callbacks, ((m_evt.ptr[pos] & ievt::BSEQ) == ievt::BSEQ) || ((m_evt.ptr[pos] & ievt::BMAP) == ievt::BMAP)); + RYML_ASSERT_BASIC_CB_(base_type::m_stack.m_callbacks, num_move > 0); + RYML_ASSERT_BASIC_CB_(base_type::m_stack.m_callbacks, 0 == (m_evt.ptr[posp1] & ievt::PSTR)); + memmove(m_evt.ptr + posp1, m_evt.ptr + pos, (size_t)num_move * sizeof(evt_bits)); + m_evt.ptr[pos] = ievt::VAL_|ievt::BMAP|ievt::BLCK; + m_evt.ptr[posp1] &= ~ievt::VAL_; + m_evt.ptr[posp1] |= ievt::KEY_; } } - ++m_curr->evt_id; + ++base_type::m_curr->evt_id; ++m_evt_prev; - ++m_evt_pos; + ++m_evt.len; _push(); } @@ -1148,9 +996,22 @@ struct EventHandlerInts : public c4::yml::EventHandlerStackevt_type = {}; + base_type::_stack_push(); + base_type::m_curr->evt_type = {}; } /** end the current scope */ void _pop() { - _stack_pop(); + base_type::_stack_pop(); } template C4_ALWAYS_INLINE void enable_() noexcept { - m_curr->evt_type |= bits; + base_type::m_curr->evt_type |= bits; } template C4_ALWAYS_INLINE void disable_() noexcept { - m_curr->evt_type &= ~bits; + base_type::m_curr->evt_type &= ~bits; } template C4_ALWAYS_INLINE bool has_any_() const noexcept { - return (m_curr->evt_type & bits) != c4::yml::type_bits(0); + return (base_type::m_curr->evt_type & bits) != c4::yml::type_bits(0); } C4_ALWAYS_INLINE evt_size _next(evt_size pos) const noexcept { - RYML_ASSERT_BASIC_CB_(m_stack.m_callbacks, pos < m_evt_size); - return pos + ((m_evt[pos] & ievt::WSTR) ? 3 : 1); + RYML_ASSERT_BASIC_CB_(base_type::m_stack.m_callbacks, pos < m_evt.cap); + return pos + ((m_evt.ptr[pos] & ievt::WSTR) ? 3 : 1); } C4_ALWAYS_INLINE evt_size _prev(evt_size pos) const noexcept { - RYML_ASSERT_BASIC_CB_(m_stack.m_callbacks, pos < m_evt_size); - return pos - ((m_evt[pos] & ievt::PSTR) ? 3 : 1); + RYML_ASSERT_BASIC_CB_(base_type::m_stack.m_callbacks, pos < m_evt.cap); + return pos - ((m_evt.ptr[pos] & ievt::PSTR) ? 3 : 1); } C4_ALWAYS_INLINE bool _is_sub_(csubstr str) const noexcept { - return (!str.str || str.is_sub(m_src) || str.is_sub(m_arena)); + return (!str.str || str.is_sub(base_type::m_src) || str.is_sub(m_arena)); + } + + void _grow_evts() + { + _grow_evts(2 * m_evt.cap); + } + void _grow_evts(evt_size next) + { + _grow_evts_exact(next > 256 ? next : 256); + } + C4_NO_INLINE void _grow_evts_exact(evt_size next) + { + _c4dbgpf("{}/{}: resize evts {}->{}", m_evt.len, m_evt.cap, m_evt.cap, next); + // the actual current len is len+1 (eg because of PSTR already + // being set on it). so temporarily bump the length to prevent + // that value from being zeroed. + evtbuf cp = m_evt; + bool tweak = (cp.len && cp.len < cp.cap); + if(tweak) + ++cp.len; + m_evt = c4::yml::detail::resize(cp, next, base_type::m_stack.m_callbacks); + // restore to the current len + if(tweak) + --m_evt.len; } - C4_ALWAYS_INLINE void _send_flag_only_(ievt::evt_bits flags) + C4_NO_INLINE void _grow_arena(size_t more) { - _c4dbgpf("{}/{}: flag only", m_evt_pos, m_evt_size); - if(m_evt_pos < m_evt_size) - m_evt[m_evt_pos] |= flags; - m_curr->evt_id = m_evt_pos; - m_evt_prev = m_evt_pos; - ++m_evt_pos; - if(m_evt_pos < m_evt_size) - m_evt[m_evt_pos] = {}; + size_t next = m_arena.len + more; + next = 2 * m_arena.len > next ? 2 * m_arena.len : next; + next = next > 256 ? next : 256; + _c4dbgpf("{}/{}: resize arena {}->{}", m_evt.len, m_evt.cap, m_arena.len, next); + m_arena = c4::yml::detail::resize(m_arena, next, base_type::m_stack.m_callbacks); } - C4_ALWAYS_INLINE void _send_str_(csubstr scalar, ievt::evt_bits flags) + C4_ALWAYS_INLINE void _send_flag_only_(evt_bits flags) { - _c4dbgpf("{}/{}: send str", m_evt_pos, m_evt_size); - if(m_evt_pos + 3 < m_evt_size) + _c4dbgpf("{}/{}: flag only", m_evt.len, m_evt.cap); + if C4_IF_CONSTEXPR (resize_buffers) + { + if C4_UNLIKELY(m_evt.len >= m_evt.cap) + _grow_evts(); + m_evt.ptr[m_evt.len] |= flags; + } + else { - m_evt[m_evt_pos] |= flags; - _add_scalar_(m_evt_pos, scalar); + if(m_evt.len < m_evt.cap) + m_evt.ptr[m_evt.len] |= flags; } - m_curr->evt_id = m_evt_pos; - m_evt_prev = m_evt_pos; - m_evt_pos += 3; + base_type::m_curr->evt_id = m_evt.len; + m_evt_prev = m_evt.len; + ++m_evt.len; + if(m_evt.len < m_evt.cap) + m_evt.ptr[m_evt.len] = {}; + } + + C4_ALWAYS_INLINE void _send_str_(csubstr scalar, evt_bits flags) + { + _c4dbgpf("{}/{}: send str", m_evt.len, m_evt.cap); + if C4_IF_CONSTEXPR (resize_buffers) + { + if C4_UNLIKELY(m_evt.len + 3 >= m_evt.cap) + _grow_evts(); + m_evt.ptr[m_evt.len] |= flags; + _add_scalar_(m_evt.len, scalar); + } + else + { + if(m_evt.len + 3 < m_evt.cap) + { + m_evt.ptr[m_evt.len] |= flags; + _add_scalar_(m_evt.len, scalar); + } + } + base_type::m_curr->evt_id = m_evt.len; + m_evt_prev = m_evt.len; + m_evt.len += 3; } void _mark_parent_with_children_() { - if(m_parent) - m_parent->has_children = true; + if(base_type::m_parent) + base_type::m_parent->has_children = true; } C4_ALWAYS_INLINE csubstr _get_latest_empty_scalar() const @@ -1242,15 +1155,15 @@ struct EventHandlerInts : public c4::yml::EventHandlerStack= 0) { - ievt::evt_bits e = m_evt[pos]; + evt_bits e = m_evt.ptr[pos]; if((e & ievt::BDOC) == ievt::BDOC) return pos; pos -= (e & ievt::PSTR) ? 3 : 1; @@ -1258,50 +1171,28 @@ struct EventHandlerInts : public c4::yml::EventHandlerStack= 0) - { - ievt::evt_bits e = m_evt[pos]; - _c4dbgpf("find_matching: pos={} count={} e={}", pos, count, m_evt[pos]); - if((e & close) == close) - { - _c4dbgpf(".............: pos={} close! count={} e={}", pos, count, m_evt[pos]); - ++count; - } - else if((e & open) == open) - { - _c4dbgpf(".............: pos={} open! count={} e={}", pos, count, m_evt[pos]); - if(!count) - return pos; - else - --count; - } - pos = _prev(pos); - } - _c4dbgpf("find_matching: not found!", 0); // LCOV_EXCL_LINE - return -1; // LCOV_EXCL_LINE - } - evt_size _extend_left_to_include_tag_and_or_anchor(evt_size pos) const { - RYML_ASSERT_BASIC_CB_(m_stack.m_callbacks, pos < m_evt_size); + RYML_ASSERT_BASIC_CB_(base_type::m_stack.m_callbacks, pos < m_evt.cap); evt_size prev = _prev(pos); - while((prev > 0) && (m_evt[prev] & (ievt::TAG_|ievt::ANCH))) + while((prev > 0) && (m_evt.ptr[prev] & (ievt::TAG_|ievt::ANCH))) { - _c4dbgpf("{}/{}: {} is anchor/tag. extend to {}", m_evt_pos, m_evt_size, prev, prev); + _c4dbgpf("{}/{}: {} is anchor/tag. extend to {}", m_evt.len, m_evt.cap, prev, prev); pos = prev; prev = _prev(prev); } return pos; } + C4_ALWAYS_INLINE evt_bits translate_flowml_(type_bits multiline_style) const noexcept + { + static_assert((uint32_t)(FLOW_ML1 << 12) == (uint32_t)ievt::FML1, ""); + static_assert((uint32_t)(FLOW_MLN << 12) == (uint32_t)ievt::FMLN, ""); + static_assert((uint32_t)(FLOW_MLX << 12) == (uint32_t)ievt::FMLX, ""); + RYML_ASSERT_BASIC_CB_(base_type::m_stack.m_callbacks, 0 == (multiline_style & ~FLOW_MLX)); + return (evt_bits)(multiline_style << 12); + } + /** @} */ #undef ryml_enable_ @@ -1313,12 +1204,13 @@ struct EventHandlerInts : public c4::yml::EventHandlerStack +#endif +#ifndef C4_YML_EXTRA_EVENT_HANDLER_INTS_HPP_ +#include "c4/yml/extra/event_handler_ints.hpp" +#endif + +namespace c4 { +namespace yml { + +// instantiate the template +template class RYML_EXPORT ParseEngine; + +} // namespace yml +} // namespace c4 diff --git a/src_extra/c4/yml/extra/event_handler_ints_resize.cpp b/src_extra/c4/yml/extra/event_handler_ints_resize.cpp new file mode 100644 index 000000000..eda5c1628 --- /dev/null +++ b/src_extra/c4/yml/extra/event_handler_ints_resize.cpp @@ -0,0 +1,15 @@ +#ifndef C4_YML_PARSE_ENGINE_DEF_HPP_ +#include +#endif +#ifndef C4_YML_EXTRA_EVENT_HANDLER_INTS_HPP_ +#include "c4/yml/extra/event_handler_ints.hpp" +#endif + +namespace c4 { +namespace yml { + +// instantiate the template +template class RYML_EXPORT ParseEngine; + +} // namespace yml +} // namespace c4 diff --git a/src_extra/c4/yml/extra/event_ints.cpp b/src_extra/c4/yml/extra/event_ints.cpp new file mode 100644 index 000000000..e95b0cdf9 --- /dev/null +++ b/src_extra/c4/yml/extra/event_ints.cpp @@ -0,0 +1,338 @@ +#ifndef C4_YML_EXTRA_EVENT_INTS_HPP_ +#include "c4/yml/extra/event_ints.hpp" +#endif +#ifndef C4_YML_EMIT_OPTIONS_HPP_ +#include "c4/yml/emit_options.hpp" +#endif +#ifndef C4_YML_SCALAR_CHARCONV_HPP_ +#include "c4/yml/scalar_charconv.hpp" +#endif +#ifndef C4_YML_SCALAR_STYLE_HPP_ +#include "c4/yml/scalar_style.hpp" +#endif + + +namespace c4 { +namespace yml { +namespace extra { +namespace ievt { + +RYML_EXPORT evt_size estimate_events_size(csubstr src) +{ + evt_size count = 7; // BSTR + BDOC + =VAL + EDOC + ESTR + for(size_t i = 0; i < src.len; ++i) + { + switch(src.str[i]) + { + case ':': // this has strings preceding/following it + case ',': // overestimate, assume map + case '%': // assume TAGD->string + TAGV->string + count += 6; + break; + // these have (or are likely to have) a string following it + case '-': + case '&': + case '*': + case '<': + case '!': + case '\'': + case '"': + case '|': + case '>': + case '\n': + count += 3; + break; + case '[': + case ']': + count += 4; + break; + case '{': + case '}': + count += 7; + break; + case '?': + count += 5; + break; + } + } + return count; +} + +// NOLINTBEGIN(hicpp-signed-bitwise) +// ensure the ievt flags work despite being signed +static_assert((ievt::MASK & ievt::BSTR) == ievt::BSTR, "overflow?"); +static_assert((ievt::MASK & ievt::ESTR) == ievt::ESTR, "overflow?"); +static_assert((ievt::MASK & ievt::BDOC) == ievt::BDOC, "overflow?"); +static_assert((ievt::MASK & ievt::EDOC) == ievt::EDOC, "overflow?"); +static_assert((ievt::MASK & ievt::BMAP) == ievt::BMAP, "overflow?"); +static_assert((ievt::MASK & ievt::EMAP) == ievt::EMAP, "overflow?"); +static_assert((ievt::MASK & ievt::BSEQ) == ievt::BSEQ, "overflow?"); +static_assert((ievt::MASK & ievt::ESEQ) == ievt::ESEQ, "overflow?"); +static_assert((ievt::MASK & ievt::ANCH) == ievt::ANCH, "overflow?"); +static_assert((ievt::MASK & ievt::ALIA) == ievt::ALIA, "overflow?"); +static_assert((ievt::MASK & ievt::TAG_) == ievt::TAG_, "overflow?"); +static_assert((ievt::MASK & ievt::PLAI) == ievt::PLAI, "overflow?"); +static_assert((ievt::MASK & ievt::SQUO) == ievt::SQUO, "overflow?"); +static_assert((ievt::MASK & ievt::DQUO) == ievt::DQUO, "overflow?"); +static_assert((ievt::MASK & ievt::LITL) == ievt::LITL, "overflow?"); +static_assert((ievt::MASK & ievt::FOLD) == ievt::FOLD, "overflow?"); +static_assert((ievt::MASK & ievt::FLOW) == ievt::FLOW, "overflow?"); +static_assert((ievt::MASK & ievt::BLCK) == ievt::BLCK, "overflow?"); +static_assert((ievt::MASK & ievt::KEY_) == ievt::KEY_, "overflow?"); +static_assert((ievt::MASK & ievt::VAL_) == ievt::VAL_, "overflow?"); +static_assert((ievt::MASK & ievt::EXPL) == ievt::EXPL, "overflow?"); +static_assert((ievt::MASK & ievt::YAML) == ievt::YAML, "overflow?"); +static_assert((ievt::MASK & ievt::TAGH) == ievt::TAGH, "overflow?"); +static_assert((ievt::MASK & ievt::TAGP) == ievt::TAGP, "overflow?"); +static_assert((ievt::MASK & ievt::AREN) == ievt::AREN, "overflow?"); +static_assert((ievt::MASK & ievt::PSTR) == ievt::PSTR, "overflow?"); +static_assert((ievt::MASK & ievt::WSTR) == ievt::WSTR, "overflow?"); +static_assert((ievt::MASK & ievt::JUMP) == ievt::JUMP, "overflow?"); +static_assert((ievt::MASK & ievt::PJUMP) == ievt::PJUMP, "overflow?"); +static_assert((ievt::MASK & ievt::FSL_) == ievt::FSL_, "overflow?"); +static_assert((ievt::MASK & ievt::FML1) == ievt::FML1, "overflow?"); +static_assert((ievt::MASK & ievt::FMLN) == ievt::FMLN, "overflow?"); +static_assert((ievt::MASK & ievt::FMLX) == ievt::FMLX, "overflow?"); +static_assert((ievt::MASK & ievt::LAST) == ievt::LAST, "overflow?"); +static_assert((ievt::MASK & ievt::UNFILT) == ievt::UNFILT, "overflow?"); + + +namespace detail { + +bool has_next_doc_and_is_expl_(evt_bits const* C4_RESTRICT evts, evt_size evts_size, evt_size pos) RYML_NOEXCEPT +{ + RYML_ASSERT_BASIC_(pos < evts_size); + RYML_ASSERT_BASIC_(evts[pos] & ievt::EDOC); + while(pos < evts_size) + { + evt_bits evt = evts[pos]; + if(detail::hasall(evt, ievt::BDOC)) + return (evt & ievt::EXPL); + else if(detail::hasall(evt, ievt::ESTR)) + break; + pos += ievt::nextstep(evt); + } + return false; +} + + +evt_bits get_all_bits_key(evt_bits const* C4_RESTRICT evts, evt_size evts_size, evt_size pos) RYML_NOEXCEPT +{ + RYML_ASSERT_BASIC_(evts[pos] & ievt::KEY_); + evt_bits accum = {}; + for( ; pos < evts_size; pos = ievt::nextpos(evts, pos)) + { + if(evts[pos] & ievt::VAL_) + break; + accum |= evts[pos]; + } + return accum; +} + + +evt_size find_matching_open_(evt_bits const* C4_RESTRICT evts, evt_size pos) RYML_NOEXCEPT +{ + evt_bits evt = evts[pos]; + RYML_ASSERT_BASIC_((evt & ievt::END_) && (evt & (mask_open_close & ~ievt::END_))); + RYML_ASSERT_BASIC_((evt & mask_begend) != mask_begend); + const evt_bits close = evt & mask_open_close; + const evt_bits open = (close & ~ievt::END_) | ievt::BEG_; + pos -= ievt::prevstep(evt); // don't count the starting close token + uint32_t count = 0; + while(pos >= 0) + { + evt = evts[pos]; + if((evt & close) == close) + { + ++count; + } + else if((evt & open) == open) + { + if(!(count--)) + return pos; + } + pos -= ievt::prevstep(evt); + } + RYML_ERR_BASIC_("evt error"); // LCOV_EXCL_LINE +} + + +evt_size find_matching_close_(evt_bits const* C4_RESTRICT evts, evt_size sz, evt_size pos) RYML_NOEXCEPT +{ + evt_bits evt = evts[pos]; + RYML_ASSERT_BASIC_((evt & ievt::BEG_) && (evt & (mask_open_close & ~ievt::BEG_))); + RYML_ASSERT_BASIC_((evt & mask_begend) != mask_begend); + const evt_bits open = evt & mask_open_close; + const evt_bits close = (open & ~ievt::BEG_) | ievt::END_; + pos += ievt::nextstep(evt); // don't count the starting close token + uint32_t count = 0; + while(pos < sz) + { + evt = evts[pos]; + if((evt & open) == open) + { + ++count; + } + else if((evt & close) == close) + { + if(!(count--)) + return pos; + } + pos += ievt::nextstep(evt); + } + RYML_ERR_BASIC_("evt error"); // LCOV_EXCL_LINE +} + + +evt_size find_next_entry_(evt_bits const* C4_RESTRICT evts, evt_size sz, evt_size pos, evt_bits key_or_val) RYML_NOEXCEPT +{ + evt_bits evt = evts[pos]; + if(detail::seqormap(evt & ~ievt::STRM)) + { + if(evt & key_or_val) + return pos; + pos = find_matching_close_(evts, sz, pos); + } + while(pos < sz) + { + evt = evts[pos]; + if((evt & key_or_val) && detail::isentry(evt)) + return pos; + pos += ievt::nextstep(evt); + } + RYML_ERR_BASIC_("evt error"); // LCOV_EXCL_LINE +} + + +MaybeParent find_parent_(evt_bits const* C4_RESTRICT evts, evt_size pos) noexcept +{ + MaybeParent p{0}; + C4_STATIC_ASSERT(std::is_signed::value); + pos -= ievt::prevstep(evts[pos]); + uint32_t count = 0; + while(pos > 0) + { + const evt_bits evt = evts[pos]; + if(evt & ievt::END_) + { + ++count; + } + else if(evt & ievt::BEG_) + { + if(evt & (detail::mask_seqmap)) + { + if(!(count--)) + { + p.pos = pos; + break; + } + } + } + pos -= ievt::prevstep(evt); + } + return p; +} + + +EmitKickoff kickoff_emit(evt_bits const* evts, evt_size sz, evt_size pos, EmitOptions const& m_opts) +{ + EmitKickoff ek = {}; + ek.parent = detail::find_parent_(evts, pos); + RYML_ASSERT_BASIC_(!ek.parent || detail::seqormap(evts[ek.parent.pos])); + ek.emit_key = m_opts.emit_nonroot_key() && ek.parent && detail::hasall(evts[ek.parent.pos], ievt::BMAP) && (evts[pos] & ievt::KEY_); + ek.emit_dash = m_opts.emit_nonroot_dash() && ek.parent && detail::hasall(evts[ek.parent.pos], ievt::BSEQ); + RYML_ASSERT_BASIC_(!(ek.emit_key && ek.emit_dash)); + const evt_bits evt = evts[pos]; + if(ek.emit_key) + { + RYML_ASSERT_BASIC_(evt & KEY_); + ek.keypos = detail::find_next_entry_(evts, sz, pos, ievt::KEY_); + ek.valpos = detail::find_next_entry_(evts, sz, ek.keypos, ievt::VAL_); + RYML_ASSERT_BASIC_(ek.keypos < sz); + RYML_ASSERT_BASIC_(ek.keypos < ek.valpos); + } + else + { + ek.valpos = pos; + if(!(detail::isentry(evt) || + detail::hasall(evt, ievt::BSTR) || + detail::hasall(evt, ievt::BDOC))) + ek.valpos = detail::find_next_entry_(evts, sz, pos, + m_opts.emit_nonroot_key() ? + ievt::VAL_ : ievt::KEY_|ievt::VAL_); + } + RYML_ASSERT_BASIC_(ek.valpos < sz); + return ek; +} + +evt_bits scalar_style_choose_json_ievt(csubstr scalar) noexcept +{ + //see also NodeType implementation in scalar_style.cpp + // do not quote numbers or special scalars + return scalar_is_plain_number_json(scalar) + || scalar_is_special_json(scalar) ? ievt::PLAI : ievt::DQUO; +} +evt_bits scalar_style_choose_block_ievt(csubstr scalar) noexcept +{ + //see also NodeType implementation in scalar_style.cpp + if(scalar.len) + { + if(scalar_style_query_plain_block(scalar)) + return ievt::PLAI; + RYML_ASSERT_BASIC_(scalar_style_query_squo(scalar) + && "if this assertion fires, please submit an issue!"); + return ievt::SQUO; + } + return scalar.str ? ievt::SQUO : ievt::PLAI; +} +evt_bits scalar_style_choose_flow_ievt(csubstr scalar) noexcept +{ + //see also NodeType implementation in scalar_style.cpp + if(scalar.len) + { + if(scalar_style_query_plain_flow(scalar)) + return ievt::PLAI; + else if(scalar_style_query_squo(scalar)) + return ievt::SQUO; + return ievt::DQUO; + } + return scalar.str ? ievt::SQUO : ievt::PLAI; +} + +} // namespace detail +} // namespace ievt +} // namespace extra + + +namespace detail { +C4_SUPPRESS_WARNING_GCC_CLANG_PUSH +C4_SUPPRESS_WARNING_GCC_CLANG("-Wold-style-cast") +C4_SUPPRESS_WARNING_GCC_CLANG("-Wcast-qual") +C4_SUPPRESS_WARNING_GCC("-Wsign-conversion") +extra::ievt::evtbuf resize(extra::ievt::evtbuf buf, extra::ievt::evt_size cap, Callbacks const& cb) +{ + RYML_ASSERT_BASIC_CB_(cb, buf.len <= buf.cap); + if(cap > buf.cap) + { + buf.ptr = yml::detail::grow_buf(buf.ptr, (size_t)buf.len, (size_t)buf.cap, (size_t)cap, cb); + buf.cap = cap; + memset(buf.ptr + buf.len, 0, sizeof(buf.ptr[0]) * (size_t)(buf.cap - buf.len)); + } + return buf; +} +substr resize(substr buf, size_t sz, Callbacks const& cb) +{ + if(sz > buf.len) + { + buf.str = yml::detail::grow_buf(buf.str, buf.len, sz, cb); + buf.len = sz; + } + return buf; +} +C4_SUPPRESS_WARNING_GCC_CLANG_POP +} // namespace detail + +// NOLINTEND(hicpp-signed-bitwise) + +} // namespace yml +} // namespace c4 diff --git a/src_extra/c4/yml/extra/event_ints.hpp b/src_extra/c4/yml/extra/event_ints.hpp new file mode 100644 index 000000000..eb5a59d34 --- /dev/null +++ b/src_extra/c4/yml/extra/event_ints.hpp @@ -0,0 +1,461 @@ +#ifndef C4_YML_EXTRA_EVENT_INTS_HPP_ +#define C4_YML_EXTRA_EVENT_INTS_HPP_ + +/** @file event_bits_ints.hpp */ + +#ifndef RYML_SINGLE_HEADER +#ifndef C4_YML_COMMON_HPP_ +#include +#endif +#ifndef C4_YML_ERROR_HPP_ +#include +#endif +#endif +#include + + +// NOLINTBEGIN(hicpp-signed-bitwise,*avoid-c-style-cast) + +namespace c4 { +namespace yml { +struct EmitOptions; +namespace extra { +namespace ievt { + +/** @addtogroup doc_event_handlers_ints + * + * An event handler used by @ref ParseEngine to create an integer + * buffer with a very compact representation of the YAML tree in a + * source buffer. This feature is an extra and is not part of the main + * rapidyaml library. It is meant for use by other programming + * languages, and supports container keys (unlike the ryml tree). It + * parses faster than the ryml tree parser, because the resulting data + * structure is much simpler. + * + * The resulting integer buffer is a linear array of integers + * containing encoded YAML events (as a mask of @ref ievt::EventBits), + * which in some cases (eg scalars) are followed by an encoded string + * (encoded as an offset and length to the parsed source buffer). + * + * For example, parsing `[a, bb, ccc]` results in the following event + * buffer (grouped to highlight the event sequence structure): + * + * ```c++ + * using namespace c4::yml::extra::ievt; + * const evt_bits arr[] = { // result of parsing: [a, bb, ccc] + * BSTR, // begin stream + * BDOC, // begin doc + * VAL_|BSEQ|FLOW, // begin seq as val, flow + * VAL_|SCLR|PLAI, 1, 1, // val scalar, plain style, "a" : string starts at offset 1 and has length 1 + * VAL_|SCLR|PLAI|PSTR, 4, 2, // val scalar, plain style, "bb" : string starts at offset 4 and has length 2; preceded by a string event (PSTR) + * VAL_|SCLR|PLAI|PSTR, 8, 3, // val scalar, plain style, "ccc": string starts at offset 8 and has length 3; preceded by a string event (PSTR) + * ESEQ|PSTR, // end seq; preceded by a string event (PSTR) + * EDOC, // end doc + * ESTR, // end stream + * }; + * ``` + * + * Here is a sketch clarifying the meaning of this event sequence: + * +@code +source : [a, bb, ccc] + has a string........ + | offset "a" + | | length "a" + | | | + event0 event1 event2 [ event3 "a"......|..| + | | | | | | +(start) +--------+-------+------------------+---------------+--+-----> (continued) +arr[i] : BSTR BDOC VAL_|BSEQ|FLOW VAL_|SCLR|PLAI..1..1 +i : 0 1 2 3 4 5 + + + has a string............. has a string............. + | offset "bb" | offset "ccc" + | | length "bb" | | length "ccc" + | | | | | | + event4 "bb"..........|..| event5 "ccc".........|..| + | | | | | | + (cont)--> -----+--------------------+--+--------------+--------------------+--+-----> (continued) +arr[i] : VAL_|SCLR|PLAI|PSTR..4..2 VAL_|SCLR|PLAI|PSTR..8..3 +i : 6 | 7 8 9 | 10 11 + | | + prev event has string prev event has string + (to get to prev, jump (to get to prev, jump + back 3 slots: ie 6->3) back 3 slots: ie 9->6) + + + + event6 ] event7 event8 + | | | + (cont)--> -----+-------------+--------+-----| (end) +arr[i] : ESEQ|PSTR EDOC ESTR +i : 12 | 13 14 + | + prev event has string + (to get to it, jump + back 3 slots: ie 12->9) +@endcode + * + * Note that the buffer contains both events (encoded as bit masks) + * and strings (encoded as integer pairs). That is, events that have + * an associated string are immediately followed by two integers + * providing the offset and length of that string in the source + * buffer. (In the example above, this happens in the events for the + * strings `a`, `bb`, and `ccc` at positions 3, 6 and 9, + * respectively). + * + * The flag @ref ievt::PSTR and the mask @ref ievt::WSTR are provided to + * enable easier iteration over the array: you can use them to test for + * presence of a string when iterating over the array. + * + * The flag @ref ievt::PSTR announces that an event is *preceded* by a + * string. That is, the previous event has a string, so that when this + * flag is found while iterating right-to-left, a jump of -3 should be + * used to get at the bitmask of the previous event. (In the example + * above, this flag is present for the events for `bb` and `ccc`, but not + * `a` because it is not preceded by a string). + * + * Likewise, to signify that the current event is *followed* by a string, + * there is the mask @ref ievt::WSTR, which is a mask of all the flags of + * events that have a string: @ref ievt::SCLR, @ref ievt::ALIA, @ref + * ievt::ANCH and @ref ievt::TAG_. While iterating left-to-right in the + * array, presence of any of the bits in the mask @ref ievt::WSTR means + * that a jump of +3 should be employed to get to the next + * event. + * + * Here's another example with the result of parsing `a: bb` + * ```c++ + * const evt_bits arr[] = { // result of parsing: `a: bb` + * BSTR, // begin stream + * BDOC, // begin doc + * VAL_|BMAP|BLCK, // begin map as val, block + * KEY_|SCLR|PLAI, 0, 1, // key scalar, plain style: "a" starts at offset 0 and has length 1 + * VAL_|SCLR|PLAI|PSTR, 3, 2, // val scalar, plain style: "bb" starts at offset 3 and has length 2 + * EMAP|PSTR, // end map + * EDOC, // end doc + * ESTR, // end stream + * }; + * ``` + * + * Typical code to iterate left-to-right over the array will look like + * this: + * + * ```c++ + * // source buffer, modified in place during parsing (IMPORTANT!) + * substr src = ...; + * substr arena = ...; // arena used for scalars/tags that are extended during filtering + * // events resulting from parsing + * const int events[] = {...}; + * int events_size = ...; + * for(int i = 0; i < events_size; ++i) + * { + * if(events[i] & ievt::WSTR) // this event has a string following it + * { + * size_t offset = (size_t)events[i+1]; + * size_t length = (size_t)events[i+2]; + * csubstr region = (events[i] & ievt::AREN) ? arena : src; // is the string in the arena? + * csubstr str = region.sub(offset, length); // get the string + * ... + * i += 2; // skip the two ints of the string + * // (the jump is three places; the loop adds the other place) + * } + * else // this is a single-int event + * { + * ... + * } + * } + * ``` + * + * @{ */ + +/** data type for integer events size. This is set to an int32_t integer + * to allow compatibility with a wide range of processing languages. */ +using evt_size = int32_t; + +/** data type for integer events bits. This is set to an int32_t integer + * to allow compatibility with a wide range of processing languages. */ +using evt_bits = int32_t; + +/** enumeration of integer event bits. */ +typedef enum : evt_bits { // NOLINT + + //------------------------------------------------------------------------- + // YAML flags + + // YAML structure flags + KEY_ = (1 << 0), ///< as key + VAL_ = (1 << 1), ///< as value + + // YAML event scopes + BEG_ = (1 << 2), ///< scope: begin + END_ = (1 << 3), ///< scope: end + SEQ_ = (1 << 4), ///< scope: seq + MAP_ = (1 << 5), ///< scope: map + DOC_ = (1 << 6), ///< scope: doc + EXPL = (1 << 7), ///< `---` (with BDOC) or `...` (with EDOC) + STRM = (1 << 8), ///< scope: stream + BSEQ = BEG_|SEQ_, ///< begin seq (+SEQ in test suite events) + ESEQ = END_|SEQ_, ///< end seq (-SEQ in test suite events) + BMAP = BEG_|MAP_, ///< begin map (+MAP in test suite events) + EMAP = END_|MAP_, ///< end map (-MAP in test suite events) + BSTR = BEG_|STRM, ///< begin stream (+STR in test suite events) + ESTR = END_|STRM, ///< end stream (-STR in test suite events) + BDOC = BEG_|DOC_, ///< begin doc (+DOC in test suite events) + EDOC = END_|DOC_, ///< end doc (-DOC in test suite events) + + // YAML string events + SCLR = (1 << 9), ///< scalar (=VAL in test suite events) + ALIA = (1 << 10), ///< *ref (reference) + ANCH = (1 << 11), ///< &anchor + TAG_ = (1 << 12), ///< !tag + // directives + YAML = (1 << 13), ///< yaml directive: `\%YAML ` + TAGH = (1 << 14), ///< tag directive, handle: `\%TAG ........` + TAGP = (1 << 15), ///< tag directive, prefix: `\%TAG ........ ` + + // YAML style flags + PLAI = (1 << 16), ///< scalar: plain + SQUO = (1 << 17), ///< scalar: single-quoted (') + DQUO = (1 << 18), ///< scalar: double-quoted ("") + LITL = (1 << 19), ///< scalar: block literal (|) + FOLD = (1 << 20), ///< scalar: block folded (>) + FLOW = (1 << 21), ///< container: flow: [] for seqs or {} for maps + BLCK = (1 << 22), ///< container: block + + /// Special flag to mark a scalar as unfiltered (when the parser + /// is set not to filter). + UNFILT = (1 << 23), + + //------------------------------------------------------------------------- + // NON-YAML FLAGS + + /// Special flag to mark events whose string was placed in the + /// arena. This happens when the filtered string is larger than + /// the original string in the YAML code (eg from tags that + /// resolve to a larger string, or from "\L" or "\P" in double + /// quotes, which expand from two to three bytes). Because of this + /// size expansion, the filtered string cannot be placed in the + /// original source and needs to be placed in the arena. + AREN = (1 << 24), + + /// WithSTRing: mask of all events that encode a string following + /// the event. For such events, the next two integers will provide + /// respectively the string's offset and length. See also @ref PSTR + WSTR = SCLR|ALIA|ANCH|TAG_|TAGH|TAGP|YAML, + + /// Special flag to enable look-back in the event array. It + /// signifies that the previous event has a string, meaning that + /// the jump back to that event is 3 positions. Without this flag + /// it would be impossible to jump to the previous event. + /// see also @ref WSTR + PSTR = (1 << 25), + + /// unused: reserved for future use (to enable rope-like buffers) + JUMP = (1 << 26), + /// unused: reserved for future use (same purpose as @ref PSTR, + /// but for @ref JUMP) + PJUMP = (1 << 27), + + // flow style flags + FSL_ = (1 << 28), ///< same as @ref c4::yml::FLOW_SL + FML1 = (1 << 29), ///< same as @ref c4::yml::FLOW_ML1 + FMLN = (1 << 30), ///< same as @ref c4::yml::FLOW_MLN + FMLX = FML1|FMLN, ///< same as @ref c4::yml::FLOW_MLX + FSPC = (1 << 31), ///< same as @ref c4::yml::FLOW_SPC + + /// the last flag defined above + LAST = FSPC, + + /// a mask of all bits in this enumeration + MASK = LAST < (1 << 31) ? (LAST << 1) - 1 : -1, + +} EventBits; + + +C4_HOT C4_ALWAYS_INLINE evt_size nextstep(evt_bits bits) noexcept +{ + return (bits & ievt::WSTR) ? 3 : 1; +} +C4_HOT C4_ALWAYS_INLINE evt_size prevstep(evt_bits bits) noexcept +{ + return (bits & ievt::PSTR) ? 3 : 1; +} + + +C4_HOT C4_ALWAYS_INLINE evt_size nextpos(evt_bits bits, evt_size pos) noexcept +{ + return pos + ((bits & ievt::WSTR) ? 3 : 1); +} +C4_HOT C4_ALWAYS_INLINE evt_size prevpos(evt_bits bits, evt_size pos) noexcept +{ + return pos - ((bits & ievt::PSTR) ? 3 : 1); +} + + +C4_HOT C4_ALWAYS_INLINE evt_size nextpos(evt_bits const *C4_RESTRICT arr, evt_size pos) noexcept +{ + return pos + ((arr[pos] & ievt::WSTR) ? 3 : 1); +} +C4_HOT C4_ALWAYS_INLINE evt_size prevpos(evt_bits const *C4_RESTRICT arr, evt_size pos) noexcept +{ + return pos - ((arr[pos] & ievt::PSTR) ? 3 : 1); +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +struct RYML_EXPORT evtbuf +{ + evt_bits *C4_RESTRICT ptr = {}; + evt_size len = {}; + evt_size cap = {}; +}; + + +C4_SUPPRESS_WARNING_MSVC_WITH_PUSH(4251) // needs to have dll-interface to be used by clients +struct RYML_EXPORT Buffers +{ + substr src = {}; + substr arena = {}; + evtbuf evts = {}; + bool owned = {}; + Callbacks callbacks = {}; + csubstr getstr(evt_size pos) const RYML_NOEXCEPT + { + RYML_ASSERT_BASIC_(pos + 2 < evts.len); + RYML_ASSERT_BASIC_(evts.ptr[pos] & ievt::WSTR); + csubstr region = (evts.ptr[pos] & ievt::AREN) ? arena : src; + RYML_ASSERT_BASIC_(static_cast(evts.ptr[pos + 1]) <= region.len); + RYML_ASSERT_BASIC_(static_cast(evts.ptr[pos + 1] + evts.ptr[pos + 2]) <= region.len); + return {region.str + evts.ptr[pos + 1], static_cast(evts.ptr[pos + 2])}; + } + void destroy() + { + if(owned) + { + if(evts.ptr) + callbacks.m_free(evts.ptr, static_cast(evts.cap) * sizeof(evts.ptr[0]), callbacks.m_user_data); + if(arena.str) + callbacks.m_free(arena.str, arena.len * sizeof(arena.str[0]), callbacks.m_user_data); + } + evts = {}; + src = {}; + arena = {}; + owned = false; + } + ~Buffers() noexcept + { + destroy(); + } +}; +C4_SUPPRESS_WARNING_MSVC_POP + + +/** Read YAML source and, without undergoing a full parse, estimate + * the size of the integer buffer required for @ref + * EventHandlerInts. This estimation is meant to exceed the actual + * number of required events, and is typically used with @ref + * EventHandlerIntsNoResize. + * + * @note This function must overpredict. It does so for every case in + * the hundreds/thousands of extensive tests of rapidyaml. If you find + * a case where that does not hold, it is a bug: please report it at + * https://github.com/biojppm/rapidyaml/issues */ +RYML_EXPORT evt_size estimate_events_size(csubstr src); + + +/** @} */ // doc_event_handlers_ints + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +/** @cond dev */ +namespace detail { + +enum : evt_bits { // NOLINT + mask_open_close = ievt::BEG_|ievt::END_|ievt::SEQ_|ievt::MAP_|ievt::DOC_|ievt::STRM, + mask_seqmap = ievt::SEQ_|ievt::MAP_, + mask_begend = ievt::BEG_|ievt::END_, +}; + +C4_HOT C4_ALWAYS_INLINE bool hasall(evt_bits evt, evt_bits bits) noexcept +{ + return (evt & bits) == bits; +} +C4_HOT C4_ALWAYS_INLINE bool hasnone(evt_bits evt, evt_bits bits) noexcept +{ + return (evt & bits) == 0; +} +C4_HOT C4_ALWAYS_INLINE bool seqormap(evt_bits evt) noexcept +{ + return (evt & ievt::BEG_) && (evt & detail::mask_seqmap); +} +inline bool isentry(evt_bits mask) noexcept +{ + return (mask & (ievt::SCLR|ievt::ALIA)) || + ((mask & ievt::BEG_) && (mask & detail::mask_seqmap)); +} + + +struct MaybeParent +{ + operator bool() const noexcept { return pos != 0; } + evt_size pos; +}; +RYML_EXPORT MaybeParent find_parent_(evt_bits const* C4_RESTRICT evts, evt_size pos) noexcept; +RYML_EXPORT bool has_next_doc_and_is_expl_(evt_bits const* C4_RESTRICT evts, evt_size evts_size, evt_size pos) RYML_NOEXCEPT; +RYML_EXPORT evt_bits get_all_bits_key(evt_bits const* C4_RESTRICT evts, evt_size evts_size, evt_size pos) RYML_NOEXCEPT; +RYML_EXPORT evt_size find_matching_open_(evt_bits const* C4_RESTRICT evts, evt_size pos) RYML_NOEXCEPT; +RYML_EXPORT evt_size find_matching_close_(evt_bits const* C4_RESTRICT evts, evt_size sz, evt_size pos) RYML_NOEXCEPT; +RYML_EXPORT evt_size find_next_entry_(evt_bits const* C4_RESTRICT evts, evt_size sz, evt_size pos, evt_bits key_or_val) RYML_NOEXCEPT; +RYML_EXPORT evt_bits scalar_style_choose_json_ievt(csubstr scalar) noexcept; +RYML_EXPORT evt_bits scalar_style_choose_block_ievt(csubstr scalar) noexcept; +RYML_EXPORT evt_bits scalar_style_choose_flow_ievt(csubstr scalar) noexcept; + + +struct EmitKickoff +{ + detail::MaybeParent parent; + evt_size keypos, valpos; + bool emit_dash, emit_key; +}; +RYML_EXPORT EmitKickoff kickoff_emit(evt_bits const* evts, evt_size sz, evt_size pos, EmitOptions const& m_opts); + + +} // namespace detail +/** @endcond */ +} // namespace ievt + +/** @cond dev */ +// LCOV_EXCL_START +RYML_DEPRECATED("use ievt::estimate_events_size") +inline ievt::evt_size estimate_events_ints_size(csubstr src) +{ + return ievt::estimate_events_size(src); +} +// LCOV_EXCL_STOP +/** @endcond */ + +} // namespace extra + +/** @cond dev */ +namespace detail { +RYML_EXPORT C4_NODISCARD extra::ievt::evtbuf resize(extra::ievt::evtbuf buf, extra::ievt::evt_size sz, Callbacks const& cb); +RYML_EXPORT C4_NODISCARD substr resize(substr buf, size_t sz, Callbacks const& cb); +} // namespace detail +/** @endcond */ + +} // namespace yml +} // namespace c4 + + + +// NOLINTEND(hicpp-signed-bitwise,*avoid-c-style-cast) + + +#endif /* C4_YML_EXTRA_EVENT_INTS_HPP_ */ diff --git a/src_extra/c4/yml/extra/ints_to_testsuite.cpp b/src_extra/c4/yml/extra/ints_to_testsuite.cpp index 79864ac20..e7ad18712 100644 --- a/src_extra/c4/yml/extra/ints_to_testsuite.cpp +++ b/src_extra/c4/yml/extra/ints_to_testsuite.cpp @@ -28,15 +28,16 @@ C4_SUPPRESS_WARNING_CLANG_WITH_PUSH("-Wold-style-cast") namespace c4 { namespace yml { namespace extra { +namespace ievt { C4_NODISCARD RYML_EXPORT size_t events_ints_to_testsuite(csubstr parsed_yaml, // NOLINT(*-use-internal-linkage) csubstr arena, - ievt::evt_bits const* evts_ints, - ievt::evt_bits evts_ints_sz, + evt_bits const* evts_ints, + evt_bits evts_ints_sz, substr evts_test_suite) { - auto getstr = [&](ievt::evt_bits i){ + auto getstr = [&](evt_bits i){ bool in_arena = evts_ints[i] & ievt::AREN; csubstr region = !in_arena ? parsed_yaml : arena; return region.sub((size_t)evts_ints[i+1], (size_t)evts_ints[i+2]); @@ -102,8 +103,8 @@ size_t events_ints_to_testsuite(csubstr parsed_yaml, // NOLINT(*-use-internal-li append(evt); append_esc(val); }; - ievt::evt_bits evt = 0; - for(ievt::evt_bits i = 0; i < evts_ints_sz; i += (evt & ievt::WSTR) ? 3 : 1) + evt_bits evt = 0; + for(evt_bits i = 0; i < evts_ints_sz; i += (evt & ievt::WSTR) ? 3 : 1) { evt = evts_ints[i]; if(evt & ievt::SCLR) @@ -184,6 +185,7 @@ size_t events_ints_to_testsuite(csubstr parsed_yaml, // NOLINT(*-use-internal-li return sz; } +} // namespace ievt } // namespace extra } // namespace yml } // namespace c4 diff --git a/src_extra/c4/yml/extra/ints_to_testsuite.hpp b/src_extra/c4/yml/extra/ints_to_testsuite.hpp index 87d25c1d0..c4a494b25 100644 --- a/src_extra/c4/yml/extra/ints_to_testsuite.hpp +++ b/src_extra/c4/yml/extra/ints_to_testsuite.hpp @@ -11,6 +11,7 @@ namespace c4 { namespace yml { namespace extra { +namespace ievt { /** @addtogroup doc_event_handlers_ints @@ -28,8 +29,8 @@ namespace extra { C4_NODISCARD RYML_EXPORT size_t events_ints_to_testsuite(csubstr parsed_yaml, csubstr arena, - ievt::evt_bits const* evts_ints, - ievt::evt_bits evts_ints_sz, + evt_bits const* evts_ints, + evt_bits evts_ints_sz, substr evts_testsuite); @@ -38,8 +39,8 @@ size_t events_ints_to_testsuite(csubstr parsed_yaml, template void events_ints_to_testsuite(csubstr parsed_yaml, csubstr arena, - ievt::evt_bits const* evts_ints, - ievt::evt_bits evts_ints_sz, + evt_bits const* evts_ints, + evt_bits evts_ints_sz, Container *evts_testsuite) { size_t len = events_ints_to_testsuite(parsed_yaml, arena, evts_ints, evts_ints_sz, to_substr(*evts_testsuite)); @@ -57,8 +58,8 @@ void events_ints_to_testsuite(csubstr parsed_yaml, template Container events_ints_to_testsuite(csubstr parsed_yaml, csubstr arena, - ievt::evt_bits const* evts_ints, - ievt::evt_bits evts_ints_sz) + evt_bits const* evts_ints, + evt_bits evts_ints_sz) { Container ret; events_ints_to_testsuite(parsed_yaml, arena, evts_ints, evts_ints_sz, &ret); @@ -67,6 +68,7 @@ Container events_ints_to_testsuite(csubstr parsed_yaml, /** @} */ +} // namespace ievt } // namespace extra } // namespace yml } // namespace c4 diff --git a/src_extra/c4/yml/extra/ints_utils.cpp b/src_extra/c4/yml/extra/ints_utils.cpp index e265cbfcd..22970bb7b 100644 --- a/src_extra/c4/yml/extra/ints_utils.cpp +++ b/src_extra/c4/yml/extra/ints_utils.cpp @@ -54,15 +54,21 @@ const FlagSym flag_syms_[] = { {"YAML", YAML}, {"TAGH", TAGH}, {"TAGP", TAGP}, + {"JUMP", JUMP}, + {"PJUMP", PJUMP}, + {"FSL_", FSL_}, + {"FML1", FML1}, + {"FMLN", FMLN}, + {"FSPC", FSPC}, }; } // namespace -size_t to_str(substr buf, ievt::evt_bits flags) noexcept +size_t to_str(substr buf, evt_bits flags) noexcept { - detail::SubstrWriter_ writer(buf); + yml::detail::SubstrWriter_ writer(buf); for(const FlagSym sym : flag_syms_) { - if(flags & sym.flags) + if((flags & sym.flags) == sym.flags) { if(writer.pos) writer.append('|'); @@ -77,7 +83,7 @@ size_t to_str(substr buf, ievt::evt_bits flags) noexcept return writer.pos; } -csubstr to_str_sub(substr buf, ievt::evt_bits flags) +csubstr to_str_sub(substr buf, evt_bits flags) { size_t reqsize = ievt::to_str(buf, flags); RYML_CHECK_BASIC_(reqsize > 0u); @@ -86,44 +92,41 @@ csubstr to_str_sub(substr buf, ievt::evt_bits flags) } -} // namespace ievt -} // namespace extra -} // namespace yml -} // namespace c4 - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -namespace c4 { -namespace yml { -namespace extra { - -void events_ints_print(csubstr parsed_yaml, csubstr arena, ievt::evt_bits const* evts, ievt::evt_bits evts_sz) +void events_ints_print(csubstr parsed_yaml, csubstr arena, evt_bits const* evts, evt_size evts_sz, bool indent) { char buf[200]; - for(ievt::evt_bits evtpos = 0, evtnumber = 0; + evt_size level = 0; + for(evt_bits evtpos = 0, evtnumber = 0; evtpos < evts_sz; ++evtnumber, - evtpos += ((evts[evtpos] & ievt::WSTR) ? 3 : 1)) + evtpos = ievt::nextpos(evts, evtpos)) { - ievt::evt_bits evt = evts[evtpos]; + evt_bits evt = evts[evtpos]; csubstr flags = ievt::to_str_sub(buf, evt); - printf("[%d][%d] %.*s(0x%x)", evtnumber, evtpos, (int)flags.len, flags.str, evt); - if (evt & ievt::WSTR) + printf("[%d][%d] ", evtnumber, evtpos); + if(indent) + { + if(evt & ievt::END_) + --level; + for(evt_size i = 0; i < level; ++i) + printf(" "); + if(evt & ievt::BEG_) + ++level; + } + printf("%.*s(0x%x)", (int)flags.len, flags.str, evt); + if(evt & ievt::WSTR) { bool in_arena = evt & ievt::AREN; csubstr region = !in_arena ? parsed_yaml : arena; bool safe = (evts[evtpos + 1] >= 0) && (evts[evtpos + 2] >= 0) - && (evts[evtpos + 1] <= (ievt::evt_bits)region.len) // NOLINT - && (evts[evtpos + 2] <= ((ievt::evt_bits)region.len - evts[evtpos + 1])); + && (evts[evtpos + 1] <= (evt_bits)region.len) // NOLINT + && (evts[evtpos + 2] <= ((evt_bits)region.len - evts[evtpos + 1])); const char *str = safe ? (region.str + evts[evtpos + 1]) : "ERR!!!"; - ievt::evt_bits len = safe ? evts[evtpos + 2] : 6; + evt_bits len = safe ? evts[evtpos + 2] : 6; printf(": %d [%d]~~~%.*s~~~", evts[evtpos+1], evts[evtpos+2], len, str); if(in_arena) - printf(" (arenasz=%zu)", arena.len); + printf(" (arenasz=%zu)", arena.len); // LCOV_EXCL_LINE else printf(" (srcsz=%zu)", parsed_yaml.len); } @@ -131,6 +134,7 @@ void events_ints_print(csubstr parsed_yaml, csubstr arena, ievt::evt_bits const* } } +} // namespace ievt } // namespace extra } // namespace yml } // namespace c4 diff --git a/src_extra/c4/yml/extra/ints_utils.hpp b/src_extra/c4/yml/extra/ints_utils.hpp index aa27fb1f8..768bb1dc5 100644 --- a/src_extra/c4/yml/extra/ints_utils.hpp +++ b/src_extra/c4/yml/extra/ints_utils.hpp @@ -1,8 +1,8 @@ #ifndef C4_YML_EXTRA_INTS_UTILS_HPP_ #define C4_YML_EXTRA_INTS_UTILS_HPP_ -#ifndef C4_YML_EXTRA_EVENT_HANDLER_INTS_HPP_ -#include "c4/yml/extra/event_handler_ints.hpp" +#ifndef C4_YML_EXTRA_EVENT_INTS_HPP_ +#include "c4/yml/extra/event_ints.hpp" #endif @@ -11,28 +11,44 @@ namespace c4 { namespace yml { namespace extra { - +namespace ievt { /** @addtogroup doc_event_handlers_ints * @{ */ +/** Convert bit mask of @ref ievt::evt_bits to text. */ +RYML_EXPORT size_t to_str(substr buf, evt_bits flags) noexcept; +/** Convert bit mask of @ref ievt::evt_bits to text. */ +RYML_EXPORT csubstr to_str_sub(substr buf, evt_bits flags); -namespace ievt { -/** Convert bit mask of @ref ievt::EventBits to text. */ -RYML_EXPORT size_t to_str(substr buf, yml::extra::ievt::evt_bits flags) noexcept; -/** Convert bit mask of @ref ievt::EventBits to text. */ -RYML_EXPORT csubstr to_str_sub(substr buf, yml::extra::ievt::evt_bits flags); -} // namespace ievt +/** Print integer events to stdout */ +RYML_EXPORT void events_ints_print(csubstr parsed_yaml, csubstr arena, + evt_bits const* evts_ints, evt_size evts_ints_sz, + bool indent=true); +/** @} */ -/** Print integer events to stdout */ -RYML_EXPORT void events_ints_print(csubstr parsed_yaml, csubstr arena, ievt::evt_bits const* evts_ints, ievt::evt_bits evts_ints_sz); +} // namespace ievt +} // namespace extra +} // namespace yml +} // namespace c4 -/** @} */ +/** @cond dev */ +namespace c4 { +namespace yml { +namespace extra { +RYML_DEPRECATED("use ievt::events_ints_print") +inline void events_ints_print(csubstr parsed_yaml, csubstr arena, + ievt::evt_bits const* evts_ints, + ievt::evt_size evts_ints_sz) +{ + ievt::events_ints_print(parsed_yaml, arena, evts_ints, evts_ints_sz); +} } // namespace extra } // namespace yml } // namespace c4 +/** @endcond */ #endif /* C4_YML_EXTRA_INTS_UTILS_HPP_ */ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 1f5179c93..902703cdd 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -82,20 +82,22 @@ function(ryml_add_quickstart_test targetname suffix) endfunction() ryml_add_quickstart_test(ryml-test-quickstart noargs LOCK) ryml_add_quickstart_test(ryml-test-quickstart quiet ARGS --quiet LOCK) -ryml_add_quickstart_test(ryml-test-quickstart-ints ints) -ryml_add_quickstart_test(ryml-test-quickstart-ints ints-help ARGS --help) -ryml_add_quickstart_test(ryml-test-quickstart-ints ints-quiet ARGS --quiet) -ryml_add_quickstart_test(ryml-test-quickstart-ints ints-zero ARGS -e 0 -a 0) -ryml_add_quickstart_test(ryml-test-quickstart-ints ints-stdin STDIN ARGS -) -ryml_add_quickstart_test(ryml-test-quickstart-ints ints-stdin2 STDIN ARGS stdin) -ryml_add_quickstart_test(ryml-test-quickstart-ints ints-noretry ARGS -n) -ryml_add_quickstart_test(ryml-test-quickstart-ints ints-noretry-fail WILL_FAIL ARGS -n -e 0) -ryml_add_quickstart_test(ryml-test-quickstart-ints ints-file ARGS ${CMAKE_CURRENT_LIST_DIR}/../bm/cases/appveyor.yml) -ryml_add_quickstart_test(ryml-test-quickstart-ints ints-too-many WILL_FAIL ARGS a b c) -ryml_add_quickstart_test(ryml-test-quickstart-ints ints-missing_events WILL_FAIL ARGS -e) -ryml_add_quickstart_test(ryml-test-quickstart-ints ints-missing_arena WILL_FAIL ARGS -a) -ryml_add_quickstart_test(ryml-test-quickstart-ints ints-bad_events WILL_FAIL ARGS -e bad) -ryml_add_quickstart_test(ryml-test-quickstart-ints ints-bad_arena WILL_FAIL ARGS -a bad) +ryml_add_quickstart_test(ryml-test-quickstart-ints noargs) +ryml_add_quickstart_test(ryml-test-quickstart-ints help ARGS --help) +ryml_add_quickstart_test(ryml-test-quickstart-ints quiet ARGS --quiet) +ryml_add_quickstart_test(ryml-test-quickstart-ints zero ARGS -f -e 0 -a 0) +ryml_add_quickstart_test(ryml-test-quickstart-ints stdin STDIN ARGS -) +ryml_add_quickstart_test(ryml-test-quickstart-ints stdin2 STDIN ARGS stdin) +ryml_add_quickstart_test(ryml-test-quickstart-ints fixedsize ARGS -f) +ryml_add_quickstart_test(ryml-test-quickstart-ints noretry ARGS -f -n) +ryml_add_quickstart_test(ryml-test-quickstart-ints noretry-fail WILL_FAIL ARGS -f -n -e 0) +ryml_add_quickstart_test(ryml-test-quickstart-ints file ARGS ${CMAKE_CURRENT_LIST_DIR}/../bm/cases/appveyor.yml) +ryml_add_quickstart_test(ryml-test-quickstart-ints file-fixedsize ARGS -f ${CMAKE_CURRENT_LIST_DIR}/../bm/cases/appveyor.yml) +ryml_add_quickstart_test(ryml-test-quickstart-ints too-many WILL_FAIL ARGS a b c) +ryml_add_quickstart_test(ryml-test-quickstart-ints missing_events WILL_FAIL ARGS -e) +ryml_add_quickstart_test(ryml-test-quickstart-ints missing_arena WILL_FAIL ARGS -a) +ryml_add_quickstart_test(ryml-test-quickstart-ints bad_events WILL_FAIL ARGS -e bad) +ryml_add_quickstart_test(ryml-test-quickstart-ints bad_arena WILL_FAIL ARGS -a bad) c4_add_library(ryml-_testlib LIBRARY_TYPE STATIC @@ -105,6 +107,8 @@ c4_add_library(ryml-_testlib LIBRARY_TYPE STATIC test_lib/test_case_node.cpp test_lib/test_case.hpp test_lib/test_case.cpp + test_lib/test_compare_events.hpp + test_lib/test_compare_events.cpp test_lib/test_engine.hpp test_lib/test_engine.cpp test_lib/test_events_ints_helpers.hpp @@ -160,6 +164,7 @@ endfunction() ryml_add_test(engine_1_doc_1 BIG) ryml_add_test(engine_1_doc_2 BIG) +ryml_add_test(engine_1_doc_3 BIG) ryml_add_test(engine_2_seq_block_1 BIG) ryml_add_test(engine_2_seq_block_2 BIG) ryml_add_test(engine_2_seq_flow_1 BIG) @@ -178,6 +183,7 @@ ryml_add_test(engine_6_qmrk_1 BIG) ryml_add_test(engine_6_qmrk_2 BIG) ryml_add_test(engine_6_qmrk_3 BIG) ryml_add_test(engine_6_qmrk_4 BIG) +ryml_add_test(engine_6_qmrk_5 BIG) ryml_add_test(engine_7_seqimap BIG) ryml_add_test(engine_8_scalars_tokens BIG) ryml_add_test(engine_9_indentation BIG) @@ -585,11 +591,13 @@ if(RYML_FUZZ_TEST OR RYML_FUZZ_DRIVERS) set(yaml_dirs yaml_fails yaml_merged yaml_rapidyamldump yaml_test_suite ${json_dirs}) endif() - ryml_add_fuzz_variant(srlz srlz ${rapidyaml_data_dir}/fuzz ${srlz_dirs}) - ryml_add_fuzz_variant(yaml_tree yaml ${rapidyaml_data_dir}/fuzz ${yaml_dirs}) - ryml_add_fuzz_variant(yaml_ints yaml ${rapidyaml_data_dir}/fuzz ${yaml_dirs}) - ryml_add_fuzz_variant(json_tree json ${rapidyaml_data_dir}/fuzz ${json_dirs}) - ryml_add_fuzz_variant(json_ints json ${rapidyaml_data_dir}/fuzz ${json_dirs}) + ryml_add_fuzz_variant(srlz srlz ${rapidyaml_data_dir}/fuzz ${srlz_dirs}) + ryml_add_fuzz_variant(yaml_tree yaml ${rapidyaml_data_dir}/fuzz ${yaml_dirs}) + ryml_add_fuzz_variant(yaml_ints_resize yaml ${rapidyaml_data_dir}/fuzz ${yaml_dirs}) + ryml_add_fuzz_variant(yaml_ints_noresize yaml ${rapidyaml_data_dir}/fuzz ${yaml_dirs}) + ryml_add_fuzz_variant(json_tree json ${rapidyaml_data_dir}/fuzz ${json_dirs}) + ryml_add_fuzz_variant(json_ints_resize json ${rapidyaml_data_dir}/fuzz ${json_dirs}) + ryml_add_fuzz_variant(json_ints_noresize json ${rapidyaml_data_dir}/fuzz ${json_dirs}) # umbrella runner if(RYML_FUZZ_DRIVERS) add_custom_target(ryml-fuzz-drivers-run diff --git a/test/test_anchor.cpp b/test/test_anchor.cpp index 8da22e4ae..6fc7da5e5 100644 --- a/test/test_anchor.cpp +++ b/test/test_anchor.cpp @@ -1654,7 +1654,7 @@ N(MFS, L{ ); -ADD_CASE_TO_GROUP("ambiguous anchor, unresolved", +ADD_CASE_TO_GROUP("ambiguous anchor, unresolved", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"(&rootanchor &a0 a0: &b0 b0 *b0 : *a0 @@ -1726,7 +1726,7 @@ N(MB, L{ ); -ADD_CASE_TO_GROUP("ambiguous anchor in seq, unresolved", +ADD_CASE_TO_GROUP("ambiguous anchor in seq, unresolved", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"( &seq - &a0 @@ -1816,7 +1816,7 @@ N(SB, L{ }) ); -ADD_CASE_TO_GROUP("anchor after complex key without value ZWK4", +ADD_CASE_TO_GROUP("anchor after complex key without value ZWK4", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"( a: 1 ? b diff --git a/test/test_doc.cpp b/test/test_doc.cpp index f58ca34aa..c8f20fef3 100644 --- a/test/test_doc.cpp +++ b/test/test_doc.cpp @@ -56,7 +56,7 @@ scalar CASE_GROUP(SIMPLE_DOC) { -ADD_CASE_TO_GROUP("one empty doc", +ADD_CASE_TO_GROUP("one empty doc", NO_COMPARE_EMITTED_INTS_JSON, R"(--- )", N(STREAM, L{DOC|VN}) @@ -102,7 +102,7 @@ R"(... NOTYPE ); -ADD_CASE_TO_GROUP("three terminations and one explicit, v0", +ADD_CASE_TO_GROUP("three terminations and one explicit, v0", NO_COMPARE_EMITTED_INTS_JSON, R"(... ... ... @@ -111,7 +111,7 @@ R"(... N(STREAM, L{DOC|VN}) ); -ADD_CASE_TO_GROUP("three terminations and one explicit, v1", +ADD_CASE_TO_GROUP("three terminations and one explicit, v1", NO_COMPARE_EMITTED_INTS, R"(... ... --- @@ -120,7 +120,7 @@ R"(... N(STREAM, L{DOC|VN}) ); -ADD_CASE_TO_GROUP("three terminations and one explicit, v2", +ADD_CASE_TO_GROUP("three terminations and one explicit, v2", NO_COMPARE_EMITTED_INTS, R"(... --- ... @@ -129,7 +129,7 @@ R"(... N(STREAM, L{DOC|VN}) ); -ADD_CASE_TO_GROUP("three terminations and one explicit, v3", +ADD_CASE_TO_GROUP("three terminations and one explicit, v3", NO_COMPARE_EMITTED_INTS, R"(--- ... ... @@ -138,28 +138,28 @@ R"(--- N(STREAM, L{DOC|VN}) ); -ADD_CASE_TO_GROUP("one empty doc, explicit termination", +ADD_CASE_TO_GROUP("one empty doc, explicit termination", NO_COMPARE_EMITTED_INTS, R"(--- ... )", N(STREAM, L{DOC|VN}) ); -ADD_CASE_TO_GROUP("one empty doc, explicit termination, first indented", +ADD_CASE_TO_GROUP("one empty doc, explicit termination, first indented", NO_COMPARE_EMITTED_INTS, R"( --- ... )", N(VP, "---") ); -ADD_CASE_TO_GROUP("two empty docs", +ADD_CASE_TO_GROUP("two empty docs", NO_COMPARE_EMITTED_INTS_JSON, R"(--- --- )", N(STREAM, L{DOC|VN, DOC|VN}) ); -ADD_CASE_TO_GROUP("two empty docs, with termination", +ADD_CASE_TO_GROUP("two empty docs, with termination", NO_COMPARE_EMITTED_INTS, R"(--- ... --- @@ -179,7 +179,7 @@ R"(--- a scalar N(STREAM, L{N(DOC|VP, "a scalar")}) ); -ADD_CASE_TO_GROUP("simple doc, empty docs", +ADD_CASE_TO_GROUP("simple doc, empty docs", NO_COMPARE_EMITTED_INTS_JSON, R"(--- --- --- @@ -197,7 +197,7 @@ R"( --- N(VP, "--- --- --- ---") ); -ADD_CASE_TO_GROUP("simple doc, empty docs, term", +ADD_CASE_TO_GROUP("simple doc, empty docs, term", NO_COMPARE_EMITTED_INTS, R"(--- ... @@ -228,7 +228,7 @@ R"( N(VP, "---\n... --- ...\n--- ... --- ...") ); -ADD_CASE_TO_GROUP("simple doc, plain scalar, multiple docs, implicit 2nd doc", +ADD_CASE_TO_GROUP("simple doc, plain scalar, multiple docs, implicit 2nd doc", NO_COMPARE_EMITTED_INTS, R"(--- - a plain scalar with several lines @@ -284,7 +284,7 @@ R"( --- N(VP, "--- a scalar with some spaces inside") ); -ADD_CASE_TO_GROUP("simple doc, single scalar, explicit doc, explicit termination", +ADD_CASE_TO_GROUP("simple doc, single scalar, explicit doc, explicit termination", NO_COMPARE_EMITTED_INTS, R"(--- a scalar with some spaces inside ... @@ -300,7 +300,7 @@ R"( --- N(VP, "--- a scalar with some spaces inside ...") ); -ADD_CASE_TO_GROUP("simple doc, multi doc, seq-map", +ADD_CASE_TO_GROUP("simple doc, multi doc, seq-map", NO_COMPARE_EMITTED_INTS, R"(--- - a - b @@ -329,7 +329,7 @@ R"( N(VP, "--- - a - b - c ... ---") ); -ADD_CASE_TO_GROUP("simple doc, 2XXW", +ADD_CASE_TO_GROUP("simple doc, 2XXW", NO_COMPARE_EMITTED_INTS_JSON, R"( --- !!set ? Mark McGwire @@ -385,7 +385,7 @@ R"(# the first : should cause a parse error Location(7, 6) ); -ADD_CASE_TO_GROUP("simple doc, multi doc, map-seq", +ADD_CASE_TO_GROUP("simple doc, multi doc, map-seq", NO_COMPARE_EMITTED_INTS, R"(--- a: 0 b: 1 @@ -449,7 +449,7 @@ R"( Location(3, 6) ); -ADD_CASE_TO_GROUP("simple doc, multi doc, impl seq-map", +ADD_CASE_TO_GROUP("simple doc, multi doc, impl seq-map", NO_COMPARE_EMITTED_INTS, R"(--- [a, b, c] ... @@ -497,7 +497,7 @@ R"( Location(5, 7) ); -ADD_CASE_TO_GROUP("simple doc, multi doc, impl map-seq", +ADD_CASE_TO_GROUP("simple doc, multi doc, impl map-seq", NO_COMPARE_EMITTED_INTS, R"(--- {a: 0, b: 1, c: 2} ... @@ -577,21 +577,67 @@ R"( ); -ADD_CASE_TO_GROUP("simple doc, tags at global scope, 9WXW", +ADD_CASE_TO_GROUP("multi doc vals", +R"(--- +aaa +--- +bbb +--- +ccc +)", +N(STREAM, L{ + N(DOC|VP, "aaa"), + N(DOC|VP, "bbb"), + N(DOC|VP, "ccc"), +}) +); + +ADD_CASE_TO_GROUP("multi doc vals tag", +R"(--- +!a aaa +--- +!b bbb +--- +!c ccc +)", +N(STREAM, L{ + N(DOC|VP, TS("!a", "aaa")), + N(DOC|VP, TS("!b", "bbb")), + N(DOC|VP, TS("!c", "ccc")), +}) +); + +ADD_CASE_TO_GROUP("multi doc cont", +R"(--- +aaa +--- +[bbb] +--- +{ccc: ddd} +)", +N(STREAM, L{ + N(DOC|VP, "aaa"), + N(DOC|SFS, L{N(VP, "bbb")}), + N(DOC|MFS, L{N(KP|VP, "ccc", "ddd")}), +}) +); + + +ADD_CASE_TO_GROUP("simple doc, tags at global scope, 9WXW", NO_COMPARE_EMITTED_INTS, R"(# Private -!foo "bar" +!foo "bar0" ... # Global %TAG ! tag:example.com,2000:app/ --- -!foo "bar" +!foo "bar1" )", N(STREAM, L{ - N(DOC|VD, TS("!foo", "bar")), + N(DOC|VD, TS("!foo", "bar0")), // strict YAML should result in this for the second doc: //N(DOC|VD, TS("", "bar")), // but since we don't do lookup, it should result in: - N(DOC|VD, TS("!foo", "bar")), + N(DOC|VD, TS("!foo", "bar1")), }) ); } diff --git a/test/test_emit.cpp b/test/test_emit.cpp index 861ec6d0c..a143ca292 100644 --- a/test/test_emit.cpp +++ b/test/test_emit.cpp @@ -10,6 +10,7 @@ #include #include "./test_lib/test_case.hpp" +#include "./test_lib/tree_and_ints.hpp" #include @@ -18,24 +19,69 @@ RYML_DEFINE_TEST_MAIN() namespace c4 { namespace yml { +// NOLINTBEGIN(*-signed-bitwise) + +namespace { +struct tmpfile +{ + std::string filename{}; + FILE *f{}; + ~tmpfile() { clear(); } + void clear() + { + if(f) + { + (void)fclose(f); //NOLINT + f = nullptr; + } + if(!filename.empty()) + { + if(fs::file_exists(filename.c_str())) + { + fs::rmfile(filename.c_str()); + } + filename.clear(); + } + } + template + std::string execget(Emit &&fn) + { + C4_SUPPRESS_WARNING_MSVC_WITH_PUSH(4996) // fopen unsafe + C4_SUPPRESS_WARNING_CLANG_WITH_PUSH("-Wdeprecated-declarations") // fopen is deprecated + static uint32_t count = 0, countopen = 0; + ++count; + ++countopen; + clear(); + filename = fs::tmpnam("_c4fs_tmpname_XXXXXXXX.test_emit.tmp"); + const char *name = filename.c_str(); + f = fopen(name, "wb"); // NOLINT + C4_CHECK_MSG(f != nullptr, "count=%u open=%u\nbase=%s\ndir=%s", count, countopen, name, fs::cwd().c_str()); + std::forward(fn)(f); + (void)fflush(f); //NOLINT + (void)fclose(f); //NOLINT + f = nullptr; + --countopen; + std::string result = fs::file_get_contents(name); + fs::rmfile(filename.c_str()); + C4_CHECK_MSG(!fs::file_exists(name), "count=%u open=%u\nbase=%s\ndir=%s", count, countopen, name, fs::cwd().c_str()); + filename = {}; + return result; + C4_SUPPRESS_WARNING_CLANG_POP + C4_SUPPRESS_WARNING_MSVC_POP + } +}; +tmpfile tmpf_ = {}; +} // namespace + + template std::string emit2file(Emit &&fn) { SCOPED_TRACE("emit2file"); - C4_SUPPRESS_WARNING_MSVC_WITH_PUSH(4996) // fopen unsafe - C4_SUPPRESS_WARNING_CLANG_WITH_PUSH("-Wdeprecated-declarations") // fopen is deprecated - std::string filename = fs::tmpnam(); - FILE *f = fopen(filename.c_str(), "wb"); - C4_CHECK(f != nullptr); - fn(f); - fflush(f); - fclose(f); - std::string result = fs::file_get_contents(filename.c_str()); - fs::rmfile(filename.c_str()); + std::string result = tmpf_.execget(std::forward(fn)); _c4dbgpf("emit result: [{}]~~~{}~~~", result.size(), to_csubstr(result)); + tmpf_.clear(); return result; - C4_SUPPRESS_WARNING_CLANG_POP - C4_SUPPRESS_WARNING_MSVC_POP } template @@ -43,7 +89,7 @@ std::string emit2stream(Emit &&fn) { SCOPED_TRACE("emit2stream"); std::ostringstream ss; - fn(ss); + std::forward(fn)(ss); std::string result = ss.str(); _c4dbgpf("emit result: [{}]~~~{}~~~", result.size(), to_csubstr(result)); return result; @@ -55,12 +101,10 @@ std::string emit2buf(Emit &&fn) SCOPED_TRACE("emit2buf"); std::string buf; buf.resize(2048); - substr out = fn(to_substr(buf)); + substr out = std::forward(fn)(to_substr(buf)); buf.resize(out.len); if(out.len > buf.size()) - { out = fn(to_substr(buf)); - } _c4dbgpf("emit result: [{}]~~~{}~~~", buf.size(), to_csubstr(buf)); return buf; } @@ -70,7 +114,7 @@ std::string emitrs_append(csubstr first_part, Emit &&fn) { SCOPED_TRACE("emitrs_append"); std::string buf(first_part.begin(), first_part.end()); - fn(&buf); + std::forward(fn)(&buf); _c4dbgpf("emit result: [{}]~~~{}~~~", buf.size(), to_csubstr(buf)); return buf; } @@ -206,9 +250,517 @@ TEST(as_json, basic) } } +TEST(emit, emitrs_null_tree) +{ + std::string s = {}; + ConstNodeRef node = {}; + EmitOptions opts = {}; + EXPECT_EQ(s, emitrs_yaml(node)); + EXPECT_EQ(s, emitrs_yaml(node, opts)); + EXPECT_EQ(s, emitrs_json(node)); + EXPECT_EQ(s, emitrs_json(node, opts)); + EXPECT_EQ(0, emitrs_yaml(node, &s).len); + EXPECT_EQ(0, emitrs_yaml(node, opts, &s).len); + EXPECT_EQ(0, emitrs_json(node, &s).len); + EXPECT_EQ(0, emitrs_json(node, opts, &s).len); + EXPECT_EQ(nullptr, emitrs_yaml(node, &s).str); + EXPECT_EQ(nullptr, emitrs_yaml(node, opts, &s).str); + EXPECT_EQ(nullptr, emitrs_json(node, &s).str); + EXPECT_EQ(nullptr, emitrs_json(node, opts, &s).str); +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + + +#define retonfail() do { if(testing::Test::HasFailure()) return; } while(0) +#define bailonfail() do { if(testing::Test::HasFailure()) goto failure; /* NOLINT */ } while(0) +void test_emits_tree(Tree const* tree, id_type id, std::string const& expected_yaml, std::string const& expected_json, EmitOptions const& opts={}) +{ + retonfail(); + RYML_TRACE_FMT("id={}", id); + std::string append_prefix = "#before\n"; + ConstNodeRef node{tree, id}; + ASSERT_EQ(node.id(), id); + ASSERT_EQ(node.tree(), tree); + bool isroot = id == NONE || (!tree->empty() && id == tree->root_id()); + if(!tree) + { + ASSERT_EQ(id, NONE); + if(opts == EmitOptions{}) + { + EXPECT_EQ(emit2buf([&](substr buf){ EmitterBuf em(EmitOptions{}, buf); em.emit_as(EMIT_YAML, tree); return em.get_result(/*error_on_excess*/true); }), expected_yaml); + bailonfail(); + EXPECT_EQ(emit2buf([&](substr buf){ EmitterBuf em(EmitOptions{}, buf); em.emit_as(EMIT_JSON, tree); return em.get_result(/*error_on_excess*/true); }), expected_json); + EXPECT_EQ(emit2file([&](FILE *f){ EmitterFile em(EmitOptions{}, f); em.emit_as(EMIT_YAML, tree); }), expected_yaml); + EXPECT_EQ(emit2file([&](FILE *f){ EmitterFile em(EmitOptions{}, f); em.emit_as(EMIT_JSON, tree); }), expected_json); + EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ EmitterOStream em(EmitOptions{}, &oss); em.emit_as(EMIT_YAML, tree); }), expected_yaml);; + EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ EmitterOStream em(EmitOptions{}, &oss); em.emit_as(EMIT_JSON, tree); }), expected_json);; + EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ oss << as_yaml(node); }), expected_yaml); + EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ oss << as_json(node); }), expected_json); + } + EXPECT_EQ(emit2buf([&](substr buf){ EmitterBuf em(opts, buf); em.emit_as(EMIT_YAML, tree); return em.get_result(/*error_on_excess*/true); }), expected_yaml); + bailonfail(); + EXPECT_EQ(emit2buf([&](substr buf){ EmitterBuf em(opts, buf); em.emit_as(EMIT_JSON, tree); return em.get_result(/*error_on_excess*/true); }), expected_json); + EXPECT_EQ(emit2file([&](FILE *f){ EmitterFile em(opts, f); em.emit_as(EMIT_YAML, tree); }), expected_yaml); + EXPECT_EQ(emit2file([&](FILE *f){ EmitterFile em(opts, f); em.emit_as(EMIT_JSON, tree); }), expected_json); + EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ EmitterOStream em(opts, &oss); em.emit_as(EMIT_YAML, tree); }), expected_yaml);; + EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ EmitterOStream em(opts, &oss); em.emit_as(EMIT_JSON, tree); }), expected_json);; + EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ oss << as_yaml(node, opts); }), expected_yaml); + EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ oss << as_json(node, opts); }), expected_json); + return; + } + if(opts == EmitOptions{}) + { + EXPECT_EQ(emit2buf([&](substr buf){ return emit_yaml(*tree, id, buf); }), expected_yaml); + bailonfail(); + EXPECT_EQ(emit2buf([&](substr buf){ return emit_json(*tree, id, buf); }), expected_json); + bailonfail(); + EXPECT_EQ(emit2buf([&](substr buf){ return emit_yaml(node, buf); }), expected_yaml); + EXPECT_EQ(emit2buf([&](substr buf){ return emit_json(node, buf); }), expected_json); + EXPECT_EQ(emit2file([&](FILE *f){ return emit_yaml(*tree, id, f); }), expected_yaml); + EXPECT_EQ(emit2file([&](FILE *f){ return emit_json(*tree, id, f); }), expected_json); + EXPECT_EQ(emit2file([&](FILE *f){ return emit_yaml(node, f); }), expected_yaml); + EXPECT_EQ(emit2file([&](FILE *f){ return emit_json(node, f); }), expected_json); + EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ oss << as_yaml(*tree, id); }), expected_yaml); + EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ oss << as_json(*tree, id); }), expected_json); + EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ oss << node; }), expected_yaml); + EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ oss << as_yaml(node); }), expected_yaml); + EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ oss << as_json(node); }), expected_json); + EXPECT_EQ(emitrs_yaml(*tree, id), expected_yaml); + EXPECT_EQ(emitrs_json(*tree, id), expected_json); + EXPECT_EQ(emitrs_yaml(node), expected_yaml); + EXPECT_EQ(emitrs_json(node), expected_json); + EXPECT_EQ(emitrs_append(to_csubstr(append_prefix), [&](std::string *s) { emitrs_yaml(*tree, id, s, /*append*/true); } ), append_prefix + expected_yaml); + EXPECT_EQ(emitrs_append(to_csubstr(append_prefix), [&](std::string *s) { emitrs_json(*tree, id, s, /*append*/true); } ), append_prefix + expected_json); + EXPECT_EQ(emitrs_append(to_csubstr(append_prefix), [&](std::string *s) { emitrs_yaml(node, s, /*append*/true); } ), append_prefix + expected_yaml); + EXPECT_EQ(emitrs_append(to_csubstr(append_prefix), [&](std::string *s) { emitrs_json(node, s, /*append*/true); } ), append_prefix + expected_json); + bailonfail(); + if(isroot) + { + EXPECT_EQ(emit2buf([&](substr buf){ return emit_yaml(*tree, buf); }), expected_yaml); + bailonfail(); + EXPECT_EQ(emit2buf([&](substr buf){ return emit_json(*tree, buf); }), expected_json); + bailonfail(); + EXPECT_EQ(emit2buf([&](substr buf){ EmitterBuf em(EmitOptions{}, buf); em.emit_as(EMIT_YAML, tree); return em.get_result(/*error_on_excess*/true); }), expected_yaml); + EXPECT_EQ(emit2buf([&](substr buf){ EmitterBuf em(EmitOptions{}, buf); em.emit_as(EMIT_JSON, tree); return em.get_result(/*error_on_excess*/true); }), expected_json); + EXPECT_EQ(emit2file([&](FILE *f){ return emit_yaml(*tree, f); }), expected_yaml); + EXPECT_EQ(emit2file([&](FILE *f){ return emit_json(*tree, f); }), expected_json); + EXPECT_EQ(emit2file([&](FILE *f){ EmitterFile em(EmitOptions{}, f); em.emit_as(EMIT_YAML, tree); }), expected_yaml); + EXPECT_EQ(emit2file([&](FILE *f){ EmitterFile em(EmitOptions{}, f); em.emit_as(EMIT_JSON, tree); }), expected_json); + EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ oss << *tree; }), expected_yaml); + EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ oss << as_yaml(*tree); }), expected_yaml); + EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ oss << as_json(*tree); }), expected_json); + EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ oss << as_yaml(node); }), expected_yaml); + EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ oss << as_json(node); }), expected_json); + EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ EmitterOStream em(EmitOptions{}, &oss); em.emit_as(EMIT_YAML, tree); }), expected_yaml);; + EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ EmitterOStream em(EmitOptions{}, &oss); em.emit_as(EMIT_JSON, tree); }), expected_json);; + EXPECT_EQ(emitrs_yaml(*tree), expected_yaml); + EXPECT_EQ(emitrs_json(*tree), expected_json); + EXPECT_EQ(emitrs_yaml(node), expected_yaml); + EXPECT_EQ(emitrs_json(node), expected_json); + EXPECT_EQ(emitrs_append(to_csubstr(append_prefix), [&](std::string *s) { emitrs_yaml(*tree, s, /*append*/true); } ), append_prefix + expected_yaml); + EXPECT_EQ(emitrs_append(to_csubstr(append_prefix), [&](std::string *s) { emitrs_json(*tree, s, /*append*/true); } ), append_prefix + expected_json); + bailonfail(); + } + } + EXPECT_EQ(emit2buf([&](substr buf){ return emit_yaml(*tree, id, opts, buf); }), expected_yaml); + bailonfail(); + EXPECT_EQ(emit2buf([&](substr buf){ return emit_json(*tree, id, opts, buf); }), expected_json); + bailonfail(); + EXPECT_EQ(emit2buf([&](substr buf){ return emit_yaml(node, opts, buf); }), expected_yaml); + EXPECT_EQ(emit2buf([&](substr buf){ return emit_json(node, opts, buf); }), expected_json); + EXPECT_EQ(emit2buf([&](substr buf){ EmitterBuf em(opts, buf); em.emit_as(EMIT_YAML, tree, id); return em.get_result(/*error_on_excess*/true); }), expected_yaml); + EXPECT_EQ(emit2buf([&](substr buf){ EmitterBuf em(opts, buf); em.emit_as(EMIT_JSON, tree, id); return em.get_result(/*error_on_excess*/true); }), expected_json); + EXPECT_EQ(emit2file([&](FILE *f){ return emit_yaml(*tree, id, opts, f); }), expected_yaml); + EXPECT_EQ(emit2file([&](FILE *f){ return emit_json(*tree, id, opts, f); }), expected_json); + EXPECT_EQ(emit2file([&](FILE *f){ return emit_yaml(node, opts, f); }), expected_yaml); + EXPECT_EQ(emit2file([&](FILE *f){ return emit_json(node, opts, f); }), expected_json); + EXPECT_EQ(emit2file([&](FILE *f){ EmitterFile em(opts, f); em.emit_as(EMIT_YAML, tree, id); }), expected_yaml); + EXPECT_EQ(emit2file([&](FILE *f){ EmitterFile em(opts, f); em.emit_as(EMIT_JSON, tree, id); }), expected_json); + EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ oss << as_yaml(*tree, id, opts); }), expected_yaml); + EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ oss << as_json(*tree, id, opts); }), expected_json); + EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ oss << as_yaml(node, opts); }), expected_yaml); + EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ oss << as_json(node, opts); }), expected_json); + EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ EmitterOStream em(opts, &oss); em.emit_as(EMIT_YAML, tree, id); }), expected_yaml); + EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ EmitterOStream em(opts, &oss); em.emit_as(EMIT_JSON, tree, id); }), expected_json); + EXPECT_EQ(emitrs_yaml(*tree, id, opts), expected_yaml); + EXPECT_EQ(emitrs_json(*tree, id, opts), expected_json); + EXPECT_EQ(emitrs_yaml(node, opts), expected_yaml); + EXPECT_EQ(emitrs_json(node, opts), expected_json); + EXPECT_EQ(emitrs_append(to_csubstr(append_prefix), [&](std::string *s) { emitrs_yaml(*tree, id, opts, s, /*append*/true); } ), append_prefix + expected_yaml); + EXPECT_EQ(emitrs_append(to_csubstr(append_prefix), [&](std::string *s) { emitrs_json(*tree, id, opts, s, /*append*/true); } ), append_prefix + expected_json); + EXPECT_EQ(emitrs_append(to_csubstr(append_prefix), [&](std::string *s) { emitrs_yaml(node, opts, s, /*append*/true); } ), append_prefix + expected_yaml); + EXPECT_EQ(emitrs_append(to_csubstr(append_prefix), [&](std::string *s) { emitrs_json(node, opts, s, /*append*/true); } ), append_prefix + expected_json); + bailonfail(); + if(isroot) + { + EXPECT_EQ(emit2buf([&](substr buf){ return emit_yaml(*tree, opts, buf); }), expected_yaml); + bailonfail(); + EXPECT_EQ(emit2buf([&](substr buf){ return emit_json(*tree, opts, buf); }), expected_json); + bailonfail(); + EXPECT_EQ(emit2buf([&](substr buf){ EmitterBuf em(opts, buf); em.emit_as(EMIT_YAML, tree); return em.get_result(/*error_on_excess*/true); }), expected_yaml); + EXPECT_EQ(emit2buf([&](substr buf){ EmitterBuf em(opts, buf); em.emit_as(EMIT_JSON, tree); return em.get_result(/*error_on_excess*/true); }), expected_json); + EXPECT_EQ(emit2file([&](FILE *f){ return emit_yaml(*tree, opts, f); }), expected_yaml); + EXPECT_EQ(emit2file([&](FILE *f){ return emit_json(*tree, opts, f); }), expected_json); + EXPECT_EQ(emit2file([&](FILE *f){ EmitterFile em(opts, f); return em.emit_as(EMIT_YAML, tree); }), expected_yaml); + EXPECT_EQ(emit2file([&](FILE *f){ EmitterFile em(opts, f); return em.emit_as(EMIT_JSON, tree); }), expected_json); + EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ oss << as_yaml(*tree, opts); }), expected_yaml); + EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ oss << as_json(*tree, opts); }), expected_json); + EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ EmitterOStream em(opts, &oss); em.emit_as(EMIT_YAML, tree); }), expected_yaml); + EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ EmitterOStream em(opts, &oss); em.emit_as(EMIT_JSON, tree); }), expected_json); + EXPECT_EQ(emitrs_yaml(*tree, opts), expected_yaml); + EXPECT_EQ(emitrs_json(*tree, opts), expected_json); + EXPECT_EQ(emitrs_append(to_csubstr(append_prefix), [&](std::string *s) { emitrs_yaml(*tree, opts, s, /*append*/true); } ), append_prefix + expected_yaml); + EXPECT_EQ(emitrs_append(to_csubstr(append_prefix), [&](std::string *s) { emitrs_json(*tree, opts, s, /*append*/true); } ), append_prefix + expected_json); + bailonfail(); + } + if(!tree->empty() && tree->depth_desc(id != NONE ? id : tree->root_id()) > 1) + { + // error on max depth + EmitOptions optsd = opts; + optsd = optsd.max_depth(0); + RYML_EXPECT_ERROR(check_error_visit(tree, [&]{ return emit2buf([&](substr buf){ return emit_yaml(*tree, id, optsd, buf); }); })); + bailonfail(); + RYML_EXPECT_ERROR(check_error_visit(tree, [&]{ return emit2buf([&](substr buf){ return emit_json(*tree, id, optsd, buf); }); })); + bailonfail(); + RYML_EXPECT_ERROR(check_error_visit(tree, [&]{ return emit2buf([&](substr buf){ return emit_yaml(node, optsd, buf); }); })); + RYML_EXPECT_ERROR(check_error_visit(tree, [&]{ return emit2buf([&](substr buf){ return emit_json(node, optsd, buf); }); })); + RYML_EXPECT_ERROR(check_error_visit(tree, [&]{ return emit2file([&](FILE *f){ emit_yaml(*tree, id, optsd, f); }); })); + RYML_EXPECT_ERROR(check_error_visit(tree, [&]{ return emit2file([&](FILE *f){ emit_json(*tree, id, optsd, f); }); })); + RYML_EXPECT_ERROR(check_error_visit(tree, [&]{ return emit2file([&](FILE *f){ emit_yaml(node, optsd, f); }); })); + RYML_EXPECT_ERROR(check_error_visit(tree, [&]{ return emit2file([&](FILE *f){ emit_json(node, optsd, f); }); })); + RYML_EXPECT_ERROR(check_error_visit(tree, [&]{ return emit2stream([&](std::ostringstream &oss){ oss << as_yaml(*tree, id, optsd); }); })); + RYML_EXPECT_ERROR(check_error_visit(tree, [&]{ return emit2stream([&](std::ostringstream &oss){ oss << as_json(*tree, id, optsd); }); })); + RYML_EXPECT_ERROR(check_error_visit(tree, [&]{ return emit2stream([&](std::ostringstream &oss){ oss << as_yaml(node, optsd); }); })); + RYML_EXPECT_ERROR(check_error_visit(tree, [&]{ return emit2stream([&](std::ostringstream &oss){ oss << as_json(node, optsd); }); })); + RYML_EXPECT_ERROR(check_error_visit(tree, [&]{ return emitrs_yaml(*tree, id, optsd); })); + RYML_EXPECT_ERROR(check_error_visit(tree, [&]{ return emitrs_json(*tree, id, optsd); })); + RYML_EXPECT_ERROR(check_error_visit(tree, [&]{ return emitrs_yaml(node, optsd); })); + RYML_EXPECT_ERROR(check_error_visit(tree, [&]{ return emitrs_json(node, optsd); })); + bailonfail(); + if(id == NONE || id == tree->root_id()) + { + RYML_EXPECT_ERROR(check_error_visit(tree, [&]{ return emit2buf([&](substr buf){ return emit_yaml(*tree, optsd, buf); }); })); + bailonfail(); + RYML_EXPECT_ERROR(check_error_visit(tree, [&]{ return emit2buf([&](substr buf){ return emit_json(*tree, optsd, buf); }); })); + bailonfail(); + RYML_EXPECT_ERROR(check_error_visit(tree, [&]{ return emit2file([&](FILE *f){ emit_yaml(*tree, optsd, f); }); })); + RYML_EXPECT_ERROR(check_error_visit(tree, [&]{ return emit2file([&](FILE *f){ emit_json(*tree, optsd, f); }); })); + RYML_EXPECT_ERROR(check_error_visit(tree, [&]{ return emit2stream([&](std::ostringstream &oss){ oss << as_yaml(ConstNodeRef(tree), optsd); }); })); + RYML_EXPECT_ERROR(check_error_visit(tree, [&]{ return emit2stream([&](std::ostringstream &oss){ oss << as_json(ConstNodeRef(tree), optsd); }); })); + RYML_EXPECT_ERROR(check_error_visit(tree, [&]{ return emitrs_yaml(*tree, optsd); })); + RYML_EXPECT_ERROR(check_error_visit(tree, [&]{ return emitrs_json(*tree, optsd); })); + bailonfail(); + } + } + tmpf_.clear(); + return; +failure: + print_tree(tree); + tmpf_.clear(); +} +void test_emits_tree(ConstNodeRef node, std::string const& expected_yaml, std::string const& expected_json, EmitOptions const& opts={}) +{ + test_emits_tree(node.tree(), node.id(), expected_yaml, expected_json, opts); +} + + +using extra::ievt::evt_size; +using extra::ievt::evt_bits; + +uint32_t getdepth(evt_bits const* evts, evt_size pos) +{ + using namespace extra; + uint32_t count = 0; + uint32_t maxcount = 0; + while(evts[pos] != ievt::ESTR) + { + evt_bits evt = evts[pos]; + if(evt & (ievt::SEQ_|ievt::MAP_)) + { + if(evt & ievt::BEG_) + { + if(++count > maxcount) + maxcount = count; + } + else if(evt & ievt::END_) + { + if(count) + --count; + else + break; + } + } + pos = ievt::nextpos(evts, pos); + } + return maxcount; +} +void test_emits_ints(IntBufsCR ints, evt_size pos, std::string const& expected_yaml, std::string const& expected_json, EmitOptions const& opts={}, bool with_json=true) +{ + uint32_t depth = 0; + retonfail(); + RYML_TRACE_FMT("startpos={}", pos); + EXPECT_EQ(ints.emitrs_yaml(opts, pos), expected_yaml); + bailonfail(); + EXPECT_EQ(emit2buf([&](substr buf){ size_t sz = ints.emit_yaml(buf, opts, pos); buf.str = nullptr; buf.len = sz ; return buf; }), expected_yaml); + EXPECT_EQ(emit2file([&](FILE *f){ return ints.emit_yaml(f, opts, pos); }), expected_yaml); + EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ ints.emit_yaml_stream(oss, opts, pos); }), expected_yaml); + bailonfail(); + depth = getdepth(ints.evts.ptr, pos); + if(depth > 1) + { + EmitOptions optsd = opts; + optsd = optsd.max_depth(0); + RYML_TRACE_FMT("depth={}", depth); + RYML_EXPECT_ERROR(check_error_basic([&]{ ints.emitrs_yaml(optsd, pos); })); + bailonfail(); + RYML_EXPECT_ERROR(check_error_basic([&]{ emit2buf([&](substr buf){ size_t sz = ints.emit_yaml(buf, optsd, pos); buf.str = nullptr; buf.len = sz ; return buf; }); })); + RYML_EXPECT_ERROR(check_error_basic([&]{ emit2file([&](FILE *f){ return ints.emit_yaml(f, optsd, pos); }); })); + RYML_EXPECT_ERROR(check_error_basic([&]{ emit2stream([&](std::ostringstream &oss){ ints.emit_yaml_stream(oss, optsd, pos); }); })); + } + if(with_json) + { + EXPECT_EQ(ints.emitrs_json(opts, pos), expected_json); + bailonfail(); + EXPECT_EQ(emit2buf([&](substr buf){ size_t sz = ints.emit_json(buf, opts, pos); buf.str = nullptr; buf.len = sz ; return buf; }), expected_json); + EXPECT_EQ(emit2file([&](FILE *f){ return ints.emit_json(f, opts, pos); }), expected_json); + EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ ints.emit_json_stream(oss, opts, pos); }), expected_json); + if(depth > 1) + { + EmitOptions optsd = opts; + optsd = optsd.max_depth(0); + RYML_TRACE_FMT("depth={}", depth); + RYML_EXPECT_ERROR(check_error_basic([&]{ ints.emitrs_json(optsd, pos); })); + bailonfail(); + RYML_EXPECT_ERROR(check_error_basic([&]{ emit2buf([&](substr buf){ size_t sz = ints.emit_json(buf, optsd, pos); buf.str = nullptr; buf.len = sz ; return buf; }); })); + RYML_EXPECT_ERROR(check_error_basic([&]{ emit2file([&](FILE *f){ return ints.emit_json(f, optsd, pos); }); })); + RYML_EXPECT_ERROR(check_error_basic([&]{ emit2stream([&](std::ostringstream &oss){ ints.emit_json_stream(oss, optsd, pos); }); })); + } + } + tmpf_.clear(); + return; +failure: + tmpf_.clear(); + ints.print(); +} +void test_emits_ints_nojson(IntBufsCR ints, evt_size pos, std::string const& expected_yaml, EmitOptions const& opts={}) +{ + test_emits_ints(ints, pos, expected_yaml, "", opts, false); +} + +void test_emits_ints(evt_size pos, std::string const& expected_yaml, std::string const& expected_json, EmitOptions const& opts={}) +{ + retonfail(); + IntBufs ints; + std::string yaml = expected_yaml; + parse_ints(to_substr(yaml), &ints); + test_emits_ints(ints, pos, expected_yaml, expected_json, opts); +} + +void test_emits(Tree const& t, id_type id, evt_size pos, std::string const& expected_yaml, std::string const& expected_json, EmitOptions const& opts={}) +{ + test_emits_tree(&t, id, expected_yaml, expected_json, opts); + test_emits_ints(pos, expected_yaml, expected_json, opts); +} +void test_emits(TreeAndInts const& ti, id_type id, evt_size pos, std::string const& expected_yaml, std::string const& expected_json, EmitOptions const& opts={}) +{ + test_emits_tree(&ti.tree, id, expected_yaml, expected_json, opts); + test_emits_ints(ti.ints, pos, expected_yaml, expected_json, opts); +} +void test_emits(Tree const& t, id_type id, std::string const& expected_yaml, std::string const& expected_json, EmitOptions const& opts={}) +{ + test_emits_tree(&t, id, expected_yaml, expected_json, opts); + if(id == NONE || id == 0) + test_emits_ints(0, expected_yaml, expected_json, opts); +} +void test_emits(TreeAndInts const& ti, id_type id, std::string const& expected_yaml, std::string const& expected_json, EmitOptions const& opts={}) +{ + test_emits_tree(&ti.tree, id, expected_yaml, expected_json, opts); + if(id == NONE || id == 0) + test_emits_ints(ti.ints, 0, expected_yaml, expected_json, opts); +} + +void test_emits(Tree const& t, std::string const& expected_yaml, std::string const& expected_json, EmitOptions const& opts={}) +{ + if(t.empty()) + test_emits_tree(&t, NONE, expected_yaml, expected_json, opts); + else + test_emits_tree(&t, t.root_id(), expected_yaml, expected_json, opts); + test_emits_ints(0, expected_yaml, expected_json, opts); +} +void test_emits(TreeAndInts const& ti, std::string const& expected_yaml, std::string const& expected_json, EmitOptions const& opts={}) +{ + if(ti.tree.empty()) + test_emits_tree(&ti.tree, NONE, expected_yaml, expected_json, opts); + else + test_emits_tree(&ti.tree, ti.tree.root_id(), expected_yaml, expected_json, opts); + test_emits_ints(ti.ints, 0, expected_yaml, expected_json, opts); +} + +void test_emits(ConstNodeRef node, evt_size pos, std::string const& expected_yaml, std::string const& expected_json, EmitOptions const& opts={}) +{ + test_emits_tree(node.tree(), node.id(), expected_yaml, expected_json, opts); + test_emits_ints(pos, expected_yaml, expected_json, opts); +} +void test_emits(TreeAndInts const& ti, ConstNodeRef node, evt_size pos, std::string const& expected_yaml, std::string const& expected_json, EmitOptions const& opts={}) +{ + ASSERT_EQ(node.tree(), &ti.tree); + test_emits_tree(node.tree(), node.id(), expected_yaml, expected_json, opts); + test_emits_ints(ti.ints, pos, expected_yaml, expected_json, opts); +} +void test_emits(ConstNodeRef node, std::string const& expected_yaml, std::string const& expected_json, EmitOptions const& opts={}) +{ + test_emits_tree(node.tree(), node.id(), expected_yaml, expected_json, opts); + if(node.id() == NONE || (node.tree() && node.id() == node.tree()->root_id_maybe())) + test_emits_ints(0, expected_yaml, expected_json, opts); +} +void test_emits(TreeAndInts const& ti, ConstNodeRef node, std::string const& expected_yaml, std::string const& expected_json, EmitOptions const& opts={}) +{ + ASSERT_EQ(node.tree(), &ti.tree); + test_emits_tree(node.tree(), node.id(), expected_yaml, expected_json, opts); + if(node.id() == NONE || (node.tree() && node.id() == node.tree()->root_id_maybe())) + test_emits_ints(ti.ints, 0, expected_yaml, expected_json, opts); +} + +#define test_emits_(...) { SCOPED_TRACE("test_emits"); test_emits(__VA_ARGS__); } +#define test_emits_tree_(...) { SCOPED_TRACE("test_emits"); test_emits_tree(__VA_ARGS__); } +#define test_emits_ints_(...) { SCOPED_TRACE("test_emits_ints"); test_emits_ints(__VA_ARGS__); } +#define test_emits_ints_nojson_(...) { SCOPED_TRACE("test_emits_ints_nojson"); test_emits_ints_nojson(__VA_ARGS__); } + + +using extra::ievt::evt_bits; +using strref = std::string const&; +namespace xievt = extra::ievt; + +struct TmpStyle +{ + Tree *tree; + id_type id; + NodeType prev; + IntBufs *ints; + evt_size evt_pos; + evt_bits evt_prev; + bool with_key; + evt_size evt_pos_key; + evt_bits evt_prev_key; + extra::ievt::evt_bits prev_ints; + TmpStyle(TreeAndInts &ti, NodeRef const& n, NodeType tmp, evt_size evt_pos_, evt_bits evt, + bool with_key_=false, evt_size evt_pos_key_={}) + : TmpStyle(&ti.tree, &ti.ints, n.id(), tmp, evt_pos_, evt, with_key_, evt_pos_key_) {} + TmpStyle(Tree *tree_, IntBufs *ints_, id_type id_, NodeType tmp, evt_size evt_pos_, evt_bits evt, + bool with_key_=false, evt_size evt_pos_key_={}) + : tree(tree_) + , id(id_) + , prev() + , ints(ints_) + , evt_pos(evt_pos_) + , evt_prev() + , with_key(with_key_) + , evt_pos_key(evt_pos_key_) + , evt_prev_key() + { + if(tree) + { + prev = tree_->type(id); + (tree->_p(id)->m_type &= ~(CONTAINER_STYLE|SCALAR_STYLE)) |= tmp; + } + if(ints) + { + RYML_ASSERT_BASIC_(evt_pos < ints->evts.len); + evt_prev = ints->evts.ptr[evt_pos]; + (ints->evts.ptr[evt_pos] &= ~(xievt::detail::styles_ievt_cont|xievt::detail::styles_ievt_sclr)) |= evt; // NOLINT + if(with_key) + { + evt_prev_key = ints->evts.ptr[evt_pos_key]; + (ints->evts.ptr[evt_pos_key] &= ~(xievt::detail::styles_ievt_cont|xievt::detail::styles_ievt_sclr)) |= evt; // NOLINT + } + } + } + ~TmpStyle() + { + if(tree) + tree->_p(id)->m_type = prev; + if(ints) + { + ints->evts.ptr[evt_pos] = evt_prev; + if(with_key) + ints->evts.ptr[evt_pos_key] = evt_prev_key; + } + } + + // legacy: + TmpStyle(NodeRef n, NodeType tmp) : TmpStyle(n.tree(), nullptr, n.id(), tmp, {}, {}) {} + TmpStyle(Tree &t_, id_type id_, NodeType tmp) : TmpStyle(&t_, nullptr, id_, tmp, {}, {}) {} + TmpStyle(TreeAndInts &ti, evt_size evt_pos_, evt_bits evt) : TmpStyle(nullptr, &ti.ints, {}, {}, evt_pos_, evt) {} + TmpStyle(TreeAndInts &ti, NodeType tmp, evt_bits evt) : TmpStyle(&ti.tree, &ti.ints, ti.tree.root_id(), tmp, 0, evt) {} +}; + +TmpStyle mknosty(TreeAndInts &ti, NodeRef n, evt_size pos) { return {ti, n, NodeType{}, pos, evt_bits{}}; } +TmpStyle mkplai(TreeAndInts &ti, NodeRef n, evt_size pos) { return {ti, n, VAL_PLAIN, pos, xievt::PLAI}; } +TmpStyle mksquo(TreeAndInts &ti, NodeRef n, evt_size pos) { return {ti, n, VAL_SQUO, pos, xievt::SQUO}; } +TmpStyle mkdquo(TreeAndInts &ti, NodeRef n, evt_size pos) { return {ti, n, VAL_DQUO, pos, xievt::DQUO}; } +TmpStyle mkfold(TreeAndInts &ti, NodeRef n, evt_size pos) { return {ti, n, VAL_FOLDED, pos, xievt::FOLD}; } +TmpStyle mklitl(TreeAndInts &ti, NodeRef n, evt_size pos) { return {ti, n, VAL_LITERAL, pos, xievt::LITL}; } + +TmpStyle mknostykv(TreeAndInts &ti, NodeRef n, evt_size kpos, evt_size vpos) { return {ti, n, NOTYPE, vpos, evt_bits{}, true, kpos}; } +TmpStyle mkplaikv(TreeAndInts &ti, NodeRef n, evt_size kpos, evt_size vpos) { return {ti, n, KEY_PLAIN|VAL_PLAIN, vpos, xievt::PLAI, true, kpos}; } +TmpStyle mksquokv(TreeAndInts &ti, NodeRef n, evt_size kpos, evt_size vpos) { return {ti, n, KEY_SQUO|VAL_SQUO, vpos, xievt::SQUO, true, kpos}; } +TmpStyle mkdquokv(TreeAndInts &ti, NodeRef n, evt_size kpos, evt_size vpos) { return {ti, n, KEY_DQUO|VAL_DQUO, vpos, xievt::DQUO, true, kpos}; } +TmpStyle mkfoldkv(TreeAndInts &ti, NodeRef n, evt_size kpos, evt_size vpos) { return {ti, n, KEY_FOLDED|VAL_FOLDED, vpos, xievt::FOLD, true, kpos}; } +TmpStyle mklitlkv(TreeAndInts &ti, NodeRef n, evt_size kpos, evt_size vpos) { return {ti, n, KEY_LITERAL|VAL_LITERAL, vpos, xievt::LITL, true, kpos}; } + +TmpStyle mkblk(TreeAndInts &ti, NodeRef n, evt_size pos) { return {ti, n, BLOCK, pos, xievt::BLCK}; } +TmpStyle mkflowsl(TreeAndInts &ti, NodeRef n, evt_size pos, evt_bits spc=0) { return {ti, n, FLOW_SL, pos, xievt::FLOW|xievt::FSL_|spc}; } +TmpStyle mkflowml1(TreeAndInts &ti, NodeRef n, evt_size pos, evt_bits spc=0) { return {ti, n, FLOW_ML1, pos, xievt::FLOW|xievt::FML1|spc}; } +TmpStyle mkflowmln(TreeAndInts &ti, NodeRef n, evt_size pos, evt_bits spc=0) { return {ti, n, FLOW_MLN, pos, xievt::FLOW|xievt::FMLN|spc}; } + +TmpStyle mknosty(IntBufs &ti, evt_size pos) { return {nullptr, &ti, 0, NOTYPE, pos, evt_bits{}}; } +TmpStyle mkblk(IntBufs &ti, evt_size pos) { return {nullptr, &ti, 0, NOTYPE, pos, xievt::BLCK}; } +TmpStyle mkflowsl(IntBufs &ti, evt_size pos, evt_bits spc=0) { return {nullptr, &ti, 0, NOTYPE, pos, xievt::FLOW|xievt::FSL_|spc}; } +TmpStyle mkflowml1(IntBufs &ti, evt_size pos, evt_bits spc=0) { return {nullptr, &ti, 0, NOTYPE, pos, xievt::FLOW|xievt::FML1|spc}; } +TmpStyle mkflowmln(IntBufs &ti, evt_size pos, evt_bits spc=0) { return {nullptr, &ti, 0, NOTYPE, pos, xievt::FLOW|xievt::FMLN|spc}; } +// use the extra arg to disambiguate overloads above ^ +TmpStyle mknosty(IntBufs &ti, IntBufs &, evt_size kpos, evt_size vpos) { return {nullptr, &ti, 0, NOTYPE, vpos, evt_bits{}, true, kpos}; } +TmpStyle mkblk(IntBufs &ti, IntBufs &, evt_size kpos, evt_size vpos) { return {nullptr, &ti, 0, NOTYPE, vpos, xievt::BLCK, true, kpos}; } +TmpStyle mkflowsl(IntBufs &ti, IntBufs &, evt_size kpos, evt_size vpos, evt_bits spc=0) { return {nullptr, &ti, 0, NOTYPE, vpos, xievt::FLOW|xievt::FSL_|spc, true, kpos}; } +TmpStyle mkflowml1(IntBufs &ti, IntBufs &, evt_size kpos, evt_size vpos, evt_bits spc=0) { return {nullptr, &ti, 0, NOTYPE, vpos, xievt::FLOW|xievt::FML1|spc, true, kpos}; } +TmpStyle mkflowmln(IntBufs &ti, IntBufs &, evt_size kpos, evt_size vpos, evt_bits spc=0) { return {nullptr, &ti, 0, NOTYPE, vpos, xievt::FLOW|xievt::FMLN|spc, true, kpos}; } +#define TMPSTY(sty, ...) TmpStyle C4_XCAT(tmpsty_, __LINE__) = mk##sty(__VA_ARGS__) + + +//----------------------------------------------------------------------------- + +#define test_emit_yaml_(...) { SCOPED_TRACE("here"); test_emit_yaml(__VA_ARGS__); } +#define test_emit_yaml_tree_(...) { SCOPED_TRACE("here"); test_emit_yaml_tree(__VA_ARGS__); } +#define test_emit_yaml_ints_(...) { SCOPED_TRACE("here"); test_emit_yaml_ints(__VA_ARGS__); } +#define test_emit_json_(...) { SCOPED_TRACE("here"); test_emit_json(__VA_ARGS__); } +#define test_emit_json_tree_(...) { SCOPED_TRACE("here"); test_emit_json_tree(__VA_ARGS__); } +#define test_emit_json_ints_(...) { SCOPED_TRACE("here"); test_emit_json_ints(__VA_ARGS__); } + +static const EmitOptions without_dash = {}; +static const EmitOptions with_dash = EmitOptions{}.emit_nonroot_dash(true); +static const EmitOptions with_key = {}; +static const EmitOptions without_key = EmitOptions{}.emit_nonroot_key(false); +static const EmitOptions noindent = EmitOptions{}.indent_flow_ml(false); +static const EmitOptions with_flow_spc = EmitOptions{}.force_flow_spc(true); + +TEST(emit_nested, preconditions) +{ + ASSERT_FALSE(without_dash.emit_nonroot_dash()); + ASSERT_TRUE(with_dash.emit_nonroot_dash()); + ASSERT_TRUE(with_key.emit_nonroot_key()); + ASSERT_FALSE(without_key.emit_nonroot_key()); + ASSERT_FALSE(noindent.indent_flow_ml()); + ASSERT_TRUE(noindent.emit_nonroot_key()); + ASSERT_TRUE(with_flow_spc.force_flow_spc()); +} + TEST(emit_nested, basic) { - const Tree tree = parse_in_arena(R"(- a + TreeAndInts ti = parse_tree_and_ints(R"(- a - b - x0: 1 x1: 2 @@ -229,58 +781,359 @@ TEST(emit_nested, basic) - members - here )"); - EmitOptions without_dash = {}; - EmitOptions with_dash = EmitOptions{}.emit_nonroot_dash(true); - EmitOptions with_key = {}; - EmitOptions without_key = EmitOptions{}.emit_nonroot_key(false); - ASSERT_FALSE(without_dash.emit_nonroot_dash()); - ASSERT_TRUE(with_dash.emit_nonroot_dash()); - ASSERT_TRUE(with_key.emit_nonroot_key()); - ASSERT_FALSE(without_key.emit_nonroot_key()); - EXPECT_EQ(emitrs_yaml(tree[3]["beer"][0], without_dash), "Rochefort 10"); - EXPECT_EQ(emitrs_yaml(tree[3]["beer"][0], with_dash), "- Rochefort 10\n"); - EXPECT_EQ(emitrs_yaml(tree[3]["beer"][3], without_dash), R"(- and so -- many other -- wonderful beers -)"); - EXPECT_EQ(emitrs_yaml(tree[3]["beer"][3], with_dash), R"(- - and so + test_emit_yaml_(ti.tree[2], ti.ints, 9, without_dash, "x0: 1\nx1: 2\n"); + test_emit_yaml_(ti.tree[2], ti.ints, 9, with_dash, "- x0: 1\n x1: 2\n"); + { + SCOPED_TRACE("nosty"); + TMPSTY(nosty, ti, ti.tree[2], 9); + test_emit_yaml_(ti.tree[2], ti.ints, 9, without_dash, "x0: 1\nx1: 2\n"); + test_emit_yaml_(ti.tree[2], ti.ints, 9, with_dash, "- x0: 1\n x1: 2\n"); + } + { + SCOPED_TRACE("flowsl"); + TMPSTY(flowsl, ti, ti.tree[2], 9); + test_emit_yaml_(ti.tree[2], ti.ints, 9, without_dash, "{x0: 1,x1: 2}"); + test_emit_yaml_(ti.tree[2], ti.ints, 9, with_dash, "- {x0: 1,x1: 2}\n"); + } + test_emit_yaml_(ti.tree[3]["beer"][0], ti.ints, 57, without_dash, "Rochefort 10"); + test_emit_yaml_(ti.tree[3]["beer"][0], ti.ints, 57, with_dash, "- Rochefort 10\n"); + { + SCOPED_TRACE("nosty"); + TMPSTY(nosty, ti, ti.tree[3]["beer"], 57); + test_emit_yaml_(ti.tree[3]["beer"][0], ti.ints, 57, without_dash, "Rochefort 10"); + test_emit_yaml_(ti.tree[3]["beer"][0], ti.ints, 57, with_dash, "- Rochefort 10\n"); + } + test_emit_yaml_(ti.tree[3]["beer"][3], ti.ints, 66, without_dash, + "- and so\n" + "- many other\n" + "- wonderful beers\n"); + test_emit_yaml_(ti.tree[3]["beer"][3], ti.ints, 66, with_dash, + "- - and so\n" + " - many other\n" + " - wonderful beers\n"); + { + SCOPED_TRACE("nosty"); + TMPSTY(nosty, ti, ti.tree[3]["beer"], 66); + test_emit_yaml_(ti.tree[3]["beer"][3], ti.ints, 66, without_dash, + "- and so\n" + "- many other\n" + "- wonderful beers\n"); + test_emit_yaml_(ti.tree[3]["beer"][3], ti.ints, 66, with_dash, + "- - and so\n" + " - many other\n" + " - wonderful beers\n"); + } + { + std::string key = "beer"; + std::string val = R"(- Rochefort 10 +- Busch +- Leffe Rituel +- - and so - many other - wonderful beers -)"); - EXPECT_EQ(emitrs_yaml(tree[3]["beer"], with_key), R"(beer: +)"; + std::string keyval = R"(beer: - Rochefort 10 - Busch - Leffe Rituel - - and so - many other - wonderful beers -)"); - EXPECT_EQ(emitrs_yaml(tree[3]["beer"], without_key), R"(- Rochefort 10 -- Busch -- Leffe Rituel -- - and so - - many other - - wonderful beers -)"); +)"; + test_emit_yaml_tree_(ti.tree[3]["beer"], with_key, keyval); + test_emit_yaml_ints_(ti.ints, 53, with_key, keyval); + test_emit_yaml_ints_(ti.ints, 56, with_key, val); + test_emit_yaml_tree_(ti.tree[3]["beer"], without_key, val); + test_emit_yaml_ints_(ti.ints, 53, without_key, key); + test_emit_yaml_ints_(ti.ints, 56, without_key, val); + { + SCOPED_TRACE("nosty"); + TMPSTY(nostykv, ti, ti.tree[3]["beer"], 53, 56); + test_emit_yaml_tree_(ti.tree[3]["beer"], with_key, keyval); + test_emit_yaml_ints_(ti.ints, 53, with_key, keyval); + test_emit_yaml_ints_(ti.ints, 56, with_key, val); + test_emit_yaml_tree_(ti.tree[3]["beer"], without_key, val); + test_emit_yaml_ints_(ti.ints, 53, without_key, key); + test_emit_yaml_ints_(ti.ints, 56, without_key, val); + } + } +} + +TEST(emit_nested, scalar_key) +{ + std::string yaml = "" + "key: {c: d}\n" + "e: [f]\n" + "g: h\n" + "bmap:\n" + " a: b\n" + "bseq:\n" + " - a\n" + " - b\n" + ""; + TreeAndInts ti = parse_tree_and_ints(to_csubstr(yaml)); + test_emit_yaml_(ti.tree, ti.ints, 0, with_key, yaml);//BSTR + test_emit_yaml_(ti.tree, ti.ints, 0, without_key, yaml);//BSTR + test_emit_yaml_(ti.tree, ti.ints, 1, with_key, yaml);//BDOC + test_emit_yaml_(ti.tree, ti.ints, 1, without_key, yaml);//BDOC + test_emit_yaml_(ti.tree, ti.ints, 2, with_key, yaml);//BMAP + test_emit_yaml_(ti.tree, ti.ints, 2, without_key, yaml);//BMAP + // + test_emit_yaml_tree_(ti.tree["key"], with_key, "key: {c: d}\n"); + test_emit_yaml_ints_(ti.ints, 3, with_key, "key: {c: d}\n"); + test_emit_yaml_ints_(ti.ints, 6, with_key, "{c: d}"); + test_emit_yaml_tree_(ti.tree["key"], without_key, "{c: d}"); + test_emit_yaml_ints_(ti.ints, 3, without_key, "key"); + test_emit_yaml_ints_(ti.ints, 6, without_key, "{c: d}"); + { + SCOPED_TRACE("nosty"); + TMPSTY(nostykv, ti, ti.tree["key"], 3, 6); + test_emit_yaml_tree_(ti.tree["key"], with_key, "key:\n c: d\n"); + test_emit_yaml_ints_(ti.ints, 3, with_key, "key:\n c: d\n"); + test_emit_yaml_ints_(ti.ints, 6, with_key, "c: d\n"); + test_emit_yaml_tree_(ti.tree["key"], without_key, "c: d\n"); + test_emit_yaml_ints_(ti.ints, 3, without_key, "key"); + test_emit_yaml_ints_(ti.ints, 6, without_key, "c: d\n"); + } + // + test_emit_yaml_tree_(ti.tree["key"]["c"], with_key , "c: d\n"); + test_emit_yaml_ints_(ti.ints, 7, with_key , "c: d\n"); + test_emit_yaml_ints_(ti.ints, 10, with_key , "d"); + test_emit_yaml_tree_(ti.tree["key"]["c"], without_key, "d"); + test_emit_yaml_ints_(ti.ints, 7, without_key, "c"); + test_emit_yaml_ints_(ti.ints, 10, without_key, "d"); + // + test_emit_yaml_tree_(ti.tree["e"], with_key , "e: [f]\n"); + test_emit_yaml_ints_(ti.ints, 14, with_key , "e: [f]\n"); + test_emit_yaml_ints_(ti.ints, 17, with_key , "[f]"); + test_emit_yaml_tree_(ti.tree["e"], without_key, "[f]"); + test_emit_yaml_ints_(ti.ints, 14, without_key, "e"); + test_emit_yaml_ints_(ti.ints, 17, without_key, "[f]"); + { + SCOPED_TRACE("nosty"); + TMPSTY(nostykv, ti, ti.tree["e"], 14, 17); + test_emit_yaml_tree_(ti.tree["e"], with_key , "e:\n - f\n"); + test_emit_yaml_ints_(ti.ints, 14, with_key , "e:\n - f\n"); + test_emit_yaml_ints_(ti.ints, 17, with_key , "- f\n"); + test_emit_yaml_tree_(ti.tree["e"], without_key, "- f\n"); + test_emit_yaml_ints_(ti.ints, 14, without_key, "e"); + test_emit_yaml_ints_(ti.ints, 17, without_key, "- f\n"); + } + // + test_emit_yaml_tree_(ti.tree["g"], with_key , "g: h\n"); + test_emit_yaml_ints_(ti.ints, 22, with_key , "g: h\n"); + test_emit_yaml_ints_(ti.ints, 25, with_key , "h"); + test_emit_yaml_tree_(ti.tree["g"], without_key, "h"); + test_emit_yaml_ints_(ti.ints, 22, without_key, "g"); + test_emit_yaml_ints_(ti.ints, 25, without_key, "h"); + // + test_emit_yaml_tree_(ti.tree["bmap"], with_key , "bmap:\n a: b\n"); + test_emit_yaml_ints_(ti.ints, 28, with_key , "bmap:\n a: b\n"); + test_emit_yaml_ints_(ti.ints, 31, with_key , "a: b\n"); + test_emit_yaml_tree_(ti.tree["bmap"], without_key, "a: b\n"); + test_emit_yaml_ints_(ti.ints, 28, without_key, "bmap"); + test_emit_yaml_ints_(ti.ints, 31, without_key, "a: b\n"); + // + test_emit_yaml_tree_(ti.tree["bseq"], with_key , "bseq:\n - a\n - b\n"); + test_emit_yaml_ints_(ti.ints, 39, with_key , "bseq:\n - a\n - b\n"); + test_emit_yaml_ints_(ti.ints, 42, with_key , "- a\n- b\n"); + test_emit_yaml_tree_(ti.tree["bseq"], without_key, "- a\n- b\n"); + test_emit_yaml_ints_(ti.ints, 39, without_key, "bseq"); + test_emit_yaml_ints_(ti.ints, 42, without_key, "- a\n- b\n"); +} + +static void check_container_key_json_errs_(IntBufs & ints) +{ + auto check = [&]{ + RYML_EXPECT_ERROR(check_error_basic([&]{ ints.emitrs_json({}, 0); })); + RYML_EXPECT_ERROR(check_error_basic([&]{ ints.emitrs_json({}, 1); })); + RYML_EXPECT_ERROR(check_error_basic([&]{ ints.emitrs_json({}, 2); })); + RYML_EXPECT_ERROR(check_error_basic([&]{ ints.emitrs_json({}, 3); })); + RYML_EXPECT_ERROR(check_error_basic([&]{ ints.emitrs_json(with_key, 3); })); + RYML_EXPECT_ERROR(check_success( [&]{ ints.emitrs_json(without_key, 3); })); + RYML_EXPECT_ERROR(check_success( [&]{ ints.emitrs_json({}, 11); })); + }; + { + SCOPED_TRACE("nosty"); + TMPSTY(nosty, ints, 2); + check(); + } + { + SCOPED_TRACE("block"); + TMPSTY(blk, ints, 2); + check(); + } + { + SCOPED_TRACE("flowsl"); + TMPSTY(flowsl, ints, 2); + check(); + } + { + SCOPED_TRACE("flowml1"); + TMPSTY(flowml1, ints, 2); + check(); + } + { + SCOPED_TRACE("flowmln"); + TMPSTY(flowmln, ints, 2); + check(); + } +} + +TEST(emit_nested, container_key_1) +{ + char src[] = "[a, b]: {c: d}"; + IntBufs ints; + parse_ints(src, &ints); + test_emit_yaml_ints_(ints, 0, with_key, "? [a,b]\n: {c: d}\n");//BSTR + test_emit_yaml_ints_(ints, 0, without_key, "? [a,b]\n: {c: d}\n");//BSTR + test_emit_yaml_ints_(ints, 1, with_key, "? [a,b]\n: {c: d}\n");//BDOC + test_emit_yaml_ints_(ints, 1, without_key, "? [a,b]\n: {c: d}\n");//BDOC + test_emit_yaml_ints_(ints, 2, with_key, "? [a,b]\n: {c: d}\n");//BMAP + test_emit_yaml_ints_(ints, 2, without_key, "? [a,b]\n: {c: d}\n");//BMAP + test_emit_yaml_ints_(ints, 3, with_key, "? [a,b]\n: {c: d}\n");//KEY|BSEQ + test_emit_yaml_ints_(ints, 3, without_key, "[a,b]");//KEY|BSEQ + test_emit_yaml_ints_(ints, 4, with_key, "a"); + test_emit_yaml_ints_(ints, 4, without_key, "a"); + test_emit_yaml_ints_(ints, 7, with_key, "b"); + test_emit_yaml_ints_(ints, 7, without_key, "b"); + test_emit_yaml_ints_(ints, 11, with_key, "{c: d}"); + test_emit_yaml_ints_(ints, 11, without_key, "{c: d}"); + test_emit_yaml_ints_(ints, 12, with_key, "c: d\n"); + test_emit_yaml_ints_(ints, 12, without_key, "c"); + test_emit_yaml_ints_(ints, 15, with_key, "d"); + test_emit_yaml_ints_(ints, 15, without_key, "d"); + { + SCOPED_TRACE("nosty"); + TMPSTY(nosty, ints, 2); + TMPSTY(nosty, ints, 3); + TMPSTY(nosty, ints, 11); + test_emit_yaml_ints_(ints, 0, with_key, "?\n - a\n - b\n:\n c: d\n");//BSTR + test_emit_yaml_ints_(ints, 0, without_key, "?\n - a\n - b\n:\n c: d\n");//BSTR + test_emit_yaml_ints_(ints, 1, with_key, "?\n - a\n - b\n:\n c: d\n");//BDOC + test_emit_yaml_ints_(ints, 1, without_key, "?\n - a\n - b\n:\n c: d\n");//BDOC + test_emit_yaml_ints_(ints, 2, with_key, "?\n - a\n - b\n:\n c: d\n");//BMAP + test_emit_yaml_ints_(ints, 2, without_key, "?\n - a\n - b\n:\n c: d\n");//BMAP + test_emit_yaml_ints_(ints, 3, with_key, "?\n - a\n - b\n:\n c: d\n");//BMAP + test_emit_yaml_ints_(ints, 3, without_key, "- a\n- b\n");//KEY|BSEQ + test_emit_yaml_ints_(ints, 4, with_key, "a"); + test_emit_yaml_ints_(ints, 4, without_key, "a"); + test_emit_yaml_ints_(ints, 7, with_key, "b"); + test_emit_yaml_ints_(ints, 7, without_key, "b"); + test_emit_yaml_ints_(ints, 11, with_key, "c: d\n"); + test_emit_yaml_ints_(ints, 11, without_key, "c: d\n"); + test_emit_yaml_ints_(ints, 12, with_key, "c: d\n"); + test_emit_yaml_ints_(ints, 12, without_key, "c"); + test_emit_yaml_ints_(ints, 15, with_key, "d"); + test_emit_yaml_ints_(ints, 15, without_key, "d"); + } + { + SCOPED_TRACE("key err"); + check_container_key_json_errs_(ints); + } +} + +TEST(emit_nested, container_key_2) +{ + char src[] = "{a: b}: [c, d]"; + IntBufs ints; + parse_ints(src, &ints); + test_emit_yaml_ints_(ints, 0, with_key, "? {a: b}\n: [c,d]\n"); + test_emit_yaml_ints_(ints, 0, without_key, "? {a: b}\n: [c,d]\n"); + test_emit_yaml_ints_(ints, 1, with_key, "? {a: b}\n: [c,d]\n"); + test_emit_yaml_ints_(ints, 1, without_key, "? {a: b}\n: [c,d]\n"); + test_emit_yaml_ints_(ints, 2, with_key, "? {a: b}\n: [c,d]\n"); + test_emit_yaml_ints_(ints, 2, without_key, "? {a: b}\n: [c,d]\n"); + test_emit_yaml_ints_(ints, 3, with_key, "? {a: b}\n: [c,d]\n"); + test_emit_yaml_ints_(ints, 3, without_key, "{a: b}"); + test_emit_yaml_ints_(ints, 4, with_key, "a: b\n"); + test_emit_yaml_ints_(ints, 4, without_key, "a"); + test_emit_yaml_ints_(ints, 7, with_key, "b"); + test_emit_yaml_ints_(ints, 7, without_key, "b"); + test_emit_yaml_ints_(ints, 11, with_key, "[c,d]"); + test_emit_yaml_ints_(ints, 11, without_key, "[c,d]"); + test_emit_yaml_ints_(ints, 12, with_key, "c"); + test_emit_yaml_ints_(ints, 12, without_key, "c"); + test_emit_yaml_ints_(ints, 15, with_key, "d"); + test_emit_yaml_ints_(ints, 15, without_key, "d"); + { + SCOPED_TRACE("nosty"); + TMPSTY(nosty, ints, 2); + TMPSTY(nosty, ints, 3); + TMPSTY(nosty, ints, 11); + test_emit_yaml_ints_(ints, 0, with_key, "?\n a: b\n:\n - c\n - d\n"); + test_emit_yaml_ints_(ints, 0, without_key, "?\n a: b\n:\n - c\n - d\n"); + test_emit_yaml_ints_(ints, 1, with_key, "?\n a: b\n:\n - c\n - d\n"); + test_emit_yaml_ints_(ints, 1, without_key, "?\n a: b\n:\n - c\n - d\n"); + test_emit_yaml_ints_(ints, 2, with_key, "?\n a: b\n:\n - c\n - d\n"); + test_emit_yaml_ints_(ints, 2, without_key, "?\n a: b\n:\n - c\n - d\n"); + test_emit_yaml_ints_(ints, 3, with_key, "?\n a: b\n:\n - c\n - d\n"); + test_emit_yaml_ints_(ints, 3, without_key, "a: b\n"); + test_emit_yaml_ints_(ints, 4, with_key, "a: b\n"); + test_emit_yaml_ints_(ints, 4, without_key, "a"); + test_emit_yaml_ints_(ints, 7, with_key, "b"); + test_emit_yaml_ints_(ints, 7, without_key, "b"); + test_emit_yaml_ints_(ints, 11, with_key, "- c\n- d\n"); + test_emit_yaml_ints_(ints, 11, without_key, "- c\n- d\n"); + test_emit_yaml_ints_(ints, 12, with_key, "c"); + test_emit_yaml_ints_(ints, 12, without_key, "c"); + test_emit_yaml_ints_(ints, 15, with_key, "d"); + test_emit_yaml_ints_(ints, 15, without_key, "d"); + } + { + SCOPED_TRACE("key err"); + check_container_key_json_errs_(ints); + } +} + + +//----------------------------------------------------------------------------- + +TEST(emit, null_ints) +{ + IntBufs ints = {}; + ASSERT_EQ(ints.evts.len, 0); + ASSERT_EQ(ints.evts.ptr, nullptr); + ASSERT_EQ(ints.src.len, 0); + ASSERT_EQ(ints.src.str, nullptr); + ASSERT_EQ(ints.arena.len, 0); + ASSERT_EQ(ints.arena.str, nullptr); + std::string ret; + RYML_EXPECT_ERROR(check_success([&]{ ret = ints.emitrs_yaml(); })); + EXPECT_TRUE(ret.empty()); + RYML_EXPECT_ERROR(check_success([&]{ ret = ints.emitrs_json(); })); } + +//----------------------------------------------------------------------------- + TEST(emit_block_seq, ambiguous_plain_emitted_as_squo) { EXPECT_EQ(scalar_style_query_plain_flow(": odd"), false); EXPECT_EQ(scalar_style_query_plain_flow(":\todd"), false); EXPECT_EQ(scalar_style_choose_flow(": odd"), SCALAR_SQUO); EXPECT_EQ(scalar_style_choose_flow(":\todd"), SCALAR_SQUO); + EXPECT_EQ(xievt::detail::scalar_style_choose_flow_ievt(": odd"), xievt::SQUO); + EXPECT_EQ(xievt::detail::scalar_style_choose_flow_ievt(":\todd"), xievt::SQUO); + EXPECT_EQ(xievt::detail::scalar_style_choose_flow_ievt("\n \t"), xievt::DQUO); + EXPECT_EQ(xievt::detail::scalar_style_choose_flow_ievt(csubstr{}), xievt::PLAI); + EXPECT_EQ(xievt::detail::scalar_style_choose_flow_ievt(csubstr("foo").first(0)), xievt::SQUO); EXPECT_EQ(scalar_style_query_plain_block(": odd"), false); EXPECT_EQ(scalar_style_query_plain_block(":\todd"), false); EXPECT_EQ(scalar_style_choose_block(": odd"), SCALAR_SQUO); EXPECT_EQ(scalar_style_choose_block(":\todd"), SCALAR_SQUO); + EXPECT_EQ(xievt::detail::scalar_style_choose_block_ievt(": odd"), xievt::SQUO); + EXPECT_EQ(xievt::detail::scalar_style_choose_block_ievt(":\todd"), xievt::SQUO); + EXPECT_EQ(xievt::detail::scalar_style_choose_block_ievt(csubstr{}), xievt::PLAI); + EXPECT_EQ(xievt::detail::scalar_style_choose_block_ievt(csubstr("foo").first(0)), xievt::SQUO); { + SCOPED_TRACE("1"); Tree t; NodeRef r = t.rootref(); r.set_seq(BLOCK); r[0].set_val(": odd", VAL_PLAIN); r[1].set_val(":\todd", VAL_PLAIN); - EXPECT_EQ(emitrs_yaml(t), "- : odd\n- :\todd\n"); + test_emit_yaml_tree(r, "- : odd\n- :\todd\n"); } { Tree t; @@ -290,7 +1143,7 @@ TEST(emit_block_seq, ambiguous_plain_emitted_as_squo) r[1].set_val(":\todd"); EXPECT_FALSE(r[0].is_val_plain()); EXPECT_FALSE(r[1].is_val_plain()); - EXPECT_EQ(emitrs_yaml(t), "- ': odd'\n- ':\todd'\n"); + test_emit_yaml_tree(r, "- ': odd'\n- ':\todd'\n"); } } @@ -304,7 +1157,7 @@ TEST(emit_block_map, ambiguous_plain_emitted_as_squo) r[0].set_val(": odd"); r[1].set_key(":\todd"); r[1].set_val(":\todd"); - EXPECT_EQ(emitrs_yaml(t), "': odd': ': odd'\n':\todd': ':\todd'\n"); + test_emit_yaml_same_ints(r, "': odd': ': odd'\n':\todd': ':\todd'\n"); } { Tree t; @@ -320,231 +1173,20 @@ TEST(emit_block_map, ambiguous_plain_emitted_as_squo) //----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -struct TmpContainerStyle -{ - Tree &t; - id_type id; - NodeType prev; - TmpContainerStyle(NodeRef n, NodeType tmp) : TmpContainerStyle(*n.tree(), n.id(), tmp) {} - TmpContainerStyle(Tree &t_, id_type id_, NodeType tmp) : t(t_), id(id_) - { - prev = t.type(id); - t._p(id)->m_type &= ~CONTAINER_STYLE; - t._p(id)->m_type |= tmp; - } - ~TmpContainerStyle() - { - t._p(id)->m_type = prev; - } -}; - -void test_emits(Tree const& t, id_type id, std::string const& expected_yaml, std::string const& expected_json, EmitOptions const& opts={}) -{ - RYML_TRACE_FMT("id={}", id); - std::string append_prefix = "#before\n"; - if(opts == EmitOptions{}) - { - EXPECT_EQ(emit2buf([&](substr buf){ return emit_yaml(t, id, buf); }), expected_yaml); - EXPECT_EQ(emit2buf([&](substr buf){ return emit_json(t, id, buf); }), expected_json); - EXPECT_EQ(emit2file([&](FILE *f){ return emit_yaml(t, id, f); }), expected_yaml); - EXPECT_EQ(emit2file([&](FILE *f){ return emit_json(t, id, f); }), expected_json); - EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ oss << as_yaml(t, id); }), expected_yaml); - EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ oss << as_json(t, id); }), expected_json); - EXPECT_EQ(emit2buf([&](substr buf){ EmitterBuf em(EmitOptions{}, buf); em.emit_as(EMIT_YAML, &t, id); return em.get_result(/*error_on_excess*/true); }), expected_yaml); - EXPECT_EQ(emit2buf([&](substr buf){ EmitterBuf em(EmitOptions{}, buf); em.emit_as(EMIT_JSON, &t, id); return em.get_result(/*error_on_excess*/true); }), expected_json); - EXPECT_EQ(emitrs_yaml(t, id), expected_yaml); - EXPECT_EQ(emitrs_json(t, id), expected_json); - EXPECT_EQ(emitrs_append(to_csubstr(append_prefix), [&](std::string *s) { emitrs_yaml(t, id, s, /*append*/true); } ), append_prefix + expected_yaml); - EXPECT_EQ(emitrs_append(to_csubstr(append_prefix), [&](std::string *s) { emitrs_json(t, id, s, /*append*/true); } ), append_prefix + expected_json); - } - EXPECT_EQ(emit2buf([&](substr buf){ return emit_yaml(t, id, opts, buf); }), expected_yaml); - EXPECT_EQ(emit2buf([&](substr buf){ return emit_json(t, id, opts, buf); }), expected_json); - EXPECT_EQ(emit2buf([&](substr buf){ EmitterBuf em(opts, buf); em.emit_as(EMIT_YAML, &t, id); return em.get_result(/*error_on_excess*/true); }), expected_yaml); - EXPECT_EQ(emit2buf([&](substr buf){ EmitterBuf em(opts, buf); em.emit_as(EMIT_JSON, &t, id); return em.get_result(/*error_on_excess*/true); }), expected_json); - EXPECT_EQ(emit2file([&](FILE *f){ return emit_yaml(t, id, opts, f); }), expected_yaml); - EXPECT_EQ(emit2file([&](FILE *f){ return emit_json(t, id, opts, f); }), expected_json); - EXPECT_EQ(emit2file([&](FILE *f){ EmitterFile em(opts, f); em.emit_as(EMIT_YAML, &t, id); }), expected_yaml); - EXPECT_EQ(emit2file([&](FILE *f){ EmitterFile em(opts, f); em.emit_as(EMIT_JSON, &t, id); }), expected_json); - EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ oss << as_yaml(t, id, opts); }), expected_yaml);; - EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ oss << as_json(t, id, opts); }), expected_json);; - EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ EmitterOStream em(opts, &oss); em.emit_as(EMIT_YAML, &t, id); }), expected_yaml);; - EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ EmitterOStream em(opts, &oss); em.emit_as(EMIT_JSON, &t, id); }), expected_json);; - EXPECT_EQ(emitrs_yaml(t, id, opts), expected_yaml); - EXPECT_EQ(emitrs_json(t, id, opts), expected_json); - EXPECT_EQ(emitrs_append(to_csubstr(append_prefix), [&](std::string *s) { emitrs_yaml(t, id, opts, s, /*append*/true); } ), append_prefix + expected_yaml); - EXPECT_EQ(emitrs_append(to_csubstr(append_prefix), [&](std::string *s) { emitrs_json(t, id, opts, s, /*append*/true); } ), append_prefix + expected_json); - // error on max depth - if(id == NONE) - return; - id_type max_depth = t.depth_desc(id); - if(max_depth > 1) - { - EmitOptions optsd = opts; - optsd = optsd.max_depth(0); - ExpectError::check_error_visit(&t, [&]{ return emit2buf([&](substr buf){ return emit_yaml(t, id, optsd, buf); }); }); - ExpectError::check_error_visit(&t, [&]{ return emit2buf([&](substr buf){ return emit_json(t, id, optsd, buf); }); }); - ExpectError::check_error_visit(&t, [&]{ return emit2file([&](FILE *f){ emit_yaml(t, id, optsd, f); }); }); - ExpectError::check_error_visit(&t, [&]{ return emit2file([&](FILE *f){ emit_json(t, id, optsd, f); }); }); - ExpectError::check_error_visit(&t, [&]{ return emit2stream([&](std::ostringstream &oss){ oss << as_yaml(t, id, optsd); }); }); - ExpectError::check_error_visit(&t, [&]{ return emit2stream([&](std::ostringstream &oss){ oss << as_json(t, id, optsd); }); }); - ExpectError::check_error_visit(&t, [&]{ return emitrs_yaml(t, id, optsd); }); - ExpectError::check_error_visit(&t, [&]{ return emitrs_json(t, id, optsd); }); - } -} - -void test_emits(Tree const& t, std::string const& expected_yaml, std::string const& expected_json, EmitOptions const& opts={}) -{ - std::string append_prefix = "#before\n"; - if(opts == EmitOptions{}) - { - EXPECT_EQ(emit2buf([&](substr buf){ return emit_yaml(t, buf); }), expected_yaml); - EXPECT_EQ(emit2buf([&](substr buf){ return emit_json(t, buf); }), expected_json); - EXPECT_EQ(emit2file([&](FILE *f){ return emit_yaml(t, f); }), expected_yaml); - EXPECT_EQ(emit2file([&](FILE *f){ return emit_json(t, f); }), expected_json); - EXPECT_EQ(emit2buf([&](substr buf){ EmitterBuf em(EmitOptions{}, buf); em.emit_as(EMIT_YAML, &t); return em.get_result(/*error_on_excess*/true); }), expected_yaml); - EXPECT_EQ(emit2buf([&](substr buf){ EmitterBuf em(EmitOptions{}, buf); em.emit_as(EMIT_JSON, &t); return em.get_result(/*error_on_excess*/true); }), expected_json); - EXPECT_EQ(emit2file([&](FILE *f){ EmitterFile em(EmitOptions{}, f); em.emit_as(EMIT_YAML, &t); }), expected_yaml); - EXPECT_EQ(emit2file([&](FILE *f){ EmitterFile em(EmitOptions{}, f); em.emit_as(EMIT_JSON, &t); }), expected_json); - if(!t.empty()) - { - EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ oss << as_yaml(t); }), expected_yaml); - EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ oss << as_json(t); }), expected_json); - EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ EmitterOStream em(EmitOptions{}, &oss); em.emit_as(EMIT_YAML, &t); }), expected_yaml); - EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ EmitterOStream em(EmitOptions{}, &oss); em.emit_as(EMIT_JSON, &t); }), expected_json); - } - EXPECT_EQ(emitrs_yaml(t), expected_yaml); - EXPECT_EQ(emitrs_json(t), expected_json); - EXPECT_EQ(emitrs_append(to_csubstr(append_prefix), [&](std::string *s) { emitrs_yaml(t, s, /*append*/true); } ), append_prefix + expected_yaml); - EXPECT_EQ(emitrs_append(to_csubstr(append_prefix), [&](std::string *s) { emitrs_json(t, s, /*append*/true); } ), append_prefix + expected_json); - } - EXPECT_EQ(emit2buf([&](substr buf){ return emit_yaml(t, opts, buf); }), expected_yaml); - EXPECT_EQ(emit2buf([&](substr buf){ return emit_json(t, opts, buf); }), expected_json); - EXPECT_EQ(emit2buf([&](substr buf){ EmitterBuf em(opts, buf); em.emit_as(EMIT_YAML, &t); return em.get_result(/*error_on_excess*/true); }), expected_yaml); - EXPECT_EQ(emit2buf([&](substr buf){ EmitterBuf em(opts, buf); em.emit_as(EMIT_JSON, &t); return em.get_result(/*error_on_excess*/true); }), expected_json); - EXPECT_EQ(emit2file([&](FILE *f){ return emit_yaml(t, opts, f); }), expected_yaml); - EXPECT_EQ(emit2file([&](FILE *f){ return emit_json(t, opts, f); }), expected_json); - EXPECT_EQ(emit2file([&](FILE *f){ EmitterFile em(opts, f); return em.emit_as(EMIT_YAML, &t); }), expected_yaml); - EXPECT_EQ(emit2file([&](FILE *f){ EmitterFile em(opts, f); return em.emit_as(EMIT_JSON, &t); }), expected_json); - EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ oss << as_yaml(t, opts); }), expected_yaml); - EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ oss << as_json(t, opts); }), expected_json); - EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ EmitterOStream em(opts, &oss); em.emit_as(EMIT_YAML, &t); }), expected_yaml); - EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ EmitterOStream em(opts, &oss); em.emit_as(EMIT_JSON, &t); }), expected_json); - EXPECT_EQ(emitrs_yaml(t, opts), expected_yaml); - EXPECT_EQ(emitrs_json(t, opts), expected_json); - EXPECT_EQ(emitrs_append(to_csubstr(append_prefix), [&](std::string *s) { emitrs_yaml(t, opts, s, /*append*/true); } ), append_prefix + expected_yaml); - EXPECT_EQ(emitrs_append(to_csubstr(append_prefix), [&](std::string *s) { emitrs_json(t, opts, s, /*append*/true); } ), append_prefix + expected_json); - // error on max depth - id_type max_depth = t.empty() ? 0 : t.depth_desc(t.root_id()); - if(max_depth > 1) - { - EmitOptions optsd = opts; - optsd = optsd.max_depth(0); - ExpectError::check_error_visit(&t, [&]{ return emit2buf([&](substr buf){ return emit_yaml(t, optsd, buf); }); }); - ExpectError::check_error_visit(&t, [&]{ return emit2buf([&](substr buf){ return emit_json(t, optsd, buf); }); }); - ExpectError::check_error_visit(&t, [&]{ return emit2file([&](FILE *f){ emit_yaml(t, optsd, f); }); }); - ExpectError::check_error_visit(&t, [&]{ return emit2file([&](FILE *f){ emit_json(t, optsd, f); }); }); - ExpectError::check_error_visit(&t, [&]{ return emit2stream([&](std::ostringstream &oss){ oss << as_yaml(ConstNodeRef(&t), optsd); }); }); - ExpectError::check_error_visit(&t, [&]{ return emit2stream([&](std::ostringstream &oss){ oss << as_json(ConstNodeRef(&t), optsd); }); }); - ExpectError::check_error_visit(&t, [&]{ return emitrs_yaml(t, optsd); }); - ExpectError::check_error_visit(&t, [&]{ return emitrs_json(t, optsd); }); - } -} - - -void test_emits(ConstNodeRef n, std::string const& expected_yaml, std::string const& expected_json, EmitOptions const& opts={}) -{ - std::string append_prefix = "#before\n"; - if(opts == EmitOptions{}) - { - EXPECT_EQ(emit2buf([&](substr buf){ return emit_yaml(n, buf); }), expected_yaml); - EXPECT_EQ(emit2buf([&](substr buf){ return emit_json(n, buf); }), expected_json); - EXPECT_EQ(emit2file([&](FILE *f){ return emit_yaml(n, f); }), expected_yaml); - EXPECT_EQ(emit2file([&](FILE *f){ return emit_json(n, f); }), expected_json); - EXPECT_EQ(emit2buf([&](substr buf){ EmitterBuf em(EmitOptions{}, buf); em.emit_as(EMIT_YAML, n.tree(), n.id()); return em.get_result(/*error_on_excess*/true); }), expected_yaml); - EXPECT_EQ(emit2buf([&](substr buf){ EmitterBuf em(EmitOptions{}, buf); em.emit_as(EMIT_JSON, n.tree(), n.id()); return em.get_result(/*error_on_excess*/true); }), expected_json); - EXPECT_EQ(emit2file([&](FILE *f){ EmitterFile em(EmitOptions{}, f); em.emit_as(EMIT_YAML, n.tree(), n.id()); }), expected_yaml); - EXPECT_EQ(emit2file([&](FILE *f){ EmitterFile em(EmitOptions{}, f); em.emit_as(EMIT_JSON, n.tree(), n.id()); }), expected_json); - EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ oss << n; }), expected_yaml); - EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ oss << as_yaml(n); }), expected_yaml); - EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ oss << as_json(n); }), expected_json); - EXPECT_EQ(emitrs_yaml(n), expected_yaml); - EXPECT_EQ(emitrs_json(n), expected_json); - EXPECT_EQ(emitrs_append(to_csubstr(append_prefix), [&](std::string *s) { emitrs_yaml(n, s, /*append*/true); } ), append_prefix + expected_yaml); - EXPECT_EQ(emitrs_append(to_csubstr(append_prefix), [&](std::string *s) { emitrs_json(n, s, /*append*/true); } ), append_prefix + expected_json); - } - EXPECT_EQ(emit2buf([&](substr buf){ return emit_yaml(n, opts, buf); }), expected_yaml); - EXPECT_EQ(emit2buf([&](substr buf){ return emit_json(n, opts, buf); }), expected_json); - EXPECT_EQ(emit2file([&](FILE *f){ return emit_yaml(n, opts, f); }), expected_yaml); - EXPECT_EQ(emit2file([&](FILE *f){ return emit_json(n, opts, f); }), expected_json); - EXPECT_EQ(emit2buf([&](substr buf){ EmitterBuf em(opts, buf); em.emit_as(EMIT_YAML, n.tree(), n.id()); return em.get_result(/*error_on_excess*/true); }), expected_yaml); - EXPECT_EQ(emit2buf([&](substr buf){ EmitterBuf em(opts, buf); em.emit_as(EMIT_JSON, n.tree(), n.id()); return em.get_result(/*error_on_excess*/true); }), expected_json); - EXPECT_EQ(emit2file([&](FILE *f){ EmitterFile em(opts, f); em.emit_as(EMIT_YAML, n.tree(), n.id()); }), expected_yaml); - EXPECT_EQ(emit2file([&](FILE *f){ EmitterFile em(opts, f); em.emit_as(EMIT_JSON, n.tree(), n.id()); }), expected_json); - EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ oss << as_yaml(n, opts); }), expected_yaml); - EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ oss << as_json(n, opts); }), expected_json); - EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ EmitterOStream em(opts, &oss); em.emit_as(EMIT_YAML, n.tree(), n.id()); }), expected_yaml); - EXPECT_EQ(emit2stream([&](std::ostringstream &oss){ EmitterOStream em(opts, &oss); em.emit_as(EMIT_JSON, n.tree(), n.id()); }), expected_json); - EXPECT_EQ(emitrs_yaml(n, opts), expected_yaml); - EXPECT_EQ(emitrs_json(n, opts), expected_json); - EXPECT_EQ(emitrs_append(to_csubstr(append_prefix), [&](std::string *s) { emitrs_yaml(n, opts, s, /*append*/true); } ), append_prefix + expected_yaml); - EXPECT_EQ(emitrs_append(to_csubstr(append_prefix), [&](std::string *s) { emitrs_json(n, opts, s, /*append*/true); } ), append_prefix + expected_json); - // error on max depth - if(n.tree() && n.id() != NONE) - { - id_type max_depth = n.depth_desc(); - if(max_depth > 1) - { - EmitOptions optsd = opts; - optsd = optsd.max_depth(0); - ExpectError::check_error_visit(n.tree(), [&]{ return emit2buf([&](substr buf){ return emit_yaml(n, optsd, buf); }); }); - ExpectError::check_error_visit(n.tree(), [&]{ return emit2buf([&](substr buf){ return emit_json(n, optsd, buf); }); }); - ExpectError::check_error_visit(n.tree(), [&]{ return emit2file([&](FILE *f){ emit_yaml(n, optsd, f); }); }); - ExpectError::check_error_visit(n.tree(), [&]{ return emit2file([&](FILE *f){ emit_json(n, optsd, f); }); }); - ExpectError::check_error_visit(n.tree(), [&]{ return emit2stream([&](std::ostringstream &oss){ oss << as_yaml(n, optsd); }); }); - ExpectError::check_error_visit(n.tree(), [&]{ return emit2stream([&](std::ostringstream &oss){ oss << as_json(n, optsd); }); }); - ExpectError::check_error_visit(n.tree(), [&]{ return emitrs_yaml(n, optsd); }); - ExpectError::check_error_visit(n.tree(), [&]{ return emitrs_json(n, optsd); }); - } - } -} - - -void test_all_emits(ConstNodeRef n, std::string const &expected, std::string const& expected_json, EmitOptions const& opts={}) -{ - SCOPED_TRACE("test_all_emits"); - { - SCOPED_TRACE("rootref"); - test_emits(n, expected, expected_json, opts); - } - if(n.is_root()) - { - SCOPED_TRACE("t"); - test_emits(*n.tree(), expected, expected_json, opts); - } - { - SCOPED_TRACE("t, id"); - test_emits(*n.tree(), n.id(), expected, expected_json, opts); - } -} - - TEST(emit, empty_tree) { const Tree t(/*capacity*/0); // must be const! ASSERT_TRUE(t.empty()); std::string expected = R"()"; - test_emits(t, expected, expected); + test_emits_(t, expected, expected); } TEST(emit, empty_node) { std::string expected = R"()"; - test_emits(NodeRef{}, expected, expected); - test_emits(ConstNodeRef{}, expected, expected); + test_emits_(NodeRef{}, 0, expected, expected); + test_emits_(ConstNodeRef{}, 0, expected, expected); } TEST(emit, existing_tree) @@ -552,7 +1194,7 @@ TEST(emit, existing_tree) const Tree t = parse_in_arena("[foo, bar]"); std::string expected = "[foo,bar]"; std::string expected_json = R"(["foo","bar"])"; - test_emits(t, expected, expected_json); + test_emits_(t, expected, expected_json); } TEST(emit, no_node) @@ -560,14 +1202,38 @@ TEST(emit, no_node) const Tree t = parse_in_arena("[foo, bar]"); std::string expected = "[foo,bar]"; std::string expected_json = R"(["foo","bar"])"; - test_emits(t, NONE, expected, expected_json); + test_emits_(t, NONE, expected, expected_json); +} + +TEST(emit, empty_map) +{ + const TreeAndInts ti = parse_tree_and_ints("{}"); + test_emits_(ti, "{}", "{}"); +} + +TEST(emit, empty_seq) +{ + const TreeAndInts ti = parse_tree_and_ints("[]"); + test_emits_(ti, "[]", "[]"); +} + +TEST(emit, empty_map_ml) +{ + const TreeAndInts ti = parse_tree_and_ints("{\n\n}"); + test_emits_(ti, "{\n}\n", "{\n}\n"); +} + +TEST(emit, empty_seq_ml) +{ + const TreeAndInts ti = parse_tree_and_ints("[\n\n]"); + test_emits_(ti, "[\n]\n", "[\n]\n"); } TEST(emit, empty_key_squo) { { SCOPED_TRACE("one only"); - const Tree t = parse_in_arena(R"( + const TreeAndInts ti = parse_tree_and_ints(R"( ? '' : literal )"); @@ -575,18 +1241,18 @@ TEST(emit, empty_key_squo) SCOPED_TRACE("indent"); std::string expected = "'': literal\n"; std::string expected_json = "{\n \"\": \"literal\"\n}\n"; - test_emits(t, t.root_id(), expected, expected_json); + test_emits_(ti, expected, expected_json); } { SCOPED_TRACE("no indent"); std::string expected = "'': literal\n"; std::string expected_json = "{\n\"\": \"literal\"\n}\n"; - test_emits(t, t.root_id(), expected, expected_json, EmitOptions{}.indent_flow_ml(false)); + test_emits_(ti, expected, expected_json, noindent); } } { SCOPED_TRACE("nested"); - const Tree t = parse_in_arena(R"( + const TreeAndInts ti = parse_tree_and_ints(R"( level1: ? '' : literal @@ -595,16 +1261,16 @@ TEST(emit, empty_key_squo) SCOPED_TRACE("indent"); std::string expected = "level1:\n '': literal\n"; std::string expected_json = "{\n \"level1\": {\n \"\": \"literal\"\n }\n}\n"; - test_emits(t, t.root_id(), expected, expected_json); + test_emits_(ti, expected, expected_json); } { SCOPED_TRACE("no indent"); std::string expected = "level1:\n '': literal\n"; std::string expected_json = "{\n\"level1\": {\n\"\": \"literal\"\n}\n}\n"; - test_emits(t, t.root_id(), expected, expected_json, EmitOptions{}.indent_flow_ml(false)); + test_emits_(ti, expected, expected_json, noindent); } } - const Tree t = parse_in_arena(R"( + const TreeAndInts ti = parse_tree_and_ints(R"( ? '' : literal level1: @@ -623,13 +1289,13 @@ TEST(emit, empty_key_squo) SCOPED_TRACE("indent"); std::string expected = "level3:\n '': literal\n"; std::string expected_json = "\"level3\": {\n \"\": \"literal\"\n}\n"; - test_emits(t, t["level1"]["level2"]["level3"].id(), expected, expected_json); + test_emits_(ti, ti.tree["level1"]["level2"]["level3"], 29, expected, expected_json); } { SCOPED_TRACE("no indent"); std::string expected = "level3:\n '': literal\n"; std::string expected_json = "\"level3\": {\n\"\": \"literal\"\n}\n"; - test_emits(t, t["level1"]["level2"]["level3"].id(), expected, expected_json, EmitOptions{}.indent_flow_ml(false)); + test_emits_(ti, ti.tree["level1"]["level2"]["level3"], 29, expected, expected_json, noindent); } } { @@ -638,13 +1304,13 @@ TEST(emit, empty_key_squo) SCOPED_TRACE("indent"); std::string expected = "level2:\n '': literal\n level3:\n '': literal\n"; std::string expected_json = "\"level2\": {\n \"\": \"literal\",\n \"level3\": {\n \"\": \"literal\"\n }\n}\n"; - test_emits(t, t["level1"]["level2"].id(), expected, expected_json); + test_emits_(ti, ti.tree["level1"]["level2"], 19, expected, expected_json); } { SCOPED_TRACE("no indent"); std::string expected = "level2:\n '': literal\n level3:\n '': literal\n"; std::string expected_json = "\"level2\": {\n\"\": \"literal\",\n\"level3\": {\n\"\": \"literal\"\n}\n}\n"; - test_emits(t, t["level1"]["level2"].id(), expected, expected_json, EmitOptions{}.indent_flow_ml(false)); + test_emits_(ti, ti.tree["level1"]["level2"].id(), 19, expected, expected_json, noindent); } } { @@ -653,13 +1319,13 @@ TEST(emit, empty_key_squo) SCOPED_TRACE("indent"); std::string expected = "level1:\n '': literal\n level2:\n '': literal\n level3:\n '': literal\n"; std::string expected_json = "\"level1\": {\n \"\": \"literal\",\n \"level2\": {\n \"\": \"literal\",\n \"level3\": {\n \"\": \"literal\"\n }\n }\n}\n"; - test_emits(t, t["level1"].id(), expected, expected_json); + test_emits_(ti, ti.tree["level1"], 9, expected, expected_json); } { SCOPED_TRACE("no indent"); std::string expected = "level1:\n '': literal\n level2:\n '': literal\n level3:\n '': literal\n"; std::string expected_json = "\"level1\": {\n\"\": \"literal\",\n\"level2\": {\n\"\": \"literal\",\n\"level3\": {\n\"\": \"literal\"\n}\n}\n}\n"; - test_emits(t, t["level1"].id(), expected, expected_json, EmitOptions{}.indent_flow_ml(false)); + test_emits_(ti, ti.tree["level1"], 9, expected, expected_json, noindent); } } { @@ -668,13 +1334,13 @@ TEST(emit, empty_key_squo) SCOPED_TRACE("indent"); std::string expected = "'': literal\nlevel1:\n '': literal\n level2:\n '': literal\n level3:\n '': literal\n"; std::string expected_json = "{\n \"\": \"literal\",\n \"level1\": {\n \"\": \"literal\",\n \"level2\": {\n \"\": \"literal\",\n \"level3\": {\n \"\": \"literal\"\n }\n }\n }\n}\n"; - test_emits(t, NONE, expected, expected_json); + test_emits_(ti, NONE, expected, expected_json); } { SCOPED_TRACE("no indent"); std::string expected = "'': literal\nlevel1:\n '': literal\n level2:\n '': literal\n level3:\n '': literal\n"; std::string expected_json = "{\n\"\": \"literal\",\n\"level1\": {\n\"\": \"literal\",\n\"level2\": {\n\"\": \"literal\",\n\"level3\": {\n\"\": \"literal\"\n}\n}\n}\n}\n"; - test_emits(t, NONE, expected, expected_json, EmitOptions{}.indent_flow_ml(false)); + test_emits_(ti, NONE, expected, expected_json, noindent); } } } @@ -683,26 +1349,26 @@ TEST(emit, empty_key_dquo) { { SCOPED_TRACE("one only"); - const Tree t = parse_in_arena(R"( + const TreeAndInts ti = parse_tree_and_ints(R"( ? "" : literal )"); std::string expected = "\"\": literal\n"; std::string expected_json = "{\n \"\": \"literal\"\n}\n"; - test_emits(t, t.root_id(), expected, expected_json); + test_emits_(ti, expected, expected_json); } { SCOPED_TRACE("nested"); - const Tree t = parse_in_arena(R"( + const TreeAndInts ti = parse_tree_and_ints(R"( level1: ? "" : literal )"); std::string expected = "level1:\n \"\": literal\n"; std::string expected_json = "{\n \"level1\": {\n \"\": \"literal\"\n }\n}\n"; - test_emits(t, t.root_id(), expected, expected_json); + test_emits_(ti, expected, expected_json); } - const Tree t = parse_in_arena(R"( + const TreeAndInts ti = parse_tree_and_ints(R"( ? "" : literal level1: @@ -719,25 +1385,25 @@ TEST(emit, empty_key_dquo) SCOPED_TRACE("level3"); std::string expected = "level3:\n \"\": literal\n"; std::string expected_json = "\"level3\": {\n \"\": \"literal\"\n}\n"; - test_emits(t, t["level1"]["level2"]["level3"].id(), expected, expected_json); + test_emits_(ti, ti.tree["level1"]["level2"]["level3"], 29, expected, expected_json); } { SCOPED_TRACE("level2"); std::string expected = "level2:\n \"\": literal\n level3:\n \"\": literal\n"; std::string expected_json = "\"level2\": {\n \"\": \"literal\",\n \"level3\": {\n \"\": \"literal\"\n }\n}\n"; - test_emits(t, t["level1"]["level2"].id(), expected, expected_json); + test_emits_(ti, ti.tree["level1"]["level2"], 19, expected, expected_json); } { SCOPED_TRACE("level1"); std::string expected = "level1:\n \"\": literal\n level2:\n \"\": literal\n level3:\n \"\": literal\n"; std::string expected_json = "\"level1\": {\n \"\": \"literal\",\n \"level2\": {\n \"\": \"literal\",\n \"level3\": {\n \"\": \"literal\"\n }\n }\n}\n"; - test_emits(t, t["level1"].id(), expected, expected_json); + test_emits_(ti, ti.tree["level1"], 9, expected, expected_json); } { SCOPED_TRACE("level0"); std::string expected = "\"\": literal\nlevel1:\n \"\": literal\n level2:\n \"\": literal\n level3:\n \"\": literal\n"; std::string expected_json = "{\n \"\": \"literal\",\n \"level1\": {\n \"\": \"literal\",\n \"level2\": {\n \"\": \"literal\",\n \"level3\": {\n \"\": \"literal\"\n }\n }\n }\n}\n"; - test_emits(t, NONE, expected, expected_json); + test_emits_(ti, expected, expected_json); } } @@ -745,26 +1411,26 @@ TEST(emit, empty_key_plain) { { SCOPED_TRACE("one only"); - const Tree t = parse_in_arena(R"( + const TreeAndInts ti = parse_tree_and_ints(R"( ? : literal )"); std::string expected = ": literal\n"; std::string expected_json = "{\n \"\": \"literal\"\n}\n"; - test_emits(t, t.root_id(), expected, expected_json); + test_emits_(ti, expected, expected_json); } { SCOPED_TRACE("nested"); - const Tree t = parse_in_arena(R"( + const TreeAndInts ti = parse_tree_and_ints(R"( level1: ? : literal )"); std::string expected = "level1:\n : literal\n"; std::string expected_json = "{\n \"level1\": {\n \"\": \"literal\"\n }\n}\n"; - test_emits(t, t.root_id(), expected, expected_json); + test_emits_(ti, expected, expected_json); } - const Tree t = parse_in_arena(R"( + const TreeAndInts ti = parse_tree_and_ints(R"( ? : literal level1: @@ -781,25 +1447,25 @@ TEST(emit, empty_key_plain) SCOPED_TRACE("level3"); std::string expected = "level3:\n : literal\n"; std::string expected_json = "\"level3\": {\n \"\": \"literal\"\n}\n"; - test_emits(t, t["level1"]["level2"]["level3"].id(), expected, expected_json); + test_emits_(ti, ti.tree["level1"]["level2"]["level3"], 29, expected, expected_json); } { SCOPED_TRACE("level2"); std::string expected = "level2:\n : literal\n level3:\n : literal\n"; std::string expected_json = "\"level2\": {\n \"\": \"literal\",\n \"level3\": {\n \"\": \"literal\"\n }\n}\n"; - test_emits(t, t["level1"]["level2"].id(), expected, expected_json); + test_emits_(ti, ti.tree["level1"]["level2"], 19, expected, expected_json); } { SCOPED_TRACE("level1"); std::string expected = "level1:\n : literal\n level2:\n : literal\n level3:\n : literal\n"; std::string expected_json = "\"level1\": {\n \"\": \"literal\",\n \"level2\": {\n \"\": \"literal\",\n \"level3\": {\n \"\": \"literal\"\n }\n }\n}\n"; - test_emits(t, t["level1"].id(), expected, expected_json); + test_emits_(ti, ti.tree["level1"], 9, expected, expected_json); } { SCOPED_TRACE("level0"); std::string expected = ": literal\nlevel1:\n : literal\n level2:\n : literal\n level3:\n : literal\n"; std::string expected_json = "{\n \"\": \"literal\",\n \"level1\": {\n \"\": \"literal\",\n \"level2\": {\n \"\": \"literal\",\n \"level3\": {\n \"\": \"literal\"\n }\n }\n }\n}\n"; - test_emits(t, NONE, expected, expected_json); + test_emits_(ti, expected, expected_json); } } @@ -807,22 +1473,22 @@ TEST(emit, empty_key_literal) { { SCOPED_TRACE("one only"); - const Tree t = parse_in_arena(R"( + const TreeAndInts ti = parse_tree_and_ints(R"( ? |- : literal )"); std::string expected = "? |-\n: literal\n"; std::string expected_json = "{\n \"\": \"literal\"\n}\n"; - test_emits(t, t.root_id(), expected, expected_json); + test_emits_(ti, expected, expected_json); } { SCOPED_TRACE("nested1"); - const Tree t = parse_in_arena("level1:\n ? |-\n : literal\n"); + const TreeAndInts ti = parse_tree_and_ints("level1:\n ? |-\n : literal\n"); std::string expected = "level1:\n ? |-\n : literal\n"; std::string expected_json = "{\n \"level1\": {\n \"\": \"literal\"\n }\n}\n"; - test_emits(t, t.root_id(), expected, expected_json); + test_emits_(ti, expected, expected_json); } - const Tree t = parse_in_arena(R"( + const TreeAndInts ti = parse_tree_and_ints(R"( ? |- : literal level1: @@ -839,25 +1505,25 @@ TEST(emit, empty_key_literal) SCOPED_TRACE("level3"); std::string expected = "level3:\n ? |-\n : literal\n"; std::string expected_json = "\"level3\": {\n \"\": \"literal\"\n}\n"; - test_emits(t, t["level1"]["level2"]["level3"].id(), expected, expected_json); + test_emits_(ti, ti.tree["level1"]["level2"]["level3"], 29, expected, expected_json); } { SCOPED_TRACE("level2"); std::string expected = "level2:\n ? |-\n : literal\n level3:\n ? |-\n : literal\n"; std::string expected_json = "\"level2\": {\n \"\": \"literal\",\n \"level3\": {\n \"\": \"literal\"\n }\n}\n"; - test_emits(t, t["level1"]["level2"].id(), expected, expected_json); + test_emits_(ti, ti.tree["level1"]["level2"], 19, expected, expected_json); } { SCOPED_TRACE("level1"); std::string expected = "level1:\n ? |-\n : literal\n level2:\n ? |-\n : literal\n level3:\n ? |-\n : literal\n"; std::string expected_json = "\"level1\": {\n \"\": \"literal\",\n \"level2\": {\n \"\": \"literal\",\n \"level3\": {\n \"\": \"literal\"\n }\n }\n}\n"; - test_emits(t, t["level1"].id(), expected, expected_json); + test_emits_(ti, ti.tree["level1"], 9, expected, expected_json); } { SCOPED_TRACE("level0"); std::string expected = "? |-\n: literal\nlevel1:\n ? |-\n : literal\n level2:\n ? |-\n : literal\n level3:\n ? |-\n : literal\n"; std::string expected_json = "{\n \"\": \"literal\",\n \"level1\": {\n \"\": \"literal\",\n \"level2\": {\n \"\": \"literal\",\n \"level3\": {\n \"\": \"literal\"\n }\n }\n }\n}\n"; - test_emits(t, NONE, expected, expected_json); + test_emits_(ti, expected, expected_json); } } @@ -865,26 +1531,26 @@ TEST(emit, empty_key_folded) { { SCOPED_TRACE("one only"); - const Tree t = parse_in_arena(R"( + const TreeAndInts ti = parse_tree_and_ints(R"( ? >- : folded )"); std::string expected = "? >-\n: folded\n"; std::string expected_json = "{\n \"\": \"folded\"\n}\n"; - test_emits(t, t.root_id(), expected, expected_json); + test_emits_(ti, expected, expected_json); } { SCOPED_TRACE("nested"); - const Tree t = parse_in_arena(R"( + const TreeAndInts ti = parse_tree_and_ints(R"( level1: ? >- : folded )"); std::string expected = "level1:\n ? >-\n : folded\n"; std::string expected_json = "{\n \"level1\": {\n \"\": \"folded\"\n }\n}\n"; - test_emits(t, t.root_id(), expected, expected_json); + test_emits_(ti, expected, expected_json); } - const Tree t = parse_in_arena(R"( + const TreeAndInts ti = parse_tree_and_ints(R"( ? >- : folded level1: @@ -901,715 +1567,1951 @@ TEST(emit, empty_key_folded) SCOPED_TRACE("level3"); std::string expected = "level3:\n ? >-\n : folded\n"; std::string expected_json = "\"level3\": {\n \"\": \"folded\"\n}\n"; - test_emits(t, t["level1"]["level2"]["level3"].id(), expected, expected_json); + test_emits_(ti, ti.tree["level1"]["level2"]["level3"], 29, expected, expected_json); } { SCOPED_TRACE("level2"); std::string expected = "level2:\n ? >-\n : folded\n level3:\n ? >-\n : folded\n"; std::string expected_json = "\"level2\": {\n \"\": \"folded\",\n \"level3\": {\n \"\": \"folded\"\n }\n}\n"; - test_emits(t, t["level1"]["level2"].id(), expected, expected_json); + test_emits_(ti, ti.tree["level1"]["level2"], 19, expected, expected_json); } { SCOPED_TRACE("level1"); std::string expected = "level1:\n ? >-\n : folded\n level2:\n ? >-\n : folded\n level3:\n ? >-\n : folded\n"; std::string expected_json = "\"level1\": {\n \"\": \"folded\",\n \"level2\": {\n \"\": \"folded\",\n \"level3\": {\n \"\": \"folded\"\n }\n }\n}\n"; - test_emits(t, t["level1"].id(), expected, expected_json); + test_emits_(ti, ti.tree["level1"], 9, expected, expected_json); } { SCOPED_TRACE("level0"); std::string expected = "? >-\n: folded\nlevel1:\n ? >-\n : folded\n level2:\n ? >-\n : folded\n level3:\n ? >-\n : folded\n"; std::string expected_json = "{\n \"\": \"folded\",\n \"level1\": {\n \"\": \"folded\",\n \"level2\": {\n \"\": \"folded\",\n \"level3\": {\n \"\": \"folded\"\n }\n }\n }\n}\n"; - test_emits(t, NONE, expected, expected_json); + test_emits_(ti, expected, expected_json); } } -TEST(emit, existing_seq_node_flow) + +TEST(emit, docval) { - Tree nct = parse_in_arena("[foo, bar, [nested, seq], {nested: map}]"); - Tree const& t = nct; - { - SCOPED_TRACE("full"); - std::string expected = "[foo,bar,[nested,seq],{nested: map}]"; - std::string expected_ml = "[\n foo,\n bar,\n [nested,seq],\n {nested: map}\n]\n"; - std::string expected_ml_all = "[\n foo,\n bar,\n [\n nested,\n seq\n ],\n {\n nested: map\n }\n]\n"; - std::string expected_json = "[\"foo\",\"bar\",[\"nested\",\"seq\"],{\"nested\": \"map\"}]"; - std::string expected_json_ml = "[\n \"foo\",\n \"bar\",\n [\"nested\",\"seq\"],\n {\"nested\": \"map\"}\n]\n"; - std::string expected_json_ml_all = "[\n \"foo\",\n \"bar\",\n [\n \"nested\",\n \"seq\"\n ],\n {\n \"nested\": \"map\"\n }\n]\n"; - { - SCOPED_TRACE("here"); - test_all_emits(t.crootref(), expected, expected_json); - } - { - SCOPED_TRACE("ml"); - TmpContainerStyle tmp(nct.rootref(), FLOW_ML1); - test_all_emits(t.crootref(), expected_ml, expected_json_ml); - } - { - SCOPED_TRACE("rootref-ml-all"); - TmpContainerStyle tmp1(nct.rootref(), FLOW_ML1); - TmpContainerStyle tmp2(nct[2], FLOW_ML1); - TmpContainerStyle tmp3(nct[3], FLOW_ML1); - test_all_emits(t.crootref(), expected_ml_all, expected_json_ml_all); - } + SCOPED_TRACE("docval"); + TreeAndInts ti = parse_tree_and_ints("a"); + ConstNodeRef root = ti.tree; + { + SCOPED_TRACE("nosty"); + TMPSTY(nosty, ti, ti.tree, 2); + test_emits_(ti, "a\n", "\"a\""); + test_emits_(ti, root, 0, "a\n", "\"a\""); + test_emits_(ti, root, 1, "a\n", "\"a\""); + test_emits_tree_(root, "a\n", "\"a\""); + test_emits_ints_(ti.ints, 2, "a", "\"a\""); + } + { + SCOPED_TRACE("plain"); + TMPSTY(plai, ti, ti.tree, 2); + test_emits_(ti, "a\n", "\"a\""); + test_emits_(ti, root, 0, "a\n", "\"a\""); + test_emits_(ti, root, 1, "a\n", "\"a\""); + test_emits_tree_(root, "a\n", "\"a\""); + test_emits_ints_(ti.ints, 2, "a", "\"a\""); + } + { + SCOPED_TRACE("squo"); + TMPSTY(squo, ti, ti.tree, 2); + test_emits_(ti, "'a'\n", "\"a\""); + test_emits_(ti, root, 0, "'a'\n", "\"a\""); + test_emits_(ti, root, 1, "'a'\n", "\"a\""); + test_emits_tree_(root, "'a'\n", "\"a\""); + test_emits_ints_(ti.ints, 2, "'a'", "\"a\""); + } + { + SCOPED_TRACE("dquo"); + TMPSTY(dquo, ti, ti.tree, 2); + test_emits_(ti, "\"a\"\n", "\"a\""); + test_emits_(ti, root, 0, "\"a\"\n", "\"a\""); + test_emits_(ti, root, 1, "\"a\"\n", "\"a\""); + test_emits_tree_(root, "\"a\"\n", "\"a\""); + test_emits_ints_(ti.ints, 2, "\"a\"", "\"a\""); + } + { + SCOPED_TRACE("literal"); + TMPSTY(litl, ti, ti.tree, 2); + test_emits_(ti, "|-\n a\n", "\"a\""); + test_emits_(ti, root, 0, "|-\n a\n", "\"a\""); + test_emits_(ti, root, 1, "|-\n a\n", "\"a\""); + test_emits_tree_(root, "|-\n a\n", "\"a\""); + test_emits_ints_(ti.ints, 2, "|-\n a", "\"a\""); + } + { + SCOPED_TRACE("fold"); + TMPSTY(fold, ti, ti.tree, 2); + test_emits_(ti, ">-\n a\n", "\"a\""); + test_emits_(ti, root, 0, ">-\n a\n", "\"a\""); + test_emits_(ti, root, 1, ">-\n a\n", "\"a\""); + test_emits_tree_(root, ">-\n a\n", "\"a\""); + test_emits_ints_(ti.ints, 2, ">-\n a", "\"a\""); } - { - SCOPED_TRACE("t[0]"); - ConstNodeRef n = t[0]; - std::string expected = "foo"; - std::string expected_json = "\"foo\""; - test_all_emits(n, expected, expected_json); - nct._add_flags(n.id(), FLOW_SL); - expected = "foo"; - expected_json = "\"foo\""; - test_all_emits(n, expected, expected_json); +} + +TEST(emit, docval_empty) +{ + SCOPED_TRACE("docval_empty"); + TreeAndInts ti = parse_tree_and_ints("|-"); + ConstNodeRef root = ti.tree; + { + SCOPED_TRACE("nosty"); + TMPSTY(nosty, ti, ti.tree, 2); + test_emits_(ti, "''\n", "\"\""); + test_emits_(ti, root, 0, "''\n", "\"\""); + test_emits_(ti, root, 1, "''\n", "\"\""); + test_emits_tree_(root, "''\n", "\"\""); + test_emits_ints_(ti.ints, 2, "''", "\"\""); + } + { + SCOPED_TRACE("plain"); + TMPSTY(plai, ti, ti.tree, 2); + test_emits_(ti, "\n", "\"\""); + test_emits_(ti, root, 0, "\n", "\"\""); + test_emits_(ti, root, 1, "\n", "\"\""); + test_emits_tree_(root, "\n", "\"\""); + test_emits_ints_(ti.ints, 2, "", "\"\""); + } + { + SCOPED_TRACE("squo"); + TMPSTY(squo, ti, ti.tree, 2); + test_emits_(ti, "''\n", "\"\""); + test_emits_(ti, root, 0, "''\n", "\"\""); + test_emits_(ti, root, 1, "''\n", "\"\""); + test_emits_tree_(root, "''\n", "\"\""); + test_emits_ints_(ti.ints, 2, "''", "\"\""); + } + { + SCOPED_TRACE("dquo"); + TMPSTY(dquo, ti, ti.tree, 2); + test_emits_(ti, "\"\"\n", "\"\""); + test_emits_(ti, root, 0, "\"\"\n", "\"\""); + test_emits_(ti, root, 1, "\"\"\n", "\"\""); + test_emits_tree_(root, "\"\"\n", "\"\""); + test_emits_ints_(ti.ints, 2, "\"\"", "\"\""); + } + { + SCOPED_TRACE("literal"); + TMPSTY(litl, ti, ti.tree, 2); + test_emits_(ti, "|-\n", "\"\""); + test_emits_(ti, root, 0, "|-\n", "\"\""); + test_emits_(ti, root, 1, "|-\n", "\"\""); + test_emits_tree_(root, "|-\n", "\"\""); + test_emits_ints_(ti.ints, 2, "|-", "\"\""); + } + { + SCOPED_TRACE("fold"); + TMPSTY(fold, ti, ti.tree, 2); + test_emits_(ti, ">-\n", "\"\""); + test_emits_(ti, root, 0, ">-\n", "\"\""); + test_emits_(ti, root, 1, ">-\n", "\"\""); + test_emits_tree_(root, ">-\n", "\"\""); + test_emits_ints_(ti.ints, 2, ">-", "\"\""); } +} + + +//----------------------------------------------------------------------------- + +static void test_emit_seq_node(TreeAndInts & ti, std::string const& yaml) +{ + RYML_TRACE_FMT("yaml:\n~~~{}\n~~~\n", yaml); + Tree & t = ti.tree; { - SCOPED_TRACE("t[1]"); - ConstNodeRef n = t[1]; - std::string expected = "bar"; - std::string expected_json = "\"bar\""; - test_all_emits(n, expected, expected_json); - nct._add_flags(n.id(), FLOW_SL); - expected = "bar"; - expected_json = "\"bar\""; - test_all_emits(n, expected, expected_json); + SCOPED_TRACE("t[0]"); + auto testfoo = [&]{ + { + SCOPED_TRACE("orig"); + test_emits_(ti, t[0], 3, "foo", "\"foo\""); + } + { + SCOPED_TRACE("plain"); + TMPSTY(plai, ti, t[0], 3); + test_emits_(ti, t[0], 3, "foo", "\"foo\""); + } + { + SCOPED_TRACE("squo"); + TMPSTY(squo, ti, t[0], 3); + test_emits_(ti, t[0], 3, "'foo'", "\"foo\""); + } + { + SCOPED_TRACE("dquo"); + TMPSTY(dquo, ti, t[0], 3); + test_emits_(ti, t[0], 3, "\"foo\"", "\"foo\""); + } + { + SCOPED_TRACE("fold"); + TMPSTY(fold, ti, t[0], 3); + test_emits_(ti, t[0], 3, ">-\n foo", "\"foo\""); + } + { + SCOPED_TRACE("litl"); + TMPSTY(litl, ti, t[0], 3); + test_emits_(ti, t[0], 3, "|-\n foo", "\"foo\""); + } + { + SCOPED_TRACE("nosty"); + TMPSTY(nosty, ti, t[0], 3); + test_emits_(ti, t[0], 3, "foo", "\"foo\""); + } + }; + { + SCOPED_TRACE("block"); + TMPSTY(blk, ti, t, 2); + testfoo(); + } + { + SCOPED_TRACE("flow_sl"); + TMPSTY(flowsl, ti, t, 2); + testfoo(); + } + { + SCOPED_TRACE("flow_ml1"); + TMPSTY(flowml1, ti, t, 2); + testfoo(); + } + { + SCOPED_TRACE("flow_mln"); + TMPSTY(flowmln, ti, t, 2); + testfoo(); + } + } + { + SCOPED_TRACE("t[1]=bar"); + auto testbar = [&]{ + { + SCOPED_TRACE("orig"); + test_emits_(ti, t[1], 6, "bar", "\"bar\""); + } + { + SCOPED_TRACE("plain"); + TMPSTY(plai, ti, t[1], 6); + test_emits_(ti, t[1], 6, "bar", "\"bar\""); + } + { + SCOPED_TRACE("squo"); + TMPSTY(squo, ti, t[1], 6); + test_emits_(ti, t[1], 6, "'bar'", "\"bar\""); + } + { + SCOPED_TRACE("dquo"); + TMPSTY(dquo, ti, t[1], 6); + test_emits_(ti, t[1], 6, "\"bar\"", "\"bar\""); + } + { + SCOPED_TRACE("fold"); + TMPSTY(fold, ti, t[1], 6); + test_emits_(ti, t[1], 6, ">-\n bar", "\"bar\""); + } + { + SCOPED_TRACE("litl"); + TMPSTY(litl, ti, t[1], 6); + test_emits_(ti, t[1], 6, "|-\n bar", "\"bar\""); + } + { + SCOPED_TRACE("nosty"); + TMPSTY(nosty, ti, t[1], 6); + test_emits_(ti, t[1], 6, "bar", "\"bar\""); + } + }; + { + SCOPED_TRACE("block"); + TMPSTY(blk, ti, t, 2); + testbar(); + } + { + SCOPED_TRACE("flow_sl"); + TMPSTY(flowsl, ti, t, 2); + testbar(); + } + { + SCOPED_TRACE("flow_ml1"); + TMPSTY(flowml1, ti, t, 2); + testbar(); + } + { + SCOPED_TRACE("flow_mln"); + TMPSTY(flowmln, ti, t, 2); + testbar(); + } } { SCOPED_TRACE("t[2]"); - NodeRef n = nct[2]; { - SCOPED_TRACE("FLOW_SL"); - TmpContainerStyle tmp(n, FLOW_SL); - std::string expected = "[nested,seq]"; - std::string expected_json = "[\"nested\",\"seq\"]"; - test_all_emits(n, expected, expected_json); + SCOPED_TRACE("block"); + TMPSTY(blk, ti, t[2], 9); + test_emits_(ti, t[2], 9, + "- nested\n- seq\n", + "[\n \"nested\",\n \"seq\"\n]\n"); + } + { + SCOPED_TRACE("flow_sl"); + TMPSTY(flowsl, ti, t[2], 9); + test_emits_(ti, t[2], 9, + "[nested,seq]", + "[\"nested\",\"seq\"]"); } { - SCOPED_TRACE("FLOW_ML1"); - TmpContainerStyle tmp(n, FLOW_ML1); - std::string expected = "[\n nested,\n seq\n]\n"; - std::string expected_json = "[\n \"nested\",\n \"seq\"\n]\n"; - test_all_emits(n, expected, expected_json); + SCOPED_TRACE("flow_ml1"); + TMPSTY(flowml1, ti, t[2], 9); + test_emits_(ti, t[2], 9, + "[\n nested,\n seq\n]\n", + "[\n \"nested\",\n \"seq\"\n]\n"); } { - SCOPED_TRACE("BLOCK"); - TmpContainerStyle tmp(n, BLOCK); - std::string expected = "- nested\n- seq\n"; - std::string expected_json = "[\n \"nested\",\n \"seq\"\n]\n"; - test_all_emits(n, expected, expected_json); + SCOPED_TRACE("flow_mln"); + TMPSTY(flowmln, ti, t[2], 9); + test_emits_(ti, t[2], 9, + "[\n nested,seq\n]\n", + "[\n \"nested\",\"seq\"\n]\n"); } } { SCOPED_TRACE("t[3]"); - NodeRef n = nct[3]; { - SCOPED_TRACE("FLOW_SL"); - TmpContainerStyle tmp(n, FLOW_SL); - std::string expected = "{nested: map}"; - std::string expected_json = "{\"nested\": \"map\"}"; - test_all_emits(n, expected, expected_json); + SCOPED_TRACE("block"); + TMPSTY(blk, ti, t[3], 17); + test_emits_(ti, t[3], 17, + "nested: map\n", + "{\n \"nested\": \"map\"\n}\n"); + } + { + SCOPED_TRACE("flow_sl"); + TMPSTY(flowsl, ti, t[3], 17); + test_emits_(ti, t[3], 17, + "{nested: map}", + "{\"nested\": \"map\"}"); } { - SCOPED_TRACE("FLOW_ML1"); - TmpContainerStyle tmp(n, FLOW_ML1); - std::string expected = "{\n nested: map\n}\n"; - std::string expected_json = "{\n \"nested\": \"map\"\n}\n"; - test_all_emits(n, expected, expected_json); + SCOPED_TRACE("flow_ml1"); + TMPSTY(flowml1, ti, t[3], 17); + test_emits_(ti, t[3], 17, + "{\n nested: map\n}\n", + "{\n \"nested\": \"map\"\n}\n"); } { - SCOPED_TRACE("BLOCK"); - TmpContainerStyle tmp(n, BLOCK); - std::string expected = "nested: map\n"; - std::string expected_json = "{\n \"nested\": \"map\"\n}\n"; - test_all_emits(n, expected, expected_json); + SCOPED_TRACE("flow_mln"); + TMPSTY(flowmln, ti, t[3], 17); + test_emits_(ti, t[3], 17, + "{\n nested: map\n}\n", + "{\n \"nested\": \"map\"\n}\n"); } } + { + SCOPED_TRACE("root"); + { + SCOPED_TRACE("block"); + TMPSTY(blk, ti, t, 2); + TMPSTY(blk, ti, t[2], 9); + TMPSTY(blk, ti, t[3], 17); + test_emits_(ti, t, 0, + "- foo\n- bar\n- - nested\n - seq\n- nested: map\n", + "[\n \"foo\",\n \"bar\",\n [\n \"nested\",\n \"seq\"\n ],\n {\n \"nested\": \"map\"\n }\n]\n"); + } + { + SCOPED_TRACE("flow_sl"); + TMPSTY(flowsl, ti, t, 2); + TMPSTY(flowsl, ti, t[2], 9); + TMPSTY(flowsl, ti, t[3], 17); + test_emits_(ti, t, 0, + "[foo,bar,[nested,seq],{nested: map}]", + "[\"foo\",\"bar\",[\"nested\",\"seq\"],{\"nested\": \"map\"}]"); + test_emits_(ti, t, 0, + "[foo, bar, [nested, seq], {nested: map}]", + "[\"foo\", \"bar\", [\"nested\", \"seq\"], {\"nested\": \"map\"}]", + with_flow_spc); + } + { + SCOPED_TRACE("flow_ml1"); + TMPSTY(flowml1, ti, t, 2); + TMPSTY(flowml1, ti, t[2], 9); + TMPSTY(flowml1, ti, t[3], 17); + { + SCOPED_TRACE("indent"); + test_emits_(ti, t, 0, + "[\n foo,\n bar,\n [\n nested,\n seq\n ],\n {\n nested: map\n }\n]\n", + "[\n \"foo\",\n \"bar\",\n [\n \"nested\",\n \"seq\"\n ],\n {\n \"nested\": \"map\"\n }\n]\n"); + } + { + SCOPED_TRACE("no indent"); + test_emits_(ti, t, 2, + "[\nfoo,\nbar,\n[\nnested,\nseq\n],\n{\nnested: map\n}\n]\n", + "[\n\"foo\",\n\"bar\",\n[\n\"nested\",\n\"seq\"\n],\n{\n\"nested\": \"map\"\n}\n]\n", + noindent); + } + } + { + SCOPED_TRACE("flow_mln"); + TMPSTY(flowmln, ti, t, 2); + TMPSTY(flowmln, ti, t[2], 9); + TMPSTY(flowmln, ti, t[3], 17); + { + SCOPED_TRACE("indent"); + test_emits_(ti, t, 0, + "[\n foo,bar,[\n nested,seq\n ],{\n nested: map\n }\n]\n", + "[\n \"foo\",\"bar\",[\n \"nested\",\"seq\"\n ],{\n \"nested\": \"map\"\n }\n]\n"); + } + { + SCOPED_TRACE("no indent"); + test_emits_(ti, t, 0, + "[\nfoo,bar,[\nnested,seq\n],{\nnested: map\n}\n]\n", + "[\n\"foo\",\"bar\",[\n\"nested\",\"seq\"\n],{\n\"nested\": \"map\"\n}\n]\n", + noindent); + } + { + SCOPED_TRACE("spc"); + test_emits_(ti, t, 0, + "[\n foo, bar, [\n nested, seq\n ], {\n nested: map\n }\n]\n", + "[\n \"foo\", \"bar\", [\n \"nested\", \"seq\"\n ], {\n \"nested\": \"map\"\n }\n]\n", + with_flow_spc); + } + } + { + SCOPED_TRACE("block-flow-ml"); + { + TMPSTY(blk, ti, t, 2); + TMPSTY(flowml1, ti, t[2], 9); + TMPSTY(flowml1, ti, t[3], 17); + { + SCOPED_TRACE("indent"); + test_emits_(ti, t, 0, + "- foo\n- bar\n- [\n nested,\n seq\n ]\n- {\n nested: map\n }\n", + "[\n \"foo\",\n \"bar\",\n [\n \"nested\",\n \"seq\"\n ],\n {\n \"nested\": \"map\"\n }\n]\n"); + } + { + SCOPED_TRACE("no indent"); + test_emits_(ti, t, 0, + "- foo\n- bar\n- [\n nested,\n seq\n ]\n- {\n nested: map\n }\n", + "[\n\"foo\",\n\"bar\",\n[\n\"nested\",\n\"seq\"\n],\n{\n\"nested\": \"map\"\n}\n]\n", + noindent); + } + } + } + } + { + SCOPED_TRACE("full-all"); + { + SCOPED_TRACE("flow_ml"); + TMPSTY(flowml1, ti, t, 2); + TMPSTY(flowml1, ti, t[2], 9); + TMPSTY(flowml1, ti, t[3], 17); + { + SCOPED_TRACE("indent"); + test_emits_(ti, t, 0, + "[\n foo,\n bar,\n [\n nested,\n seq\n ],\n {\n nested: map\n }\n]\n", + "[\n \"foo\",\n \"bar\",\n [\n \"nested\",\n \"seq\"\n ],\n {\n \"nested\": \"map\"\n }\n]\n"); + } + { + SCOPED_TRACE("no indent ml"); + test_emits_(ti, t, 0, + "[\nfoo,\nbar,\n[\nnested,\nseq\n],\n{\nnested: map\n}\n]\n", + "[\n\"foo\",\n\"bar\",\n[\n\"nested\",\n\"seq\"\n],\n{\n\"nested\": \"map\"\n}\n]\n", + noindent); + } + } + { + SCOPED_TRACE("flow_sl"); + TMPSTY(flowsl, ti, t, 2); + TMPSTY(flowsl, ti, t[2], 9); + TMPSTY(flowsl, ti, t[3], 17); + test_emits_(ti, t, 0, + "[foo,bar,[nested,seq],{nested: map}]", + "[\"foo\",\"bar\",[\"nested\",\"seq\"],{\"nested\": \"map\"}]"); + test_emits_(ti, t, 0, + "[foo, bar, [nested, seq], {nested: map}]", + "[\"foo\", \"bar\", [\"nested\", \"seq\"], {\"nested\": \"map\"}]", + with_flow_spc); + } + } +} + +TEST(emit, existing_seq_node_flow_sl) +{ + const std::string yaml = "[foo,bar,[nested,seq],{nested: map}]"; + SCOPED_TRACE(yaml); + TreeAndInts ti = parse_tree_and_ints(to_csubstr(yaml)); + { + SCOPED_TRACE("orig"); + test_emits_(ti, ti.tree, 0, + "[foo,bar,[nested,seq],{nested: map}]", + "[\"foo\",\"bar\",[\"nested\",\"seq\"],{\"nested\": \"map\"}]"); + test_emits_(ti, ti.tree, 0, + "[foo, bar, [nested, seq], {nested: map}]", + "[\"foo\", \"bar\", [\"nested\", \"seq\"], {\"nested\": \"map\"}]", + with_flow_spc); + } + test_emit_seq_node(ti, yaml); +} + +TEST(emit, existing_seq_node_flow_ml) +{ + const std::string yaml = "[\n foo,\n bar,\n [\n nested,\n seq\n ],\n {\n nested: map\n }\n]\n"; + SCOPED_TRACE(yaml); + TreeAndInts ti = parse_tree_and_ints(to_csubstr(yaml)); + { + SCOPED_TRACE("orig"); + test_emits_(ti, ti.tree, 0, + "[\n foo,\n bar,\n [\n nested,\n seq\n ],\n {\n nested: map\n }\n]\n", + "[\n \"foo\",\n \"bar\",\n [\n \"nested\",\n \"seq\"\n ],\n {\n \"nested\": \"map\"\n }\n]\n"); + } + test_emit_seq_node(ti, yaml); } TEST(emit, existing_seq_node_block) { - Tree nct = parse_in_arena("- foo\n- bar\n- - nested\n - seq\n- nested: map\n"); - Tree const& t = nct; + const std::string yaml = "- foo\n- bar\n- - nested\n - seq\n- nested: map\n"; + SCOPED_TRACE(yaml); + TreeAndInts ti = parse_tree_and_ints(to_csubstr(yaml)); + { + SCOPED_TRACE("orig"); + test_emits_(ti, ti.tree, 0, + "- foo\n- bar\n- - nested\n - seq\n- nested: map\n", + "[\n \"foo\",\n \"bar\",\n [\n \"nested\",\n \"seq\"\n ],\n {\n \"nested\": \"map\"\n }\n]\n"); + } + test_emit_seq_node(ti, yaml); +} + + +//----------------------------------------------------------------------------- + + +static void test_emit_map_node(TreeAndInts & ti, std::string const& yaml) +{ + SCOPED_TRACE(yaml); + Tree & t = ti.tree; { - SCOPED_TRACE("full-top"); + SCOPED_TRACE("root"); { SCOPED_TRACE("block"); - TmpContainerStyle tmp(nct.rootref(), BLOCK); - std::string expected = "- foo\n- bar\n- - nested\n - seq\n- nested: map\n"; - std::string expected_json = "[\n \"foo\",\n \"bar\",\n [\n \"nested\",\n \"seq\"\n ],\n {\n \"nested\": \"map\"\n }\n]\n"; - test_all_emits(t.crootref(), expected, expected_json); + TMPSTY(blk, ti, t, 2); + TMPSTY(blk, ti, t[2], 18); + TMPSTY(blk, ti, t[3], 29); + test_emits_(ti, t, 0, + "0: foo\n1: bar\n2:\n - nested\n - seq\n3:\n nested: map\n", + "{\n \"0\": \"foo\",\n \"1\": \"bar\",\n \"2\": [\n \"nested\",\n \"seq\"\n ],\n \"3\": {\n \"nested\": \"map\"\n }\n}\n"); } { - SCOPED_TRACE("block-flow-ml"); + SCOPED_TRACE("flow_sl"); + TMPSTY(flowsl, ti, t, 2); + TMPSTY(flowsl, ti, t[2], 18); + TMPSTY(flowsl, ti, t[3], 29); + test_emits_(ti, t, 0, + "{0: foo,1: bar,2: [nested,seq],3: {nested: map}}", + R"({"0": "foo","1": "bar","2": ["nested","seq"],"3": {"nested": "map"}})"); + test_emits_(ti, t, 0, + "{0: foo, 1: bar, 2: [nested, seq], 3: {nested: map}}", + R"({"0": "foo", "1": "bar", "2": ["nested", "seq"], "3": {"nested": "map"}})", + with_flow_spc); + } + { + SCOPED_TRACE("flow_ml1"); + TMPSTY(flowml1, ti, t, 2); + TMPSTY(flowml1, ti, t[2], 18); + TMPSTY(flowml1, ti, t[3], 29); { SCOPED_TRACE("indent"); - TmpContainerStyle tmp(nct.rootref(), BLOCK); - TmpContainerStyle tmp2(nct[2], FLOW_ML1); - TmpContainerStyle tmp3(nct[3], FLOW_ML1); - std::string expected = "- foo\n- bar\n- [\n nested,\n seq\n ]\n- {\n nested: map\n }\n"; - std::string expected_json = "[\n \"foo\",\n \"bar\",\n [\n \"nested\",\n \"seq\"\n ],\n {\n \"nested\": \"map\"\n }\n]\n"; - test_all_emits(t.crootref(), expected, expected_json); + test_emits_(ti, t, 0, + "{\n 0: foo,\n 1: bar,\n 2: [\n nested,\n seq\n ],\n 3: {\n nested: map\n }\n}\n", + "{\n \"0\": \"foo\",\n \"1\": \"bar\",\n \"2\": [\n \"nested\",\n \"seq\"\n ],\n \"3\": {\n \"nested\": \"map\"\n }\n}\n"); } { SCOPED_TRACE("no indent"); - TmpContainerStyle tmp(nct.rootref(), BLOCK); - TmpContainerStyle tmp2(nct[2], FLOW_ML1); - TmpContainerStyle tmp3(nct[3], FLOW_ML1); - std::string expected = "- foo\n- bar\n- [\n nested,\n seq\n ]\n- {\n nested: map\n }\n"; - std::string expected_json = "[\n\"foo\",\n\"bar\",\n[\n\"nested\",\n\"seq\"\n],\n{\n\"nested\": \"map\"\n}\n]\n"; - test_all_emits(t.crootref(), expected, expected_json, EmitOptions{}.indent_flow_ml(false)); + test_emits_(ti, t, 0, + "{\n0: foo,\n1: bar,\n2: [\nnested,\nseq\n],\n3: {\nnested: map\n}\n}\n", + "{\n\"0\": \"foo\",\n\"1\": \"bar\",\n\"2\": [\n\"nested\",\n\"seq\"\n],\n\"3\": {\n\"nested\": \"map\"\n}\n}\n", + noindent); } } { - SCOPED_TRACE("flow_ml"); + SCOPED_TRACE("flow_ml1-flowsl"); + TMPSTY(flowml1, ti, t, 2); + TMPSTY(flowsl, ti, t[2], 18); + TMPSTY(flowsl, ti, t[3], 29); { SCOPED_TRACE("indent"); - TmpContainerStyle tmp(nct.rootref(), FLOW_ML1); - std::string expected = "[\n foo,\n bar,\n [nested,seq],\n {nested: map}\n]\n"; - std::string expected_json = "[\n \"foo\",\n \"bar\",\n [\n \"nested\",\n \"seq\"\n ],\n {\n \"nested\": \"map\"\n }\n]\n"; - test_all_emits(t.crootref(), expected, expected_json); + test_emits_(ti, t, 0, + "{\n 0: foo,\n 1: bar,\n 2: [nested,seq],\n 3: {nested: map}\n}\n", + "{\n \"0\": \"foo\",\n \"1\": \"bar\",\n \"2\": [\"nested\",\"seq\"],\n \"3\": {\"nested\": \"map\"}\n}\n"); } { SCOPED_TRACE("no indent"); - TmpContainerStyle tmp(nct.rootref(), FLOW_ML1); - std::string expected = "[\nfoo,\nbar,\n[nested,seq],\n{nested: map}\n]\n"; - std::string expected_json = "[\n\"foo\",\n\"bar\",\n[\n\"nested\",\n\"seq\"\n],\n{\n\"nested\": \"map\"\n}\n]\n"; - test_all_emits(t.crootref(), expected, expected_json, EmitOptions{}.indent_flow_ml(false)); + test_emits_(ti, t, 0, + "{\n0: foo,\n1: bar,\n2: [nested,seq],\n3: {nested: map}\n}\n", + "{\n\"0\": \"foo\",\n\"1\": \"bar\",\n\"2\": [\"nested\",\"seq\"],\n\"3\": {\"nested\": \"map\"}\n}\n", + noindent); } } { - SCOPED_TRACE("flow_sl"); - TmpContainerStyle tmp(nct.rootref(), FLOW_SL); - std::string expected = "[foo,bar,[nested,seq],{nested: map}]"; - std::string expected_json = "[\"foo\",\"bar\",[\"nested\",\"seq\"],{\"nested\": \"map\"}]"; - test_all_emits(t.crootref(), expected, expected_json); + SCOPED_TRACE("flow_mln-flowsl"); + TMPSTY(flowmln, ti, t, 2); + TMPSTY(flowsl, ti, t[2], 18); + TMPSTY(flowsl, ti, t[3], 29); + { + SCOPED_TRACE("indent"); + test_emits_(ti, t, 0, + "{\n 0: foo,1: bar,2: [nested,seq],3: {nested: map}\n}\n", + "{\n \"0\": \"foo\",\"1\": \"bar\",\"2\": [\"nested\",\"seq\"],\"3\": {\"nested\": \"map\"}\n}\n"); + } + { + SCOPED_TRACE("no indent"); + test_emits_(ti, t, 0, + "{\n0: foo,1: bar,2: [nested,seq],3: {nested: map}\n}\n", + "{\n\"0\": \"foo\",\"1\": \"bar\",\"2\": [\"nested\",\"seq\"],\"3\": {\"nested\": \"map\"}\n}\n", + noindent); + } } } { SCOPED_TRACE("full-all"); { - SCOPED_TRACE("block"); - TmpContainerStyle tmp0(nct.rootref(), BLOCK); - TmpContainerStyle tmp2(nct[2], BLOCK); - TmpContainerStyle tmp3(nct[3], BLOCK); - std::string expected = "- foo\n- bar\n- - nested\n - seq\n- nested: map\n"; - std::string expected_json = "[\n \"foo\",\n \"bar\",\n [\n \"nested\",\n \"seq\"\n ],\n {\n \"nested\": \"map\"\n }\n]\n"; - test_all_emits(t.crootref(), expected, expected_json); } { SCOPED_TRACE("flow_ml"); + TMPSTY(flowml1, ti, t, 2); + TMPSTY(flowml1, ti, t[2], 18); + TMPSTY(flowml1, ti, t[3], 29); { SCOPED_TRACE("indent"); - TmpContainerStyle tmp(nct.rootref(), FLOW_ML1); - TmpContainerStyle tmp2(nct[2], FLOW_ML1); - TmpContainerStyle tmp3(nct[3], FLOW_ML1); - std::string expected = "[\n foo,\n bar,\n [\n nested,\n seq\n ],\n {\n nested: map\n }\n]\n"; - std::string expected_json = "[\n \"foo\",\n \"bar\",\n [\n \"nested\",\n \"seq\"\n ],\n {\n \"nested\": \"map\"\n }\n]\n"; - test_all_emits(t.crootref(), expected, expected_json); + test_emits_(ti, t, 0, + "{\n 0: foo,\n 1: bar,\n 2: [\n nested,\n seq\n ],\n 3: {\n nested: map\n }\n}\n", + "{\n \"0\": \"foo\",\n \"1\": \"bar\",\n \"2\": [\n \"nested\",\n \"seq\"\n ],\n \"3\": {\n \"nested\": \"map\"\n }\n}\n"); } { - SCOPED_TRACE("no indent ml"); - TmpContainerStyle tmp(nct.rootref(), FLOW_ML1); - TmpContainerStyle tmp2(nct[2], FLOW_ML1); - TmpContainerStyle tmp3(nct[3], FLOW_ML1); - std::string expected = "[\nfoo,\nbar,\n[\nnested,\nseq\n],\n{\nnested: map\n}\n]\n"; - std::string expected_json = "[\n\"foo\",\n\"bar\",\n[\n\"nested\",\n\"seq\"\n],\n{\n\"nested\": \"map\"\n}\n]\n"; - test_all_emits(t.crootref(), expected, expected_json, EmitOptions{}.indent_flow_ml(false)); + SCOPED_TRACE("no indent"); + test_emits_(ti, t, 0, + "{\n0: foo,\n1: bar,\n2: [\nnested,\nseq\n],\n3: {\nnested: map\n}\n}\n", + "{\n\"0\": \"foo\",\n\"1\": \"bar\",\n\"2\": [\n\"nested\",\n\"seq\"\n],\n\"3\": {\n\"nested\": \"map\"\n}\n}\n", + noindent); } } { SCOPED_TRACE("flow_sl"); - TmpContainerStyle tmp(nct.rootref(), FLOW_SL); - TmpContainerStyle tmp2(nct[2], FLOW_SL); - TmpContainerStyle tmp3(nct[3], FLOW_SL); - std::string expected = "[foo,bar,[nested,seq],{nested: map}]"; - std::string expected_json = "[\"foo\",\"bar\",[\"nested\",\"seq\"],{\"nested\": \"map\"}]"; - test_all_emits(t.crootref(), expected, expected_json); + TMPSTY(flowsl, ti, t, 2); + TMPSTY(flowsl, ti, t[2], 18); + TMPSTY(flowsl, ti, t[3], 29); + test_emits_(ti, t, 0, + "{0: foo,1: bar,2: [nested,seq],3: {nested: map}}", + R"({"0": "foo","1": "bar","2": ["nested","seq"],"3": {"nested": "map"}})"); + test_emits_(ti, t, 0, + "{0: foo, 1: bar, 2: [nested, seq], 3: {nested: map}}", + R"({"0": "foo", "1": "bar", "2": ["nested", "seq"], "3": {"nested": "map"}})", + with_flow_spc); } } { SCOPED_TRACE("t[0]"); - NodeRef n = nct[0]; + auto testfoo = [&]{ + { + SCOPED_TRACE("orig"); + { + SCOPED_TRACE("key"); + test_emits_(ti, t[0], 3, "0: foo\n", "\"0\": \"foo\"\n"); + } + { + SCOPED_TRACE("nokey"); + test_emits_(ti, t[0], 6, "foo", "\"foo\"", without_key); + } + } + { + SCOPED_TRACE("plai"); + TMPSTY(plaikv, ti, t[0], 3, 6); + { + SCOPED_TRACE("key"); + test_emits_(ti, t[0], 3, "0: foo\n", "\"0\": \"foo\"\n"); + } + { + SCOPED_TRACE("nokey"); + test_emits_(ti, t[0], 6, "foo", "\"foo\"", without_key); + } + } + { + SCOPED_TRACE("squo"); + TMPSTY(squokv, ti, t[0], 3, 6); + { + SCOPED_TRACE("key"); + test_emits_(ti, t[0], 3, "'0': 'foo'\n", "\"0\": \"foo\"\n"); + } + { + SCOPED_TRACE("nokey"); + test_emits_(ti, t[0], 6, "'foo'", "\"foo\"", without_key); + } + } + { + SCOPED_TRACE("dquo"); + TMPSTY(dquokv, ti, t[0], 3, 6); + { + SCOPED_TRACE("key"); + test_emits_(ti, t[0], 3, "\"0\": \"foo\"\n", "\"0\": \"foo\"\n"); + } + { + SCOPED_TRACE("nokey"); + test_emits_(ti, t[0], 6, "\"foo\"", "\"foo\"", without_key); + } + } + { + SCOPED_TRACE("litl"); + TMPSTY(litlkv, ti, t[0], 3, 6); + { + SCOPED_TRACE("key"); + test_emits_(ti, t[0], 3, "? |-\n 0\n: |-\n foo\n", "\"0\": \"foo\"\n"); + } + { + SCOPED_TRACE("nokey"); + test_emits_(ti, t[0], 6, "|-\n foo", "\"foo\"", without_key); + } + } + { + SCOPED_TRACE("fold"); + TMPSTY(foldkv, ti, t[0], 3, 6); + { + SCOPED_TRACE("key"); + test_emits_(ti, t[0], 3, "? >-\n 0\n: >-\n foo\n", "\"0\": \"foo\"\n"); + } + { + SCOPED_TRACE("nokey"); + test_emits_(ti, t[0], 6, ">-\n foo", "\"foo\"", without_key); + } + } + }; { SCOPED_TRACE("block"); - TmpContainerStyle tmp(n, BLOCK); - std::string expected = "foo"; - std::string expected_json = "\"foo\"\n"; - test_all_emits(n, expected, expected_json); + TMPSTY(blk, ti, t, 2); + testfoo(); } { - SCOPED_TRACE("flow_ml"); - TmpContainerStyle tmp(n, FLOW_ML1); - std::string expected = "foo\n"; - std::string expected_json = "\"foo\"\n"; - test_all_emits(n, expected, expected_json); + SCOPED_TRACE("flow_ml1"); + TMPSTY(flowml1, ti, t, 2); + testfoo(); + } + { + SCOPED_TRACE("flow_mln"); + TMPSTY(flowmln, ti, t, 2); + testfoo(); } { SCOPED_TRACE("flow_sl"); - TmpContainerStyle tmp(n, FLOW_SL); - std::string expected = "foo"; - std::string expected_json = "\"foo\""; - test_all_emits(n, expected, expected_json); + TMPSTY(flowsl, ti, t, 2); + testfoo(); } } { SCOPED_TRACE("t[1]"); - NodeRef n = nct[1]; { SCOPED_TRACE("block"); - TmpContainerStyle tmp(n, BLOCK); - std::string expected = "bar"; - std::string expected_json = "\"bar\"\n"; - test_all_emits(n, expected, expected_json); + TMPSTY(blk, ti, t, 2); + test_emits_(ti, t[1], 9, + "1: bar\n", + "\"1\": \"bar\"\n"); } { SCOPED_TRACE("flow_ml"); - TmpContainerStyle tmp(n, FLOW_ML1); - std::string expected = "bar\n"; - std::string expected_json = "\"bar\"\n"; - test_all_emits(n, expected, expected_json); + TMPSTY(flowml1, ti, t, 2); + test_emits_(ti, t[1], 9, + "1: bar\n", + "\"1\": \"bar\"\n"); } { SCOPED_TRACE("flow_sl"); - TmpContainerStyle tmp(n, FLOW_SL); - std::string expected = "bar"; - std::string expected_json = "\"bar\""; - test_all_emits(n, expected, expected_json); + TMPSTY(flowsl, ti, t, 2); + test_emits_(ti, t[1], 9, + "1: bar\n", + "\"1\": \"bar\"\n"); } } { SCOPED_TRACE("t[2]"); - NodeRef n = nct[2]; { SCOPED_TRACE("block"); - TmpContainerStyle tmp(n, BLOCK); - std::string expected = "- nested\n- seq\n"; - std::string expected_json = "[\n \"nested\",\n \"seq\"\n]\n"; - test_all_emits(n, expected, expected_json); + TMPSTY(blk, ti, t[2], 18); + test_emits_(ti, t[2], 15, + "2:\n - nested\n - seq\n", + "\"2\": [\n \"nested\",\n \"seq\"\n]\n"); } { - SCOPED_TRACE("flow_ml"); - TmpContainerStyle tmp(n, FLOW_ML1); - std::string expected = "[\n nested,\n seq\n]\n"; - std::string expected_json = "[\n \"nested\",\n \"seq\"\n]\n"; - test_all_emits(n, expected, expected_json); + SCOPED_TRACE("flow_ml1"); + TMPSTY(flowml1, ti, t[2], 18); + test_emits_(ti, t[2], 15, + "2: [\n nested,\n seq\n ]\n", // FIXME should be indented one level, not two + "\"2\": [\n \"nested\",\n \"seq\"\n]\n"); } { SCOPED_TRACE("flow_sl"); - TmpContainerStyle tmp(n, FLOW_SL); - std::string expected = "[nested,seq]"; - std::string expected_json = "[\"nested\",\"seq\"]"; - test_all_emits(n, expected, expected_json); + TMPSTY(flowsl, ti, t[2], 18); + test_emits_(ti, t[2], 15, + "2: [nested,seq]\n", + "\"2\": [\"nested\",\"seq\"]\n"); + test_emits_(ti, t[2], 15, + "2: [nested, seq]\n", + "\"2\": [\"nested\", \"seq\"]\n", + with_flow_spc); } } { SCOPED_TRACE("t[3]"); - NodeRef n = nct[3]; { SCOPED_TRACE("block"); - TmpContainerStyle tmp(n, BLOCK); - std::string expected = "nested: map\n"; - std::string expected_json = "{\n \"nested\": \"map\"\n}\n"; - test_all_emits(n, expected, expected_json); + TMPSTY(blk, ti, t[3], 29); + test_emits_(ti, t[3], 26, + "3:\n nested: map\n", + "\"3\": {\n \"nested\": \"map\"\n}\n"); } { SCOPED_TRACE("flow_ml"); - TmpContainerStyle tmp(n, FLOW_ML1); - std::string expected = "{\n nested: map\n}\n"; - std::string expected_json = "{\n \"nested\": \"map\"\n}\n"; - test_all_emits(n, expected, expected_json); + TMPSTY(flowml1, ti, t[3], 29); + test_emits_(ti, t[3], 26, + "3: {\n nested: map\n }\n", // FIXME should be indented one level, not two + "\"3\": {\n \"nested\": \"map\"\n}\n"); } { SCOPED_TRACE("flow_sl"); - TmpContainerStyle tmp(n, FLOW_SL); - std::string expected = "{nested: map}"; - std::string expected_json = "{\"nested\": \"map\"}"; - test_all_emits(n, expected, expected_json); + TMPSTY(flowsl, ti, t[3], 29); + test_emits_(ti, t[3], 26, + "3: {nested: map}\n", + "\"3\": {\"nested\": \"map\"}\n"); } } } -TEST(emit, existing_map_node_flow) + +TEST(emit, existing_map_node_flow_sl) { - Tree nct = parse_in_arena("{0: foo, 1: bar, 2: [nested, seq], 3: {nested: map}}"); - Tree const& t = nct; + const std::string yaml = "{0: foo, 1: bar, 2: [nested, seq], 3: {nested: map}}"; + TreeAndInts ti = parse_tree_and_ints(to_csubstr(yaml)); + Tree & t = ti.tree; { - SCOPED_TRACE("full-top"); - { - SCOPED_TRACE("block"); - TmpContainerStyle tmp(nct.rootref(), BLOCK); - std::string expected = "0: foo\n1: bar\n2: [nested,seq]\n3: {nested: map}\n"; - std::string expected_json = "{\n \"0\": \"foo\",\n \"1\": \"bar\",\n \"2\": [\"nested\",\"seq\"],\n \"3\": {\"nested\": \"map\"}\n}\n"; - test_all_emits(t.crootref(), expected, expected_json); - } + SCOPED_TRACE("orig"); + test_emits_(ti, t, 0, + "{0: foo,1: bar,2: [nested,seq],3: {nested: map}}", + R"({"0": "foo","1": "bar","2": ["nested","seq"],"3": {"nested": "map"}})"); + } + { + SCOPED_TRACE("here"); + test_emit_map_node(ti, yaml); + } +} + +TEST(emit, existing_map_node_flow_ml) +{ + const std::string yaml = "{\n 0: foo, 1: bar, 2: [nested, seq], 3: {nested: map}\n}\n"; + TreeAndInts ti = parse_tree_and_ints(to_csubstr(yaml)); + Tree & t = ti.tree; + { + SCOPED_TRACE("orig"); + test_emits_(ti, t, 0, + "{\n 0: foo,\n 1: bar,\n 2: [nested,seq],\n 3: {nested: map}\n}\n", + "{\n \"0\": \"foo\",\n \"1\": \"bar\",\n \"2\": [\"nested\",\"seq\"],\n \"3\": {\"nested\": \"map\"}\n}\n"); + } + { + SCOPED_TRACE("here"); + test_emit_map_node(ti, yaml); + } +} + +TEST(emit, existing_map_node_block) +{ + const std::string yaml = "0: foo\n1: bar\n2:\n - nested\n - seq\n3:\n nested: map\n"; + TreeAndInts ti = parse_tree_and_ints(to_csubstr(yaml)); + Tree & t = ti.tree; + { + SCOPED_TRACE("orig"); + test_emits_(ti, t, 0, + "0: foo\n1: bar\n2:\n - nested\n - seq\n3:\n nested: map\n", + "{\n \"0\": \"foo\",\n \"1\": \"bar\",\n \"2\": [\n \"nested\",\n \"seq\"\n ],\n \"3\": {\n \"nested\": \"map\"\n }\n}\n"); + } + { + SCOPED_TRACE("here"); + test_emit_map_node(ti, yaml); + } +} + + +//----------------------------------------------------------------------------- + +TEST(emit, container_key_seq_flow) +{ + SCOPED_TRACE("container_key_map_flow"); + IntBufs ints; + std::string yaml = "[key, is, a, seq]: [val, is, a, seq]"; + parse_ints(to_substr(yaml), &ints); + test_emits_ints_nojson_(ints, 0, "? [key,is,a,seq]\n: [val,is,a,seq]\n"); + { + SCOPED_TRACE("root-blk"); + TMPSTY(blk, ints, 2); + auto dotest = [&](strref keyval, strref key, strref val){ + test_emits_ints_nojson_(ints, 0, keyval); + test_emits_ints_nojson_(ints, 1, keyval); + test_emits_ints_nojson_(ints, 2, keyval); + test_emits_ints_nojson_(ints, 2, keyval, without_key); + test_emits_ints_nojson_(ints, 3, keyval); + test_emits_ints_nojson_(ints, 3, key, without_key); + test_emits_ints_nojson_(ints, 17, val); + test_emits_ints_nojson_(ints, 17, val, without_key); + }; + { + SCOPED_TRACE("kv-blk"); + TMPSTY(blk, ints, ints, 3, 17); + dotest("?\n - key\n - is\n - a\n - seq\n:\n - val\n - is\n - a\n - seq\n", + "- key\n- is\n- a\n- seq\n", + "- val\n- is\n- a\n- seq\n"); + } + { + SCOPED_TRACE("kv-flowml1"); + TMPSTY(flowml1, ints, ints, 3, 17); + dotest("? [\n key,\n is,\n a,\n seq\n ]\n: [\n val,\n is,\n a,\n seq\n ]\n", + "[\n key,\n is,\n a,\n seq\n]\n", + "[\n val,\n is,\n a,\n seq\n]\n"); + } + { + SCOPED_TRACE("kv-flowmln"); + TMPSTY(flowmln, ints, ints, 3, 17); + dotest("? [\n key,is,a,seq\n ]\n: [\n val,is,a,seq\n ]\n", + "[\n key,is,a,seq\n]\n", + "[\n val,is,a,seq\n]\n"); + } + { + SCOPED_TRACE("kv-flowmln-spc"); + TMPSTY(flowmln, ints, ints, 3, 17, xievt::FSPC); + dotest("? [\n key, is, a, seq\n ]\n: [\n val, is, a, seq\n ]\n", + "[\n key, is, a, seq\n]\n", + "[\n val, is, a, seq\n]\n"); + } + { + SCOPED_TRACE("kv-flowsl"); + TMPSTY(flowsl, ints, ints, 3, 17); + dotest("? [key,is,a,seq]\n: [val,is,a,seq]\n", + "[key,is,a,seq]", + "[val,is,a,seq]"); + } + { + SCOPED_TRACE("kv-flowsl-spc"); + TMPSTY(flowsl, ints, ints, 3, 17, xievt::FSPC); + dotest("? [key, is, a, seq]\n: [val, is, a, seq]\n", + "[key, is, a, seq]", + "[val, is, a, seq]"); + } + } + auto dotest = [&](strref full, strref keyval, strref key, strref val){ + test_emits_ints_nojson_(ints, 0, full); + test_emits_ints_nojson_(ints, 1, full); + test_emits_ints_nojson_(ints, 2, full); + test_emits_ints_nojson_(ints, 2, full, without_key); + test_emits_ints_nojson_(ints, 3, keyval); + test_emits_ints_nojson_(ints, 3, key, without_key); + test_emits_ints_nojson_(ints, 17, val); + test_emits_ints_nojson_(ints, 17, val, without_key); + }; + { + SCOPED_TRACE("root-flowsl"); + TMPSTY(flowsl, ints, 2); { - SCOPED_TRACE("flow_ml"); - { - SCOPED_TRACE("indent"); - TmpContainerStyle tmp(nct.rootref(), FLOW_ML1); - std::string expected = "{\n 0: foo,\n 1: bar,\n 2: [nested,seq],\n 3: {nested: map}\n}\n"; - std::string expected_json = "{\n \"0\": \"foo\",\n \"1\": \"bar\",\n \"2\": [\"nested\",\"seq\"],\n \"3\": {\"nested\": \"map\"}\n}\n"; - test_all_emits(t.crootref(), expected, expected_json); - } - { - SCOPED_TRACE("no indent"); - TmpContainerStyle tmp(nct.rootref(), FLOW_ML1); - std::string expected = "{\n0: foo,\n1: bar,\n2: [nested,seq],\n3: {nested: map}\n}\n"; - std::string expected_json = "{\n\"0\": \"foo\",\n\"1\": \"bar\",\n\"2\": [\"nested\",\"seq\"],\n\"3\": {\"nested\": \"map\"}\n}\n"; - test_all_emits(t.crootref(), expected, expected_json, EmitOptions{}.indent_flow_ml(false)); - } + SCOPED_TRACE("kv-flowml1"); + TMPSTY(flowml1, ints, ints, 3, 17); + dotest("{? [\n key,\n is,\n a,\n seq\n]: [\n val,\n is,\n a,\n seq\n]}", + "? [\n key,\n is,\n a,\n seq\n ]\n: [\n val,\n is,\n a,\n seq\n ]\n", + "[\n key,\n is,\n a,\n seq\n]\n", + "[\n val,\n is,\n a,\n seq\n]\n"); } { - SCOPED_TRACE("flow_sl"); - TmpContainerStyle tmp(nct.rootref(), FLOW_SL); - std::string expected = "{0: foo,1: bar,2: [nested,seq],3: {nested: map}}"; - std::string expected_json = "{\"0\": \"foo\",\"1\": \"bar\",\"2\": [\"nested\",\"seq\"],\"3\": {\"nested\": \"map\"}}"; - test_all_emits(t.crootref(), expected, expected_json); + SCOPED_TRACE("kv-flowmln"); + TMPSTY(flowmln, ints, ints, 3, 17); + dotest("{? [\n key,is,a,seq\n]: [\n val,is,a,seq\n]}", + "? [\n key,is,a,seq\n ]\n: [\n val,is,a,seq\n ]\n", + "[\n key,is,a,seq\n]\n", + "[\n val,is,a,seq\n]\n"); } - } - { - SCOPED_TRACE("full-all"); { - SCOPED_TRACE("block"); - TmpContainerStyle tmp0(nct.rootref(), BLOCK); - TmpContainerStyle tmp2(nct[2], BLOCK); - TmpContainerStyle tmp3(nct[3], BLOCK); - std::string expected = "0: foo\n1: bar\n2:\n - nested\n - seq\n3:\n nested: map\n"; - std::string expected_json = "{\n \"0\": \"foo\",\n \"1\": \"bar\",\n \"2\": [\n \"nested\",\n \"seq\"\n ],\n \"3\": {\n \"nested\": \"map\"\n }\n}\n"; - test_all_emits(t.crootref(), expected, expected_json); + SCOPED_TRACE("kv-flowmln-spc"); + TMPSTY(flowmln, ints, ints, 3, 17, xievt::FSPC); + dotest("{? [\n key, is, a, seq\n]: [\n val, is, a, seq\n]}", + "? [\n key, is, a, seq\n ]\n: [\n val, is, a, seq\n ]\n", + "[\n key, is, a, seq\n]\n", + "[\n val, is, a, seq\n]\n"); } { - SCOPED_TRACE("flow_ml"); - { - SCOPED_TRACE("indent"); - TmpContainerStyle tmp(nct.rootref(), FLOW_ML1); - TmpContainerStyle tmp2(nct[2], FLOW_ML1); - TmpContainerStyle tmp3(nct[3], FLOW_ML1); - std::string expected = "{\n 0: foo,\n 1: bar,\n 2: [\n nested,\n seq\n ],\n 3: {\n nested: map\n }\n}\n"; - std::string expected_json = "{\n \"0\": \"foo\",\n \"1\": \"bar\",\n \"2\": [\n \"nested\",\n \"seq\"\n ],\n \"3\": {\n \"nested\": \"map\"\n }\n}\n"; - test_all_emits(t.crootref(), expected, expected_json); - } - { - SCOPED_TRACE("no indent"); - TmpContainerStyle tmp(nct.rootref(), FLOW_ML1); - TmpContainerStyle tmp2(nct[2], FLOW_ML1); - TmpContainerStyle tmp3(nct[3], FLOW_ML1); - std::string expected = "{\n0: foo,\n1: bar,\n2: [\nnested,\nseq\n],\n3: {\nnested: map\n}\n}\n"; - std::string expected_json = "{\n\"0\": \"foo\",\n\"1\": \"bar\",\n\"2\": [\n\"nested\",\n\"seq\"\n],\n\"3\": {\n\"nested\": \"map\"\n}\n}\n"; - test_all_emits(t.crootref(), expected, expected_json, EmitOptions{}.indent_flow_ml(false)); - } + SCOPED_TRACE("kv-flowsl"); + TMPSTY(flowsl, ints, ints, 3, 17); + dotest("{? [key,is,a,seq]: [val,is,a,seq]}", + "? [key,is,a,seq]\n: [val,is,a,seq]\n", + "[key,is,a,seq]", + "[val,is,a,seq]"); } { - SCOPED_TRACE("flow_sl"); - TmpContainerStyle tmp(nct.rootref(), FLOW_SL); - TmpContainerStyle tmp2(nct[2], FLOW_SL); - TmpContainerStyle tmp3(nct[3], FLOW_SL); - std::string expected = "{0: foo,1: bar,2: [nested,seq],3: {nested: map}}"; - std::string expected_json = "{\"0\": \"foo\",\"1\": \"bar\",\"2\": [\"nested\",\"seq\"],\"3\": {\"nested\": \"map\"}}"; - test_all_emits(t.crootref(), expected, expected_json); + SCOPED_TRACE("kv-flowsl-spc"); + TMPSTY(flowsl, ints, ints, 3, 17, xievt::FSPC); + dotest("{? [key, is, a, seq]: [val, is, a, seq]}", + "? [key, is, a, seq]\n: [val, is, a, seq]\n", + "[key, is, a, seq]", + "[val, is, a, seq]"); } } { - SCOPED_TRACE("t[0]"); - NodeRef n = nct[0]; + SCOPED_TRACE("root-flowml1"); + TMPSTY(flowml1, ints, 2); { - SCOPED_TRACE("block"); - TmpContainerStyle tmp(n, BLOCK); - std::string expected = "0: foo\n"; - std::string expected_json = "\"0\": \"foo\"\n"; - test_all_emits(n, expected, expected_json); + SCOPED_TRACE("kv-flowml1"); + TMPSTY(flowml1, ints, ints, 3, 17); + dotest("{\n ? [\n key,\n is,\n a,\n seq\n ]: [\n val,\n is,\n a,\n seq\n ]\n}\n", + "? [\n key,\n is,\n a,\n seq\n ]\n: [\n val,\n is,\n a,\n seq\n ]\n", + "[\n key,\n is,\n a,\n seq\n]\n", + "[\n val,\n is,\n a,\n seq\n]\n"); } { - SCOPED_TRACE("flow_ml"); - TmpContainerStyle tmp(n, FLOW_ML1); - std::string expected = "0: foo\n"; - std::string expected_json = "\"0\": \"foo\"\n"; - test_all_emits(n, expected, expected_json); + SCOPED_TRACE("kv-flowmln"); + TMPSTY(flowmln, ints, ints, 3, 17); + dotest("{\n ? [\n key,is,a,seq\n ]: [\n val,is,a,seq\n ]\n}\n", + "? [\n key,is,a,seq\n ]\n: [\n val,is,a,seq\n ]\n", + "[\n key,is,a,seq\n]\n", + "[\n val,is,a,seq\n]\n"); } { - SCOPED_TRACE("flow_sl"); - TmpContainerStyle tmp(n, FLOW_SL); - std::string expected = "0: foo\n"; - std::string expected_json = "\"0\": \"foo\""; // FIXME should have trailing newline - test_all_emits(n, expected, expected_json); - } - } - { - SCOPED_TRACE("t[1]"); - NodeRef n = nct[1]; - { - SCOPED_TRACE("block"); - TmpContainerStyle tmp(n, BLOCK); - std::string expected = "1: bar\n"; - std::string expected_json = "\"1\": \"bar\"\n"; - test_all_emits(n, expected, expected_json); + SCOPED_TRACE("kv-flowmln-spc"); + TMPSTY(flowmln, ints, ints, 3, 17, xievt::FSPC); + dotest("{\n ? [\n key, is, a, seq\n ]: [\n val, is, a, seq\n ]\n}\n", + "? [\n key, is, a, seq\n ]\n: [\n val, is, a, seq\n ]\n", + "[\n key, is, a, seq\n]\n", + "[\n val, is, a, seq\n]\n"); } { - SCOPED_TRACE("flow_ml"); - TmpContainerStyle tmp(n, FLOW_ML1); - std::string expected = "1: bar\n"; - std::string expected_json = "\"1\": \"bar\"\n"; - test_all_emits(n, expected, expected_json); + SCOPED_TRACE("kv-flowsl"); + TMPSTY(flowsl, ints, ints, 3, 17); + dotest("{\n ? [key,is,a,seq]: [val,is,a,seq]\n}\n", + "? [key,is,a,seq]\n: [val,is,a,seq]\n", + "[key,is,a,seq]", + "[val,is,a,seq]"); } { - SCOPED_TRACE("flow_sl"); - TmpContainerStyle tmp(n, FLOW_SL); - std::string expected = "1: bar\n"; - std::string expected_json = "\"1\": \"bar\""; // FIXME should have trailing newline - test_all_emits(n, expected, expected_json); + SCOPED_TRACE("kv-flowsl-spc"); + TMPSTY(flowsl, ints, ints, 3, 17, xievt::FSPC); + dotest("{\n ? [key, is, a, seq]: [val, is, a, seq]\n}\n", + "? [key, is, a, seq]\n: [val, is, a, seq]\n", + "[key, is, a, seq]", + "[val, is, a, seq]"); } } { - SCOPED_TRACE("t[2]"); - NodeRef n = nct[2]; + SCOPED_TRACE("root-flowmln"); + TMPSTY(flowmln, ints, 2); { - SCOPED_TRACE("block"); - TmpContainerStyle tmp(n, BLOCK); - std::string expected = "2:\n - nested\n - seq\n"; - std::string expected_json = "\"2\": [\n \"nested\",\n \"seq\"\n]\n"; - test_all_emits(n, expected, expected_json); + SCOPED_TRACE("kv-flowml1"); + TMPSTY(flowml1, ints, ints, 3, 17); + dotest("{\n ? [\n key,is,a,seq\n ]: [\n val,is,a,seq\n ]\n}\n", + "? [\n key,\n is,\n a,\n seq\n ]\n: [\n val,\n is,\n a,\n seq\n ]\n", + "[\n key,\n is,\n a,\n seq\n]\n", + "[\n val,\n is,\n a,\n seq\n]\n"); } { - SCOPED_TRACE("flow_ml"); - TmpContainerStyle tmp(n, FLOW_ML1); - std::string expected = "2: [\n nested,\n seq\n ]\n"; // FIXME should be indented one level, not two - std::string expected_json = "\"2\": [\n \"nested\",\n \"seq\"\n]\n"; - test_all_emits(n, expected, expected_json); + SCOPED_TRACE("kv-flowmln"); + TMPSTY(flowmln, ints, ints, 3, 17); + dotest("{\n ? [\n key,is,a,seq\n ]: [\n val,is,a,seq\n ]\n}\n", + "? [\n key,is,a,seq\n ]\n: [\n val,is,a,seq\n ]\n", + "[\n key,is,a,seq\n]\n", + "[\n val,is,a,seq\n]\n"); } { - SCOPED_TRACE("flow_sl"); - TmpContainerStyle tmp(n, FLOW_SL); - std::string expected = "2: [nested,seq]\n"; - std::string expected_json = "\"2\": [\"nested\",\"seq\"]"; // FIXME should have trailing newline - test_all_emits(n, expected, expected_json); - } - } - { - SCOPED_TRACE("t[3]"); - NodeRef n = nct[3]; - { - SCOPED_TRACE("block"); - TmpContainerStyle tmp(n, BLOCK); - std::string expected = "3:\n nested: map\n"; - std::string expected_json = "\"3\": {\n \"nested\": \"map\"\n}\n"; - test_all_emits(n, expected, expected_json); + SCOPED_TRACE("kv-flowmln-spc"); + TMPSTY(flowmln, ints, ints, 3, 17, xievt::FSPC); + // FIXME! + dotest("{\n ? [\n key,is,a,seq\n ]: [\n val,is,a,seq\n ]\n}\n", + "? [\n key, is, a, seq\n ]\n: [\n val, is, a, seq\n ]\n", + "[\n key, is, a, seq\n]\n", + "[\n val, is, a, seq\n]\n"); } { - SCOPED_TRACE("flow_ml"); - TmpContainerStyle tmp(n, FLOW_ML1); - std::string expected = "3: {\n nested: map\n }\n"; // FIXME should be indented one level, not two - std::string expected_json = "\"3\": {\n \"nested\": \"map\"\n}\n"; - test_all_emits(n, expected, expected_json); + SCOPED_TRACE("kv-flowsl"); + TMPSTY(flowsl, ints, ints, 3, 17); + dotest("{\n ? [key,is,a,seq]: [val,is,a,seq]\n}\n", + "? [key,is,a,seq]\n: [val,is,a,seq]\n", + "[key,is,a,seq]", + "[val,is,a,seq]"); } { - SCOPED_TRACE("flow_sl"); - TmpContainerStyle tmp(n, FLOW_SL); - std::string expected = "3: {nested: map}\n"; - std::string expected_json = "\"3\": {\"nested\": \"map\"}"; // FIXME should have trailing newline - test_all_emits(n, expected, expected_json); + SCOPED_TRACE("kv-flowsl-spc"); + TMPSTY(flowsl, ints, ints, 3, 17, xievt::FSPC); + // FIXME! + dotest("{\n ? [key,is,a,seq]: [val,is,a,seq]\n}\n", + "? [key, is, a, seq]\n: [val, is, a, seq]\n", + "[key, is, a, seq]", + "[val, is, a, seq]"); } } } -TEST(emit, existing_map_node_block) +TEST(emit, container_key_map_flow) { - Tree nct = parse_in_arena("0: foo\n1: bar\n2:\n - nested\n - seq\n3:\n nested: map\n"); - Tree const& t = nct; + SCOPED_TRACE("container_key_map_flow"); + IntBufs ints; + std::string yaml = "{key: is, a: map}: {val: is, a: map}"; + parse_ints(to_substr(yaml), &ints); + test_emits_ints_nojson_(ints, 0, "? {key: is,a: map}\n: {val: is,a: map}\n"); + { + SCOPED_TRACE("error on key container"); + test_emit_error_json_ints(ints, 3); + } + { + SCOPED_TRACE("root-blk"); + TMPSTY(blk, ints, 2); + auto dotest = [&](strref keyval, strref key, strref val){ + test_emits_ints_nojson_(ints, 0, keyval); + test_emits_ints_nojson_(ints, 1, keyval); + test_emits_ints_nojson_(ints, 2, keyval); + test_emits_ints_nojson_(ints, 2, keyval, without_key); + test_emits_ints_nojson_(ints, 3, keyval); + test_emits_ints_nojson_(ints, 3, key, without_key); + test_emits_ints_nojson_(ints, 17, val); + test_emits_ints_nojson_(ints, 17, val, without_key); + }; + { + SCOPED_TRACE("kv-blk"); + TMPSTY(blk, ints, ints, 3, 17); + dotest("?\n key: is\n a: map\n:\n val: is\n a: map\n", + "key: is\na: map\n", + "val: is\na: map\n"); + } + { + SCOPED_TRACE("kv-flowml1"); + TMPSTY(flowml1, ints, ints, 3, 17); + dotest("? {\n key: is,\n a: map\n }\n: {\n val: is,\n a: map\n }\n", + "{\n key: is,\n a: map\n}\n", + "{\n val: is,\n a: map\n}\n"); + } + { + SCOPED_TRACE("kv-flowmln"); + TMPSTY(flowmln, ints, ints, 3, 17); + dotest("? {\n key: is,a: map\n }\n: {\n val: is,a: map\n }\n", + "{\n key: is,a: map\n}\n", + "{\n val: is,a: map\n}\n"); + } + { + SCOPED_TRACE("kv-flowmln-spc"); + TMPSTY(flowmln, ints, ints, 3, 17, xievt::FSPC); + dotest("? {\n key: is, a: map\n }\n: {\n val: is, a: map\n }\n", + "{\n key: is, a: map\n}\n", + "{\n val: is, a: map\n}\n"); + } + { + SCOPED_TRACE("kv-flowsl"); + TMPSTY(flowsl, ints, ints, 3, 17); + dotest("? {key: is,a: map}\n: {val: is,a: map}\n", + "{key: is,a: map}", + "{val: is,a: map}"); + } + { + SCOPED_TRACE("kv-flowsl-spc"); + TMPSTY(flowsl, ints, ints, 3, 17, xievt::FSPC); + dotest("? {key: is, a: map}\n: {val: is, a: map}\n", + "{key: is, a: map}", + "{val: is, a: map}"); + } + } + auto dotest = [&](strref full, strref keyval, strref key, strref val){ + test_emits_ints_nojson_(ints, 0, full); + test_emits_ints_nojson_(ints, 1, full); + test_emits_ints_nojson_(ints, 2, full); + test_emits_ints_nojson_(ints, 2, full, without_key); + test_emits_ints_nojson_(ints, 3, keyval); + test_emits_ints_nojson_(ints, 3, key, without_key); + test_emits_ints_nojson_(ints, 17, val); + test_emits_ints_nojson_(ints, 17, val, without_key); + }; { - SCOPED_TRACE("full-top"); + SCOPED_TRACE("root-flowsl"); + TMPSTY(flowsl, ints, 2); { - SCOPED_TRACE("block"); - TmpContainerStyle tmp(nct.rootref(), BLOCK); - std::string expected = "0: foo\n1: bar\n2:\n - nested\n - seq\n3:\n nested: map\n"; - std::string expected_json = "{\n \"0\": \"foo\",\n \"1\": \"bar\",\n \"2\": [\n \"nested\",\n \"seq\"\n ],\n \"3\": {\n \"nested\": \"map\"\n }\n}\n"; - test_all_emits(t.crootref(), expected, expected_json); + SCOPED_TRACE("kv-flowml1"); + TMPSTY(flowml1, ints, ints, 3, 17); + dotest("{? {\n key: is,\n a: map\n}: {\n val: is,\n a: map\n}}", + "? {\n key: is,\n a: map\n }\n: {\n val: is,\n a: map\n }\n", + "{\n key: is,\n a: map\n}\n", + "{\n val: is,\n a: map\n}\n"); } { - SCOPED_TRACE("block-flow-ml"); - { - SCOPED_TRACE("indent"); - TmpContainerStyle tmp(nct.rootref(), BLOCK); - TmpContainerStyle tmp2(nct[2], FLOW_ML1); - TmpContainerStyle tmp3(nct[3], FLOW_ML1); - std::string expected = "0: foo\n1: bar\n2: [\n nested,\n seq\n ]\n3: {\n nested: map\n }\n"; - std::string expected_json = "{\n \"0\": \"foo\",\n \"1\": \"bar\",\n \"2\": [\n \"nested\",\n \"seq\"\n ],\n \"3\": {\n \"nested\": \"map\"\n }\n}\n"; - test_all_emits(t.crootref(), expected, expected_json); - } - { - SCOPED_TRACE("no indent"); - TmpContainerStyle tmp(nct.rootref(), BLOCK); - TmpContainerStyle tmp2(nct[2], FLOW_ML1); - TmpContainerStyle tmp3(nct[3], FLOW_ML1); - std::string expected = "0: foo\n1: bar\n2: [\n nested,\n seq\n ]\n3: {\n nested: map\n }\n"; - std::string expected_json = "{\n\"0\": \"foo\",\n\"1\": \"bar\",\n\"2\": [\n\"nested\",\n\"seq\"\n],\n\"3\": {\n\"nested\": \"map\"\n}\n}\n"; - test_all_emits(t.crootref(), expected, expected_json, EmitOptions{}.indent_flow_ml(false)); - } + SCOPED_TRACE("kv-flowmln"); + TMPSTY(flowmln, ints, ints, 3, 17); + dotest("{? {\n key: is,a: map\n}: {\n val: is,a: map\n}}", + "? {\n key: is,a: map\n }\n: {\n val: is,a: map\n }\n", + "{\n key: is,a: map\n}\n", + "{\n val: is,a: map\n}\n"); } { - SCOPED_TRACE("flow_ml"); - TmpContainerStyle tmp(nct.rootref(), FLOW_ML1); - { - SCOPED_TRACE("indent"); - std::string expected = "{\n 0: foo,\n 1: bar,\n 2: [nested,seq],\n 3: {nested: map}\n}\n"; - std::string expected_json = "{\n \"0\": \"foo\",\n \"1\": \"bar\",\n \"2\": [\n \"nested\",\n \"seq\"\n ],\n \"3\": {\n \"nested\": \"map\"\n }\n}\n"; - test_all_emits(t.crootref(), expected, expected_json); - } - { - SCOPED_TRACE("no indent"); - std::string expected = "{\n0: foo,\n1: bar,\n2: [nested,seq],\n3: {nested: map}\n}\n"; - std::string expected_json = "{\n\"0\": \"foo\",\n\"1\": \"bar\",\n\"2\": [\n\"nested\",\n\"seq\"\n],\n\"3\": {\n\"nested\": \"map\"\n}\n}\n"; - test_all_emits(t.crootref(), expected, expected_json, EmitOptions{}.indent_flow_ml(false)); - } + SCOPED_TRACE("kv-flowmln-spc"); + TMPSTY(flowmln, ints, ints, 3, 17, xievt::FSPC); + dotest("{? {\n key: is, a: map\n}: {\n val: is, a: map\n}}", + "? {\n key: is, a: map\n }\n: {\n val: is, a: map\n }\n", + "{\n key: is, a: map\n}\n", + "{\n val: is, a: map\n}\n"); } { - SCOPED_TRACE("flow_sl"); - TmpContainerStyle tmp(nct.rootref(), FLOW_SL); - std::string expected = "{0: foo,1: bar,2: [nested,seq],3: {nested: map}}"; - std::string expected_json = R"({"0": "foo","1": "bar","2": ["nested","seq"],"3": {"nested": "map"}})"; - test_all_emits(t.crootref(), expected, expected_json); + SCOPED_TRACE("kv-flowsl"); + TMPSTY(flowsl, ints, ints, 3, 17); + dotest("{? {key: is,a: map}: {val: is,a: map}}", + "? {key: is,a: map}\n: {val: is,a: map}\n", + "{key: is,a: map}", + "{val: is,a: map}"); + } + { + SCOPED_TRACE("kv-flowsl-spc"); + TMPSTY(flowsl, ints, ints, 3, 17, xievt::FSPC); + dotest("{? {key: is, a: map}: {val: is, a: map}}", + "? {key: is, a: map}\n: {val: is, a: map}\n", + "{key: is, a: map}", + "{val: is, a: map}"); } } { - SCOPED_TRACE("full-all"); + SCOPED_TRACE("root-flowml1"); + TMPSTY(flowml1, ints, 2); { - SCOPED_TRACE("block"); - TmpContainerStyle tmp0(nct.rootref(), BLOCK); - TmpContainerStyle tmp2(nct[2], BLOCK); - TmpContainerStyle tmp3(nct[3], BLOCK); - std::string expected = "0: foo\n1: bar\n2:\n - nested\n - seq\n3:\n nested: map\n"; - std::string expected_json = "{\n \"0\": \"foo\",\n \"1\": \"bar\",\n \"2\": [\n \"nested\",\n \"seq\"\n ],\n \"3\": {\n \"nested\": \"map\"\n }\n}\n"; - test_all_emits(t.crootref(), expected, expected_json); + SCOPED_TRACE("kv-flowml1"); + TMPSTY(flowml1, ints, ints, 3, 17); + dotest("{\n ? {\n key: is,\n a: map\n }: {\n val: is,\n a: map\n }\n}\n", + "? {\n key: is,\n a: map\n }\n: {\n val: is,\n a: map\n }\n", + "{\n key: is,\n a: map\n}\n", + "{\n val: is,\n a: map\n}\n"); } { - SCOPED_TRACE("flow_ml"); - TmpContainerStyle tmp(nct.rootref(), FLOW_ML1); - TmpContainerStyle tmp2(nct[2], FLOW_ML1); - TmpContainerStyle tmp3(nct[3], FLOW_ML1); - { - SCOPED_TRACE("indent"); - std::string expected = "{\n 0: foo,\n 1: bar,\n 2: [\n nested,\n seq\n ],\n 3: {\n nested: map\n }\n}\n"; - std::string expected_json = "{\n \"0\": \"foo\",\n \"1\": \"bar\",\n \"2\": [\n \"nested\",\n \"seq\"\n ],\n \"3\": {\n \"nested\": \"map\"\n }\n}\n"; - test_all_emits(t.crootref(), expected, expected_json); - } - { - SCOPED_TRACE("no indent"); - std::string expected = "{\n0: foo,\n1: bar,\n2: [\nnested,\nseq\n],\n3: {\nnested: map\n}\n}\n"; - std::string expected_json = "{\n\"0\": \"foo\",\n\"1\": \"bar\",\n\"2\": [\n\"nested\",\n\"seq\"\n],\n\"3\": {\n\"nested\": \"map\"\n}\n}\n"; - test_all_emits(t.crootref(), expected, expected_json, EmitOptions{}.indent_flow_ml(false)); - } + SCOPED_TRACE("kv-flowmln"); + TMPSTY(flowmln, ints, ints, 3, 17); + dotest("{\n ? {\n key: is,a: map\n }: {\n val: is,a: map\n }\n}\n", + "? {\n key: is,a: map\n }\n: {\n val: is,a: map\n }\n", + "{\n key: is,a: map\n}\n", + "{\n val: is,a: map\n}\n"); } { - SCOPED_TRACE("flow_sl"); - TmpContainerStyle tmp(nct.rootref(), FLOW_SL); - TmpContainerStyle tmp2(nct[2], FLOW_SL); - TmpContainerStyle tmp3(nct[3], FLOW_SL); - std::string expected = "{0: foo,1: bar,2: [nested,seq],3: {nested: map}}"; - std::string expected_json = R"({"0": "foo","1": "bar","2": ["nested","seq"],"3": {"nested": "map"}})"; - test_all_emits(t.crootref(), expected, expected_json); + SCOPED_TRACE("kv-flowmln-spc"); + TMPSTY(flowmln, ints, ints, 3, 17, xievt::FSPC); + dotest("{\n ? {\n key: is, a: map\n }: {\n val: is, a: map\n }\n}\n", + "? {\n key: is, a: map\n }\n: {\n val: is, a: map\n }\n", + "{\n key: is, a: map\n}\n", + "{\n val: is, a: map\n}\n"); + } + { + SCOPED_TRACE("kv-flowsl"); + TMPSTY(flowsl, ints, ints, 3, 17); + dotest("{\n ? {key: is,a: map}: {val: is,a: map}\n}\n", + "? {key: is,a: map}\n: {val: is,a: map}\n", + "{key: is,a: map}", + "{val: is,a: map}"); + } + { + SCOPED_TRACE("kv-flowsl-spc"); + TMPSTY(flowsl, ints, ints, 3, 17, xievt::FSPC); + dotest("{\n ? {key: is, a: map}: {val: is, a: map}\n}\n", + "? {key: is, a: map}\n: {val: is, a: map}\n", + "{key: is, a: map}", + "{val: is, a: map}"); } } { - SCOPED_TRACE("t[0]"); - NodeRef n = nct[0]; + SCOPED_TRACE("root-flowmln"); + TMPSTY(flowmln, ints, 2); { - SCOPED_TRACE("block"); - TmpContainerStyle tmp(n, BLOCK); - std::string expected = "0: foo\n"; - std::string expected_json = "\"0\": \"foo\"\n"; - test_all_emits(n, expected, expected_json); + SCOPED_TRACE("kv-flowml1"); + TMPSTY(flowml1, ints, ints, 3, 17); + dotest("{\n ? {\n key: is,a: map\n }: {\n val: is,a: map\n }\n}\n", + "? {\n key: is,\n a: map\n }\n: {\n val: is,\n a: map\n }\n", + "{\n key: is,\n a: map\n}\n", + "{\n val: is,\n a: map\n}\n"); } { - SCOPED_TRACE("flow_ml"); - TmpContainerStyle tmp(n, FLOW_ML1); - std::string expected = "0: foo\n"; - std::string expected_json = "\"0\": \"foo\"\n"; - test_all_emits(n, expected, expected_json); + SCOPED_TRACE("kv-flowmln"); + TMPSTY(flowmln, ints, ints, 3, 17); + dotest("{\n ? {\n key: is,a: map\n }: {\n val: is,a: map\n }\n}\n", + "? {\n key: is,a: map\n }\n: {\n val: is,a: map\n }\n", + "{\n key: is,a: map\n}\n", + "{\n val: is,a: map\n}\n"); } { - SCOPED_TRACE("flow_sl"); - TmpContainerStyle tmp(n, FLOW_SL); - std::string expected = "0: foo\n"; - std::string expected_json = "\"0\": \"foo\""; // FIXME should have trailing newline - test_all_emits(n, expected, expected_json); + SCOPED_TRACE("kv-flowmln-spc"); + TMPSTY(flowmln, ints, ints, 3, 17, xievt::FSPC); + dotest("{\n ? {\n key: is,a: map\n }: {\n val: is,a: map\n }\n}\n", + "? {\n key: is, a: map\n }\n: {\n val: is, a: map\n }\n", + "{\n key: is, a: map\n}\n", + "{\n val: is, a: map\n}\n"); } + { + SCOPED_TRACE("kv-flowsl"); + TMPSTY(flowsl, ints, ints, 3, 17); + dotest("{\n ? {key: is,a: map}: {val: is,a: map}\n}\n", + "? {key: is,a: map}\n: {val: is,a: map}\n", + "{key: is,a: map}", + "{val: is,a: map}"); + } + { + SCOPED_TRACE("kv-flowsl-spc"); + TMPSTY(flowsl, ints, ints, 3, 17, xievt::FSPC); + dotest("{\n ? {key: is,a: map}: {val: is,a: map}\n}\n", + "? {key: is, a: map}\n: {val: is, a: map}\n", + "{key: is, a: map}", + "{val: is, a: map}"); + } + } +} + + +TEST(emit, stream_docval) +{ + SCOPED_TRACE("stream_docval"); + std::string yaml = R"(doc0 +--- +doc1 +--- +doc2 +)"; + std::string expected_json = R"([ + "doc0", + "doc1", + "doc2" +] +)"; + TreeAndInts ti = parse_tree_and_ints(to_csubstr(yaml)); + test_emits_tree_(ti.tree.rootref(), "--- doc0\n--- doc1\n--- doc2\n", expected_json); + test_emits_ints_(ti.ints, 0, "doc0\n--- doc1\n--- doc2\n", expected_json); + test_emits_tree_(ti.tree.docref(0), "--- doc0", "\"doc0\""); // FIXME newline + test_emits_ints_(ti.ints, 1, "doc0\n", "\"doc0\""); + test_emits_ints_(ti.ints, 2, "doc0", "\"doc0\""); + test_emits_ints_(ti.ints, 5, "doc1", "\"doc1\""); + test_emits_tree_(ti.tree.docref(1), "--- doc1", "\"doc1\""); // FIXME newline + test_emits_ints_(ti.ints, 6, "--- doc1\n", "\"doc1\""); + test_emits_ints_(ti.ints, 7, "doc1", "\"doc1\""); + test_emits_ints_(ti.ints, 10, "doc2", "\"doc2\""); + test_emits_tree_(ti.tree.docref(2), "--- doc2", "\"doc2\""); // FIXME newline + test_emits_ints_(ti.ints, 11, "--- doc2\n", "\"doc2\""); + test_emits_ints_(ti.ints, 12, "doc2", "\"doc2\""); + { + SCOPED_TRACE("error on stream"); + const EmitOptions opts = EmitOptions{}.json_err_on_stream(true); + test_emit_error_json_ints(ti.ints, 0, opts); + } +} + +TEST(emit, stream_docval_2) +{ + SCOPED_TRACE("stream_docval2"); + std::string yaml = R"(--- doc0 +--- +doc1 +--- +doc2 +)"; + std::string expected_json = R"([ + "doc0", + "doc1", + "doc2" +] +)"; + TreeAndInts ti = parse_tree_and_ints(to_csubstr(yaml)); + test_emits(ti, "--- doc0\n--- doc1\n--- doc2\n", expected_json); + test_emits_tree_(ti.tree.docref(0), "--- doc0", "\"doc0\""); // FIXME newline + test_emits_ints_(ti.ints, 1, "--- doc0\n", "\"doc0\""); + test_emits_ints_(ti.ints, 2, "doc0", "\"doc0\""); + test_emits_ints_(ti.ints, 5, "doc1", "\"doc1\""); + test_emits_tree_(ti.tree.docref(1), "--- doc1", "\"doc1\""); // FIXME newline + test_emits_ints_(ti.ints, 6, "--- doc1\n", "\"doc1\""); + test_emits_ints_(ti.ints, 7, "doc1", "\"doc1\""); + test_emits_ints_(ti.ints, 10, "doc2", "\"doc2\""); + test_emits_tree_(ti.tree.docref(2), "--- doc2", "\"doc2\""); // FIXME newline + test_emits_ints_(ti.ints, 11, "--- doc2\n", "\"doc2\""); + test_emits_ints_(ti.ints, 12, "doc2", "\"doc2\""); +} + +TEST(emit, stream_seq) +{ + SCOPED_TRACE("stream_seq"); + std::string yaml = "--- [a, b]\n--- [c, d]\n--- [e, f]\n"; + std::string exp = "--- [a,b]\n--- [c,d]\n--- [e,f]\n"; + std::string expjson = "[\n [\"a\",\"b\"],\n [\"c\",\"d\"],\n [\"e\",\"f\"]\n]\n"; + TreeAndInts ti = parse_tree_and_ints(to_csubstr(yaml)); + { + SCOPED_TRACE("orig"); + test_emits_(ti, exp, expjson); + test_emits_tree_(ti.tree.docref(0), "--- [a,b]", "[\"a\",\"b\"]"); // FIXME newline + test_emits_ints_(ti.ints, 1, "--- [a,b]\n", "[\"a\",\"b\"]"); + test_emits_ints_(ti.ints, 2, "[a,b]", "[\"a\",\"b\"]"); + test_emits_tree_(ti.tree.docref(1), "--- [c,d]", "[\"c\",\"d\"]"); // FIXME newline + test_emits_ints_(ti.ints, 11, "--- [c,d]\n", "[\"c\",\"d\"]"); + test_emits_ints_(ti.ints, 12, "[c,d]", "[\"c\",\"d\"]"); + test_emits_tree_(ti.tree.docref(2), "--- [e,f]", "[\"e\",\"f\"]"); // FIXME newline + test_emits_ints_(ti.ints, 21, "--- [e,f]\n", "[\"e\",\"f\"]"); + test_emits_ints_(ti.ints, 22, "[e,f]", "[\"e\",\"f\"]"); + } + { + SCOPED_TRACE("flow spc"); + test_emits_(ti, exp, expjson); + test_emits_tree_(ti.tree.docref(0), "--- [a,b]", "[\"a\",\"b\"]"); // FIXME newline + test_emits_ints_(ti.ints, 1, "--- [a,b]\n", "[\"a\",\"b\"]"); + test_emits_ints_(ti.ints, 2, "[a,b]", "[\"a\",\"b\"]"); + test_emits_tree_(ti.tree.docref(1), "--- [c,d]", "[\"c\",\"d\"]"); // FIXME newline + test_emits_ints_(ti.ints, 11, "--- [c,d]\n", "[\"c\",\"d\"]"); + test_emits_ints_(ti.ints, 12, "[c,d]", "[\"c\",\"d\"]"); + test_emits_tree_(ti.tree.docref(2), "--- [e,f]", "[\"e\",\"f\"]"); // FIXME newline + test_emits_ints_(ti.ints, 21, "--- [e,f]\n", "[\"e\",\"f\"]"); + test_emits_ints_(ti.ints, 22, "[e,f]", "[\"e\",\"f\"]"); + } + { + SCOPED_TRACE("block"); + TMPSTY(blk, ti, ti.tree.docref(0), 2); + TMPSTY(blk, ti, ti.tree.docref(1), 12); + TMPSTY(blk, ti, ti.tree.docref(2), 22); + test_emits_(ti, "---\n- a\n- b\n---\n- c\n- d\n---\n- e\n- f\n", + "[\n [\n \"a\",\n \"b\"\n ],\n [\n \"c\",\n \"d\"\n ],\n [\n \"e\",\n \"f\"\n ]\n]\n"); + test_emits_tree_(ti.tree.docref(0), "---\n- a\n- b\n", "[\n \"a\",\n \"b\"\n]\n"); + test_emits_ints_(ti.ints, 1, "---\n- a\n- b\n", "[\n \"a\",\n \"b\"\n]"); // FIXME newline + test_emits_ints_(ti.ints, 2, "- a\n- b\n", "[\n \"a\",\n \"b\"\n]\n"); + test_emits_tree_(ti.tree.docref(1), "---\n- c\n- d\n", "[\n \"c\",\n \"d\"\n]\n"); + test_emits_ints_(ti.ints, 11, "---\n- c\n- d\n", "[\n \"c\",\n \"d\"\n]"); // FIXME newline + test_emits_ints_(ti.ints, 12, "- c\n- d\n", "[\n \"c\",\n \"d\"\n]\n"); + test_emits_tree_(ti.tree.docref(2), "---\n- e\n- f\n", "[\n \"e\",\n \"f\"\n]\n"); + test_emits_ints_(ti.ints, 21, "---\n- e\n- f\n", "[\n \"e\",\n \"f\"\n]"); // FIXME newline + test_emits_ints_(ti.ints, 22, "- e\n- f\n", "[\n \"e\",\n \"f\"\n]\n"); + } +} + +TEST(emit, stream_map) +{ + SCOPED_TRACE("stream_map"); + std::string yaml = "--- {a: b}\n--- {c: d}\n--- {e: f}\n"; + std::string expjson = "[\n {\"a\": \"b\"},\n {\"c\": \"d\"},\n {\"e\": \"f\"}\n]\n"; + TreeAndInts ti = parse_tree_and_ints(to_csubstr(yaml)); + test_emits_(ti, yaml, expjson); + { + SCOPED_TRACE("orig"); + test_emits_tree_(ti.tree.docref(0), "--- {a: b}", "{\"a\": \"b\"}"); // FIXME newline + test_emits_ints_(ti.ints, 1, "--- {a: b}\n", "{\"a\": \"b\"}"); + test_emits_ints_(ti.ints, 2, "{a: b}", "{\"a\": \"b\"}"); + test_emits_tree_(ti.tree.docref(1), "--- {c: d}", "{\"c\": \"d\"}"); // FIXME newline + test_emits_ints_(ti.ints, 11, "--- {c: d}\n", "{\"c\": \"d\"}"); + test_emits_ints_(ti.ints, 12, "{c: d}", "{\"c\": \"d\"}"); + test_emits_tree_(ti.tree.docref(2), "--- {e: f}", "{\"e\": \"f\"}"); // FIXME newline + test_emits_ints_(ti.ints, 21, "--- {e: f}\n", "{\"e\": \"f\"}"); + test_emits_ints_(ti.ints, 22, "{e: f}", "{\"e\": \"f\"}"); + } + { + SCOPED_TRACE("block"); + TMPSTY(blk, ti, ti.tree.docref(0), 2); + TMPSTY(blk, ti, ti.tree.docref(1), 12); + TMPSTY(blk, ti, ti.tree.docref(2), 22); + test_emits_(ti, "---\na: b\n---\nc: d\n---\ne: f\n", + "[\n {\n \"a\": \"b\"\n },\n {\n \"c\": \"d\"\n },\n {\n \"e\": \"f\"\n }\n]\n"); + test_emits_tree_(ti.tree.docref(0), "---\na: b\n", "{\n \"a\": \"b\"\n}\n"); + test_emits_ints_(ti.ints, 1, "---\na: b\n", "{\n \"a\": \"b\"\n}"); // FIXME newline + test_emits_ints_(ti.ints, 2, "a: b\n", "{\n \"a\": \"b\"\n}\n"); + test_emits_tree_(ti.tree.docref(1), "---\nc: d\n", "{\n \"c\": \"d\"\n}\n"); + test_emits_ints_(ti.ints, 11, "---\nc: d\n", "{\n \"c\": \"d\"\n}"); // FIXME newline + test_emits_ints_(ti.ints, 12, "c: d\n", "{\n \"c\": \"d\"\n}\n"); + test_emits_tree_(ti.tree.docref(2), "---\ne: f\n", "{\n \"e\": \"f\"\n}\n"); + test_emits_ints_(ti.ints, 21, "---\ne: f\n", "{\n \"e\": \"f\"\n}"); // FIXME newline + test_emits_ints_(ti.ints, 22, "e: f\n", "{\n \"e\": \"f\"\n}\n"); + } +} + + +TEST(emit, anchor_ref) +{ + SCOPED_TRACE("anchor_ref"); + TreeAndInts ti = parse_tree_and_ints("[&a a,*a]"); + auto dotest = [&](std::string const& expected, std::string const& expected_json){ + test_emits_(ti, ti.tree, 0, expected, expected_json); + test_emits_(ti, ti.tree, 1, expected, expected_json); + test_emits_(ti, ti.tree, 2, expected, expected_json); + test_emits_(ti, ti.tree[0], 3, "&a a", "\"a\""); + test_emits_ints_(ti.ints, 6, "a", "\"a\""); + test_emits_(ti, ti.tree[1], 9, "*a", "\"*a\""); + }; + { + TMPSTY(flowml1, ti, ti.tree, 2); + dotest("[\n &a a,\n *a\n]\n", "[\n \"a\",\n \"*a\"\n]\n"); } { - SCOPED_TRACE("t[1]"); - NodeRef n = nct[1]; + TMPSTY(flowsl, ti, ti.tree, 2); + dotest("[&a a,*a]", "[\"a\",\"*a\"]"); + } +} + + +TEST(emit, anchor_ref_err_json) +{ + SCOPED_TRACE("anchor_ref_err_json"); + const EmitOptions opts = EmitOptions{}.json_err_on_anchor(true); + { + SCOPED_TRACE("seq"); + TreeAndInts ti = parse_tree_and_ints("[*a, *b]"); { - SCOPED_TRACE("block"); - TmpContainerStyle tmp(n, BLOCK); - std::string expected = "1: bar\n"; - std::string expected_json = "\"1\": \"bar\"\n"; - test_all_emits(n, expected, expected_json); + SCOPED_TRACE("flowsl"); + TMPSTY(flowsl, ti, ti.tree, 2); + test_emit_error_json(ti, opts); } { - SCOPED_TRACE("flow_ml"); - TmpContainerStyle tmp(n, FLOW_ML1); - std::string expected = "1: bar\n"; - std::string expected_json = "\"1\": \"bar\"\n"; - test_all_emits(n, expected, expected_json); + SCOPED_TRACE("flowml1"); + TMPSTY(flowml1, ti, ti.tree, 2); + test_emit_error_json(ti, opts); } { - SCOPED_TRACE("flow_sl"); - TmpContainerStyle tmp(n, FLOW_SL); - std::string expected = "1: bar\n"; - std::string expected_json = "\"1\": \"bar\""; // FIXME should have trailing newline - test_all_emits(n, expected, expected_json); + SCOPED_TRACE("nested a"); + test_emit_error_json(ti.tree[0], ti.ints, 2, opts); } - } - { - SCOPED_TRACE("t[2]"); - NodeRef n = nct[2]; { - SCOPED_TRACE("block"); - TmpContainerStyle tmp(n, BLOCK); - std::string expected = "2:\n - nested\n - seq\n"; - std::string expected_json = "\"2\": [\n \"nested\",\n \"seq\"\n]\n"; - test_all_emits(n, expected, expected_json); + SCOPED_TRACE("nested b"); + test_emit_error_json(ti.tree[1], ti.ints, 5, opts); } + } + { + TreeAndInts ti = parse_tree_and_ints("*a"); { - SCOPED_TRACE("flow_ml"); - TmpContainerStyle tmp(n, FLOW_ML1); - std::string expected = "2: [\n nested,\n seq\n ]\n"; // FIXME should be indented one level, not two - std::string expected_json = "\"2\": [\n \"nested\",\n \"seq\"\n]\n"; - test_all_emits(n, expected, expected_json); + SCOPED_TRACE("docval"); + test_emit_error_json(ti, opts); } { - SCOPED_TRACE("flow_sl"); - TmpContainerStyle tmp(n, FLOW_SL); - std::string expected = "2: [nested,seq]\n"; - std::string expected_json = "\"2\": [\"nested\",\"seq\"]"; // FIXME should have trailing newline - test_all_emits(n, expected, expected_json); + SCOPED_TRACE("nested"); + test_emit_error_json(ti.tree.rootref(), ti.ints, 2, opts); } } +} + + +TEST(emit, tag_anchor) +{ + SCOPED_TRACE("tag_anchor_ml"); + TreeAndInts ti = parse_tree_and_ints(R"({ + !kt a: !vt 8, + &ka b: &va 9, + &ka !kt c: &va !vt 10, + !kt &ka d: !vt &va 11, +})"); + auto dotest = [&](std::string const& expected, std::string const& expected_json){ + test_emits_(ti, ti.tree, 0, expected, expected_json); + test_emits_(ti, ti.tree, 1, expected, expected_json); + test_emits_(ti, ti.tree, 2, expected, expected_json); + // + test_emits_(ti, ti.tree[0], 3, "!kt a: !vt 8\n", "\"a\": 8\n"); + test_emits_(ti.tree[0], "!vt 8", "8", without_key); + test_emits_ints_(ti.ints, 3, "!kt a", "\"a\"", without_key); + test_emits_ints_(ti.ints, 6, "a: !vt 8\n", "\"a\": 8\n"); + test_emits_ints_(ti.ints, 6, "a", "\"a\"", without_key); + test_emits_ints_(ti.ints, 9, "!vt 8", "8"); + test_emits_ints_(ti.ints, 9, "!vt 8", "8", without_key); + test_emits_ints_(ti.ints, 12, "8", "8"); + test_emits_ints_(ti.ints, 12, "8", "8", without_key); + // + test_emits_(ti, ti.tree[1], 15, "&ka b: &va 9\n", "\"b\": 9\n"); + test_emits_(ti.tree[1], "&va 9", "9", without_key); + test_emits_ints_(ti.ints, 15, "&ka b", "\"b\"", without_key); + test_emits_ints_(ti.ints, 18, "b: &va 9\n", "\"b\": 9\n"); + test_emits_ints_(ti.ints, 18, "b", "\"b\"", without_key); + test_emits_ints_(ti.ints, 21, "&va 9", "9"); + test_emits_ints_(ti.ints, 21, "&va 9", "9", without_key); + test_emits_ints_(ti.ints, 24, "9", "9"); + test_emits_ints_(ti.ints, 24, "9", "9", without_key); + // + test_emits_(ti, ti.tree[2], 27, "&ka !kt c: &va !vt 10\n", "\"c\": 10\n"); + test_emits_(ti.tree[2], "&va !vt 10", "10", without_key); + test_emits_ints_(ti.ints, 27, "&ka !kt c", "\"c\"", without_key); + test_emits_ints_(ti.ints, 30, "!kt c: &va !vt 10\n", "\"c\": 10\n"); + test_emits_ints_(ti.ints, 30, "!kt c", "\"c\"", without_key); + test_emits_ints_(ti.ints, 33, "c: &va !vt 10\n", "\"c\": 10\n"); + test_emits_ints_(ti.ints, 33, "c", "\"c\"", without_key); + test_emits_ints_(ti.ints, 36, "&va !vt 10", "10"); + test_emits_ints_(ti.ints, 36, "&va !vt 10", "10", without_key); + test_emits_ints_(ti.ints, 39, "!vt 10", "10"); + test_emits_ints_(ti.ints, 39, "!vt 10", "10", without_key); + test_emits_ints_(ti.ints, 42, "10", "10"); + test_emits_ints_(ti.ints, 42, "10", "10", without_key); + // + test_emits_(ti, ti.tree[3], 45, "&ka !kt d: &va !vt 11\n", "\"d\": 11\n"); + test_emits_(ti.tree[3], "&va !vt 11", "11", without_key); + test_emits_ints_(ti.ints, 45, "&ka !kt d", "\"d\"", without_key); + test_emits_ints_(ti.ints, 48, "!kt d: &va !vt 11\n", "\"d\": 11\n"); + test_emits_ints_(ti.ints, 48, "!kt d", "\"d\"", without_key); + test_emits_ints_(ti.ints, 51, "d: &va !vt 11\n", "\"d\": 11\n"); + test_emits_ints_(ti.ints, 51, "d", "\"d\"", without_key); + test_emits_ints_(ti.ints, 54, "&va !vt 11", "11"); + test_emits_ints_(ti.ints, 54, "&va !vt 11", "11", without_key); + test_emits_ints_(ti.ints, 57, "!vt 11", "11"); + test_emits_ints_(ti.ints, 57, "!vt 11", "11", without_key); + test_emits_ints_(ti.ints, 60, "11", "11"); + test_emits_ints_(ti.ints, 60, "11", "11", without_key); + }; { - SCOPED_TRACE("t[3]"); - NodeRef n = nct[3]; + TMPSTY(flowml1, ti, ti.tree, 2); + dotest("{\n !kt a: !vt 8,\n &ka b: &va 9,\n &ka !kt c: &va !vt 10,\n &ka !kt d: &va !vt 11\n}\n", + "{\n \"a\": 8,\n \"b\": 9,\n \"c\": 10,\n \"d\": 11\n}\n"); + } + { + TMPSTY(flowsl, ti, ti.tree, 2); + dotest(R"({!kt a: !vt 8,&ka b: &va 9,&ka !kt c: &va !vt 10,&ka !kt d: &va !vt 11})", + R"({"a": 8,"b": 9,"c": 10,"d": 11})"); + } + { + SCOPED_TRACE("json err on tag"); + const EmitOptions opts = EmitOptions{}.json_err_on_tag(true); { - SCOPED_TRACE("block"); - TmpContainerStyle tmp(n, BLOCK); - std::string expected = "3:\n nested: map\n"; - std::string expected_json = "\"3\": {\n \"nested\": \"map\"\n}\n"; - test_all_emits(n, expected, expected_json); + SCOPED_TRACE("flowsl"); + TMPSTY(flowsl, ti, ti.tree, 2); + test_emit_error_json(ti, opts); } { - SCOPED_TRACE("flow_ml"); - TmpContainerStyle tmp(n, FLOW_ML1); - std::string expected = "3: {\n nested: map\n }\n"; // FIXME should be indented one level, not two - std::string expected_json = "\"3\": {\n \"nested\": \"map\"\n}\n"; - test_all_emits(n, expected, expected_json); + SCOPED_TRACE("flowml1"); + TMPSTY(flowml1, ti, ti.tree, 2); + test_emit_error_json(ti, opts); + } + } + { + SCOPED_TRACE("json err on anchor"); + const EmitOptions opts = EmitOptions{}.json_err_on_anchor(true); + { + SCOPED_TRACE("flowsl"); + TMPSTY(flowsl, ti, ti.tree, 2); + test_emit_error_json(ti, opts); } { - SCOPED_TRACE("flow_sl"); - TmpContainerStyle tmp(n, FLOW_SL); - std::string expected = "3: {nested: map}\n"; - std::string expected_json = "\"3\": {\"nested\": \"map\"}"; // FIXME should have trailing newline - test_all_emits(n, expected, expected_json); + SCOPED_TRACE("flowml1"); + TMPSTY(flowml1, ti, ti.tree, 2); + test_emit_error_json(ti, opts); } } } + +TEST(emit, container_key_tag_anchor) +{ + SCOPED_TRACE("container_key_tag_anchor"); + IntBufs ints; + std::string yaml = R"({ + !kt []: !vt 0, + &ka []: &va 1, + &ka !kt []: &va !vt 2, + !kt &ka []: !vt &va 3, + !kt {}: !vt 4, + &ka {}: &va 5, + &ka !kt {}: &va !vt 6, + !kt &ka {}: !vt &va 7, + !kt a: !vt 8, + &ka b: &va 9, + &ka !kt c: &va !vt 10, + !kt &ka d: !vt &va 11, +})"; + parse_ints(to_substr(yaml), &ints); + { + SCOPED_TRACE("orig"); + std::string expected = R"({ + ? !kt []: !vt 0, + ? &ka []: &va 1, + ? &ka !kt []: &va !vt 2, + ? &ka !kt []: &va !vt 3, + ? !kt {}: !vt 4, + ? &ka {}: &va 5, + ? &ka !kt {}: &va !vt 6, + ? &ka !kt {}: &va !vt 7, + !kt a: !vt 8, + &ka b: &va 9, + &ka !kt c: &va !vt 10, + &ka !kt d: &va !vt 11 +} +)"; + test_emits_ints_nojson_(ints, 0, expected); + test_emits_ints_nojson_(ints, 1, expected); + test_emits_ints_nojson_(ints, 2, expected); + test_emits_ints_nojson_(ints, 3, "? !kt []\n: !vt 0\n"); + test_emits_ints_nojson_(ints, 3, "!kt []", without_key); + test_emits_ints_nojson_(ints, 6, "? []\n: !vt 0\n"); + test_emits_ints_nojson_(ints, 6, "[]", without_key); + test_emits_ints_nojson_(ints, 8, "!vt 0"); + test_emits_ints_nojson_(ints, 8, "!vt 0", without_key); + test_emits_ints_nojson_(ints, 11, "0"); + test_emits_ints_nojson_(ints, 11, "0", without_key); + { + SCOPED_TRACE("nosty"); + TMPSTY(nosty, ints, 6); + test_emits_ints_nojson_(ints, 3, "? !kt\n []\n: !vt 0\n"); + test_emits_ints_nojson_(ints, 3, "!kt\n[]", without_key); + test_emits_ints_nojson_(ints, 6, "?\n []\n: !vt 0\n"); + test_emits_ints_nojson_(ints, 6, "[]", without_key); + } + // + test_emits_ints_nojson_(ints, 14, "? &ka []\n: &va 1\n"); + test_emits_ints_nojson_(ints, 14, "&ka []", without_key); + test_emits_ints_nojson_(ints, 17, "? []\n: &va 1\n"); + test_emits_ints_nojson_(ints, 17, "[]", without_key); + test_emits_ints_nojson_(ints, 19, "&va 1"); + test_emits_ints_nojson_(ints, 19, "&va 1", without_key); + test_emits_ints_nojson_(ints, 22, "1"); + test_emits_ints_nojson_(ints, 22, "1", without_key); + { + SCOPED_TRACE("nosty"); + TMPSTY(nosty, ints, 17); + test_emits_ints_nojson_(ints, 14, "? &ka\n []\n: &va 1\n"); + test_emits_ints_nojson_(ints, 14, "&ka\n[]", without_key); + test_emits_ints_nojson_(ints, 17, "?\n []\n: &va 1\n"); + test_emits_ints_nojson_(ints, 17, "[]", without_key); + } + // + test_emits_ints_nojson_(ints, 25, "? &ka !kt []\n: &va !vt 2\n"); + test_emits_ints_nojson_(ints, 25, "&ka !kt []", without_key); + test_emits_ints_nojson_(ints, 28, "? !kt []\n: &va !vt 2\n"); + test_emits_ints_nojson_(ints, 28, "!kt []", without_key); + test_emits_ints_nojson_(ints, 31, "? []\n: &va !vt 2\n"); + test_emits_ints_nojson_(ints, 31, "[]", without_key); + test_emits_ints_nojson_(ints, 33, "&va !vt 2"); + test_emits_ints_nojson_(ints, 33, "&va !vt 2", without_key); + test_emits_ints_nojson_(ints, 36, "!vt 2"); + test_emits_ints_nojson_(ints, 36, "!vt 2", without_key); + test_emits_ints_nojson_(ints, 39, "2"); + test_emits_ints_nojson_(ints, 39, "2", without_key); + // + test_emits_ints_nojson_(ints, 42, "? &ka !kt []\n: &va !vt 3\n"); + test_emits_ints_nojson_(ints, 42, "&ka !kt []", without_key); + test_emits_ints_nojson_(ints, 45, "? !kt []\n: &va !vt 3\n"); + test_emits_ints_nojson_(ints, 45, "!kt []", without_key); + test_emits_ints_nojson_(ints, 48, "? []\n: &va !vt 3\n"); + test_emits_ints_nojson_(ints, 48, "[]", without_key); + test_emits_ints_nojson_(ints, 50, "&va !vt 3"); + test_emits_ints_nojson_(ints, 50, "&va !vt 3", without_key); + test_emits_ints_nojson_(ints, 53, "!vt 3"); + test_emits_ints_nojson_(ints, 53, "!vt 3", without_key); + test_emits_ints_nojson_(ints, 56, "3"); + test_emits_ints_nojson_(ints, 56, "3", without_key); + // + // + test_emits_ints_nojson_(ints, 56+3, "? !kt {}\n: !vt 4\n"); + test_emits_ints_nojson_(ints, 56+3, "!kt {}", without_key); + test_emits_ints_nojson_(ints, 56+6, "? {}\n: !vt 4\n"); + test_emits_ints_nojson_(ints, 56+6, "{}", without_key); + test_emits_ints_nojson_(ints, 56+8, "!vt 4"); + test_emits_ints_nojson_(ints, 56+8, "!vt 4", without_key); + test_emits_ints_nojson_(ints, 56+11, "4"); + test_emits_ints_nojson_(ints, 56+11, "4", without_key); + // + test_emits_ints_nojson_(ints, 56+14, "? &ka {}\n: &va 5\n"); + test_emits_ints_nojson_(ints, 56+14, "&ka {}", without_key); + test_emits_ints_nojson_(ints, 56+17, "? {}\n: &va 5\n"); + test_emits_ints_nojson_(ints, 56+17, "{}", without_key); + test_emits_ints_nojson_(ints, 56+19, "&va 5"); + test_emits_ints_nojson_(ints, 56+19, "&va 5", without_key); + test_emits_ints_nojson_(ints, 56+22, "5"); + test_emits_ints_nojson_(ints, 56+22, "5", without_key); + // + test_emits_ints_nojson_(ints, 56+25, "? &ka !kt {}\n: &va !vt 6\n"); + test_emits_ints_nojson_(ints, 56+25, "&ka !kt {}", without_key); + test_emits_ints_nojson_(ints, 56+28, "? !kt {}\n: &va !vt 6\n"); + test_emits_ints_nojson_(ints, 56+28, "!kt {}", without_key); + test_emits_ints_nojson_(ints, 56+31, "? {}\n: &va !vt 6\n"); + test_emits_ints_nojson_(ints, 56+31, "{}", without_key); + test_emits_ints_nojson_(ints, 56+33, "&va !vt 6"); + test_emits_ints_nojson_(ints, 56+33, "&va !vt 6", without_key); + test_emits_ints_nojson_(ints, 56+36, "!vt 6"); + test_emits_ints_nojson_(ints, 56+36, "!vt 6", without_key); + test_emits_ints_nojson_(ints, 56+39, "6"); + test_emits_ints_nojson_(ints, 56+39, "6", without_key); + // + test_emits_ints_nojson_(ints, 56+42, "? &ka !kt {}\n: &va !vt 7\n"); + test_emits_ints_nojson_(ints, 56+42, "&ka !kt {}", without_key); + test_emits_ints_nojson_(ints, 56+45, "? !kt {}\n: &va !vt 7\n"); + test_emits_ints_nojson_(ints, 56+45, "!kt {}", without_key); + test_emits_ints_nojson_(ints, 56+48, "? {}\n: &va !vt 7\n"); + test_emits_ints_nojson_(ints, 56+48, "{}", without_key); + test_emits_ints_nojson_(ints, 56+50, "&va !vt 7"); + test_emits_ints_nojson_(ints, 56+50, "&va !vt 7", without_key); + test_emits_ints_nojson_(ints, 56+53, "!vt 7"); + test_emits_ints_nojson_(ints, 56+53, "!vt 7", without_key); + test_emits_ints_nojson_(ints, 56+56, "7"); + test_emits_ints_nojson_(ints, 56+56, "7", without_key); + // + // + test_emits_ints_nojson_(ints, 112+3, "!kt a: !vt 8\n"); + test_emits_ints_nojson_(ints, 112+3, "!kt a", without_key); + test_emits_ints_nojson_(ints, 112+6, "a: !vt 8\n"); + test_emits_ints_nojson_(ints, 112+6, "a", without_key); + test_emits_ints_nojson_(ints, 112+9, "!vt 8"); + test_emits_ints_nojson_(ints, 112+9, "!vt 8", without_key); + test_emits_ints_nojson_(ints, 112+12, "8"); + test_emits_ints_nojson_(ints, 112+12, "8", without_key); + // + test_emits_ints_nojson_(ints, 112+15, "&ka b: &va 9\n"); + test_emits_ints_nojson_(ints, 112+15, "&ka b", without_key); + test_emits_ints_nojson_(ints, 112+18, "b: &va 9\n"); + test_emits_ints_nojson_(ints, 112+18, "b", without_key); + test_emits_ints_nojson_(ints, 112+21, "&va 9"); + test_emits_ints_nojson_(ints, 112+21, "&va 9", without_key); + test_emits_ints_nojson_(ints, 112+24, "9"); + test_emits_ints_nojson_(ints, 112+24, "9", without_key); + // + test_emits_ints_nojson_(ints, 112+27, "&ka !kt c: &va !vt 10\n"); + test_emits_ints_nojson_(ints, 112+27, "&ka !kt c", without_key); + test_emits_ints_nojson_(ints, 112+30, "!kt c: &va !vt 10\n"); + test_emits_ints_nojson_(ints, 112+30, "!kt c", without_key); + test_emits_ints_nojson_(ints, 112+33, "c: &va !vt 10\n"); + test_emits_ints_nojson_(ints, 112+33, "c", without_key); + test_emits_ints_nojson_(ints, 112+36, "&va !vt 10"); + test_emits_ints_nojson_(ints, 112+36, "&va !vt 10", without_key); + test_emits_ints_nojson_(ints, 112+39, "!vt 10"); + test_emits_ints_nojson_(ints, 112+39, "!vt 10", without_key); + test_emits_ints_nojson_(ints, 112+42, "10"); + test_emits_ints_nojson_(ints, 112+42, "10", without_key); + // + test_emits_ints_nojson_(ints, 112+45, "&ka !kt d: &va !vt 11\n"); + test_emits_ints_nojson_(ints, 112+45, "&ka !kt d", without_key); + test_emits_ints_nojson_(ints, 112+48, "!kt d: &va !vt 11\n"); + test_emits_ints_nojson_(ints, 112+48, "!kt d", without_key); + test_emits_ints_nojson_(ints, 112+51, "d: &va !vt 11\n"); + test_emits_ints_nojson_(ints, 112+51, "d", without_key); + test_emits_ints_nojson_(ints, 112+54, "&va !vt 11"); + test_emits_ints_nojson_(ints, 112+54, "&va !vt 11", without_key); + test_emits_ints_nojson_(ints, 112+57, "!vt 11"); + test_emits_ints_nojson_(ints, 112+57, "!vt 11", without_key); + test_emits_ints_nojson_(ints, 112+60, "11"); + test_emits_ints_nojson_(ints, 112+60, "11", without_key); + } +} + +TEST(emit, blck_seq_nosty) +{ + SCOPED_TRACE("blck_seq_nosty"); + std::string yaml = R"(- !str scalar +- &str scalar +- !map {a: b} +- &map {c: d} +- !seq [e,f] +- &seq [g,h] +)"; + TreeAndInts ti = parse_tree_and_ints(to_csubstr(yaml)); + test_emit_yaml_tree_(ti.tree, yaml); + test_emit_yaml_ints_(ti.ints, 0, yaml); + test_emit_yaml_ints_(ti.ints, 1, yaml); + test_emit_yaml_ints_(ti.ints, 2, yaml); + { + SCOPED_TRACE("nosty"); + TMPSTY(nosty, ti, ti.tree[0], 6); + TMPSTY(nosty, ti, ti.tree[1], 12); + TMPSTY(nosty, ti, ti.tree[2], 18); + TMPSTY(nosty, ti, ti.tree[3], 29); + TMPSTY(nosty, ti, ti.tree[4], 40); + TMPSTY(nosty, ti, ti.tree[5], 51); + std::string expected = R"(- !str scalar +- &str scalar +- !map + a: b +- &map + c: d +- !seq + - e + - f +- &seq + - g + - h +)"; + test_emit_yaml_tree_(ti.tree, expected); + test_emit_yaml_ints_(ti.ints, 0, expected); + test_emit_yaml_ints_(ti.ints, 1, expected); + test_emit_yaml_ints_(ti.ints, 2, expected); + } + + test_emit_yaml_tree_(ti.tree[0], without_dash, "!str scalar"); + test_emit_yaml_tree_(ti.tree[0], with_dash, "- !str scalar\n"); + test_emit_yaml_ints_(ti.ints, 3, without_dash, "!str scalar"); + test_emit_yaml_ints_(ti.ints, 3, with_dash, "- !str scalar\n"); + test_emit_yaml_ints_(ti.ints, 6, without_dash, "scalar"); + test_emit_yaml_ints_(ti.ints, 6, with_dash, "- scalar\n"); + { + SCOPED_TRACE("nosty"); + TMPSTY(nosty, ti, ti.tree[0], 6); + test_emit_yaml_tree_(ti.tree[0], without_dash, "!str scalar"); + test_emit_yaml_tree_(ti.tree[0], with_dash, "- !str scalar\n"); + test_emit_yaml_ints_(ti.ints, 3, without_dash, "!str scalar"); + test_emit_yaml_ints_(ti.ints, 3, with_dash, "- !str scalar\n"); + test_emit_yaml_ints_(ti.ints, 6, without_dash, "scalar"); + test_emit_yaml_ints_(ti.ints, 6, with_dash, "- scalar\n"); + } + + test_emit_yaml_tree_(ti.tree[1], without_dash, "&str scalar"); + test_emit_yaml_tree_(ti.tree[1], with_dash, "- &str scalar\n"); + test_emit_yaml_ints_(ti.ints, 9, without_dash, "&str scalar"); + test_emit_yaml_ints_(ti.ints, 9, with_dash, "- &str scalar\n"); + test_emit_yaml_ints_(ti.ints, 12, without_dash, "scalar"); + test_emit_yaml_ints_(ti.ints, 12, with_dash, "- scalar\n"); + { + SCOPED_TRACE("nosty"); + TMPSTY(nosty, ti, ti.tree[1], 12); + test_emit_yaml_tree_(ti.tree[1], without_dash, "&str scalar"); + test_emit_yaml_tree_(ti.tree[1], with_dash, "- &str scalar\n"); + test_emit_yaml_ints_(ti.ints, 9, without_dash, "&str scalar"); + test_emit_yaml_ints_(ti.ints, 9, with_dash, "- &str scalar\n"); + test_emit_yaml_ints_(ti.ints, 12, without_dash, "scalar"); + test_emit_yaml_ints_(ti.ints, 12, with_dash, "- scalar\n"); + } + + test_emit_yaml_tree_(ti.tree[2], without_dash, "!map {a: b}"); + test_emit_yaml_tree_(ti.tree[2], with_dash, "- !map {a: b}\n"); + test_emit_yaml_ints_(ti.ints, 15, without_dash, "!map {a: b}"); + test_emit_yaml_ints_(ti.ints, 15, with_dash, "- !map {a: b}\n"); + test_emit_yaml_ints_(ti.ints, 18, without_dash, "{a: b}"); + test_emit_yaml_ints_(ti.ints, 18, with_dash, "- {a: b}\n"); + { + SCOPED_TRACE("nosty"); + TMPSTY(nosty, ti, ti.tree[2], 18); + test_emit_yaml_tree_(ti.tree[2], without_dash, "!map\na: b\n"); + test_emit_yaml_tree_(ti.tree[2], with_dash, "- !map\n a: b\n"); + test_emit_yaml_ints_(ti.ints, 15, without_dash, "!map\na: b\n"); + test_emit_yaml_ints_(ti.ints, 15, with_dash, "- !map\n a: b\n"); + test_emit_yaml_ints_(ti.ints, 18, without_dash, "a: b\n"); + test_emit_yaml_ints_(ti.ints, 18, with_dash, "- a: b\n"); + } + + test_emit_yaml_tree_(ti.tree[3], without_dash, "&map {c: d}"); + test_emit_yaml_tree_(ti.tree[3], with_dash, "- &map {c: d}\n"); + test_emit_yaml_ints_(ti.ints, 26, without_dash, "&map {c: d}"); + test_emit_yaml_ints_(ti.ints, 26, with_dash, "- &map {c: d}\n"); + test_emit_yaml_ints_(ti.ints, 29, without_dash, "{c: d}"); + test_emit_yaml_ints_(ti.ints, 29, with_dash, "- {c: d}\n"); + { + SCOPED_TRACE("nosty"); + TMPSTY(nosty, ti, ti.tree[3], 29); + test_emit_yaml_tree_(ti.tree[3], without_dash, "&map\nc: d\n"); + test_emit_yaml_tree_(ti.tree[3], with_dash, "- &map\n c: d\n"); + test_emit_yaml_ints_(ti.ints, 26, without_dash, "&map\nc: d\n"); + test_emit_yaml_ints_(ti.ints, 26, with_dash, "- &map\n c: d\n"); + test_emit_yaml_ints_(ti.ints, 29, without_dash, "c: d\n"); + test_emit_yaml_ints_(ti.ints, 29, with_dash, "- c: d\n"); + } + + test_emit_yaml_tree_(ti.tree[4], without_dash, "!seq [e,f]"); + test_emit_yaml_tree_(ti.tree[4], with_dash, "- !seq [e,f]\n"); + test_emit_yaml_ints_(ti.ints, 37, without_dash, "!seq [e,f]"); + test_emit_yaml_ints_(ti.ints, 37, with_dash, "- !seq [e,f]\n"); + test_emit_yaml_ints_(ti.ints, 40, without_dash, "[e,f]"); + test_emit_yaml_ints_(ti.ints, 40, with_dash, "- [e,f]\n"); + { + SCOPED_TRACE("nosty"); + TMPSTY(nosty, ti, ti.tree[4], 40); + test_emit_yaml_tree_(ti.tree[4], without_dash, "!seq\n- e\n- f\n"); + test_emit_yaml_tree_(ti.tree[4], with_dash, "- !seq\n - e\n - f\n"); + test_emit_yaml_ints_(ti.ints, 37, without_dash, "!seq\n- e\n- f\n"); + test_emit_yaml_ints_(ti.ints, 37, with_dash, "- !seq\n - e\n - f\n"); + test_emit_yaml_ints_(ti.ints, 40, without_dash, "- e\n- f\n"); + test_emit_yaml_ints_(ti.ints, 40, with_dash, "- - e\n - f\n"); + } + + test_emit_yaml_tree_(ti.tree[5], without_dash, "&seq [g,h]"); + test_emit_yaml_tree_(ti.tree[5], with_dash, "- &seq [g,h]\n"); + test_emit_yaml_ints_(ti.ints, 48, without_dash, "&seq [g,h]"); + test_emit_yaml_ints_(ti.ints, 48, with_dash, "- &seq [g,h]\n"); + test_emit_yaml_ints_(ti.ints, 51, without_dash, "[g,h]"); + test_emit_yaml_ints_(ti.ints, 51, with_dash, "- [g,h]\n"); + { + SCOPED_TRACE("nosty"); + TMPSTY(nosty, ti, ti.tree[5], 51); + test_emit_yaml_tree_(ti.tree[5], without_dash, "&seq\n- g\n- h\n"); + test_emit_yaml_tree_(ti.tree[5], with_dash, "- &seq\n - g\n - h\n"); + test_emit_yaml_ints_(ti.ints, 48, without_dash, "&seq\n- g\n- h\n"); + test_emit_yaml_ints_(ti.ints, 48, with_dash, "- &seq\n - g\n - h\n"); + test_emit_yaml_ints_(ti.ints, 51, without_dash, "- g\n- h\n"); + test_emit_yaml_ints_(ti.ints, 51, with_dash, "- - g\n - h\n"); + } +} + + +//----------------------------------------------------------------------------- + TEST(emit, percent_is_quoted) { Tree ti = parse_in_arena("{}"); @@ -1673,13 +3575,13 @@ TEST(emit, at_is_quoted__issue_309) { Tree ti = parse_in_arena("{at: [], backtick: []}"); ti.set_serialized(ti["at"].append_child().id(), "@test"); - ti.set_val (ti["at"].append_child().id(), "@test2"); + ti.set_val (ti["at"].append_child().id(), "@test2"); ti.set_serialized(ti["at"].append_child().id(), "@"); - ti.set_val (ti["at"].append_child().id(), "@"); + ti.set_val (ti["at"].append_child().id(), "@"); ti.set_serialized(ti["backtick"].append_child().id(), "`test"); - ti.set_val (ti["backtick"].append_child().id(), "`test2"); + ti.set_val (ti["backtick"].append_child().id(), "`test2"); ti.set_serialized(ti["backtick"].append_child().id(), "`"); - ti.set_val (ti["backtick"].append_child().id(), "`"); + ti.set_val (ti["backtick"].append_child().id(), "`"); std::string yaml = emitrs_yaml(ti); test_check_emit_check(to_csubstr(yaml), check); } @@ -1807,5 +3709,7 @@ Case const* get_case(csubstr /*name*/) return nullptr; } +// NOLINTEND(*-signed-bitwise) + } // namespace yml } // namespace c4 diff --git a/test/test_engine_1_doc_1.cpp b/test/test_engine_1_doc_1.cpp index 1369b065a..babb0a7a0 100644 --- a/test/test_engine_1_doc_1.cpp +++ b/test/test_engine_1_doc_1.cpp @@ -766,740 +766,6 @@ ENGINE_TEST(DocEmptyExplMultImplFirst, ___(ps.end_stream()); } - -//----------------------------------------------------------------------------- - -ENGINE_TEST(DocScalarPlain0, - "foo\n" - , - "+STR\n" - "+DOC\n" - "=VAL :foo\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.set_val_scalar_plain("foo")); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(DocScalarPlain1, - "--- foo\n" - , - "+STR\n" - "+DOC ---\n" - "=VAL :foo\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc_expl()); - ___(ps.set_val_scalar_plain("foo")); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(DocScalarPlainEmpty, - "---\n" - , - "+STR\n" - "+DOC ---\n" - "=VAL :\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc_expl()); - ___(ps.set_val_scalar_plain_empty()); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(DocScalarPlain2, - "--- ---\n" - , - "---\n ---\n" - , - "+STR\n" - "+DOC ---\n" - "=VAL :---\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc_expl()); - ___(ps.set_val_scalar_plain("---")); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(DocScalarPlain2_1, - "------\n" - , - " ------\n" - , - "+STR\n" - "+DOC\n" - "=VAL :------\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.set_val_scalar_plain("------")); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(DocScalarPlain2_2, - "......\n" - , - " ......\n" - , - "+STR\n" - "+DOC\n" - "=VAL :......\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.set_val_scalar_plain("......")); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(DocScalarPlain3, - "--- ...\n" - , - "---\n ...\n" - , - "+STR\n" - "+DOC ---\n" - "=VAL :...\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc_expl()); - ___(ps.set_val_scalar_plain("...")); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(DocScalarPlain3_1, - "---...\n" - , - " ---...\n" - , - "+STR\n" - "+DOC\n" - "=VAL :---...\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.set_val_scalar_plain("---...")); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(DocScalarPlainMultiline0, - HAS_MULTILINE_SCALAR, - "--- foo\n bar\n" - , - "--- foo bar\n" - , - "+STR\n" - "+DOC ---\n" - "=VAL :foo bar\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc_expl()); - ___(ps.set_val_scalar_plain("foo bar")); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(DocScalarPlainMultiline0Indented, - HAS_MULTILINE_SCALAR, - " --- foo\n bar\n" - , " --- foo bar\n" - , - "+STR\n" - "+DOC\n" - "=VAL :--- foo bar\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.set_val_scalar_plain("--- foo bar")); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(DocScalarPlainMultiline0Indented1, - HAS_MULTILINE_SCALAR - , - " --- foo\n bar\n" - , - " --- foo bar\n" - , - "+STR\n" - "+DOC\n" - "=VAL :--- foo bar\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.set_val_scalar_plain("--- foo bar")); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(DocScalarPlainMultiline, - HAS_MULTILINE_SCALAR - , - "foo\nbar\n\nfew\nbars" - , - "foo bar\n\n few bars\n" - , - "+STR\n" - "+DOC\n" - "=VAL :foo bar\\nfew bars\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.set_val_scalar_plain("foo bar\nfew bars")); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(DocScalarPlainMultilineComment0, - HAS_MULTILINE_SCALAR - , - "# comment\nfoo\nbar\n\nfew\nbars" - , - "foo bar\n\n few bars\n" - , - "+STR\n" - "+DOC\n" - "=VAL :foo bar\\nfew bars\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.set_val_scalar_plain("foo bar\nfew bars")); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(DocScalarPlainMultilineComment1, - HAS_MULTILINE_SCALAR - , - "foo\nbar\n\nfew\nbars\n# comment\n" - , - "foo bar\n\n few bars\n" - , - "+STR\n" - "+DOC\n" - "=VAL :foo bar\\nfew bars\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.set_val_scalar_plain("foo bar\nfew bars")); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - - -ENGINE_TEST(DocScalarPlainIndentation, - HAS_MULTILINE_SCALAR, - " foo\n" - " bar\n" - "baz\n" - "--- foo\n" - "bar\n" - "baz\n" - "---\n" - "- foo\n" - " bar\n" - "- baz\n" - "---\n" - "aaa: bbb\n" - " ccc\n" - "ddd: eee\n" - , - "--- foo bar baz\n" - "--- foo bar baz\n" - "---\n" - "- foo bar\n" - "- baz\n" - "---\n" - "aaa: bbb ccc\n" - "ddd: eee\n" - , - "+STR\n" - "+DOC\n" - "=VAL :foo bar baz\n" - "-DOC\n" - "+DOC ---\n" - "=VAL :foo bar baz\n" - "-DOC\n" - "+DOC ---\n" - "+SEQ\n" - "=VAL :foo bar\n" - "=VAL :baz\n" - "-SEQ\n" - "-DOC\n" - "+DOC ---\n" - "+MAP\n" - "=VAL :aaa\n" - "=VAL :bbb ccc\n" - "=VAL :ddd\n" - "=VAL :eee\n" - "-MAP\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.set_val_scalar_plain("foo bar baz")); - ___(ps.end_doc()); - ___(ps.begin_doc_expl()); - ___(ps.set_val_scalar_plain("foo bar baz")); - ___(ps.end_doc()); - ___(ps.begin_doc_expl()); - ___(ps.begin_seq_val_block()); - ___(ps.set_val_scalar_plain("foo bar")); - ___(ps.add_sibling()); - ___(ps.set_val_scalar_plain("baz")); - ___(ps.end_seq_block()); - ___(ps.end_doc()); - ___(ps.begin_doc_expl()); - ___(ps.begin_map_val_block()); - ___(ps.set_key_scalar_plain("aaa")); - ___(ps.set_val_scalar_plain("bbb ccc")); - ___(ps.add_sibling()); - ___(ps.set_key_scalar_plain("ddd")); - ___(ps.set_val_scalar_plain("eee")); - ___(ps.end_map_block()); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - - -//----------------------------------------------------------------------------- - -ENGINE_TEST(DocScalarSQuoted, - "'foo'\n" - , - "+STR\n" - "+DOC\n" - "=VAL 'foo\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.set_val_scalar_squoted("foo")); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(DocScalarSQuotedExpl, - "--- ''" - , - "--- ''\n" - , - "+STR\n" - "+DOC ---\n" - "=VAL '\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc_expl()); - ___(ps.set_val_scalar_squoted("")); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(DocScalarSQuotedMultiline, - HAS_MULTILINE_SCALAR - , - "'foo\nbar\nbaz\n\nbat'\n" - , - "'foo bar baz\n\n bat'\n", - "+STR\n" - "+DOC\n" - "=VAL 'foo bar baz\\nbat\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.set_val_scalar_squoted("foo bar baz\nbat")); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(DocScalarSQuotedMultilineComment0, - HAS_MULTILINE_SCALAR - , - "# a comment\n'foo\nbar\nbaz\n\nbat'\n" - , - "'foo bar baz\n\n bat'\n" - , - "+STR\n" - "+DOC\n" - "=VAL 'foo bar baz\\nbat\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.set_val_scalar_squoted("foo bar baz\nbat")); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(DocScalarSQuotedMultilineComment1, - HAS_MULTILINE_SCALAR - , - "'foo\nbar\nbaz\n\nbat'\n# a comment\n" - , - "'foo bar baz\n\n bat'\n", - "+STR\n" - "+DOC\n" - "=VAL 'foo bar baz\\nbat\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.set_val_scalar_squoted("foo bar baz\nbat")); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - - -//----------------------------------------------------------------------------- - -ENGINE_TEST(DocScalarDQuoted, - "\"foo\"\n" - , - "+STR\n" - "+DOC\n" - "=VAL \"foo\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.set_val_scalar_dquoted("foo")); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(DocScalarDQuotedExpl, - "--- \"\"" - , - "--- \"\"\n" - , - "+STR\n" - "+DOC ---\n" - "=VAL \"\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc_expl()); - ___(ps.set_val_scalar_dquoted("")); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(DocScalarDQuotedMultiline, - HAS_MULTILINE_SCALAR - , - "\"foo\nbar\nbaz\n\nbat\"\n" - , - "\"foo bar baz\\nbat\"\n", - "+STR\n" - "+DOC\n" - "=VAL \"foo bar baz\\nbat\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.set_val_scalar_dquoted("foo bar baz\nbat")); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(DocScalarDQuotedMultilineComment0, - HAS_MULTILINE_SCALAR - , - "# a comment\n\"foo\nbar\nbaz\n\nbat\"\n" - , - "\"foo bar baz\\nbat\"\n" - , - "+STR\n" - "+DOC\n" - "=VAL \"foo bar baz\\nbat\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.set_val_scalar_dquoted("foo bar baz\nbat")); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(DocScalarDQuotedMultilineComment1, - HAS_MULTILINE_SCALAR - , - "\"foo\nbar\nbaz\n\nbat\"\n# a comment\n" - , - "\"foo bar baz\\nbat\"\n" - , - "+STR\n" - "+DOC\n" - "=VAL \"foo bar baz\\nbat\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.set_val_scalar_dquoted("foo bar baz\nbat")); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - - -//----------------------------------------------------------------------------- - -ENGINE_TEST(DocScalarLiteral, - HAS_MULTILINE_SCALAR - , - "|-\n foo\n" - , - "+STR\n" - "+DOC\n" - "=VAL |foo\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.set_val_scalar_literal("foo")); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(DocScalarLiteralExpl, - HAS_MULTILINE_SCALAR - , - "--- |1-" - , - "--- |-\n" - , - "+STR\n" - "+DOC ---\n" - "=VAL |\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc_expl()); - ___(ps.set_val_scalar_literal("")); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(DocScalarLiteralComment0, - HAS_MULTILINE_SCALAR - , - "# comment\n|-\n foo\n" - , - "|-\n foo\n", - "+STR\n" - "+DOC\n" - "=VAL |foo\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.set_val_scalar_literal("foo")); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(DocScalarLiteralComment1, - HAS_MULTILINE_SCALAR - , - "|-\n foo\n# comment\n" - , - "|-\n foo\n" - , - "+STR\n" - "+DOC\n" - "=VAL |foo\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.set_val_scalar_literal("foo")); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - - -//----------------------------------------------------------------------------- - -ENGINE_TEST(DocScalarFolded, - HAS_MULTILINE_SCALAR - , - ">-\n foo\n" - , - "+STR\n" - "+DOC\n" - "=VAL >foo\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.set_val_scalar_folded("foo")); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(DocScalarFoldedExpl, - HAS_MULTILINE_SCALAR - , - "--- >1-" - , - "--- >-\n" - , - "+STR\n" - "+DOC ---\n" - "=VAL >\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc_expl()); - ___(ps.set_val_scalar_folded("")); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(DocScalarFoldedComment0, - HAS_MULTILINE_SCALAR - , - "# comment\n>-\n foo\n" - , - ">-\n foo\n" - , - "+STR\n" - "+DOC\n" - "=VAL >foo\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.set_val_scalar_folded("foo")); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(DocScalarFoldedComment1, - HAS_MULTILINE_SCALAR - , - ">-\n foo\n# comment\n" - , - ">-\n foo\n" - , - "+STR\n" - "+DOC\n" - "=VAL >foo\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.set_val_scalar_folded("foo")); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - - -//----------------------------------------------------------------------------- - -ENGINE_TEST(ScalarMixedDoc, - HAS_MULTILINE_SCALAR, - ". \"dquo\" plain 'squo'" - , - ". \"dquo\" plain 'squo'\n" - , - "+STR\n" - "+DOC\n" - "=VAL :. \"dquo\" plain 'squo'\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.set_val_scalar_plain(". \"dquo\" plain 'squo'")); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(ScalarMixedMap, - HAS_MULTILINE_SCALAR - , - "foo: . \"dquo\" plain 'squo'" - , - "foo: . \"dquo\" plain 'squo'\n" - , - "+STR\n" - "+DOC\n" - "+MAP\n" - "=VAL :foo\n" - "=VAL :. \"dquo\" plain 'squo'\n" - "-MAP\n" - "-DOC\n" - "-STR\n") -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.begin_map_val_block()); - ___(ps.set_key_scalar_plain("foo")); - ___(ps.set_val_scalar_plain(". \"dquo\" plain 'squo'")); - ___(ps.end_map_block()); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - } // namespace yml } // namespace c4 diff --git a/test/test_engine_1_doc_3.cpp b/test/test_engine_1_doc_3.cpp new file mode 100644 index 000000000..849c9fa70 --- /dev/null +++ b/test/test_engine_1_doc_3.cpp @@ -0,0 +1,764 @@ +#include "./test_lib/test_engine.hpp" + +// WARNING: don't use raw string literals -- g++4.8 cannot accept them +// as macro arguments + +RYML_DEFINE_TEST_MAIN() + +namespace c4 { +namespace yml { + +ENGINE_TEST(DocScalarPlain0, + "foo\n" + , + "+STR\n" + "+DOC\n" + "=VAL :foo\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.set_val_scalar_plain("foo")); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(DocScalarPlain1, + "--- foo\n" + , + "+STR\n" + "+DOC ---\n" + "=VAL :foo\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc_expl()); + ___(ps.set_val_scalar_plain("foo")); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(DocScalarPlainEmpty, + "---\n" + , + "+STR\n" + "+DOC ---\n" + "=VAL :\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc_expl()); + ___(ps.set_val_scalar_plain_empty()); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(DocScalarPlain2, + "--- ---\n" + , + "---\n ---\n" + , + "+STR\n" + "+DOC ---\n" + "=VAL :---\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc_expl()); + ___(ps.set_val_scalar_plain("---")); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(DocScalarPlain2_1, + "------\n" + , + " ------\n" + , + "+STR\n" + "+DOC\n" + "=VAL :------\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.set_val_scalar_plain("------")); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(DocScalarPlain2_2, + "......\n" + , + " ......\n" + , + "+STR\n" + "+DOC\n" + "=VAL :......\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.set_val_scalar_plain("......")); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(DocScalarPlain3, + "--- ...\n" + , + "---\n ...\n" + , + "+STR\n" + "+DOC ---\n" + "=VAL :...\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc_expl()); + ___(ps.set_val_scalar_plain("...")); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(DocScalarPlain3_1, + "---...\n" + , + " ---...\n" + , + "+STR\n" + "+DOC\n" + "=VAL :---...\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.set_val_scalar_plain("---...")); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(DocScalarPlainMultiline0, + HAS_MULTILINE_SCALAR, + "--- foo\n bar\n" + , + "--- foo bar\n" + , + "+STR\n" + "+DOC ---\n" + "=VAL :foo bar\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc_expl()); + ___(ps.set_val_scalar_plain("foo bar")); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(DocScalarPlainMultiline0Indented, + HAS_MULTILINE_SCALAR, + " --- foo\n bar\n" + , " --- foo bar\n" + , + "+STR\n" + "+DOC\n" + "=VAL :--- foo bar\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.set_val_scalar_plain("--- foo bar")); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(DocScalarPlainMultiline0Indented1, + HAS_MULTILINE_SCALAR + , + " --- foo\n bar\n" + , + " --- foo bar\n" + , + "+STR\n" + "+DOC\n" + "=VAL :--- foo bar\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.set_val_scalar_plain("--- foo bar")); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(DocScalarPlainMultiline, + HAS_MULTILINE_SCALAR + , + "foo\nbar\n\nfew\nbars" + , + "foo bar\n\n few bars\n" + , + "+STR\n" + "+DOC\n" + "=VAL :foo bar\\nfew bars\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.set_val_scalar_plain("foo bar\nfew bars")); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(DocScalarPlainMultilineComment0, + HAS_MULTILINE_SCALAR + , + "# comment\nfoo\nbar\n\nfew\nbars" + , + "foo bar\n\n few bars\n" + , + "+STR\n" + "+DOC\n" + "=VAL :foo bar\\nfew bars\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.set_val_scalar_plain("foo bar\nfew bars")); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(DocScalarPlainMultilineComment1, + HAS_MULTILINE_SCALAR + , + "foo\nbar\n\nfew\nbars\n# comment\n" + , + "foo bar\n\n few bars\n" + , + "+STR\n" + "+DOC\n" + "=VAL :foo bar\\nfew bars\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.set_val_scalar_plain("foo bar\nfew bars")); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + + +ENGINE_TEST(DocScalarPlainIndentation, + HAS_MULTILINE_SCALAR, + " foo\n" + " bar\n" + "baz\n" + "--- foo\n" + "bar\n" + "baz\n" + "---\n" + "- foo\n" + " bar\n" + "- baz\n" + "---\n" + "aaa: bbb\n" + " ccc\n" + "ddd: eee\n" + , + "--- foo bar baz\n" + "--- foo bar baz\n" + "---\n" + "- foo bar\n" + "- baz\n" + "---\n" + "aaa: bbb ccc\n" + "ddd: eee\n" + , + "+STR\n" + "+DOC\n" + "=VAL :foo bar baz\n" + "-DOC\n" + "+DOC ---\n" + "=VAL :foo bar baz\n" + "-DOC\n" + "+DOC ---\n" + "+SEQ\n" + "=VAL :foo bar\n" + "=VAL :baz\n" + "-SEQ\n" + "-DOC\n" + "+DOC ---\n" + "+MAP\n" + "=VAL :aaa\n" + "=VAL :bbb ccc\n" + "=VAL :ddd\n" + "=VAL :eee\n" + "-MAP\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.set_val_scalar_plain("foo bar baz")); + ___(ps.end_doc()); + ___(ps.begin_doc_expl()); + ___(ps.set_val_scalar_plain("foo bar baz")); + ___(ps.end_doc()); + ___(ps.begin_doc_expl()); + ___(ps.begin_seq_val_block()); + ___(ps.set_val_scalar_plain("foo bar")); + ___(ps.add_sibling()); + ___(ps.set_val_scalar_plain("baz")); + ___(ps.end_seq_block()); + ___(ps.end_doc()); + ___(ps.begin_doc_expl()); + ___(ps.begin_map_val_block()); + ___(ps.set_key_scalar_plain("aaa")); + ___(ps.set_val_scalar_plain("bbb ccc")); + ___(ps.add_sibling()); + ___(ps.set_key_scalar_plain("ddd")); + ___(ps.set_val_scalar_plain("eee")); + ___(ps.end_map_block()); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + + +//----------------------------------------------------------------------------- + +ENGINE_TEST(DocScalarSQuoted, + "'foo'\n" + , + "+STR\n" + "+DOC\n" + "=VAL 'foo\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.set_val_scalar_squoted("foo")); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(DocScalarSQuotedExpl, + "--- ''" + , + "--- ''\n" + , + "+STR\n" + "+DOC ---\n" + "=VAL '\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc_expl()); + ___(ps.set_val_scalar_squoted("")); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(DocScalarSQuotedMultiline, + HAS_MULTILINE_SCALAR + , + "'foo\nbar\nbaz\n\nbat'\n" + , + "'foo bar baz\n\n bat'\n", + "+STR\n" + "+DOC\n" + "=VAL 'foo bar baz\\nbat\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.set_val_scalar_squoted("foo bar baz\nbat")); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(DocScalarSQuotedMultilineComment0, + HAS_MULTILINE_SCALAR + , + "# a comment\n'foo\nbar\nbaz\n\nbat'\n" + , + "'foo bar baz\n\n bat'\n" + , + "+STR\n" + "+DOC\n" + "=VAL 'foo bar baz\\nbat\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.set_val_scalar_squoted("foo bar baz\nbat")); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(DocScalarSQuotedMultilineComment1, + HAS_MULTILINE_SCALAR + , + "'foo\nbar\nbaz\n\nbat'\n# a comment\n" + , + "'foo bar baz\n\n bat'\n", + "+STR\n" + "+DOC\n" + "=VAL 'foo bar baz\\nbat\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.set_val_scalar_squoted("foo bar baz\nbat")); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + + +//----------------------------------------------------------------------------- + +ENGINE_TEST(DocScalarDQuoted, + "\"foo\"\n" + , + "+STR\n" + "+DOC\n" + "=VAL \"foo\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.set_val_scalar_dquoted("foo")); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(DocScalarDQuotedExpl, + "--- \"\"" + , + "--- \"\"\n" + , + "+STR\n" + "+DOC ---\n" + "=VAL \"\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc_expl()); + ___(ps.set_val_scalar_dquoted("")); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(DocScalarDQuotedMultiline, + HAS_MULTILINE_SCALAR + , + "\"foo\nbar\nbaz\n\nbat\"\n" + , + "\"foo bar baz\\nbat\"\n", + "+STR\n" + "+DOC\n" + "=VAL \"foo bar baz\\nbat\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.set_val_scalar_dquoted("foo bar baz\nbat")); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(DocScalarDQuotedMultilineComment0, + HAS_MULTILINE_SCALAR + , + "# a comment\n\"foo\nbar\nbaz\n\nbat\"\n" + , + "\"foo bar baz\\nbat\"\n" + , + "+STR\n" + "+DOC\n" + "=VAL \"foo bar baz\\nbat\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.set_val_scalar_dquoted("foo bar baz\nbat")); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(DocScalarDQuotedMultilineComment1, + HAS_MULTILINE_SCALAR + , + "\"foo\nbar\nbaz\n\nbat\"\n# a comment\n" + , + "\"foo bar baz\\nbat\"\n" + , + "+STR\n" + "+DOC\n" + "=VAL \"foo bar baz\\nbat\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.set_val_scalar_dquoted("foo bar baz\nbat")); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + + +//----------------------------------------------------------------------------- + +ENGINE_TEST(DocScalarLiteral, + HAS_MULTILINE_SCALAR + , + "|-\n foo\n" + , + "+STR\n" + "+DOC\n" + "=VAL |foo\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.set_val_scalar_literal("foo")); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(DocScalarLiteralExpl, + HAS_MULTILINE_SCALAR + , + "--- |1-" + , + "--- |-\n" + , + "+STR\n" + "+DOC ---\n" + "=VAL |\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc_expl()); + ___(ps.set_val_scalar_literal("")); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(DocScalarLiteralComment0, + HAS_MULTILINE_SCALAR + , + "# comment\n|-\n foo\n" + , + "|-\n foo\n", + "+STR\n" + "+DOC\n" + "=VAL |foo\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.set_val_scalar_literal("foo")); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(DocScalarLiteralComment1, + HAS_MULTILINE_SCALAR + , + "|-\n foo\n# comment\n" + , + "|-\n foo\n" + , + "+STR\n" + "+DOC\n" + "=VAL |foo\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.set_val_scalar_literal("foo")); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + + +//----------------------------------------------------------------------------- + +ENGINE_TEST(DocScalarFolded, + HAS_MULTILINE_SCALAR + , + ">-\n foo\n" + , + "+STR\n" + "+DOC\n" + "=VAL >foo\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.set_val_scalar_folded("foo")); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(DocScalarFoldedExpl, + HAS_MULTILINE_SCALAR + , + "--- >1-" + , + "--- >-\n" + , + "+STR\n" + "+DOC ---\n" + "=VAL >\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc_expl()); + ___(ps.set_val_scalar_folded("")); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(DocScalarFoldedComment0, + HAS_MULTILINE_SCALAR + , + "# comment\n>-\n foo\n" + , + ">-\n foo\n" + , + "+STR\n" + "+DOC\n" + "=VAL >foo\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.set_val_scalar_folded("foo")); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(DocScalarFoldedComment1, + HAS_MULTILINE_SCALAR + , + ">-\n foo\n# comment\n" + , + ">-\n foo\n" + , + "+STR\n" + "+DOC\n" + "=VAL >foo\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.set_val_scalar_folded("foo")); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + + +//----------------------------------------------------------------------------- + +ENGINE_TEST(ScalarMixedDoc, + HAS_MULTILINE_SCALAR, + ". \"dquo\" plain 'squo'" + , + ". \"dquo\" plain 'squo'\n" + , + "+STR\n" + "+DOC\n" + "=VAL :. \"dquo\" plain 'squo'\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.set_val_scalar_plain(". \"dquo\" plain 'squo'")); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(ScalarMixedMap, + HAS_MULTILINE_SCALAR + , + "foo: . \"dquo\" plain 'squo'" + , + "foo: . \"dquo\" plain 'squo'\n" + , + "+STR\n" + "+DOC\n" + "+MAP\n" + "=VAL :foo\n" + "=VAL :. \"dquo\" plain 'squo'\n" + "-MAP\n" + "-DOC\n" + "-STR\n") +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.begin_map_val_block()); + ___(ps.set_key_scalar_plain("foo")); + ___(ps.set_val_scalar_plain(". \"dquo\" plain 'squo'")); + ___(ps.end_map_block()); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +} // namespace yml +} // namespace c4 + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +// this is needed to use the test case library + +#ifndef RYML_SINGLE_HEADER +#include "c4/substr.hpp" +#endif + +namespace c4 { +namespace yml { +struct Case; +Case const* get_case(csubstr /*name*/) +{ + return nullptr; +} +} // namespace yml +} // namespace c4 diff --git a/test/test_engine_3_map_block_1.cpp b/test/test_engine_3_map_block_1.cpp index 38cf0f5ff..09948e0fd 100644 --- a/test/test_engine_3_map_block_1.cpp +++ b/test/test_engine_3_map_block_1.cpp @@ -101,7 +101,10 @@ ENGINE_TEST(BlockEmptyVals, "c:\n" "d:\n" , - "a: \nb: \nc: \nd: \n" + "a: \n" + "b: \n" + "c: \n" + "d: \n" , "+STR\n" "+DOC\n" diff --git a/test/test_engine_3_map_block_2.cpp b/test/test_engine_3_map_block_2.cpp index 87ede3dd8..b6aa12131 100644 --- a/test/test_engine_3_map_block_2.cpp +++ b/test/test_engine_3_map_block_2.cpp @@ -15,6 +15,9 @@ ENGINE_TEST(ContainerKey1Block0_0, HAS_CONTAINER_KEYS, "{this: is, a: keymap}: [and,now,a,seq,val]" , + "? {this: is,a: keymap}\n" + ": [and,now,a,seq,val]\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -37,8 +40,8 @@ ENGINE_TEST(ContainerKey1Block0_0, { ___(ps.begin_stream()); ___(ps.begin_doc()); - ___(ps.begin_map_key_block()); - ___(ps.begin_map_val_flow()); + ___(ps.begin_map_val_block()); + ___(ps.begin_map_key_flow()); ___(ps.set_key_scalar_plain("this")); ___(ps.set_val_scalar_plain("is")); ___(ps.add_sibling()); @@ -65,6 +68,9 @@ ENGINE_TEST(ContainerKey1Block0_1, HAS_CONTAINER_KEYS, "{this: is, a: keymap}: [and,now,a,seq,val]" , + "? {this: is,a: keymap}\n" + ": [and,now,a,seq,val]\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -115,6 +121,9 @@ ENGINE_TEST(ContainerKey1Block1_0, HAS_CONTAINER_KEYS, "[this,is,a,seq,key]: [and,now,a,seq,val]" , + "? [this,is,a,seq,key]\n" + ": [and,now,a,seq,val]\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -138,7 +147,7 @@ ENGINE_TEST(ContainerKey1Block1_0, { ___(ps.begin_stream()); ___(ps.begin_doc()); - ___(ps.begin_map_key_block()); + ___(ps.begin_map_val_block()); ___(ps.begin_seq_key_flow()); ___(ps.set_val_scalar_plain("this")); ___(ps.add_sibling()); @@ -170,6 +179,9 @@ ENGINE_TEST(ContainerKey1Block1_1, HAS_CONTAINER_KEYS, "[this,is,a,seq,key]: [and,now,a,seq,val]" , + "? [this,is,a,seq,key]\n" + ": [and,now,a,seq,val]\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -193,7 +205,7 @@ ENGINE_TEST(ContainerKey1Block1_1, { ___(ps.begin_stream()); ___(ps.begin_doc()); - ___(ps.begin_seq_key_flow()); + ___(ps.begin_seq_val_flow()); ___(ps.set_val_scalar_plain("this")); ___(ps.add_sibling()); ___(ps.set_val_scalar_plain("is")); @@ -225,6 +237,9 @@ ENGINE_TEST(ContainerKey1Block2_0, HAS_CONTAINER_KEYS, "{this: is, a: keymap}: [and,now,a,seq,val]" , + "? {this: is,a: keymap}\n" + ": [and,now,a,seq,val]\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -275,6 +290,9 @@ ENGINE_TEST(ContainerKey1Block2_1, HAS_CONTAINER_KEYS, "{this: is, a: keymap}: [and,now,a,seq,val]" , + "? {this: is,a: keymap}\n" + ": [and,now,a,seq,val]\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -328,6 +346,13 @@ ENGINE_TEST(ContainerKey1Block3_0, "---\n" "[A,SEQ]: {A: MAP}\n" , + "---\n" + "? {a: map}\n" + ": [a,seq]\n" + "---\n" + "? [A,SEQ]\n" + ": {A: MAP}\n" + , "+STR\n" "+DOC ---\n" "+MAP\n" @@ -376,7 +401,7 @@ ENGINE_TEST(ContainerKey1Block3_0, ___(ps.add_sibling()); ___(ps.set_val_scalar_plain("SEQ")); ___(ps.end_seq_flow(singleline)); - ___(ps.begin_map_key_flow()); + ___(ps.begin_map_val_flow()); ___(ps.set_key_scalar_plain("A")); ___(ps.set_val_scalar_plain("MAP")); ___(ps.end_map_flow(singleline)); @@ -392,6 +417,13 @@ ENGINE_TEST(ContainerKey1Block3_1, "---\n" "[A,SEQ]: {A: MAP}\n" , + "---\n" + "? {a: map}\n" + ": [a,seq]\n" + "---\n" + "? [A,SEQ]\n" + ": {A: MAP}\n" + , "+STR\n" "+DOC ---\n" "+MAP\n" @@ -440,7 +472,7 @@ ENGINE_TEST(ContainerKey1Block3_1, ___(ps.set_val_scalar_plain("SEQ")); ___(ps.end_seq_flow(singleline)); ___(ps.actually_val_is_first_key_of_new_map_block()); - ___(ps.begin_map_key_flow()); + ___(ps.begin_map_val_flow()); ___(ps.set_key_scalar_plain("A")); ___(ps.set_val_scalar_plain("MAP")); ___(ps.end_map_flow(singleline)); @@ -462,6 +494,12 @@ ENGINE_TEST(ContainerKey2Block_1, "!maptag &mapanchor {this: is, a: keymap}: [and,now,a,seq,val]\n" "!seqtag &seqanchor [now, reversed]: {of: course}\n" , + "foo: bar\n" + "? &mapanchor !maptag {this: is,a: keymap}\n" + ": [and,now,a,seq,val]\n" + "? &seqanchor !seqtag [now,reversed]\n" + ": {of: course}\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -498,8 +536,8 @@ ENGINE_TEST(ContainerKey2Block_1, ___(ps.set_key_scalar_plain("foo")); ___(ps.set_val_scalar_plain("bar")); ___(ps.add_sibling()); - ___(ps.set_key_tag("!maptag")); ___(ps.set_key_anchor("mapanchor")); + ___(ps.set_key_tag("!maptag")); ___(ps.begin_map_key_flow()); ___(ps.set_key_scalar_plain("this")); ___(ps.set_val_scalar_plain("is")); @@ -519,8 +557,8 @@ ENGINE_TEST(ContainerKey2Block_1, ___(ps.set_val_scalar_plain("val")); ___(ps.end_seq_flow(singleline)); ___(ps.add_sibling()); - ___(ps.set_key_tag("!seqtag")); ___(ps.set_key_anchor("seqanchor")); + ___(ps.set_key_tag("!seqtag")); ___(ps.begin_seq_key_flow()); ___(ps.set_val_scalar_plain("now")); ___(ps.add_sibling()); @@ -542,6 +580,11 @@ ENGINE_TEST(ContainerKey3Block4_C2SP_0, HAS_CONTAINER_KEYS, "[21]: 42\n" "[23]: 42\n" , + "? [21]\n" + ": 42\n" + "? [23]\n" + ": 42\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -699,6 +742,11 @@ ENGINE_TEST(ContainerKey3Block5_C2SP_0, HAS_CONTAINER_KEYS, "{a: b}: 42\n" "{c: d}: 42\n" , + "? {a: b}\n" + ": 42\n" + "? {c: d}\n" + ": 42\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -803,6 +851,10 @@ ENGINE_TEST(MapKeyBlock, "? foo: bar\n" ": baz" , + "?\n" + " foo: bar\n" + ": baz\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -833,6 +885,9 @@ ENGINE_TEST(MapKeyBlockFlow, "? {foo: bar}\n" ": baz" , + "? {foo: bar}\n" + ": baz\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -865,6 +920,11 @@ ENGINE_TEST(SeqKeyBlock, " - bar\n" ": baz\n" , + "?\n" + " - foo\n" + " - bar\n" + ": baz\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -896,6 +956,9 @@ ENGINE_TEST(SeqKeyBlockFlow, "? [foo, bar]\n" ": baz\n" , + "? [foo,bar]\n" + ": baz\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -931,6 +994,13 @@ ENGINE_TEST(SeqKeyBlock2_0, "- baz\n" "- bat\n" , + "?\n" + " - foo\n" + " - bar\n" + ":\n" + " - baz\n" + " - bat\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -954,7 +1024,7 @@ ENGINE_TEST(SeqKeyBlock2_0, ___(ps.add_sibling()); ___(ps.set_val_scalar_plain("bar")); ___(ps.end_seq_block()); - ___(ps.begin_seq_key_block()); + ___(ps.begin_seq_val_block()); ___(ps.set_val_scalar_plain("baz")); ___(ps.add_sibling()); ___(ps.set_val_scalar_plain("bat")); @@ -983,6 +1053,13 @@ ENGINE_TEST(SeqKeyBlock3, " - baz\n" " - bat\n" , + "?\n" + " - foo\n" + " - bar\n" + ":\n" + " - baz\n" + " - bat\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -1006,7 +1083,7 @@ ENGINE_TEST(SeqKeyBlock3, ___(ps.add_sibling()); ___(ps.set_val_scalar_plain("bar")); ___(ps.end_seq_block()); - ___(ps.begin_seq_key_block()); + ___(ps.begin_seq_val_block()); ___(ps.set_val_scalar_plain("baz")); ___(ps.add_sibling()); ___(ps.set_val_scalar_plain("bat")); @@ -1022,6 +1099,10 @@ ENGINE_TEST(MapKeyBlock4Squo0, "? 'foo' : bar\n" ": baz\n" , + "?\n" + " 'foo': bar\n" + ": baz\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -1054,6 +1135,11 @@ ENGINE_TEST(MapKeyBlock4Squo1, " &scalarkey 'foo' : bar\n" ": baz\n" , + "&blockanchor\n" + "? &mapkey\n" + " &scalarkey 'foo': bar\n" + ": baz\n" + , "+STR\n" "+DOC\n" "+MAP &blockanchor\n" @@ -1088,6 +1174,10 @@ ENGINE_TEST(MapKeyBlock4Dquo0, "? \"foo\" : bar\n" ": baz\n" , + "?\n" + " \"foo\": bar\n" + ": baz\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -1120,6 +1210,11 @@ ENGINE_TEST(MapKeyBlock4Dquo1, " &scalarkey \"foo\" : bar\n" ": baz\n" , + "&blockanchor\n" + "? &mapkey\n" + " &scalarkey \"foo\": bar\n" + ": baz\n" + , "+STR\n" "+DOC\n" "+MAP &blockanchor\n" diff --git a/test/test_engine_3_map_flow_1.cpp b/test/test_engine_3_map_flow_1.cpp index 4037cc008..fd6a7cf1a 100644 --- a/test/test_engine_3_map_flow_1.cpp +++ b/test/test_engine_3_map_flow_1.cpp @@ -112,7 +112,7 @@ ENGINE_TEST(NestedMapFlow, , Location(1,1,2) , - "{{}: {}}" + "{? {}: {}}" , "+STR\n" "+DOC\n" @@ -142,7 +142,7 @@ ENGINE_TEST(NestedMap3FlowEmpty, , Location(1,1,2) , - "{{{}: {}}: {{}: {}}}", + "{? {? {}: {}}: {? {}: {}}}", "+STR\n" "+DOC\n" "+MAP {}\n" @@ -686,6 +686,8 @@ ENGINE_TEST(SimpleMapContainerKeyFlow, HAS_CONTAINER_KEYS, "{{this: is, a: keymap}: [and,now,a,seq,val]}" , + "{? {this: is,a: keymap}: [and,now,a,seq,val]}" + , "+STR\n" "+DOC\n" "+MAP {}\n" @@ -708,8 +710,8 @@ ENGINE_TEST(SimpleMapContainerKeyFlow, { ___(ps.begin_stream()); ___(ps.begin_doc()); - ___(ps.begin_map_key_flow()); ___(ps.begin_map_val_flow()); + ___(ps.begin_map_key_flow()); ___(ps.set_key_scalar_plain("this")); ___(ps.set_val_scalar_plain("is")); ___(ps.add_sibling()); @@ -737,6 +739,8 @@ ENGINE_TEST(MapKeyFlow, HAS_CONTAINER_KEYS, Location(1, 1, 2), "{{foo: bar}: baz}" , + "{? {foo: bar}: baz}" + , "+STR\n" "+DOC\n" "+MAP {}\n" @@ -767,6 +771,8 @@ ENGINE_TEST(SeqKeyFlow, HAS_CONTAINER_KEYS, Location(1,1,2), "{[foo, bar]: baz}" , + "{? [foo,bar]: baz}" + , "+STR\n" "+DOC\n" "+MAP {}\n" diff --git a/test/test_engine_4_anchor.cpp b/test/test_engine_4_anchor.cpp index 910ae0913..616f445ca 100644 --- a/test/test_engine_4_anchor.cpp +++ b/test/test_engine_4_anchor.cpp @@ -854,11 +854,11 @@ ENGINE_TEST(AnchorMapMapSuckerPunch, { ___(ps.begin_stream()); ___(ps.begin_doc()); - ___(ps.set_val_tag("!mymap")); ___(ps.set_val_anchor("mymap")); + ___(ps.set_val_tag("!mymap")); ___(ps.begin_map_val_block()); - ___(ps.set_key_tag("!footag")); ___(ps.set_key_anchor("fooanch")); + ___(ps.set_key_tag("!footag")); ___(ps.set_key_scalar_plain("foo")); ___(ps.set_val_anchor("seq")); ___(ps.begin_map_val_block()); @@ -873,48 +873,48 @@ ENGINE_TEST(AnchorMapMapSuckerPunch, ___(ps.set_val_scalar_plain("val2")); ___(ps.end_map_block()); ___(ps.add_sibling()); - ___(ps.set_key_tag("!bartag")); ___(ps.set_key_anchor("baranch")); + ___(ps.set_key_tag("!bartag")); ___(ps.set_key_scalar_plain("bar")); - ___(ps.set_val_tag("!a")); ___(ps.set_val_anchor("map2")); + ___(ps.set_val_tag("!a")); ___(ps.begin_map_val_block()); - ___(ps.set_key_tag("!b")); ___(ps.set_key_anchor("key10")); + ___(ps.set_key_tag("!b")); ___(ps.set_key_scalar_plain("key10")); - ___(ps.set_val_tag("!c")); ___(ps.set_val_anchor("val10")); + ___(ps.set_val_tag("!c")); ___(ps.set_val_scalar_plain("val10")); ___(ps.add_sibling()); - ___(ps.set_key_tag("!b")); ___(ps.set_key_anchor("key20")); + ___(ps.set_key_tag("!b")); ___(ps.set_key_scalar_plain("key20")); - ___(ps.set_val_tag("!c")); ___(ps.set_val_anchor("val20")); + ___(ps.set_val_tag("!c")); ___(ps.set_val_scalar_plain("val20")); ___(ps.add_sibling()); ___(ps.set_key_scalar_plain("key10")); ___(ps.set_val_scalar_plain("20")); ___(ps.end_map_block()); ___(ps.add_sibling()); - ___(ps.set_key_tag("!baztag")); ___(ps.set_key_anchor("bazanch")); + ___(ps.set_key_tag("!baztag")); ___(ps.set_key_scalar_plain("baz")); - ___(ps.set_val_tag("!a")); ___(ps.set_val_anchor("map2")); + ___(ps.set_val_tag("!a")); ___(ps.begin_map_val_block()); - ___(ps.set_key_tag("!b")); ___(ps.set_key_anchor("key10")); + ___(ps.set_key_tag("!b")); ___(ps.set_key_scalar_plain("key10")); - ___(ps.set_val_tag("!c")); ___(ps.set_val_anchor("val10")); + ___(ps.set_val_tag("!c")); ___(ps.set_val_scalar_plain("val10")); ___(ps.add_sibling()); - ___(ps.set_key_tag("!b")); ___(ps.set_key_anchor("key20")); + ___(ps.set_key_tag("!b")); ___(ps.set_key_scalar_plain("key20")); - ___(ps.set_val_tag("!c")); ___(ps.set_val_anchor("val20")); + ___(ps.set_val_tag("!c")); ___(ps.set_val_scalar_plain("val20")); ___(ps.add_sibling()); ___(ps.set_key_scalar_plain("key10")); @@ -1129,6 +1129,10 @@ ENGINE_TEST(DocDoubleAnchorSeqMap, "--- &docanchor\n" "&anchor [seq, yeah]: foo\n" , + "--- &docanchor\n" + "? &anchor [seq,yeah]\n" + ": foo\n" + , "+STR\n" "+DOC ---\n" "+MAP &docanchor\n" @@ -1157,10 +1161,15 @@ ENGINE_TEST(DocDoubleAnchorSeqMap, } ENGINE_TEST(DoubleAnchorSeqMap, - HAS_CONTAINER_KEYS, + HAS_CONTAINER_KEYS + , "&docanchor\n" "&anchor [seq, yeah]: foo\n" , + "&docanchor\n" + "? &anchor [seq,yeah]\n" + ": foo\n" + , "+STR\n" "+DOC\n" "+MAP &docanchor\n" @@ -1193,6 +1202,10 @@ ENGINE_TEST(DocDoubleAnchorKeyMap, "--- &docanchor\n" "&anchor {key: val}: foo\n" , + "--- &docanchor\n" + "? &anchor {key: val}\n" + ": foo\n" + , "+STR\n" "+DOC ---\n" "+MAP &docanchor\n" @@ -1211,7 +1224,7 @@ ENGINE_TEST(DocDoubleAnchorKeyMap, ___(ps.begin_map_val_block()); ___(ps.set_key_anchor("anchor")); ___(ps.begin_map_key_flow()); - ___(ps.set_val_scalar_plain("key")); + ___(ps.set_key_scalar_plain("key")); ___(ps.set_val_scalar_plain("val")); ___(ps.end_map_flow(false)); ___(ps.set_val_scalar_plain("foo")); @@ -1225,6 +1238,10 @@ ENGINE_TEST(DoubleAnchorKeyMap, "&docanchor\n" "&anchor {key: val}: foo\n" , + "&docanchor\n" + "? &anchor {key: val}\n" + ": foo\n" + , "+STR\n" "+DOC\n" "+MAP &docanchor\n" @@ -1243,7 +1260,7 @@ ENGINE_TEST(DoubleAnchorKeyMap, ___(ps.begin_map_val_block()); ___(ps.set_key_anchor("anchor")); ___(ps.begin_map_key_flow()); - ___(ps.set_val_scalar_plain("key")); + ___(ps.set_key_scalar_plain("key")); ___(ps.set_val_scalar_plain("val")); ___(ps.end_map_flow(false)); ___(ps.set_val_scalar_plain("foo")); diff --git a/test/test_engine_5_tag_1.cpp b/test/test_engine_5_tag_1.cpp index 4384d3626..28ef30a7e 100644 --- a/test/test_engine_5_tag_1.cpp +++ b/test/test_engine_5_tag_1.cpp @@ -560,14 +560,14 @@ ENGINE_TEST(TagPlacementMapFlow0, HAS_CONTAINER_KEYS, "{\n" " !tag : ,\n" " !tag0 0: ,\n" - " !tags []: ,\n" - " !tagm {}: ,\n" + " ? !tags []: ,\n" + " ? !tagm {}: ,\n" " !tag1 : ,\n" " !tag2 : ,\n" " !tag3 : ,\n" " !tag4 's': ,\n" " !tag5 \"d\": ,\n" - " !tag6 : ,\n" + " !tag6 : \n" "}\n" "" , @@ -896,14 +896,14 @@ ENGINE_TEST(TagPlacementMapValBlock, ___(ps.set_key_scalar_plain("e")); ___(ps.set_val_tag("!tag")); ___(ps.set_val_scalar_plain_empty()); - ___(ps.end_map_flow(singleline)); + ___(ps.end_map_block()); ___(ps.add_sibling()); ___(ps.set_key_scalar_plain("f")); ___(ps.set_val_tag("!tag")); ___(ps.begin_seq_val_block()); ___(ps.set_val_tag("!tag")); ___(ps.set_val_scalar_plain("g")); - ___(ps.end_seq_flow(singleline)); + ___(ps.end_seq_block()); ___(ps.end_map_block()); ___(ps.end_doc()); ___(ps.end_stream()); @@ -922,6 +922,16 @@ ENGINE_TEST(TagPlacementMapKeyFlow, "" , "" + "!mtag {\n" + " !tag : x,\n" + " !tag a: x,\n" + " ? !tag []: x,\n" + " ? !tag {}: x,\n" + " !tag : \n" + "}\n" + "" + , + "" "+STR\n" "+DOC\n" "+MAP {} \n" @@ -983,6 +993,17 @@ ENGINE_TEST(TagPlacementMapKeyBlock, "" , "" + "!mtag\n" + "!tag : x\n" + "!tag a: x\n" + "? !tag []\n" + ": x\n" + "? !tag {}\n" + ": x\n" + "!tag : \n" + "" + , + "" "+STR\n" "+DOC\n" "+MAP \n" @@ -1173,12 +1194,12 @@ ENGINE_TEST(TagPlacementMapComplex, " !a : !b\n" ": !tag1\n" " !a : !b\n" - + "" "? !tag2\n" " !a 1: !b 2\n" ": !tag3\n" " !a : !b\n" - + "" "? !tag4\n" " - !a 1\n" " - !b 2\n" @@ -1188,6 +1209,27 @@ ENGINE_TEST(TagPlacementMapComplex, "" , "" + "!mtag\n" + "? !tag0\n" + " !a : !b \n" + ": !tag1\n" + " !a : !b \n" + "" + "? !tag2\n" + " !a 1: !b 2\n" + ": !tag3\n" + " !a : !b \n" + "" + "? !tag4\n" + " - !a 1\n" + " - !b 2\n" + ": !tag5\n" + " !a : !b \n" + "" + "!tag6 : \n" + "" + , + "" "+STR\n" "+DOC\n" "+MAP \n" diff --git a/test/test_engine_5_tag_2.cpp b/test/test_engine_5_tag_2.cpp index e8a274887..daf7c8e7e 100644 --- a/test/test_engine_5_tag_2.cpp +++ b/test/test_engine_5_tag_2.cpp @@ -825,6 +825,8 @@ ENGINE_TEST(TagTestSuiteUGM3, ENGINE_TEST(TagTestSuiteUKK6_02_0, "!" , + "!\n" + , "+STR\n" "+DOC\n" "=VAL :\n" diff --git a/test/test_engine_6_qmrk_1.cpp b/test/test_engine_6_qmrk_1.cpp index dd2559ac3..71b47a365 100644 --- a/test/test_engine_6_qmrk_1.cpp +++ b/test/test_engine_6_qmrk_1.cpp @@ -19,6 +19,12 @@ ENGINE_TEST(Qmrk0, "a simple key: a value\n" "? an explicit key: another value\n" , + "" + "a simple key: a value\n" + "?\n" + " an explicit key: another value\n" + ": \n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -86,6 +92,12 @@ ENGINE_TEST(Qmrk1_1, "? an explicit key: another value\n" "a simple key: a value\n" , + "" + "?\n" + " an explicit key: another value\n" + ": \n" + "a simple key: a value\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -124,6 +136,18 @@ ENGINE_TEST(Qmrk1_2, "? an explicit key deindented: its value\n" "? more: siblings\n" , + "map:\n" + " ?\n" + " an explicit key: another value\n" + " : \n" + " a simple key: a value\n" + "?\n" + " an explicit key deindented: its value\n" + ": \n" + "?\n" + " more: siblings\n" + ": \n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -168,13 +192,13 @@ ENGINE_TEST(Qmrk1_2, ___(ps.add_sibling()); ___(ps.begin_map_key_block()); ___(ps.set_key_scalar_plain("an explicit key deindented")); - ___(ps.set_key_scalar_plain("its value")); + ___(ps.set_val_scalar_plain("its value")); ___(ps.end_map_block()); ___(ps.set_val_scalar_plain_empty()); ___(ps.add_sibling()); ___(ps.begin_map_key_block()); ___(ps.set_key_scalar_plain("more")); - ___(ps.set_key_scalar_plain("siblings")); + ___(ps.set_val_scalar_plain("siblings")); ___(ps.end_map_block()); ___(ps.set_val_scalar_plain_empty()); ___(ps.end_map_block()); @@ -399,6 +423,12 @@ ENGINE_TEST(Qmrk5, "?\n" "?\n" , + "?\n" + " a: b\n" + ": \n" + ": \n" + ": \n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -442,6 +472,14 @@ ENGINE_TEST(Qmrk6, " a simple key: a value\n" "- ? another explicit key: its value\n" , + "- ?\n" + " an explicit key: another value\n" + " : \n" + " a simple key: a value\n" + "- ?\n" + " another explicit key: its value\n" + " : \n" + , "+STR\n" "+DOC\n" "+SEQ\n" @@ -498,6 +536,16 @@ ENGINE_TEST(Qmrk7, "- ? : \n" "- ? :\n" , + "- ?\n" + " : x\n" + " : \n" + "- ?\n" + " : \n" + " : \n" + "- ?\n" + " : \n" + " : \n" + , "+STR\n" "+DOC\n" "+SEQ\n" @@ -713,6 +761,10 @@ ENGINE_TEST(Qmrk11, "?" "\n" " :" "\n" , + "?" "\n" + " : " "\n" + ": " "\n" + , "+STR" "\n" "+DOC" "\n" "+MAP" "\n" @@ -742,7 +794,11 @@ ENGINE_TEST(Qmrk11, ENGINE_TEST(Qmrk12, HAS_CONTAINER_KEYS, Location(3,2,2), "?" "\n" - " :" "\n" + " :" "\n" + , + "?" "\n" + " : " "\n" + ": " "\n" , "+STR" "\n" "+DOC" "\n" @@ -832,6 +888,11 @@ ENGINE_TEST(QmrkWithTags, " !bt : b2\n" ": c3\n" , + "a1: b1\n" + "? !at\n" + " !bt : b2\n" + ": c3\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -1060,6 +1121,13 @@ ENGINE_TEST(QmrkSameLineUnkSeq, HAS_CONTAINER_KEYS, ": - a\n" " - b\n" , + "?\n" + " - a\n" + " - b\n" + ":\n" + " - a\n" + " - b\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -1125,6 +1193,11 @@ ENGINE_TEST(QmrkSameLineUnkMap, HAS_CONTAINER_KEYS, "? a: b\n" ": c: d\n" , + "?\n" + " a: b\n" + ":\n" + " c: d\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -1186,6 +1259,14 @@ ENGINE_TEST(QmrkSameLineMapSeq, HAS_CONTAINER_KEYS, ": - a\n" " - b\n" , + "k: v\n" + "?\n" + " - a\n" + " - b\n" + ":\n" + " - a\n" + " - b\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -1261,6 +1342,12 @@ ENGINE_TEST(QmrkSameLineMapMap, HAS_CONTAINER_KEYS, "? a: b\n" ": c: d\n" , + "k: v\n" + "?\n" + " a: b\n" + ":\n" + " c: d\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -1330,6 +1417,13 @@ ENGINE_TEST(QmrkSameLineSeqSeq, HAS_CONTAINER_KEYS, " : - a\n" " - b\n" , + "- ?\n" + " - a\n" + " - b\n" + " :\n" + " - a\n" + " - b\n" + , "+STR\n" "+DOC\n" "+SEQ\n" @@ -1349,7 +1443,7 @@ ENGINE_TEST(QmrkSameLineSeqSeq, HAS_CONTAINER_KEYS, { ___(ps.begin_stream()); ___(ps.begin_doc()); - ___(ps.begin_seq_key_block()); + ___(ps.begin_seq_val_block()); ___(ps.begin_map_val_block()); ___(ps.begin_seq_key_block()); ___(ps.set_val_scalar_plain("a")); @@ -1399,6 +1493,11 @@ ENGINE_TEST(QmrkSameLineSeqMap, HAS_CONTAINER_KEYS, "- ? a: b\n" " : c: d\n" , + "- ?\n" + " a: b\n" + " :\n" + " c: d\n" + , "+STR\n" "+DOC\n" "+SEQ\n" @@ -1460,6 +1559,12 @@ ENGINE_TEST_ERRLOC_(QmrkSameLineSeqMapErr3, HAS_CONTAINER_KEYS, ENGINE_TEST(QmrkSameLineNested0Seq, HAS_CONTAINER_KEYS, "? ? - a\n" , + "?\n" + " ?\n" + " - a\n" + " : \n" + ": \n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -1493,6 +1598,12 @@ ENGINE_TEST(QmrkSameLineNested0Seq_1, HAS_CONTAINER_KEYS, "?\n" " ? - a\n" , + "?\n" + " ?\n" + " - a\n" + " : \n" + ": \n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -1525,6 +1636,12 @@ ENGINE_TEST(QmrkSameLineNested0Seq_1, HAS_CONTAINER_KEYS, ENGINE_TEST(QmrkSameLineNested0Map, HAS_CONTAINER_KEYS, "? ? a: b\n" , + "?\n" + " ?\n" + " a: b\n" + " : \n" + ": \n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -1560,6 +1677,12 @@ ENGINE_TEST(QmrkSameLineNested0Map_1, HAS_CONTAINER_KEYS, "?\n" " ? a: b\n" , + "?\n" + " ?\n" + " a: b\n" + " : \n" + ": \n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -1599,6 +1722,18 @@ ENGINE_TEST(QmrkSameLineNested1SeqRkcl0, HAS_CONTAINER_KEYS, " ? - b\n" "? - c\n" , + "?\n" + " ?\n" + " - a\n" + " : \n" + " ?\n" + " - b\n" + " : \n" + ": \n" + "?\n" + " - c\n" + ": \n" + , "+STR\n" "+DOC\n" "+MAP\n" diff --git a/test/test_engine_6_qmrk_2.cpp b/test/test_engine_6_qmrk_2.cpp index 71adf8462..32ebfcbc8 100644 --- a/test/test_engine_6_qmrk_2.cpp +++ b/test/test_engine_6_qmrk_2.cpp @@ -13,6 +13,10 @@ ENGINE_TEST(QmrkNestedSameline0_0, HAS_CONTAINER_KEYS, "? ?" "\n" ": a" "\n" , + "?\n" + " : \n" + ": a" "\n" + , "+STR" "\n" "+DOC" "\n" "+MAP" "\n" @@ -28,7 +32,7 @@ ENGINE_TEST(QmrkNestedSameline0_0, HAS_CONTAINER_KEYS, { ___(ps.begin_stream()); ___(ps.begin_doc()); - ___(ps.begin_map_key_block()); + ___(ps.begin_map_val_block()); ___(ps.begin_map_key_block()); ___(ps.set_key_scalar_plain_empty()); ___(ps.set_val_scalar_plain_empty()); @@ -42,6 +46,12 @@ ENGINE_TEST(QmrkNestedSameline0_1, HAS_CONTAINER_KEYS, "? ? ?" "\n" ": a" "\n" , + "?\n" + " ?\n" + " : \n" + " : \n" + ": a" "\n" + , "+STR" "\n" "+DOC" "\n" "+MAP" "\n" @@ -60,7 +70,7 @@ ENGINE_TEST(QmrkNestedSameline0_1, HAS_CONTAINER_KEYS, { ___(ps.begin_stream()); ___(ps.begin_doc()); - ___(ps.begin_map_key_block()); + ___(ps.begin_map_val_block()); ___(ps.begin_map_key_block()); ___(ps.begin_map_key_block()); ___(ps.set_key_scalar_plain_empty()); @@ -77,6 +87,14 @@ ENGINE_TEST(QmrkNestedSameline0_2, HAS_CONTAINER_KEYS, "? ? ? ?" "\n" ": a" "\n" , + "?\n" + " ?\n" + " ?\n" + " : " "\n" + " : " "\n" + " : " "\n" + ": a" "\n" + , "+STR" "\n" "+DOC" "\n" "+MAP" "\n" @@ -98,7 +116,7 @@ ENGINE_TEST(QmrkNestedSameline0_2, HAS_CONTAINER_KEYS, { ___(ps.begin_stream()); ___(ps.begin_doc()); - ___(ps.begin_map_key_block()); + ___(ps.begin_map_val_block()); ___(ps.begin_map_key_block()); ___(ps.begin_map_key_block()); ___(ps.begin_map_key_block()); @@ -118,6 +136,16 @@ ENGINE_TEST(QmrkNestedSameline0_3, HAS_CONTAINER_KEYS, "? ? ? ? ?" "\n" ": a" "\n" , + "?\n" + " ?\n" + " ?\n" + " ?\n" + " : " "\n" + " : " "\n" + " : " "\n" + " : " "\n" + ": a" "\n" + , "+STR" "\n" "+DOC" "\n" "+MAP" "\n" @@ -142,7 +170,7 @@ ENGINE_TEST(QmrkNestedSameline0_3, HAS_CONTAINER_KEYS, { ___(ps.begin_stream()); ___(ps.begin_doc()); - ___(ps.begin_map_key_block()); + ___(ps.begin_map_val_block()); ___(ps.begin_map_key_block()); ___(ps.begin_map_key_block()); ___(ps.begin_map_key_block()); @@ -165,6 +193,10 @@ ENGINE_TEST(QmrkNestedSameline0_3, HAS_CONTAINER_KEYS, ENGINE_TEST(QmrkNestedSameline1_00, HAS_CONTAINER_KEYS, "? ?" "\n" , + "?\n" + " : " "\n" + ": " "\n" + , "+STR" "\n" "+DOC" "\n" "+MAP" "\n" @@ -180,7 +212,7 @@ ENGINE_TEST(QmrkNestedSameline1_00, HAS_CONTAINER_KEYS, { ___(ps.begin_stream()); ___(ps.begin_doc()); - ___(ps.begin_map_key_block()); + ___(ps.begin_map_val_block()); ___(ps.begin_map_key_block()); ___(ps.set_key_scalar_plain_empty()); ___(ps.set_val_scalar_plain_empty()); @@ -193,6 +225,12 @@ ENGINE_TEST(QmrkNestedSameline1_00, HAS_CONTAINER_KEYS, ENGINE_TEST(QmrkNestedSameline1_01, HAS_CONTAINER_KEYS, "? ? ?" "\n" , + "?\n" + " ?\n" + " : " "\n" + " : " "\n" + ": " "\n" + , "+STR" "\n" "+DOC" "\n" "+MAP" "\n" @@ -211,7 +249,7 @@ ENGINE_TEST(QmrkNestedSameline1_01, HAS_CONTAINER_KEYS, { ___(ps.begin_stream()); ___(ps.begin_doc()); - ___(ps.begin_map_key_block()); + ___(ps.begin_map_val_block()); ___(ps.begin_map_key_block()); ___(ps.begin_map_key_block()); ___(ps.set_key_scalar_plain_empty()); @@ -227,6 +265,14 @@ ENGINE_TEST(QmrkNestedSameline1_01, HAS_CONTAINER_KEYS, ENGINE_TEST(QmrkNestedSameline1_02, HAS_CONTAINER_KEYS, "? ? ? ?" "\n" , + "?\n" + " ?\n" + " ?\n" + " : " "\n" + " : " "\n" + " : " "\n" + ": " "\n" + , "+STR" "\n" "+DOC" "\n" "+MAP" "\n" @@ -248,7 +294,7 @@ ENGINE_TEST(QmrkNestedSameline1_02, HAS_CONTAINER_KEYS, { ___(ps.begin_stream()); ___(ps.begin_doc()); - ___(ps.begin_map_key_block()); + ___(ps.begin_map_val_block()); ___(ps.begin_map_key_block()); ___(ps.begin_map_key_block()); ___(ps.begin_map_key_block()); @@ -267,6 +313,16 @@ ENGINE_TEST(QmrkNestedSameline1_02, HAS_CONTAINER_KEYS, ENGINE_TEST(QmrkNestedSameline1_03, HAS_CONTAINER_KEYS, "? ? ? ? ?" "\n" , + "?\n" + " ?\n" + " ?\n" + " ?" "\n" + " : " "\n" + " : " "\n" + " : " "\n" + " : " "\n" + ": " "\n" + , "+STR" "\n" "+DOC" "\n" "+MAP" "\n" @@ -291,7 +347,7 @@ ENGINE_TEST(QmrkNestedSameline1_03, HAS_CONTAINER_KEYS, { ___(ps.begin_stream()); ___(ps.begin_doc()); - ___(ps.begin_map_key_block()); + ___(ps.begin_map_val_block()); ___(ps.begin_map_key_block()); ___(ps.begin_map_key_block()); ___(ps.begin_map_key_block()); @@ -318,6 +374,10 @@ ENGINE_TEST(QmrkNestedSamelineTag0_00, HAS_CONTAINER_KEYS, "? ? &a !t" "\n" ": a" "\n" , + "?\n" + " &a !t : " "\n" + ": a" "\n" + , "+STR" "\n" "+DOC" "\n" "+MAP" "\n" @@ -333,7 +393,7 @@ ENGINE_TEST(QmrkNestedSamelineTag0_00, HAS_CONTAINER_KEYS, { ___(ps.begin_stream()); ___(ps.begin_doc()); - ___(ps.begin_map_key_block()); + ___(ps.begin_map_val_block()); ___(ps.begin_map_key_block()); ___(ps.set_key_anchor("a")); ___(ps.set_key_tag("!t")); @@ -351,6 +411,10 @@ ENGINE_TEST(QmrkNestedSamelineTag0_01, HAS_CONTAINER_KEYS, " ? &a !t" "\n" ": a" "\n" , + "? &a !t\n" + " &a !t : " "\n" + ": a" "\n" + , "+STR" "\n" "+DOC" "\n" "+MAP" "\n" @@ -366,7 +430,7 @@ ENGINE_TEST(QmrkNestedSamelineTag0_01, HAS_CONTAINER_KEYS, { ___(ps.begin_stream()); ___(ps.begin_doc()); - ___(ps.begin_map_key_block()); + ___(ps.begin_map_val_block()); ___(ps.set_key_anchor("a")); ___(ps.set_key_tag("!t")); ___(ps.begin_map_key_block()); @@ -382,7 +446,8 @@ ENGINE_TEST(QmrkNestedSamelineTag0_01, HAS_CONTAINER_KEYS, } ENGINE_TEST(QmrkNestedSamelineTag0_02, HAS_CONTAINER_KEYS, - "? &a !t ? &a !t" "\n" + "? &a !t\n" + " &a !t : " "\n" ": a" "\n" , "+STR" "\n" @@ -400,7 +465,7 @@ ENGINE_TEST(QmrkNestedSamelineTag0_02, HAS_CONTAINER_KEYS, { ___(ps.begin_stream()); ___(ps.begin_doc()); - ___(ps.begin_map_key_block()); + ___(ps.begin_map_val_block()); ___(ps.set_key_anchor("a")); ___(ps.set_key_tag("!t")); ___(ps.begin_map_key_block()); @@ -450,14 +515,18 @@ ENGINE_TEST(QmrkNestedBlock2, " ? a\n" " : b\n" , + "?\n" + " a: b\n" + ": \n" + , "+STR" "\n" "+DOC" "\n" "+MAP" "\n" "+MAP" "\n" - "=VAL :a" "\n" - "=VAL :b" "\n" + "=VAL :a" "\n" + "=VAL :b" "\n" "-MAP" "\n" - "=VAL :" "\n" + "=VAL :" "\n" "-MAP" "\n" "-DOC" "\n" "-STR" "\n" @@ -465,7 +534,7 @@ ENGINE_TEST(QmrkNestedBlock2, { ___(ps.begin_stream()); ___(ps.begin_doc()); - ___(ps.begin_map_key_block()); + ___(ps.begin_map_val_block()); ___(ps.begin_map_key_block()); ___(ps.set_key_scalar_plain("a")); ___(ps.set_val_scalar_plain("b")); @@ -483,6 +552,12 @@ ENGINE_TEST(QmrkNestedBlock3, " ? a\n" " : b\n" , + "?\n" + " ?\n" + " a: b\n" + " : \n" + ": \n" + , "+STR" "\n" "+DOC" "\n" "+MAP" "\n" @@ -501,7 +576,7 @@ ENGINE_TEST(QmrkNestedBlock3, { ___(ps.begin_stream()); ___(ps.begin_doc()); - ___(ps.begin_map_key_block()); + ___(ps.begin_map_val_block()); ___(ps.begin_map_key_block()); ___(ps.begin_map_key_block()); ___(ps.set_key_scalar_plain("a")); @@ -523,6 +598,14 @@ ENGINE_TEST(QmrkNestedBlock4, " ? a\n" " : b\n" , + "?\n" + " ?\n" + " ?\n" + " a: b\n" + " : \n" + " : \n" + ": \n" + , "+STR" "\n" "+DOC" "\n" "+MAP" "\n" @@ -544,7 +627,7 @@ ENGINE_TEST(QmrkNestedBlock4, { ___(ps.begin_stream()); ___(ps.begin_doc()); - ___(ps.begin_map_key_block()); + ___(ps.begin_map_val_block()); ___(ps.begin_map_key_block()); ___(ps.begin_map_key_block()); ___(ps.begin_map_key_block()); @@ -566,6 +649,10 @@ ENGINE_TEST(QmrkNestedBlock5_0, "?" "\n" " ?" "\n" , + "?" "\n" + " : " "\n" + ": " "\n" + , "+STR" "\n" "+DOC" "\n" "+MAP" "\n" @@ -581,7 +668,7 @@ ENGINE_TEST(QmrkNestedBlock5_0, { ___(ps.begin_stream()); ___(ps.begin_doc()); - ___(ps.begin_map_key_block()); + ___(ps.begin_map_val_block()); ___(ps.begin_map_key_block()); ___(ps.set_key_scalar_plain_empty()); ___(ps.set_val_scalar_plain_empty()); @@ -598,6 +685,12 @@ ENGINE_TEST(QmrkNestedBlock5_1, " ?" "\n" " ?" "\n" , + "?" "\n" + " ?" "\n" + " : " "\n" + " : " "\n" + ": " "\n" + , "+STR" "\n" "+DOC" "\n" "+MAP" "\n" @@ -616,7 +709,7 @@ ENGINE_TEST(QmrkNestedBlock5_1, { ___(ps.begin_stream()); ___(ps.begin_doc()); - ___(ps.begin_map_key_block()); + ___(ps.begin_map_val_block()); ___(ps.begin_map_key_block()); ___(ps.begin_map_key_block()); ___(ps.set_key_scalar_plain_empty()); @@ -638,6 +731,16 @@ ENGINE_TEST(QmrkNestedBlock5_2, " ?" "\n" " ?" "\n" , + "?" "\n" + " ?" "\n" + " ?" "\n" + " ?" "\n" + " : " "\n" + " : " "\n" + " : " "\n" + " : " "\n" + ": " "\n" + , "+STR" "\n" "+DOC" "\n" "+MAP" "\n" @@ -662,7 +765,7 @@ ENGINE_TEST(QmrkNestedBlock5_2, { ___(ps.begin_stream()); ___(ps.begin_doc()); - ___(ps.begin_map_key_block()); + ___(ps.begin_map_val_block()); ___(ps.begin_map_key_block()); ___(ps.begin_map_key_block()); ___(ps.begin_map_key_block()); @@ -688,6 +791,11 @@ ENGINE_TEST(QmrkNestedBlock5_3, " ?" "\n" "?" "\n" , + "?" "\n" + " : " "\n" + ": " "\n" + ": " "\n" + , "+STR" "\n" "+DOC" "\n" "+MAP" "\n" @@ -705,7 +813,7 @@ ENGINE_TEST(QmrkNestedBlock5_3, { ___(ps.begin_stream()); ___(ps.begin_doc()); - ___(ps.begin_map_key_block()); + ___(ps.begin_map_val_block()); ___(ps.begin_map_key_block()); ___(ps.set_key_scalar_plain_empty()); ___(ps.set_val_scalar_plain_empty()); @@ -733,6 +841,23 @@ ENGINE_TEST(QmrkNestedBlock5_4, " ?" "\n" "?" "\n" , + "?" "\n" + " ?" "\n" + " ?" "\n" + " ?" "\n" + " ?" "\n" + " : ""\n" + " : " "\n" + " : " "\n" + " : " "\n" + " : " "\n" + " : " "\n" + " : " "\n" + " : " "\n" + " : " "\n" + ": " "\n" + ": " "\n" + , "+STR" "\n" "+DOC" "\n" "+MAP" "\n" @@ -770,7 +895,7 @@ ENGINE_TEST(QmrkNestedBlock5_4, { ___(ps.begin_stream()); ___(ps.begin_doc()); - ___(ps.begin_map_key_block()); + ___(ps.begin_map_val_block()); ___(ps.begin_map_key_block()); ___(ps.begin_map_key_block()); ___(ps.begin_map_key_block()); @@ -814,6 +939,20 @@ ENGINE_TEST(QmrkNestedBlock5_5, " ?" "\n" "?" "\n" , + "?" "\n" + " ?" "\n" + " ?" "\n" + " ?" "\n" + " ?" "\n" + " : " "\n" + " : " "\n" + " : " "\n" + " : " "\n" + " : " "\n" + " : " "\n" + ": " "\n" + ": " "\n" + , "+STR" "\n" "+DOC" "\n" "+MAP" "\n" @@ -845,7 +984,7 @@ ENGINE_TEST(QmrkNestedBlock5_5, { ___(ps.begin_stream()); ___(ps.begin_doc()); - ___(ps.begin_map_key_block()); + ___(ps.begin_map_val_block()); ___(ps.begin_map_key_block()); ___(ps.begin_map_key_block()); ___(ps.begin_map_key_block()); diff --git a/test/test_engine_6_qmrk_3.cpp b/test/test_engine_6_qmrk_3.cpp index 876d98f3b..b979efef6 100644 --- a/test/test_engine_6_qmrk_3.cpp +++ b/test/test_engine_6_qmrk_3.cpp @@ -240,7 +240,7 @@ ENGINE_TEST(QmrkFlowSeq1, HAS_CONTAINER_KEYS, "{ ? [a, b]: c , }" , - "{? [a, b] : c}" + "{? [a,b]: c}" , "+STR\n" "+DOC\n" @@ -271,7 +271,7 @@ ENGINE_TEST(QmrkFlowSeq1Double, HAS_CONTAINER_KEYS, "{ ? [a, b]: c , ? [a, b]: c }" , - "{? [a, b] : c,? [a, b]: c}" + "{? [a,b]: c,? [a,b]: c}" , "+STR\n" "+DOC\n" @@ -313,7 +313,7 @@ ENGINE_TEST(QmrkFlowSeq1Anchor, HAS_CONTAINER_KEYS, "{ ? &anchor [a, b]: c , }" , - "{? &anchor [a, b] : c}" + "{? &anchor [a,b]: c}" , "+STR\n" "+DOC\n" @@ -345,7 +345,7 @@ ENGINE_TEST(QmrkFlowSeq1Tag, HAS_CONTAINER_KEYS, "{ ? !tag [a, b]: c , }" , - "{? !tag [a, b] : c}" + "{? !tag [a,b]: c}" , "+STR\n" "+DOC\n" @@ -377,7 +377,7 @@ ENGINE_TEST(QmrkFlow1Map, HAS_CONTAINER_KEYS, "{ ? {a: b}: c , }" , - "{? {a: b} : c}" + "{? {a: b}: c}" , "+STR\n" "+DOC\n" @@ -408,7 +408,7 @@ ENGINE_TEST(QmrkFlow1MapAnchor, HAS_CONTAINER_KEYS, "{ ? &anchor {a: b}: c , }" , - "{? &anchor {a: b} : c}" + "{? &anchor {a: b}: c}" , "+STR\n" "+DOC\n" @@ -440,7 +440,7 @@ ENGINE_TEST(QmrkFlow1MapTag, HAS_CONTAINER_KEYS, "{ ? !tag {a: b}: c , }" , - "{? !tag {a: b} : c}" + "{? !tag {a: b}: c}" , "+STR\n" "+DOC\n" @@ -475,6 +475,10 @@ ENGINE_TEST(QmrkNestedSamelineTag0_00, HAS_CONTAINER_KEYS, "? ? &a !t" "\n" ": a" "\n" , + "?\n" + " &a !t : " "\n" + ": a" "\n" + , "+STR" "\n" "+DOC" "\n" "+MAP" "\n" @@ -490,7 +494,7 @@ ENGINE_TEST(QmrkNestedSamelineTag0_00, HAS_CONTAINER_KEYS, { ___(ps.begin_stream()); ___(ps.begin_doc()); - ___(ps.begin_map_key_block()); + ___(ps.begin_map_val_block()); ___(ps.begin_map_key_block()); ___(ps.set_key_anchor("a")); ___(ps.set_key_tag("!t")); @@ -508,6 +512,10 @@ ENGINE_TEST(QmrkNestedSamelineTag0_01, HAS_CONTAINER_KEYS, " ? &a !t" "\n" ": a" "\n" , + "? &a !t\n" + " &a !t : " "\n" + ": a" "\n" + , "+STR" "\n" "+DOC" "\n" "+MAP" "\n" @@ -523,7 +531,7 @@ ENGINE_TEST(QmrkNestedSamelineTag0_01, HAS_CONTAINER_KEYS, { ___(ps.begin_stream()); ___(ps.begin_doc()); - ___(ps.begin_map_key_block()); + ___(ps.begin_map_val_block()); ___(ps.set_key_anchor("a")); ___(ps.set_key_tag("!t")); ___(ps.begin_map_key_block()); @@ -542,6 +550,10 @@ ENGINE_TEST(QmrkNestedSamelineTag0_02, HAS_CONTAINER_KEYS, "? &a !t ? &a !t" "\n" ": a" "\n" , + "? &a !t\n" + " &a !t : " "\n" + ": a" "\n" + , "+STR" "\n" "+DOC" "\n" "+MAP" "\n" @@ -557,7 +569,7 @@ ENGINE_TEST(QmrkNestedSamelineTag0_02, HAS_CONTAINER_KEYS, { ___(ps.begin_stream()); ___(ps.begin_doc()); - ___(ps.begin_map_key_block()); + ___(ps.begin_map_val_block()); ___(ps.set_key_anchor("a")); ___(ps.set_key_tag("!t")); ___(ps.begin_map_key_block()); @@ -615,11 +627,14 @@ ENGINE_TEST(QmrkNestedSamelineTag0_03, ENGINE_TEST(MapKeyBlock4Plain1_0, HAS_CONTAINER_KEYS, - "\n" "? &mapanchor\n" " foo : bar\n" ": baz\n" , + "? &mapanchor\n" + " foo: bar\n" + ": baz\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -652,6 +667,10 @@ ENGINE_TEST(MapKeyBlock4Plain1_0_tag, " foo : bar\n" ": baz\n" , + "? !maptag\n" + " foo: bar\n" + ": baz\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -684,6 +703,10 @@ ENGINE_TEST(MapKeyBlock4Plain1_1, " &keyanchor foo : bar\n" ": baz\n" , + "?\n" + " &keyanchor foo: bar\n" + ": baz\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -715,6 +738,10 @@ ENGINE_TEST(MapKeyBlock4Plain1_2, "? &keyanchor foo : bar\n" ": baz\n" , + "?\n" + " &keyanchor foo: bar\n" + ": baz\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -749,6 +776,10 @@ ENGINE_TEST(MapKeyBlock4Ref1_0, " *ref : bar\n" ": baz\n" , + "? &mapanchor\n" + " *ref : bar\n" + ": baz\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -815,7 +846,6 @@ ENGINE_TEST(MapKeyBlock5AllPlain, ENGINE_TEST(MapKeyBlock5AllSquo, HAS_CONTAINER_KEYS, - "\n" "? &mapanchor !maptag\n" " &keyanchor !keytag 'foo': bar\n" ": baz\n" @@ -851,7 +881,6 @@ ENGINE_TEST(MapKeyBlock5AllSquo, ENGINE_TEST(MapKeyBlock5AllDquo, HAS_CONTAINER_KEYS, - "\n" "? &mapanchor !maptag\n" " &keyanchor !keytag \"foo\": bar\n" ": baz\n" @@ -974,6 +1003,10 @@ ENGINE_TEST(MapKeyBlock6_0_flowseq, "&ma !mt\n" "&ka0 !kt0 []: b\n" , + "&ma !mt\n" + "? &ka0 !kt0 []\n" + ": b\n" + , "+STR\n" "+DOC\n" "+MAP &ma \n" @@ -1004,6 +1037,10 @@ ENGINE_TEST(MapKeyBlock6_0_flowmap, "&ma !mt\n" "&ka1 !kt1 {}: c\n" , + "&ma !mt\n" + "? &ka1 !kt1 {}\n" + ": c\n" + , "+STR\n" "+DOC\n" "+MAP &ma \n" @@ -1143,7 +1180,8 @@ ENGINE_TEST(MapKeyBlock6_1_flowseq, "&ka !kt []: b\n" , "&ma !mt : \n" - "&ka !kt []: b\n" + "? &ka !kt []\n" + ": b\n" , "+STR\n" "+DOC\n" @@ -1181,7 +1219,8 @@ ENGINE_TEST(MapKeyBlock6_1_flowmap, "&ka !kt {}: b\n" , "&ma !mt : \n" - "&ka !kt {}: b\n" + "? &ka !kt {}\n" + ": b\n" , "+STR\n" "+DOC\n" @@ -1337,7 +1376,8 @@ ENGINE_TEST(MapKeyBlock6_2_flowseq, "&ka !kt []: b\n" , "&ma !mt : &va !vt \n" - "&ka !kt []: b\n" + "? &ka !kt []\n" + ": b\n" , "+STR\n" "+DOC\n" @@ -1378,7 +1418,8 @@ ENGINE_TEST(MapKeyBlock6_2_flowmap, "&ka !kt {}: b\n" , "&ma !mt : &va !vt \n" - "&ka !kt {}: b\n" + "? &ka !kt {}\n" + ": b\n" , "+STR\n" "+DOC\n" diff --git a/test/test_engine_6_qmrk_4.cpp b/test/test_engine_6_qmrk_4.cpp index 4383c702f..5f63f8aed 100644 --- a/test/test_engine_6_qmrk_4.cpp +++ b/test/test_engine_6_qmrk_4.cpp @@ -97,6 +97,9 @@ ENGINE_TEST(QmrkTestSuiteM2N8_01_seq, HAS_CONTAINER_KEYS, "? []" , + "? []\n" + ": \n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -150,6 +153,9 @@ ENGINE_TEST(QmrkTestSuiteM2N8_01_map, HAS_CONTAINER_KEYS, "? {}" , + "? {}\n" + ": \n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -203,6 +209,10 @@ ENGINE_TEST(QmrkTestSuiteM2N8_01_keyscalar, HAS_CONTAINER_KEYS, "? k: x" , + "?\n" + " k: x\n" + ": \n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -234,6 +244,10 @@ ENGINE_TEST(QmrkTestSuiteM2N8_01_keyscalar_colon, "? k: x\n" ":" , + "?\n" + " k: x\n" + ": \n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -265,6 +279,10 @@ ENGINE_TEST(QmrkTestSuiteM2N8_01_keyscalar_colon_y, "? k: x\n" ": y" , + "?\n" + " k: x\n" + ": y\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -295,6 +313,10 @@ ENGINE_TEST(QmrkTestSuiteM2N8_01_keyscalar2, HAS_CONTAINER_KEYS, "? k:" , + "?\n" + " k: \n" + ": \n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -326,6 +348,10 @@ ENGINE_TEST(QmrkTestSuiteM2N8_01_keyscalar2_colon, "? k:\n" ":" , + "?\n" + " k: \n" + ": \n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -357,6 +383,10 @@ ENGINE_TEST(QmrkTestSuiteM2N8_01_keyscalar2_colon_x, "? k:\n" ": x" , + "?\n" + " k: \n" + ": x\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -387,6 +417,11 @@ ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseq0_0, HAS_CONTAINER_KEYS, "? []: x" , + "?\n" + " ? []\n" + " : x\n" + ": \n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -420,6 +455,11 @@ ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseq0_0_colon, "? []: x" "\n" ":" , + "?\n" + " ? []\n" + " : x" "\n" + ": \n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -453,6 +493,11 @@ ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseq0_0_colon_y, "? []: x" "\n" ": y" , + "?\n" + " ? []\n" + " : x" "\n" + ": y\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -483,7 +528,12 @@ ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseq0_0_colon_y, ENGINE_TEST(QmrkTestSuiteM2N8_01_keymap0_0, HAS_CONTAINER_KEYS, - "? {}: x" + "? {}: x" + , + "?\n" + " ? {}\n" + " : x\n" + ": \n" , "+STR\n" "+DOC\n" @@ -518,6 +568,11 @@ ENGINE_TEST(QmrkTestSuiteM2N8_01_keymap0_0_colon, "? {}: x" "\n" ":" , + "?\n" + " ? {}\n" + " : x" "\n" + ": \n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -551,6 +606,11 @@ ENGINE_TEST(QmrkTestSuiteM2N8_01_keymap0_0_colon_y, "? {}: x" "\n" ": y" , + "?\n" + " ? {}\n" + " : x" "\n" + ": y\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -584,6 +644,11 @@ ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseq0_1, HAS_CONTAINER_KEYS, "? [a]: x" , + "?\n" + " ? [a]\n" + " : x\n" + ": \n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -619,6 +684,11 @@ ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseq0_1_colon, "? [a]: x" "\n" ":" , + "?\n" + " ? [a]\n" + " : x" "\n" + ": \n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -654,6 +724,11 @@ ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseq0_1_colon_y, "? [a]: x" "\n" ": y" , + "?\n" + " ? [a]\n" + " : x" "\n" + ": y\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -689,6 +764,11 @@ ENGINE_TEST(QmrkTestSuiteM2N8_01_keymap0_1, HAS_CONTAINER_KEYS, "? {a}: x" , + "?\n" + " ? {a: }\n" + " : x\n" + ": \n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -726,6 +806,11 @@ ENGINE_TEST(QmrkTestSuiteM2N8_01_keymap0_1_colon, "? {a}: x" "\n" ":" , + "?\n" + " ? {a: }\n" + " : x" "\n" + ": \n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -763,6 +848,11 @@ ENGINE_TEST(QmrkTestSuiteM2N8_01_keymap0_1_colon_y, "? {a}: x" "\n" ": y" , + "?\n" + " ? {a: }\n" + " : x" "\n" + ": y\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -799,6 +889,11 @@ ENGINE_TEST(QmrkTestSuiteM2N8_01_keymap0_1_1, HAS_CONTAINER_KEYS, "? {a: }: x" , + "?\n" + " ? {a: }\n" + " : x\n" + ": \n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -836,6 +931,11 @@ ENGINE_TEST(QmrkTestSuiteM2N8_01_keymap0_1_1_colon, "? {a: }: x" "\n" ":" , + "?\n" + " ? {a: }\n" + " : x" "\n" + ": \n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -873,6 +973,11 @@ ENGINE_TEST(QmrkTestSuiteM2N8_01_keymap0_1_1_colon_y, "? {a: }: x" "\n" ": y" , + "?\n" + " ? {a: }\n" + " : x" "\n" + ": y\n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -909,6 +1014,11 @@ ENGINE_TEST(QmrkTestSuiteM2N8_01_keymap0_1_2, HAS_CONTAINER_KEYS, "? {a: b}: x" , + "?\n" + " ? {a: b}\n" + " : x\n" + ": \n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -946,6 +1056,11 @@ ENGINE_TEST(QmrkTestSuiteM2N8_01_keymap0_1_2_colon, "? {a: b}: x" "\n" ":" , + "?\n" + " ? {a: b}\n" + " : x" "\n" + ": \n" + , "+STR\n" "+DOC\n" "+MAP\n" @@ -983,220 +1098,10 @@ ENGINE_TEST(QmrkTestSuiteM2N8_01_keymap0_1_2_colon_y, "? {a: b}: x" "\n" ": y" , - "+STR\n" - "+DOC\n" - "+MAP\n" - "+MAP\n" - "+MAP {}\n" - "=VAL :a\n" - "=VAL :b\n" - "-MAP\n" - "=VAL :x\n" - "-MAP\n" - "=VAL :y\n" - "-MAP\n" - "-DOC\n" - "-STR\n" -) -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.begin_map_val_block()); - ___(ps.begin_map_key_block()); - ___(ps.begin_map_key_flow()); - ___(ps.set_key_scalar_plain("a")); - ___(ps.set_val_scalar_plain("b")); - ___(ps.end_map_flow(singleline)); - ___(ps.set_val_scalar_plain("x")); - ___(ps.end_map_block()); - ___(ps.set_val_scalar_plain("y")); - ___(ps.end_map_block()); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - - -ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseq0_2, - HAS_CONTAINER_KEYS, - "? [a,]: x" - , - "+STR\n" - "+DOC\n" - "+MAP\n" - "+MAP\n" - "+SEQ []\n" - "=VAL :a\n" - "-SEQ\n" - "=VAL :x\n" - "-MAP\n" - "=VAL :\n" - "-MAP\n" - "-DOC\n" - "-STR\n" -) -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.begin_map_val_block()); - ___(ps.begin_map_key_block()); - ___(ps.begin_seq_key_flow()); - ___(ps.set_val_scalar_plain("a")); - ___(ps.end_seq_flow(singleline)); - ___(ps.set_val_scalar_plain("x")); - ___(ps.end_map_block()); - ___(ps.set_val_scalar_plain_empty()); - ___(ps.end_map_block()); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseq0_2_colon, - HAS_CONTAINER_KEYS, - "? [a,]: x" "\n" - ":" - , - "+STR\n" - "+DOC\n" - "+MAP\n" - "+MAP\n" - "+SEQ []\n" - "=VAL :a\n" - "-SEQ\n" - "=VAL :x\n" - "-MAP\n" - "=VAL :\n" - "-MAP\n" - "-DOC\n" - "-STR\n" -) -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.begin_map_val_block()); - ___(ps.begin_map_key_block()); - ___(ps.begin_seq_key_flow()); - ___(ps.set_val_scalar_plain("a")); - ___(ps.end_seq_flow(singleline)); - ___(ps.set_val_scalar_plain("x")); - ___(ps.end_map_block()); - ___(ps.set_val_scalar_plain_empty()); - ___(ps.end_map_block()); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseq0_2_colon_y, - HAS_CONTAINER_KEYS, - "? [a,]: x" "\n" - ": y" - , - "+STR\n" - "+DOC\n" - "+MAP\n" - "+MAP\n" - "+SEQ []\n" - "=VAL :a\n" - "-SEQ\n" - "=VAL :x\n" - "-MAP\n" - "=VAL :y\n" - "-MAP\n" - "-DOC\n" - "-STR\n" -) -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.begin_map_val_block()); - ___(ps.begin_map_key_block()); - ___(ps.begin_seq_key_flow()); - ___(ps.set_val_scalar_plain("a")); - ___(ps.end_seq_flow(singleline)); - ___(ps.set_val_scalar_plain("x")); - ___(ps.end_map_block()); - ___(ps.set_val_scalar_plain("y")); - ___(ps.end_map_block()); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(QmrkTestSuiteM2N8_01_keymap0_2, - HAS_CONTAINER_KEYS, - "? {a: b, }: x" - , - "+STR\n" - "+DOC\n" - "+MAP\n" - "+MAP\n" - "+MAP {}\n" - "=VAL :a\n" - "=VAL :b\n" - "-MAP\n" - "=VAL :x\n" - "-MAP\n" - "=VAL :\n" - "-MAP\n" - "-DOC\n" - "-STR\n" -) -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.begin_map_val_block()); - ___(ps.begin_map_key_block()); - ___(ps.begin_map_key_flow()); - ___(ps.set_key_scalar_plain("a")); - ___(ps.set_val_scalar_plain("b")); - ___(ps.end_map_flow(singleline)); - ___(ps.set_val_scalar_plain("x")); - ___(ps.end_map_block()); - ___(ps.set_val_scalar_plain_empty()); - ___(ps.end_map_block()); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(QmrkTestSuiteM2N8_01_keymap0_2_colon, - HAS_CONTAINER_KEYS, - "? {a: b, }: x" "\n" - ":" - , - "+STR\n" - "+DOC\n" - "+MAP\n" - "+MAP\n" - "+MAP {}\n" - "=VAL :a\n" - "=VAL :b\n" - "-MAP\n" - "=VAL :x\n" - "-MAP\n" - "=VAL :\n" - "-MAP\n" - "-DOC\n" - "-STR\n" -) -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.begin_map_val_block()); - ___(ps.begin_map_key_block()); - ___(ps.begin_map_key_flow()); - ___(ps.set_key_scalar_plain("a")); - ___(ps.set_val_scalar_plain("b")); - ___(ps.end_map_flow(singleline)); - ___(ps.set_val_scalar_plain("x")); - ___(ps.end_map_block()); - ___(ps.set_val_scalar_plain_empty()); - ___(ps.end_map_block()); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(QmrkTestSuiteM2N8_01_keymap0_2_colon_y, - HAS_CONTAINER_KEYS, - "? {a: b, }: x" "\n" - ": y" + "?\n" + " ? {a: b}\n" + " : x" "\n" + ": y\n" , "+STR\n" "+DOC\n" @@ -1230,616 +1135,6 @@ ENGINE_TEST(QmrkTestSuiteM2N8_01_keymap0_2_colon_y, ___(ps.end_stream()); } -ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseq0_3, - HAS_CONTAINER_KEYS, - "? [a, b]: x" - , - "+STR\n" - "+DOC\n" - "+MAP\n" - "+MAP\n" - "+SEQ []\n" - "=VAL :a\n" - "=VAL :b\n" - "-SEQ\n" - "=VAL :x\n" - "-MAP\n" - "=VAL :\n" - "-MAP\n" - "-DOC\n" - "-STR\n" -) -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.begin_map_val_block()); - ___(ps.begin_map_key_block()); - ___(ps.begin_seq_key_flow()); - ___(ps.set_val_scalar_plain("a")); - ___(ps.add_sibling()); - ___(ps.set_val_scalar_plain("b")); - ___(ps.end_seq_flow(singleline)); - ___(ps.set_val_scalar_plain("x")); - ___(ps.end_map_block()); - ___(ps.set_val_scalar_plain_empty()); - ___(ps.end_map_block()); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseq0_3_colon, - HAS_CONTAINER_KEYS, - "? [a, b]: x" "\n" - ":" - , - "+STR\n" - "+DOC\n" - "+MAP\n" - "+MAP\n" - "+SEQ []\n" - "=VAL :a\n" - "=VAL :b\n" - "-SEQ\n" - "=VAL :x\n" - "-MAP\n" - "=VAL :\n" - "-MAP\n" - "-DOC\n" - "-STR\n" -) -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.begin_map_val_block()); - ___(ps.begin_map_key_block()); - ___(ps.begin_seq_key_flow()); - ___(ps.set_val_scalar_plain("a")); - ___(ps.add_sibling()); - ___(ps.set_val_scalar_plain("b")); - ___(ps.end_seq_flow(singleline)); - ___(ps.set_val_scalar_plain("x")); - ___(ps.end_map_block()); - ___(ps.set_val_scalar_plain_empty()); - ___(ps.end_map_block()); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseq0_3_colon_y, - HAS_CONTAINER_KEYS, - "? [a, b]: x" "\n" - ": y" - , - "+STR\n" - "+DOC\n" - "+MAP\n" - "+MAP\n" - "+SEQ []\n" - "=VAL :a\n" - "=VAL :b\n" - "-SEQ\n" - "=VAL :x\n" - "-MAP\n" - "=VAL :y\n" - "-MAP\n" - "-DOC\n" - "-STR\n" -) -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.begin_map_val_block()); - ___(ps.begin_map_key_block()); - ___(ps.begin_seq_key_flow()); - ___(ps.set_val_scalar_plain("a")); - ___(ps.add_sibling()); - ___(ps.set_val_scalar_plain("b")); - ___(ps.end_seq_flow(singleline)); - ___(ps.set_val_scalar_plain("x")); - ___(ps.end_map_block()); - ___(ps.set_val_scalar_plain("y")); - ___(ps.end_map_block()); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(QmrkTestSuiteM2N8_01_keymap0_3, - HAS_CONTAINER_KEYS, - "? {a: b, c: d}: x" - , - "+STR\n" - "+DOC\n" - "+MAP\n" - "+MAP\n" - "+MAP {}\n" - "=VAL :a\n" - "=VAL :b\n" - "=VAL :c\n" - "=VAL :d\n" - "-MAP\n" - "=VAL :x\n" - "-MAP\n" - "=VAL :\n" - "-MAP\n" - "-DOC\n" - "-STR\n" -) -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.begin_map_val_block()); - ___(ps.begin_map_key_block()); - ___(ps.begin_map_key_flow()); - ___(ps.set_key_scalar_plain("a")); - ___(ps.set_val_scalar_plain("b")); - ___(ps.add_sibling()); - ___(ps.set_key_scalar_plain("c")); - ___(ps.set_val_scalar_plain("d")); - ___(ps.end_map_flow(singleline)); - ___(ps.set_val_scalar_plain("x")); - ___(ps.end_map_block()); - ___(ps.set_val_scalar_plain_empty()); - ___(ps.end_map_block()); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(QmrkTestSuiteM2N8_01_keymap0_3_colon, - HAS_CONTAINER_KEYS, - "? {a: b, c: d}: x" "\n" - ":" - , - "+STR\n" - "+DOC\n" - "+MAP\n" - "+MAP\n" - "+MAP {}\n" - "=VAL :a\n" - "=VAL :b\n" - "=VAL :c\n" - "=VAL :d\n" - "-MAP\n" - "=VAL :x\n" - "-MAP\n" - "=VAL :\n" - "-MAP\n" - "-DOC\n" - "-STR\n" -) -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.begin_map_val_block()); - ___(ps.begin_map_key_block()); - ___(ps.begin_map_key_flow()); - ___(ps.set_key_scalar_plain("a")); - ___(ps.set_val_scalar_plain("b")); - ___(ps.add_sibling()); - ___(ps.set_key_scalar_plain("c")); - ___(ps.set_val_scalar_plain("d")); - ___(ps.end_map_flow(singleline)); - ___(ps.set_val_scalar_plain("x")); - ___(ps.end_map_block()); - ___(ps.set_val_scalar_plain_empty()); - ___(ps.end_map_block()); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(QmrkTestSuiteM2N8_01_keymap0_3_colon_y, - HAS_CONTAINER_KEYS, - "? {a: b, c: d}: x" "\n" - ": y" - , - "+STR\n" - "+DOC\n" - "+MAP\n" - "+MAP\n" - "+MAP {}\n" - "=VAL :a\n" - "=VAL :b\n" - "=VAL :c\n" - "=VAL :d\n" - "-MAP\n" - "=VAL :x\n" - "-MAP\n" - "=VAL :y\n" - "-MAP\n" - "-DOC\n" - "-STR\n" -) -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.begin_map_val_block()); - ___(ps.begin_map_key_block()); - ___(ps.begin_map_key_flow()); - ___(ps.set_key_scalar_plain("a")); - ___(ps.set_val_scalar_plain("b")); - ___(ps.add_sibling()); - ___(ps.set_key_scalar_plain("c")); - ___(ps.set_val_scalar_plain("d")); - ___(ps.end_map_flow(singleline)); - ___(ps.set_val_scalar_plain("x")); - ___(ps.end_map_block()); - ___(ps.set_val_scalar_plain("y")); - ___(ps.end_map_block()); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - - -//----------------------------------------------------------------------------- - -ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseqmap0_1, - HAS_CONTAINER_KEYS, - "? [a: b]: x" - , - "+STR\n" - "+DOC\n" - "+MAP\n" - "+MAP\n" - "+SEQ []\n" - "+MAP {}\n" - "=VAL :a\n" - "=VAL :b\n" - "-MAP\n" - "-SEQ\n" - "=VAL :x\n" - "-MAP\n" - "=VAL :\n" - "-MAP\n" - "-DOC\n" - "-STR\n" -) -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.begin_map_val_block()); - ___(ps.begin_map_key_block()); - ___(ps.begin_seq_key_flow()); - ___(ps.begin_map_key_flow()); - ___(ps.set_key_scalar_plain("a")); - ___(ps.set_val_scalar_plain("b")); - ___(ps.end_map_flow(singleline)); - ___(ps.end_seq_flow(singleline)); - ___(ps.set_val_scalar_plain("x")); - ___(ps.end_map_block()); - ___(ps.set_val_scalar_plain_empty()); - ___(ps.end_map_block()); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseqmap0_1_colon, - HAS_CONTAINER_KEYS, - "? [a: b]: x" "\n" - ":" - , - "+STR\n" - "+DOC\n" - "+MAP\n" - "+MAP\n" - "+SEQ []\n" - "+MAP {}\n" - "=VAL :a\n" - "=VAL :b\n" - "-MAP\n" - "-SEQ\n" - "=VAL :x\n" - "-MAP\n" - "=VAL :\n" - "-MAP\n" - "-DOC\n" - "-STR\n" -) -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.begin_map_val_block()); - ___(ps.begin_map_key_block()); - ___(ps.begin_seq_key_flow()); - ___(ps.begin_map_key_flow()); - ___(ps.set_key_scalar_plain("a")); - ___(ps.set_val_scalar_plain("b")); - ___(ps.end_map_flow(singleline)); - ___(ps.end_seq_flow(singleline)); - ___(ps.set_val_scalar_plain("x")); - ___(ps.end_map_block()); - ___(ps.set_val_scalar_plain_empty()); - ___(ps.end_map_block()); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseqmap0_1_colon_y, - HAS_CONTAINER_KEYS, - "? [a: b]: x" "\n" - ": y" - , - "+STR\n" - "+DOC\n" - "+MAP\n" - "+MAP\n" - "+SEQ []\n" - "+MAP {}\n" - "=VAL :a\n" - "=VAL :b\n" - "-MAP\n" - "-SEQ\n" - "=VAL :x\n" - "-MAP\n" - "=VAL :y\n" - "-MAP\n" - "-DOC\n" - "-STR\n" -) -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.begin_map_val_block()); - ___(ps.begin_map_key_block()); - ___(ps.begin_seq_key_flow()); - ___(ps.begin_map_key_flow()); - ___(ps.set_key_scalar_plain("a")); - ___(ps.set_val_scalar_plain("b")); - ___(ps.end_map_flow(singleline)); - ___(ps.end_seq_flow(singleline)); - ___(ps.set_val_scalar_plain("x")); - ___(ps.end_map_block()); - ___(ps.set_val_scalar_plain("y")); - ___(ps.end_map_block()); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseqmap0_2, - HAS_CONTAINER_KEYS, - "? [a: ]: x" - , - "+STR\n" - "+DOC\n" - "+MAP\n" - "+MAP\n" - "+SEQ []\n" - "+MAP {}\n" - "=VAL :a\n" - "=VAL :\n" - "-MAP\n" - "-SEQ\n" - "=VAL :x\n" - "-MAP\n" - "=VAL :\n" - "-MAP\n" - "-DOC\n" - "-STR\n" -) -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.begin_map_val_block()); - ___(ps.begin_map_key_block()); - ___(ps.begin_seq_key_flow()); - ___(ps.begin_map_key_flow()); - ___(ps.set_key_scalar_plain("a")); - ___(ps.set_val_scalar_plain_empty()); - ___(ps.end_map_flow(singleline)); - ___(ps.end_seq_flow(singleline)); - ___(ps.set_val_scalar_plain("x")); - ___(ps.end_map_block()); - ___(ps.set_val_scalar_plain_empty()); - ___(ps.end_map_block()); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseqmap0_2_colon, - HAS_CONTAINER_KEYS, - "? [a: ]: x" "\n" - ":" - , - "+STR\n" - "+DOC\n" - "+MAP\n" - "+MAP\n" - "+SEQ []\n" - "+MAP {}\n" - "=VAL :a\n" - "=VAL :\n" - "-MAP\n" - "-SEQ\n" - "=VAL :x\n" - "-MAP\n" - "=VAL :\n" - "-MAP\n" - "-DOC\n" - "-STR\n" -) -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.begin_map_val_block()); - ___(ps.begin_map_key_block()); - ___(ps.begin_seq_key_flow()); - ___(ps.begin_map_key_flow()); - ___(ps.set_key_scalar_plain("a")); - ___(ps.set_val_scalar_plain_empty()); - ___(ps.end_map_flow(singleline)); - ___(ps.end_seq_flow(singleline)); - ___(ps.set_val_scalar_plain("x")); - ___(ps.end_map_block()); - ___(ps.set_val_scalar_plain_empty()); - ___(ps.end_map_block()); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseqmap0_2_colon_y, - HAS_CONTAINER_KEYS, - "? [a: ]: x" "\n" - ": y" - , - "+STR\n" - "+DOC\n" - "+MAP\n" - "+MAP\n" - "+SEQ []\n" - "+MAP {}\n" - "=VAL :a\n" - "=VAL :\n" - "-MAP\n" - "-SEQ\n" - "=VAL :x\n" - "-MAP\n" - "=VAL :y\n" - "-MAP\n" - "-DOC\n" - "-STR\n" -) -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.begin_map_val_block()); - ___(ps.begin_map_key_block()); - ___(ps.begin_seq_key_flow()); - ___(ps.begin_map_key_flow()); - ___(ps.set_key_scalar_plain("a")); - ___(ps.set_val_scalar_plain_empty()); - ___(ps.end_map_flow(singleline)); - ___(ps.end_seq_flow(singleline)); - ___(ps.set_val_scalar_plain("x")); - ___(ps.end_map_block()); - ___(ps.set_val_scalar_plain("y")); - ___(ps.end_map_block()); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - - -ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseqmap0_3, - HAS_CONTAINER_KEYS, - "? [a: b, ]: x" - , - "+STR\n" - "+DOC\n" - "+MAP\n" - "+MAP\n" - "+SEQ []\n" - "+MAP {}\n" - "=VAL :a\n" - "=VAL :b\n" - "-MAP\n" - "-SEQ\n" - "=VAL :x\n" - "-MAP\n" - "=VAL :\n" - "-MAP\n" - "-DOC\n" - "-STR\n" -) -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.begin_map_val_block()); - ___(ps.begin_map_key_block()); - ___(ps.begin_seq_key_flow()); - ___(ps.begin_map_key_flow()); - ___(ps.set_key_scalar_plain("a")); - ___(ps.set_val_scalar_plain("b")); - ___(ps.end_map_flow(singleline)); - ___(ps.end_seq_flow(singleline)); - ___(ps.set_val_scalar_plain("x")); - ___(ps.end_map_block()); - ___(ps.set_val_scalar_plain_empty()); - ___(ps.end_map_block()); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseqmap0_3_colon, - HAS_CONTAINER_KEYS, - "? [a: b, ]: x" "\n" - ":" - , - "+STR\n" - "+DOC\n" - "+MAP\n" - "+MAP\n" - "+SEQ []\n" - "+MAP {}\n" - "=VAL :a\n" - "=VAL :b\n" - "-MAP\n" - "-SEQ\n" - "=VAL :x\n" - "-MAP\n" - "=VAL :\n" - "-MAP\n" - "-DOC\n" - "-STR\n" -) -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.begin_map_val_block()); - ___(ps.begin_map_key_block()); - ___(ps.begin_seq_key_flow()); - ___(ps.begin_map_key_flow()); - ___(ps.set_key_scalar_plain("a")); - ___(ps.set_val_scalar_plain("b")); - ___(ps.end_map_flow(singleline)); - ___(ps.end_seq_flow(singleline)); - ___(ps.set_val_scalar_plain("x")); - ___(ps.end_map_block()); - ___(ps.set_val_scalar_plain_empty()); - ___(ps.end_map_block()); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - -ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseqmap0_3_colon_y, - HAS_CONTAINER_KEYS, - "? [a: b, ]: x" "\n" - ": y" - , - "+STR\n" - "+DOC\n" - "+MAP\n" - "+MAP\n" - "+SEQ []\n" - "+MAP {}\n" - "=VAL :a\n" - "=VAL :b\n" - "-MAP\n" - "-SEQ\n" - "=VAL :x\n" - "-MAP\n" - "=VAL :y\n" - "-MAP\n" - "-DOC\n" - "-STR\n" -) -{ - ___(ps.begin_stream()); - ___(ps.begin_doc()); - ___(ps.begin_map_val_block()); - ___(ps.begin_map_key_block()); - ___(ps.begin_seq_key_flow()); - ___(ps.begin_map_key_flow()); - ___(ps.set_key_scalar_plain("a")); - ___(ps.set_val_scalar_plain("b")); - ___(ps.end_map_flow(singleline)); - ___(ps.end_seq_flow(singleline)); - ___(ps.set_val_scalar_plain("x")); - ___(ps.end_map_block()); - ___(ps.set_val_scalar_plain("y")); - ___(ps.end_map_block()); - ___(ps.end_doc()); - ___(ps.end_stream()); -} - - - } // namespace yml } // namespace c4 diff --git a/test/test_engine_6_qmrk_5.cpp b/test/test_engine_6_qmrk_5.cpp new file mode 100644 index 000000000..9210f672f --- /dev/null +++ b/test/test_engine_6_qmrk_5.cpp @@ -0,0 +1,967 @@ +#include "./test_lib/test_engine.hpp" +C4_SUPPRESS_WARNING_MSVC_WITH_PUSH(4702) + +// WARNING: don't use raw string literals -- g++4.8 cannot accept them +// as macro arguments + +RYML_DEFINE_TEST_MAIN() + +namespace c4 { +namespace yml { + + +//static constexpr const bool multiline = true; +static constexpr const bool singleline = false; + + +ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseq0_2, + HAS_CONTAINER_KEYS, + "? [a,]: x" + , + "?\n" + " ? [a]\n" + " : x\n" + ": \n" + , + "+STR\n" + "+DOC\n" + "+MAP\n" + "+MAP\n" + "+SEQ []\n" + "=VAL :a\n" + "-SEQ\n" + "=VAL :x\n" + "-MAP\n" + "=VAL :\n" + "-MAP\n" + "-DOC\n" + "-STR\n" +) +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.begin_map_val_block()); + ___(ps.begin_map_key_block()); + ___(ps.begin_seq_key_flow()); + ___(ps.set_val_scalar_plain("a")); + ___(ps.end_seq_flow(singleline)); + ___(ps.set_val_scalar_plain("x")); + ___(ps.end_map_block()); + ___(ps.set_val_scalar_plain_empty()); + ___(ps.end_map_block()); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseq0_2_colon, + HAS_CONTAINER_KEYS, + "?\n" + " ? [a]\n" + " : x" "\n" + ": \n" + , + "+STR\n" + "+DOC\n" + "+MAP\n" + "+MAP\n" + "+SEQ []\n" + "=VAL :a\n" + "-SEQ\n" + "=VAL :x\n" + "-MAP\n" + "=VAL :\n" + "-MAP\n" + "-DOC\n" + "-STR\n" +) +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.begin_map_val_block()); + ___(ps.begin_map_key_block()); + ___(ps.begin_seq_key_flow()); + ___(ps.set_val_scalar_plain("a")); + ___(ps.end_seq_flow(singleline)); + ___(ps.set_val_scalar_plain("x")); + ___(ps.end_map_block()); + ___(ps.set_val_scalar_plain_empty()); + ___(ps.end_map_block()); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseq0_2_colon_y, + HAS_CONTAINER_KEYS, + "? [a,]: x" "\n" + ": y" + , + "?\n" + " ? [a]\n" + " : x" "\n" + ": y\n" + , + "+STR\n" + "+DOC\n" + "+MAP\n" + "+MAP\n" + "+SEQ []\n" + "=VAL :a\n" + "-SEQ\n" + "=VAL :x\n" + "-MAP\n" + "=VAL :y\n" + "-MAP\n" + "-DOC\n" + "-STR\n" +) +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.begin_map_val_block()); + ___(ps.begin_map_key_block()); + ___(ps.begin_seq_key_flow()); + ___(ps.set_val_scalar_plain("a")); + ___(ps.end_seq_flow(singleline)); + ___(ps.set_val_scalar_plain("x")); + ___(ps.end_map_block()); + ___(ps.set_val_scalar_plain("y")); + ___(ps.end_map_block()); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(QmrkTestSuiteM2N8_01_keymap0_2, + HAS_CONTAINER_KEYS, + "? {a: b, }: x" + , + "?\n" + " ? {a: b}\n" + " : x\n" + ": \n" + , + "+STR\n" + "+DOC\n" + "+MAP\n" + "+MAP\n" + "+MAP {}\n" + "=VAL :a\n" + "=VAL :b\n" + "-MAP\n" + "=VAL :x\n" + "-MAP\n" + "=VAL :\n" + "-MAP\n" + "-DOC\n" + "-STR\n" +) +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.begin_map_val_block()); + ___(ps.begin_map_key_block()); + ___(ps.begin_map_key_flow()); + ___(ps.set_key_scalar_plain("a")); + ___(ps.set_val_scalar_plain("b")); + ___(ps.end_map_flow(singleline)); + ___(ps.set_val_scalar_plain("x")); + ___(ps.end_map_block()); + ___(ps.set_val_scalar_plain_empty()); + ___(ps.end_map_block()); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(QmrkTestSuiteM2N8_01_keymap0_2_colon, + HAS_CONTAINER_KEYS, + "? {a: b, }: x" "\n" + ":" + , + "?\n" + " ? {a: b}\n" + " : x" "\n" + ": \n" + , + "+STR\n" + "+DOC\n" + "+MAP\n" + "+MAP\n" + "+MAP {}\n" + "=VAL :a\n" + "=VAL :b\n" + "-MAP\n" + "=VAL :x\n" + "-MAP\n" + "=VAL :\n" + "-MAP\n" + "-DOC\n" + "-STR\n" +) +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.begin_map_val_block()); + ___(ps.begin_map_key_block()); + ___(ps.begin_map_key_flow()); + ___(ps.set_key_scalar_plain("a")); + ___(ps.set_val_scalar_plain("b")); + ___(ps.end_map_flow(singleline)); + ___(ps.set_val_scalar_plain("x")); + ___(ps.end_map_block()); + ___(ps.set_val_scalar_plain_empty()); + ___(ps.end_map_block()); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(QmrkTestSuiteM2N8_01_keymap0_2_colon_y, + HAS_CONTAINER_KEYS, + "? {a: b, }: x" "\n" + ": y" + , + "?\n" + " ? {a: b}\n" + " : x" "\n" + ": y\n" + , + "+STR\n" + "+DOC\n" + "+MAP\n" + "+MAP\n" + "+MAP {}\n" + "=VAL :a\n" + "=VAL :b\n" + "-MAP\n" + "=VAL :x\n" + "-MAP\n" + "=VAL :y\n" + "-MAP\n" + "-DOC\n" + "-STR\n" +) +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.begin_map_val_block()); + ___(ps.begin_map_key_block()); + ___(ps.begin_map_key_flow()); + ___(ps.set_key_scalar_plain("a")); + ___(ps.set_val_scalar_plain("b")); + ___(ps.end_map_flow(singleline)); + ___(ps.set_val_scalar_plain("x")); + ___(ps.end_map_block()); + ___(ps.set_val_scalar_plain("y")); + ___(ps.end_map_block()); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseq0_3, + HAS_CONTAINER_KEYS, + "? [a, b]: x" + , + "?\n" + " ? [a,b]\n" + " : x\n" + ": \n" + , + "+STR\n" + "+DOC\n" + "+MAP\n" + "+MAP\n" + "+SEQ []\n" + "=VAL :a\n" + "=VAL :b\n" + "-SEQ\n" + "=VAL :x\n" + "-MAP\n" + "=VAL :\n" + "-MAP\n" + "-DOC\n" + "-STR\n" +) +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.begin_map_val_block()); + ___(ps.begin_map_key_block()); + ___(ps.begin_seq_key_flow()); + ___(ps.set_val_scalar_plain("a")); + ___(ps.add_sibling()); + ___(ps.set_val_scalar_plain("b")); + ___(ps.end_seq_flow(singleline)); + ___(ps.set_val_scalar_plain("x")); + ___(ps.end_map_block()); + ___(ps.set_val_scalar_plain_empty()); + ___(ps.end_map_block()); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseq0_3_colon, + HAS_CONTAINER_KEYS, + "? [a, b]: x" "\n" + ":" + , + "?\n" + " ? [a,b]\n" + " : x" "\n" + ": \n" + , + "+STR\n" + "+DOC\n" + "+MAP\n" + "+MAP\n" + "+SEQ []\n" + "=VAL :a\n" + "=VAL :b\n" + "-SEQ\n" + "=VAL :x\n" + "-MAP\n" + "=VAL :\n" + "-MAP\n" + "-DOC\n" + "-STR\n" +) +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.begin_map_val_block()); + ___(ps.begin_map_key_block()); + ___(ps.begin_seq_key_flow()); + ___(ps.set_val_scalar_plain("a")); + ___(ps.add_sibling()); + ___(ps.set_val_scalar_plain("b")); + ___(ps.end_seq_flow(singleline)); + ___(ps.set_val_scalar_plain("x")); + ___(ps.end_map_block()); + ___(ps.set_val_scalar_plain_empty()); + ___(ps.end_map_block()); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseq0_3_colon_y, + HAS_CONTAINER_KEYS, + "? [a, b]: x" "\n" + ": y" + , + "?\n" + " ? [a,b]\n" + " : x" "\n" + ": y\n" + , + "+STR\n" + "+DOC\n" + "+MAP\n" + "+MAP\n" + "+SEQ []\n" + "=VAL :a\n" + "=VAL :b\n" + "-SEQ\n" + "=VAL :x\n" + "-MAP\n" + "=VAL :y\n" + "-MAP\n" + "-DOC\n" + "-STR\n" +) +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.begin_map_val_block()); + ___(ps.begin_map_key_block()); + ___(ps.begin_seq_key_flow()); + ___(ps.set_val_scalar_plain("a")); + ___(ps.add_sibling()); + ___(ps.set_val_scalar_plain("b")); + ___(ps.end_seq_flow(singleline)); + ___(ps.set_val_scalar_plain("x")); + ___(ps.end_map_block()); + ___(ps.set_val_scalar_plain("y")); + ___(ps.end_map_block()); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(QmrkTestSuiteM2N8_01_keymap0_3, + HAS_CONTAINER_KEYS, + "? {a: b, c: d}: x" + , + "?\n" + " ? {a: b,c: d}\n" + " : x\n" + ": \n" + , + "+STR\n" + "+DOC\n" + "+MAP\n" + "+MAP\n" + "+MAP {}\n" + "=VAL :a\n" + "=VAL :b\n" + "=VAL :c\n" + "=VAL :d\n" + "-MAP\n" + "=VAL :x\n" + "-MAP\n" + "=VAL :\n" + "-MAP\n" + "-DOC\n" + "-STR\n" +) +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.begin_map_val_block()); + ___(ps.begin_map_key_block()); + ___(ps.begin_map_key_flow()); + ___(ps.set_key_scalar_plain("a")); + ___(ps.set_val_scalar_plain("b")); + ___(ps.add_sibling()); + ___(ps.set_key_scalar_plain("c")); + ___(ps.set_val_scalar_plain("d")); + ___(ps.end_map_flow(singleline)); + ___(ps.set_val_scalar_plain("x")); + ___(ps.end_map_block()); + ___(ps.set_val_scalar_plain_empty()); + ___(ps.end_map_block()); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(QmrkTestSuiteM2N8_01_keymap0_3_colon, + HAS_CONTAINER_KEYS, + "? {a: b, c: d}: x" "\n" + ":" + , + "?\n" + " ? {a: b,c: d}\n" + " : x" "\n" + ": \n" + , + "+STR\n" + "+DOC\n" + "+MAP\n" + "+MAP\n" + "+MAP {}\n" + "=VAL :a\n" + "=VAL :b\n" + "=VAL :c\n" + "=VAL :d\n" + "-MAP\n" + "=VAL :x\n" + "-MAP\n" + "=VAL :\n" + "-MAP\n" + "-DOC\n" + "-STR\n" +) +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.begin_map_val_block()); + ___(ps.begin_map_key_block()); + ___(ps.begin_map_key_flow()); + ___(ps.set_key_scalar_plain("a")); + ___(ps.set_val_scalar_plain("b")); + ___(ps.add_sibling()); + ___(ps.set_key_scalar_plain("c")); + ___(ps.set_val_scalar_plain("d")); + ___(ps.end_map_flow(singleline)); + ___(ps.set_val_scalar_plain("x")); + ___(ps.end_map_block()); + ___(ps.set_val_scalar_plain_empty()); + ___(ps.end_map_block()); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(QmrkTestSuiteM2N8_01_keymap0_3_colon_y, + HAS_CONTAINER_KEYS, + "? {a: b, c: d}: x" "\n" + ": y" + , + "?\n" + " ? {a: b,c: d}\n" + " : x" "\n" + ": y\n" + , + "+STR\n" + "+DOC\n" + "+MAP\n" + "+MAP\n" + "+MAP {}\n" + "=VAL :a\n" + "=VAL :b\n" + "=VAL :c\n" + "=VAL :d\n" + "-MAP\n" + "=VAL :x\n" + "-MAP\n" + "=VAL :y\n" + "-MAP\n" + "-DOC\n" + "-STR\n" +) +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.begin_map_val_block()); + ___(ps.begin_map_key_block()); + ___(ps.begin_map_key_flow()); + ___(ps.set_key_scalar_plain("a")); + ___(ps.set_val_scalar_plain("b")); + ___(ps.add_sibling()); + ___(ps.set_key_scalar_plain("c")); + ___(ps.set_val_scalar_plain("d")); + ___(ps.end_map_flow(singleline)); + ___(ps.set_val_scalar_plain("x")); + ___(ps.end_map_block()); + ___(ps.set_val_scalar_plain("y")); + ___(ps.end_map_block()); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + + +//----------------------------------------------------------------------------- + +ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseqmap0_1, + HAS_CONTAINER_KEYS, + "? [a: b]: x" + , + "?\n" + " ? [{a: b}]\n" + " : x\n" + ": \n" + , + "+STR\n" + "+DOC\n" + "+MAP\n" + "+MAP\n" + "+SEQ []\n" + "+MAP {}\n" + "=VAL :a\n" + "=VAL :b\n" + "-MAP\n" + "-SEQ\n" + "=VAL :x\n" + "-MAP\n" + "=VAL :\n" + "-MAP\n" + "-DOC\n" + "-STR\n" +) +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.begin_map_val_block()); + ___(ps.begin_map_key_block()); + ___(ps.begin_seq_key_flow()); + ___(ps.begin_map_val_flow()); + ___(ps.set_key_scalar_plain("a")); + ___(ps.set_val_scalar_plain("b")); + ___(ps.end_map_flow(singleline)); + ___(ps.end_seq_flow(singleline)); + ___(ps.set_val_scalar_plain("x")); + ___(ps.end_map_block()); + ___(ps.set_val_scalar_plain_empty()); + ___(ps.end_map_block()); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseqmap0_1_colon, + HAS_CONTAINER_KEYS, + "? [a: b]: x" "\n" + ":" + , + "?\n" + " ? [{a: b}]\n" + " : x" "\n" + ": \n" + , + "+STR\n" + "+DOC\n" + "+MAP\n" + "+MAP\n" + "+SEQ []\n" + "+MAP {}\n" + "=VAL :a\n" + "=VAL :b\n" + "-MAP\n" + "-SEQ\n" + "=VAL :x\n" + "-MAP\n" + "=VAL :\n" + "-MAP\n" + "-DOC\n" + "-STR\n" +) +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.begin_map_val_block()); + ___(ps.begin_map_key_block()); + ___(ps.begin_seq_key_flow()); + ___(ps.begin_map_val_flow()); + ___(ps.set_key_scalar_plain("a")); + ___(ps.set_val_scalar_plain("b")); + ___(ps.end_map_flow(singleline)); + ___(ps.end_seq_flow(singleline)); + ___(ps.set_val_scalar_plain("x")); + ___(ps.end_map_block()); + ___(ps.set_val_scalar_plain_empty()); + ___(ps.end_map_block()); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseqmap0_1_colon_y, + HAS_CONTAINER_KEYS, + "? [a: b]: x" "\n" + ": y" + , + "?\n" + " ? [{a: b}]\n" + " : x" "\n" + ": y\n" + , + "+STR\n" + "+DOC\n" + "+MAP\n" + "+MAP\n" + "+SEQ []\n" + "+MAP {}\n" + "=VAL :a\n" + "=VAL :b\n" + "-MAP\n" + "-SEQ\n" + "=VAL :x\n" + "-MAP\n" + "=VAL :y\n" + "-MAP\n" + "-DOC\n" + "-STR\n" +) +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.begin_map_val_block()); + ___(ps.begin_map_key_block()); + ___(ps.begin_seq_key_flow()); + ___(ps.begin_map_val_flow()); + ___(ps.set_key_scalar_plain("a")); + ___(ps.set_val_scalar_plain("b")); + ___(ps.end_map_flow(singleline)); + ___(ps.end_seq_flow(singleline)); + ___(ps.set_val_scalar_plain("x")); + ___(ps.end_map_block()); + ___(ps.set_val_scalar_plain("y")); + ___(ps.end_map_block()); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseqmap0_2, + HAS_CONTAINER_KEYS, + "? [a: ]: x" + , + "?\n" + " ? [{a: }]\n" + " : x\n" + ": \n" + , + "+STR\n" + "+DOC\n" + "+MAP\n" + "+MAP\n" + "+SEQ []\n" + "+MAP {}\n" + "=VAL :a\n" + "=VAL :\n" + "-MAP\n" + "-SEQ\n" + "=VAL :x\n" + "-MAP\n" + "=VAL :\n" + "-MAP\n" + "-DOC\n" + "-STR\n" +) +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.begin_map_val_block()); + ___(ps.begin_map_key_block()); + ___(ps.begin_seq_key_flow()); + ___(ps.begin_map_val_flow()); + ___(ps.set_key_scalar_plain("a")); + ___(ps.set_val_scalar_plain_empty()); + ___(ps.end_map_flow(singleline)); + ___(ps.end_seq_flow(singleline)); + ___(ps.set_val_scalar_plain("x")); + ___(ps.end_map_block()); + ___(ps.set_val_scalar_plain_empty()); + ___(ps.end_map_block()); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseqmap0_2_colon, + HAS_CONTAINER_KEYS, + "? [a: ]: x" "\n" + ":" + , + "?\n" + " ? [{a: }]\n" + " : x" "\n" + ": \n" + , + "+STR\n" + "+DOC\n" + "+MAP\n" + "+MAP\n" + "+SEQ []\n" + "+MAP {}\n" + "=VAL :a\n" + "=VAL :\n" + "-MAP\n" + "-SEQ\n" + "=VAL :x\n" + "-MAP\n" + "=VAL :\n" + "-MAP\n" + "-DOC\n" + "-STR\n" +) +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.begin_map_val_block()); + ___(ps.begin_map_key_block()); + ___(ps.begin_seq_key_flow()); + ___(ps.begin_map_val_flow()); + ___(ps.set_key_scalar_plain("a")); + ___(ps.set_val_scalar_plain_empty()); + ___(ps.end_map_flow(singleline)); + ___(ps.end_seq_flow(singleline)); + ___(ps.set_val_scalar_plain("x")); + ___(ps.end_map_block()); + ___(ps.set_val_scalar_plain_empty()); + ___(ps.end_map_block()); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseqmap0_2_colon_y, + HAS_CONTAINER_KEYS, + "? [a: ]: x" "\n" + ": y" + , + "?\n" + " ? [{a: }]\n" + " : x" "\n" + ": y\n" + , + "+STR\n" + "+DOC\n" + "+MAP\n" + "+MAP\n" + "+SEQ []\n" + "+MAP {}\n" + "=VAL :a\n" + "=VAL :\n" + "-MAP\n" + "-SEQ\n" + "=VAL :x\n" + "-MAP\n" + "=VAL :y\n" + "-MAP\n" + "-DOC\n" + "-STR\n" +) +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.begin_map_val_block()); + ___(ps.begin_map_key_block()); + ___(ps.begin_seq_key_flow()); + ___(ps.begin_map_val_flow()); + ___(ps.set_key_scalar_plain("a")); + ___(ps.set_val_scalar_plain_empty()); + ___(ps.end_map_flow(singleline)); + ___(ps.end_seq_flow(singleline)); + ___(ps.set_val_scalar_plain("x")); + ___(ps.end_map_block()); + ___(ps.set_val_scalar_plain("y")); + ___(ps.end_map_block()); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + + +ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseqmap0_3, + HAS_CONTAINER_KEYS, + "? [a: b, ]: x" + , + "?\n" + " ? [{a: b}]\n" + " : x\n" + ": \n" + , + "+STR\n" + "+DOC\n" + "+MAP\n" + "+MAP\n" + "+SEQ []\n" + "+MAP {}\n" + "=VAL :a\n" + "=VAL :b\n" + "-MAP\n" + "-SEQ\n" + "=VAL :x\n" + "-MAP\n" + "=VAL :\n" + "-MAP\n" + "-DOC\n" + "-STR\n" +) +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.begin_map_val_block()); + ___(ps.begin_map_key_block()); + ___(ps.begin_seq_key_flow()); + ___(ps.begin_map_val_flow()); + ___(ps.set_key_scalar_plain("a")); + ___(ps.set_val_scalar_plain("b")); + ___(ps.end_map_flow(singleline)); + ___(ps.end_seq_flow(singleline)); + ___(ps.set_val_scalar_plain("x")); + ___(ps.end_map_block()); + ___(ps.set_val_scalar_plain_empty()); + ___(ps.end_map_block()); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseqmap0_3_colon, + HAS_CONTAINER_KEYS, + "? [a: b, ]: x" "\n" + ":" + , + "?\n" + " ? [{a: b}]\n" + " : x" "\n" + ": \n" + , + "+STR\n" + "+DOC\n" + "+MAP\n" + "+MAP\n" + "+SEQ []\n" + "+MAP {}\n" + "=VAL :a\n" + "=VAL :b\n" + "-MAP\n" + "-SEQ\n" + "=VAL :x\n" + "-MAP\n" + "=VAL :\n" + "-MAP\n" + "-DOC\n" + "-STR\n" +) +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.begin_map_val_block()); + ___(ps.begin_map_key_block()); + ___(ps.begin_seq_key_flow()); + ___(ps.begin_map_val_flow()); + ___(ps.set_key_scalar_plain("a")); + ___(ps.set_val_scalar_plain("b")); + ___(ps.end_map_flow(singleline)); + ___(ps.end_seq_flow(singleline)); + ___(ps.set_val_scalar_plain("x")); + ___(ps.end_map_block()); + ___(ps.set_val_scalar_plain_empty()); + ___(ps.end_map_block()); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + +ENGINE_TEST(QmrkTestSuiteM2N8_01_keyseqmap0_3_colon_y, + HAS_CONTAINER_KEYS, + "? [a: b, ]: x" "\n" + ": y" + , + "?\n" + " ? [{a: b}]\n" + " : x" "\n" + ": y\n" + , + "+STR\n" + "+DOC\n" + "+MAP\n" + "+MAP\n" + "+SEQ []\n" + "+MAP {}\n" + "=VAL :a\n" + "=VAL :b\n" + "-MAP\n" + "-SEQ\n" + "=VAL :x\n" + "-MAP\n" + "=VAL :y\n" + "-MAP\n" + "-DOC\n" + "-STR\n" +) +{ + ___(ps.begin_stream()); + ___(ps.begin_doc()); + ___(ps.begin_map_val_block()); + ___(ps.begin_map_key_block()); + ___(ps.begin_seq_key_flow()); + ___(ps.begin_map_val_flow()); + ___(ps.set_key_scalar_plain("a")); + ___(ps.set_val_scalar_plain("b")); + ___(ps.end_map_flow(singleline)); + ___(ps.end_seq_flow(singleline)); + ___(ps.set_val_scalar_plain("x")); + ___(ps.end_map_block()); + ___(ps.set_val_scalar_plain("y")); + ___(ps.end_map_block()); + ___(ps.end_doc()); + ___(ps.end_stream()); +} + + + +} // namespace yml +} // namespace c4 + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +// this is needed to use the test case library + +#ifndef RYML_SINGLE_HEADER +#include "c4/substr.hpp" +#endif + +namespace c4 { +namespace yml { +struct Case; +Case const* get_case(csubstr /*name*/) +{ + return nullptr; +} +} // namespace yml +} // namespace c4 + +C4_SUPPRESS_WARNING_MSVC_POP diff --git a/test/test_engine_7_seqimap.cpp b/test/test_engine_7_seqimap.cpp index de2476804..808da1c46 100644 --- a/test/test_engine_7_seqimap.cpp +++ b/test/test_engine_7_seqimap.cpp @@ -466,7 +466,7 @@ ENGINE_TEST(SeqIMap4, , "[val0,val1,[rat,rot]: [foo: bar],wtf]" , - "[val0,val1,{[rat,rot]: [{foo: bar}]},wtf]" + "[val0,val1,{? [rat,rot]: [{foo: bar}]},wtf]" , "+STR\n" "+DOC\n" @@ -521,7 +521,7 @@ ENGINE_TEST(SeqIMap4_actually, HAS_CONTAINER_KEYS, Location(20,1,21), "[val0,val1,[rat,rot]: [foo: bar],wtf]" , - "[val0,val1,{[rat,rot]: [{foo: bar}]},wtf]" + "[val0,val1,{? [rat,rot]: [{foo: bar}]},wtf]" , "+STR\n" "+DOC\n" @@ -862,7 +862,7 @@ ENGINE_TEST(SeqIMap5QmrkSeq, HAS_CONTAINER_KEYS, "[? &anchor [a, seq]: ]" , - "[{&anchor [a, seq]: }]" + "[{? &anchor [a,seq]: }]" , "+STR\n" "+DOC\n" @@ -881,7 +881,6 @@ ENGINE_TEST(SeqIMap5QmrkSeq, ___(ps.begin_stream()); ___(ps.begin_doc()); ___(ps.begin_seq_val_flow()); - ___(ps.set_key_tag("!tag")); ___(ps.begin_map_val_flow()); ___(ps.set_key_anchor("anchor")); ___(ps.begin_seq_key_flow()); @@ -899,7 +898,7 @@ ENGINE_TEST(SeqIMap5QmrkMap, HAS_CONTAINER_KEYS, "[? &anchor {a: map}: ]" , - "[{&anchor {a: map}: }]" + "[{? &anchor {a: map}: }]" , "+STR\n" "+DOC\n" @@ -918,7 +917,6 @@ ENGINE_TEST(SeqIMap5QmrkMap, ___(ps.begin_stream()); ___(ps.begin_doc()); ___(ps.begin_seq_val_flow()); - ___(ps.set_key_tag("!tag")); ___(ps.begin_map_val_flow()); ___(ps.set_key_anchor("anchor")); ___(ps.begin_map_key_flow()); diff --git a/test/test_extra_ints.cpp b/test/test_extra_ints.cpp index 695fa8114..2ba5dfb78 100644 --- a/test/test_extra_ints.cpp +++ b/test/test_extra_ints.cpp @@ -16,7 +16,7 @@ TEST(flags, to_chars) using namespace ievt; char buf1_[1]; substr buf1 = buf1_; char buf_[200]; substr buf = buf_; -#define _(flags, str) \ + #define _(flags, str) \ { \ ievt::evt_bits flags_{flags}; \ csubstr actual(str); \ @@ -33,24 +33,153 @@ TEST(flags, to_chars) _(KEY_, "KEY_"); _(VAL_, "VAL_"); _(KEY_|VAL_, "KEY_|VAL_"); + #undef _ +} + +TEST(ints, find_matching_open_close_next_entry) +{ + #define CHECK_MATCHING_OPEN_CLOSE(open, close) \ + do { \ + ASSERT_GE(open, 0); \ + ASSERT_LT(open, ints.evts.len); \ + EXPECT_EQ(open, ievt::detail::find_matching_open_(ints.evts.ptr, close)); \ + ASSERT_GE(close, 0); \ + ASSERT_LT(close, ints.evts.len); \ + EXPECT_EQ(close, ievt::detail::find_matching_close_(ints.evts.ptr, ints.evts.len, open)); \ + } while(0) + ievt::TestBuffers ints; + std::string src = "[{a: b}: [c, d]]: {{e: f}: [g: h]}"; + parse_ints(to_substr(src), &ints); + CHECK_MATCHING_OPEN_CLOSE(0, 45); + CHECK_MATCHING_OPEN_CLOSE(1, 44); + CHECK_MATCHING_OPEN_CLOSE(2, 43); + CHECK_MATCHING_OPEN_CLOSE(3, 22); + CHECK_MATCHING_OPEN_CLOSE(4, 21); + CHECK_MATCHING_OPEN_CLOSE(5, 12); + CHECK_MATCHING_OPEN_CLOSE(13, 20); + CHECK_MATCHING_OPEN_CLOSE(23, 42); + CHECK_MATCHING_OPEN_CLOSE(24, 31); + CHECK_MATCHING_OPEN_CLOSE(32, 41); + CHECK_MATCHING_OPEN_CLOSE(33, 40); + if(testing::Test::HasFailure()) + ints.print(); + #undef CHECK_MATCHING_OPEN_CLOSE +} + +TEST(ints, grow_evts) +{ + using Handler = ievt::EventHandlerInts; + auto test_grow_evts = [&](ievt::evt_size cap, csubstr yaml, csubstr expected){ + RYML_TRACE_FMT("cap={}", cap); + if(!expected.len && yaml.len) + expected = yaml; + std::string src(yaml.str, yaml.len); + Handler handler; + ParseEngine parser(&handler); + handler.reset(to_substr(src)); + ASSERT_EQ(handler.m_evt.cap, 0); + handler._grow_evts_exact(cap); + ASSERT_EQ(handler.m_evt.cap, cap); + parser.parse_in_place_ev("(testyaml)", to_substr(src)); + ievt::evt_size finalcap = handler.m_evt.cap; + ASSERT_LE(handler.m_evt.len, handler.m_evt.cap); + bool ok = true; + if(handler.m_evt.len <= cap) + { + ok = false; + EXPECT_GT(handler.m_evt.cap, cap); + } + ievt::TestBuffers ints; + handler.get_buffers(&ints, true); + ASSERT_EQ(ints.evts.cap, finalcap); + std::string actual = ints.emitrs_yaml(); + if(expected != actual) + { + RYML_TRACE_FMT("yaml=~~~{}~~~", yaml); + EXPECT_EQ(expected, actual); + ok = false; + } + if(!ok) + ints.print(); + }; + #define test_grow_evts_(...) { SCOPED_TRACE("call"); test_grow_evts(__VA_ARGS__); } + test_grow_evts_(1, "a\n", {}); + test_grow_evts_(1, "[a]", {}); + test_grow_evts_(2, "[a]", {}); + test_grow_evts_(3, "[a,b]", {}); + test_grow_evts_(3, "[a: b]", "[{a: b}]"); + test_grow_evts_(6, "[a: b]", "[{a: b}]"); + test_grow_evts_(7, "[a: b]", "[{a: b}]"); + test_grow_evts_(3, "[[a,b]: {c: d}]", "[{? [a,b]: {c: d}}]"); + test_grow_evts_(6, "[[a,b]: {c: d}]", "[{? [a,b]: {c: d}}]"); + test_grow_evts_(11, "[[a,b]: {c: d}]", "[{? [a,b]: {c: d}}]"); } +TEST(ints, grow_arena) +{ + using Handler = ievt::EventHandlerInts; + { + Handler handler; + ASSERT_EQ(handler.m_arena.len, 0); + ASSERT_EQ(handler.m_arena.str, nullptr); + ASSERT_EQ(handler.arena(), handler.m_arena); + } + { + Handler handler = {}; + ASSERT_EQ(handler.m_arena.len, 0); + ASSERT_EQ(handler.m_arena.str, nullptr); + ASSERT_EQ(handler.arena(), handler.m_arena); + } + Handler handler; + ASSERT_EQ(handler.arena().len, 0); + std::string sofar; + #define grow_arena(s_) \ + do \ + { \ + SCOPED_TRACE("grow_arena"); \ + csubstr s = to_csubstr(s_); \ + size_t lenprev = handler.arena().len; \ + ASSERT_EQ(sofar, handler.arena()); \ + substr ret = handler.alloc_arena(s.len); \ + ASSERT_EQ(ret.len, s.len); \ + ASSERT_EQ(handler.arena().len, lenprev + s.len); \ + sofar.append(s.str, s.len); \ + if(s.len) \ + memcpy(ret.str, s.str, s.len); \ + ASSERT_EQ(sofar, handler.arena()); \ + } while(0) + ASSERT_EQ(handler.m_arena.len, 0); + grow_arena("0123"); + ASSERT_EQ(handler.m_arena.len, 256); + grow_arena("456789"); + ASSERT_EQ(handler.m_arena.len, 256); + std::string growit; + growit.assign(256, '-'); + ASSERT_EQ(growit.size(), 256); + grow_arena(growit); + ASSERT_GT(handler.m_arena.len, 256); + #undef grow_arena +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + + struct IntEventsCase { const char *file; const int line; ParserOptions opts; csubstr yaml; - const std::vector evt; + const std::vector evt; void testeq(csubstr parsed_source, csubstr arena, ievt::evt_bits const* actual, size_t actual_size) const { RYML_TRACE_FMT("defined in:\n{}:{}: (here)\n", file, line); - #ifdef RYML_DBG - events_ints_print(parsed_source, arena, actual, (extra::ievt::evt_bits)actual_size); - #endif - test_events_ints_invariants(parsed_source, arena, actual, (ievt::evt_bits)actual_size); + extra::ievt::test_events_ints_invariants(parsed_source, arena, actual, (ievt::evt_bits)actual_size); test_events_ints(evt.data(), evt.size(), actual, actual_size, yaml, parsed_source, arena); } }; @@ -147,7 +276,7 @@ const IntEventsCase test_cases[] = { { e(BSTR), e(BDOC), - e(VAL_|BSEQ|FLOW), + e(VAL_|BSEQ|FLOW|FSL_), e(VAL_|SCLR|PLAI, 1, 1, "a"), e(VAL_|SCLR|PLAI|PSTR, 4, 1, "b"), e(VAL_|SCLR|PLAI|PSTR, 7, 1, "c"), @@ -160,8 +289,8 @@ const IntEventsCase test_cases[] = { { e(BSTR), e(BDOC), - e(VAL_|BSEQ|FLOW), - e(VAL_|BMAP|FLOW), + e(VAL_|BSEQ|FLOW|FSL_), + e(VAL_|BMAP|FLOW|FSL_), e(KEY_|SCLR|PLAI, 1, 1, "a"), e(VAL_|SCLR|PLAI|PSTR, 4, 1, "b"), e(EMAP|PSTR), @@ -195,11 +324,11 @@ const IntEventsCase test_cases[] = { e(KEY_|SCLR|PLAI, 19, 3, "foo"), e(VAL_|TAG_|PSTR, 24, 1, "!"), e(VAL_|BSEQ|BLCK|PSTR), - e(VAL_|BMAP|FLOW), + e(VAL_|BMAP|FLOW|FSL_), e(KEY_|SCLR|PLAI, 29, 1, "x"), e(VAL_|SCLR|PLAI|PSTR, 32, 1, "y"), e(EMAP|PSTR), - e(VAL_|BSEQ|FLOW), + e(VAL_|BSEQ|FLOW|FSL_), e(VAL_|SCLR|PLAI, 38, 1, "x"), e(VAL_|SCLR|PLAI|PSTR, 41, 1, "y"), e(ESEQ|PSTR), @@ -208,15 +337,15 @@ const IntEventsCase test_cases[] = { e(VAL_|SCLR|DQUO|PSTR, 61, 3, "foo"), e(VAL_|SCLR|LITL|PSTR, 70, 4, "foo\n", needs_filter), e(VAL_|SCLR|FOLD|PSTR, 80, 4, "foo\n", needs_filter), - e(VAL_|BSEQ|FLOW|PSTR), + e(VAL_|BSEQ|FLOW|FSL_|PSTR), e(VAL_|SCLR|PLAI, 89, 1, "1"), e(VAL_|SCLR|PLAI|PSTR, 92, 1, "2"), e(VAL_|SCLR|PLAI|PSTR, 95, 4, "true"), e(VAL_|SCLR|PLAI|PSTR, 101, 5, "false"), e(VAL_|SCLR|PLAI|PSTR, 108, 4, "null"), e(ESEQ|PSTR), - e(VAL_|TAG_, 126, 6, "!tag-1"), - e(VAL_|ANCH|PSTR, 117, 8, "anchor-1"), + e(VAL_|ANCH, 117, 8, "anchor-1"), + e(VAL_|TAG_|PSTR, 126, 6, "!tag-1"), e(VAL_|SCLR|PLAI|PSTR, 133, 6, "foobar"), e(ESEQ|PSTR), e(EMAP), @@ -270,7 +399,7 @@ const IntEventsCase test_cases[] = { e(BDOC), e(VAL_|BSEQ|BLCK), e(VAL_|TAG_, 2, 5, "!!seq"), - e(VAL_|BSEQ|FLOW|PSTR), + e(VAL_|BSEQ|FLOW|FSL_|PSTR), e(ESEQ), e(ESEQ), e(EDOC), @@ -394,11 +523,11 @@ const IntEventsCase test_cases[] = { e(BSTR), e(BDOC), e(VAL_|BMAP|BLCK), - e(KEY_|BMAP|FLOW), + e(KEY_|BMAP|FLOW|FSL_), e(KEY_|SCLR|PLAI, 1, 3, "key"), e(VAL_|SCLR|PLAI|PSTR, 6, 3, "map"), e(EMAP|PSTR), - e(VAL_|BSEQ|FLOW), + e(VAL_|BSEQ|FLOW|FSL_), e(VAL_|SCLR|PLAI, 13, 3, "seq"), e(VAL_|SCLR|PLAI|PSTR, 18, 3, "val"), e(ESEQ|PSTR), @@ -413,11 +542,11 @@ const IntEventsCase test_cases[] = { e(BSTR), e(BDOC), e(VAL_|BMAP|BLCK), - e(KEY_|BSEQ|FLOW), + e(KEY_|BSEQ|FLOW|FSL_), e(VAL_|SCLR|PLAI, 1, 3, "key"), e(VAL_|SCLR|PLAI|PSTR, 6, 3, "seq"), e(ESEQ|PSTR), - e(VAL_|BMAP|FLOW), + e(VAL_|BMAP|FLOW|FSL_), e(KEY_|SCLR|PLAI, 13, 3, "map"), e(VAL_|SCLR|PLAI|PSTR, 18, 3, "val"), e(EMAP|PSTR), @@ -432,7 +561,7 @@ const IntEventsCase test_cases[] = { e(BSTR), e(BDOC), e(VAL_|BMAP|BLCK), - e(KEY_|BSEQ|FLOW), + e(KEY_|BSEQ|FLOW|FSL_), e(VAL_|SCLR|PLAI, 1, 1, "b"), e(VAL_|SCLR|PLAI|PSTR, 3, 1, "c"), e(ESEQ|PSTR), @@ -448,8 +577,8 @@ const IntEventsCase test_cases[] = { e(BSTR), e(BDOC), e(VAL_|BMAP|BLCK), - e(KEY_|BSEQ|FLOW), - e(VAL_|BSEQ|FLOW), + e(KEY_|BSEQ|FLOW|FSL_), + e(VAL_|BSEQ|FLOW|FSL_), e(VAL_|SCLR|PLAI, 2, 1, "b"), e(VAL_|SCLR|PLAI|PSTR, 4, 1, "c"), e(ESEQ|PSTR), @@ -466,12 +595,12 @@ const IntEventsCase test_cases[] = { e(BSTR), e(BDOC), e(VAL_|BMAP|BLCK), - e(KEY_|BSEQ|FLOW), + e(KEY_|BSEQ|FLOW|FSL_), e(VAL_|SCLR|PLAI, 2, 1, "a"), - e(VAL_|BSEQ|FLOW|PSTR), - e(VAL_|BMAP|FLOW), - e(KEY_|BSEQ|FLOW), - e(VAL_|BSEQ|FLOW), + e(VAL_|BSEQ|FLOW|FSL_|PSTR), + e(VAL_|BMAP|FLOW|FSL_), + e(KEY_|BSEQ|FLOW|FSL_), + e(VAL_|BSEQ|FLOW|FSL_), e(VAL_|SCLR|PLAI, 9, 1, "b"), e(VAL_|SCLR|PLAI|PSTR, 11, 1, "c"), e(ESEQ|PSTR), @@ -493,7 +622,7 @@ const IntEventsCase test_cases[] = { { e(BSTR), e(BDOC), - e(VAL_|BSEQ|FLOW), + e(VAL_|BSEQ|FLOW|FSL_), e(VAL_|SCLR|DQUO|AREN, 0, 18, dqesc_L6), e(VAL_|SCLR|DQUO|AREN|PSTR, 18, 18, dqesc_P6), e(ESEQ|PSTR), @@ -597,14 +726,16 @@ const IntEventsCase test_cases[] = { //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- +constexpr bool dynamic_size = true; +constexpr bool fixed_size = false; struct IntEventsTestHelper { IntEventsCase const& ec; size_t required_size_expected; size_t required_size_actual; - extra::EventHandlerInts handler; - ParseEngine parser; + extra::ievt::EventHandlerInts handler; + ParseEngine> parser; std::string src_copy; std::vector actual; std::string arena; @@ -646,7 +777,7 @@ struct IntEventsTest : public testing::TestWithParam } }; -TEST_P(IntEventsTest, size_large_enough) +TEST_P(IntEventsTest, fixed_size_large_enough) { IntEventsTestHelper h(GetParam()); h.run_with_size(2u * h.required_size_expected, 2u * h.ec.yaml.len); @@ -656,7 +787,7 @@ TEST_P(IntEventsTest, size_large_enough) h.ec.testeq(to_csubstr(h.src_copy), to_csubstr(h.arena), h.actual.data(), h.required_size_actual); } -TEST_P(IntEventsTest, size_too_small) +TEST_P(IntEventsTest, fixed_size_too_small) { IntEventsTestHelper h(GetParam()); size_t small = h.required_size_expected / 2u; @@ -673,7 +804,7 @@ TEST_P(IntEventsTest, size_too_small) h.ec.testeq(to_csubstr(h.src_copy), to_csubstr(h.arena), h.actual.data(), h.required_size_actual); } -TEST_P(IntEventsTest, size_null) +TEST_P(IntEventsTest, fixed_size_null) { IntEventsTestHelper h(GetParam()); h.run_with_size(0, 0); @@ -683,6 +814,29 @@ TEST_P(IntEventsTest, size_null) h.ec.testeq(to_csubstr(h.src_copy), to_csubstr(h.arena), h.actual.data(), h.required_size_actual); } + +void test_dynamic_size(IntEventsCase const& ec, bool transfer_ownership) +{ + extra::ievt::EventHandlerInts handler; + ParseEngine> parser(&handler, ec.opts); + std::vector src(ec.yaml.begin(), ec.yaml.end()); + handler.reset(to_substr(src)); + parser.parse_in_place_ev("(testyaml)", to_substr(src)); + extra::ievt::Buffers buf; + handler.get_buffers(&buf, transfer_ownership); + ec.testeq(to_csubstr(src), buf.arena, buf.evts.ptr, (size_t)buf.evts.len); +} + +TEST_P(IntEventsTest, dynamic_size_notransfer) +{ + test_dynamic_size(GetParam(), false); +} + +TEST_P(IntEventsTest, dynamic_size_transfer) +{ + test_dynamic_size(GetParam(), true); +} + INSTANTIATE_TEST_SUITE_P(IntEvents, IntEventsTest, testing::ValuesIn(test_cases), &IntEventsTest::name2str); diff --git a/test/test_fuzz/test_fuzz_common.hpp b/test/test_fuzz/test_fuzz_common.hpp index ad348c361..123f409ba 100644 --- a/test/test_fuzz/test_fuzz_common.hpp +++ b/test/test_fuzz/test_fuzz_common.hpp @@ -139,55 +139,91 @@ inline int fuzztest_json_tree(uint32_t case_number, csubstr src) //----------------------------------------------------------------------------- -using HandlerInts = extra::EventHandlerInts; -using ParserInts = ParseEngine; -template +template using HandlerInts = extra::ievt::EventHandlerInts; +template using ParserInts = ParseEngine>; +template inline int fuzztest_ints(uint32_t case_number, csubstr src, FnParse const& fn) { C4_UNUSED(case_number); set_callbacks(create_custom_callbacks()); - using I = HandlerInts::value_type; - HandlerInts handler{}; - ParserInts parser(&handler); + using I = typename HandlerInts::value_type; + HandlerInts handler{}; + ParserInts parser(&handler); std::string str(src.begin(), src.end()); - std::vector arena(str.size()); - std::vector evts; - evts.reserve(256); - handler.reset(to_substr(str), to_substr(arena), - evts.data(), static_cast(evts.size())); - C4_IF_EXCEPTIONS_(try, if(setjmp(jmp_env) == 0)) + if C4_IF_CONSTEXPR (resize_buffers) { - _if_dbg(dbg_printf_("in[{}]: [{}]~~~\n{}\n~~~\n", case_number, src.len, src); fflush(NULL)); - fn(parser, c4::to_substr(str)); - C4_DONT_OPTIMIZE(evts); + C4_IF_EXCEPTIONS_(try, if(setjmp(jmp_env) == 0)) + { + _if_dbg(dbg_printf_("in[{}]: [{}]~~~\n{}\n~~~\n", case_number, src.len, src); fflush(NULL)); + fn(parser, c4::to_substr(str)); + C4_DONT_OPTIMIZE(handler); + } + C4_IF_EXCEPTIONS_(catch(std::exception const&), else) + { + // if an exception leaks from here, it is likely because of a greedy noexcept + _if_dbg(fprintf(stdout, "err\n"); fflush(NULL)); + return 1; + } } - C4_IF_EXCEPTIONS_(catch(std::exception const&), else) + else { - // if an exception leaks from here, it is likely because of a greedy noexcept - _if_dbg(fprintf(stdout, "err\n"); fflush(NULL)); - return 1; + std::vector arena(str.size()); + std::vector evts; + evts.reserve(256); + handler.reset(to_substr(str), to_substr(arena), + evts.data(), static_cast(evts.size())); + C4_IF_EXCEPTIONS_(try, if(setjmp(jmp_env) == 0)) + { + _if_dbg(dbg_printf_("in[{}]: [{}]~~~\n{}\n~~~\n", case_number, src.len, src); fflush(NULL)); + fn(parser, c4::to_substr(str)); + C4_DONT_OPTIMIZE(evts); + } + C4_IF_EXCEPTIONS_(catch(std::exception const&), else) + { + // if an exception leaks from here, it is likely because of a greedy noexcept + _if_dbg(fprintf(stdout, "err\n"); fflush(NULL)); + return 1; + } } return 0; } +template inline int fuzztest_yaml_ints(uint32_t case_number, csubstr src) { - return fuzztest_ints( + return fuzztest_ints( case_number, src, - [](ParserInts &parser, c4::substr str){ + [](ParserInts &parser, c4::substr str){ parser.parse_in_place_ev("input.yaml", c4::to_substr(str)); }); } +template inline int fuzztest_json_ints(uint32_t case_number, csubstr src) { - return fuzztest_ints( + return fuzztest_ints( case_number, src, - [](ParserInts &parser, c4::substr str){ + [](ParserInts &parser, c4::substr str){ parser.parse_json_in_place_ev("input.json", c4::to_substr(str)); }); } +inline int fuzztest_yaml_ints_resize(uint32_t case_number, csubstr src) +{ + return fuzztest_yaml_ints(case_number, src); +} +inline int fuzztest_yaml_ints_noresize(uint32_t case_number, csubstr src) +{ + return fuzztest_yaml_ints(case_number, src); +} +inline int fuzztest_json_ints_resize(uint32_t case_number, csubstr src) +{ + return fuzztest_json_ints(case_number, src); +} +inline int fuzztest_json_ints_noresize(uint32_t case_number, csubstr src) +{ + return fuzztest_json_ints(case_number, src); +} //----------------------------------------------------------------------------- diff --git a/test/test_fuzz/test_fuzz_json_ints_noresize.cpp b/test/test_fuzz/test_fuzz_json_ints_noresize.cpp new file mode 100644 index 000000000..9cf22b7ca --- /dev/null +++ b/test/test_fuzz/test_fuzz_json_ints_noresize.cpp @@ -0,0 +1,9 @@ +#include "./test_fuzz_common.hpp" +#include + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *str, size_t len) +{ + static std::atomic case_number{0}; + c4::csubstr src = {reinterpret_cast(str), len}; + return c4::yml::fuzztest_json_ints_noresize(case_number++, src); +} diff --git a/test/test_fuzz/test_fuzz_json_ints.cpp b/test/test_fuzz/test_fuzz_json_ints_resize.cpp similarity index 78% rename from test/test_fuzz/test_fuzz_json_ints.cpp rename to test/test_fuzz/test_fuzz_json_ints_resize.cpp index b7146ed49..8bd827c34 100644 --- a/test/test_fuzz/test_fuzz_json_ints.cpp +++ b/test/test_fuzz/test_fuzz_json_ints_resize.cpp @@ -5,5 +5,5 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *str, size_t len) { static std::atomic case_number{0}; c4::csubstr src = {reinterpret_cast(str), len}; - return c4::yml::fuzztest_json_ints(case_number++, src); + return c4::yml::fuzztest_json_ints_resize(case_number++, src); } diff --git a/test/test_fuzz/test_fuzz_yaml_ints_noresize.cpp b/test/test_fuzz/test_fuzz_yaml_ints_noresize.cpp new file mode 100644 index 000000000..ef247dafa --- /dev/null +++ b/test/test_fuzz/test_fuzz_yaml_ints_noresize.cpp @@ -0,0 +1,9 @@ +#include "./test_fuzz_common.hpp" +#include + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *str, size_t len) +{ + static std::atomic case_number{0}; + c4::csubstr src = {reinterpret_cast(str), len}; + return c4::yml::fuzztest_yaml_ints_noresize(case_number++, src); +} diff --git a/test/test_fuzz/test_fuzz_yaml_ints.cpp b/test/test_fuzz/test_fuzz_yaml_ints_resize.cpp similarity index 78% rename from test/test_fuzz/test_fuzz_yaml_ints.cpp rename to test/test_fuzz/test_fuzz_yaml_ints_resize.cpp index 6bcea5585..205719b33 100644 --- a/test/test_fuzz/test_fuzz_yaml_ints.cpp +++ b/test/test_fuzz/test_fuzz_yaml_ints_resize.cpp @@ -5,5 +5,5 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *str, size_t len) { static std::atomic case_number{0}; c4::csubstr src = {reinterpret_cast(str), len}; - return c4::yml::fuzztest_yaml_ints(case_number++, src); + return c4::yml::fuzztest_yaml_ints_resize(case_number++, src); } diff --git a/test/test_github_issues.cpp b/test/test_github_issues.cpp index d17ab846a..c8e5eb361 100644 --- a/test/test_github_issues.cpp +++ b/test/test_github_issues.cpp @@ -410,14 +410,14 @@ N(MB, L{N(KP|SFS, "translation", L{N(VP, "-2"), N(VP, "-2"), N(VP, "5")})}) ); // these must work without quotes -ADD_CASE_TO_GROUP("github3-problem2-ex1", +ADD_CASE_TO_GROUP("github3-problem2-ex1", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"( audio resource: )", N(MB, L{N(KP|VN, "audio resource", /*"~"*/{})}) ); -ADD_CASE_TO_GROUP("github3-problem2-ex2", +ADD_CASE_TO_GROUP("github3-problem2-ex2", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"( audio resource: more: diff --git a/test/test_json.cpp b/test/test_json.cpp index 21c4ab413..a78ce9936 100644 --- a/test/test_json.cpp +++ b/test/test_json.cpp @@ -9,6 +9,11 @@ #endif #include "./test_lib/test_case.hpp" +#include "./test_lib/tree_and_ints.hpp" +#define test_emit_json_same_ints_(...) { SCOPED_TRACE("here"); test_emit_json_same_ints(__VA_ARGS__); } +#define test_emit_yaml_same_ints_(...) { SCOPED_TRACE("here"); test_emit_yaml_same_ints(__VA_ARGS__); } +#define test_emit_json_(...) { SCOPED_TRACE("here"); test_emit_json(__VA_ARGS__); } +#define test_emit_yaml_(...) { SCOPED_TRACE("here"); test_emit_yaml(__VA_ARGS__); } #include @@ -82,13 +87,14 @@ TEST(serialize, type_as_str) } } // namespace foo -namespace c4 { -namespace yml { //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- +namespace c4 { +namespace yml { + TEST(general, emitting) { std::string cmpbuf; @@ -202,34 +208,26 @@ TEST(emit_json, issue72) r["true"].set_val("2"); r["false"].set_val("3"); - std::string out; - emitrs_json(t, &out); - - EXPECT_EQ(out, R"({"1": null,"2": true,"3": false,"null": 1,"true": 2,"false": 3})"); + test_emit_json_same_ints_(r, R"({"1": null,"2": true,"3": false,"null": 1,"true": 2,"false": 3})"); } TEST(emit_json, issue121) { - csubstr json = R"({"string_value": "string","number_value": "9001","broken_value": "0.30.2"})"; - const Tree t = parse_json_in_arena(json); + const std::string json = R"({"string_value": "string","number_value": "9001","broken_value": "0.30.2"})"; + const Tree t = parse_json_in_arena(to_csubstr(json)); EXPECT_TRUE(t["string_value"].get()->m_type.m_bits & VAL_DQUO); EXPECT_TRUE(t["number_value"].get()->m_type.m_bits & VAL_DQUO); EXPECT_TRUE(t["broken_value"].get()->m_type.m_bits & VAL_DQUO); - std::string out; - emitrs_json(t, &out); - EXPECT_EQ(out, json); - out.clear(); - emitrs_yaml(t, &out); - EXPECT_EQ(out, json); + test_emit_json_same_ints_(t, json); + test_emit_yaml_same_ints_(t, json); } TEST(emit_json, issue291) { Tree t = parse_json_in_arena("{}"); t["james"].set_val("045"); - auto s = emitrs_json(t); - EXPECT_EQ(s, "{\"james\": \"045\"}"); + test_emit_json_same_ints_(t, "{\"james\": \"045\"}"); } TEST(emit_json, issue292) @@ -251,15 +249,15 @@ TEST(emit_json, issue292) EXPECT_FALSE(csubstr("1.2.3").is_real()); Tree t = parse_json_in_arena("{}"); t["james"].set_val("0.0.0"); - EXPECT_EQ(emitrs_json(t), "{\"james\": \"0.0.0\"}"); + test_emit_json_same_ints_(t, "{\"james\": \"0.0.0\"}"); t["james"].set_val("0.1.0"); - EXPECT_EQ(emitrs_json(t), "{\"james\": \"0.1.0\"}"); + test_emit_json_same_ints_(t, "{\"james\": \"0.1.0\"}"); t["james"].set_val("0.6.1"); - EXPECT_EQ(emitrs_json(t), "{\"james\": \"0.6.1\"}"); + test_emit_json_same_ints_(t, "{\"james\": \"0.6.1\"}"); t["james"].set_val("1.1.9"); - EXPECT_EQ(emitrs_json(t), "{\"james\": \"1.1.9\"}"); + test_emit_json_same_ints_(t, "{\"james\": \"1.1.9\"}"); t["james"].set_val("1.2.3"); - EXPECT_EQ(emitrs_json(t), "{\"james\": \"1.2.3\"}"); + test_emit_json_same_ints_(t, "{\"james\": \"1.2.3\"}"); } TEST(emit_json, issue297) @@ -270,8 +268,7 @@ comment: | def )"; Tree t = parse_in_place(yml_buf); - auto s = emitrs_json(t); - EXPECT_EQ(s, "{\n \"comment\": \"abc\\ndef\\n\"\n}\n"); + test_emit_json_same_ints_(t, "{\n \"comment\": \"abc\\ndef\\n\"\n}\n"); } TEST(emit_json, issue297_escaped_chars) @@ -284,9 +281,7 @@ TEST(emit_json, issue297_escaped_chars) t["backslash"].set_val("abc\\def"); t["backspace"].set_val("abc\bdef"); t["formfeed"].set_val("abc\fdef"); - std::string expected = R"({"quote": "abc\"def","newline": "abc\ndef","tab": "abc\tdef","carriage": "abc\rdef","backslash": "abc\\def","backspace": "abc\bdef","formfeed": "abc\fdef"})"; - auto actual = emitrs_json(t); - EXPECT_EQ(actual, expected); + test_emit_json_same_ints_(t, R"({"quote": "abc\"def","newline": "abc\ndef","tab": "abc\tdef","carriage": "abc\rdef","backslash": "abc\\def","backspace": "abc\bdef","formfeed": "abc\fdef"})"); } namespace { @@ -321,8 +316,9 @@ TEST(emit_json, issue313_quoted_numbers__1) 0.91054189205169678, 0.13215841352939606, ])"); - std::string yaml = emitrs_json(t0); - test_check_emit_check(to_csubstr(yaml), [&](Tree const &t){ + std::string json = emitrs_json(t0); + test_emit_json_same_ints_(t0, json); + test_check_emit_check(to_csubstr(json), [&](Tree const &t){ for(ConstNodeRef number : t.rootref().children()) { ASSERT_TRUE(number.is_val()); @@ -358,8 +354,9 @@ TEST(emit_json, issue313_quoted_numbers__2) [1.1130030155181885, 1.5196701288223267], # 14 [1.0621790885925293, 1.1791903972625732] # 15 ]})"); - std::string yaml = emitrs_json(ti); - test_check_emit_check(to_csubstr(yaml), [](Tree const &t){ + std::string json = emitrs_json(ti); + test_emit_json_same_ints_(ti, json); + test_check_emit_check(to_csubstr(json), [](Tree const &t){ for(ConstNodeRef node : t.rootref().children()) { ASSERT_TRUE(node.is_seq()); @@ -390,28 +387,46 @@ TEST(emit_json, issue313_quoted_numbers__2) } -#define _test(actual_src, expected_src) \ - { \ - SCOPED_TRACE(__LINE__); \ - csubstr file = __FILE__ ":" C4_XQUOTE(__LINE__); \ - const Tree actual = parse_json_in_arena(file, actual_src); \ - const Tree expected = parse_json_in_arena(file, expected_src); \ - print_tree(actual); \ - test_compare(actual, expected); \ +#define _test(actual_src, expected_src) \ + { \ + csubstr file = __FILE__ ":" C4_XQUOTE(__LINE__); \ + const Tree actual = parse_json_in_arena(file, actual_src); \ + const Tree expected = parse_json_in_arena(file, expected_src); \ + { \ + SCOPED_TRACE(__LINE__); \ + test_compare(actual, expected); \ + } \ + std::string emitted = emitrs_json(expected); \ + { \ + SCOPED_TRACE("actual"); \ + test_emit_json_same_ints(actual, emitted); \ + } \ + { \ + SCOPED_TRACE("expected"); \ + test_emit_json_same_ints(expected, emitted); \ + } \ } -TEST(json, compact_map) +TEST(json, empty) { _test("", ""); _test("{}", "{}"); + _test("[]", "[]"); + _test("{\n}", "{\n}"); // test ML + _test("[\n]", "[\n]"); // test ML + _test("{\n\n\n}", "{\n\n\n}"); // test ML + _test("[\n\n\n]", "[\n\n\n]"); // test ML +} +TEST(json, compact_map) +{ _test(R"({"a":{"a":"b"}})", R"({"a": {"a": "b"}})"); } TEST(json, compact_seq) { - _test(R"(["a",["a","b"]])", R"(["a", ["a", "b"]])"); + _test(R"(["a",["a","b"]])", R"(["a", ["a","b"]])"); } TEST(json, github142) @@ -495,7 +510,7 @@ TEST(json, issue390) const Tree tree = parse_in_arena(R"(quntity: 9.5e7 quntity2: 95000000)"); EXPECT_TRUE(csubstr("9.5e7").is_number()); - EXPECT_EQ(emitrs_json(tree), "{\n \"quntity\": 9.5e7,\n \"quntity2\": 95000000\n}\n"); + test_emit_json_same_ints_(tree, "{\n \"quntity\": 9.5e7,\n \"quntity2\": 95000000\n}\n"); } TEST(parse_json, error_on_missing_seq_val) @@ -741,11 +756,11 @@ TEST(parse_json, seq_nested_on_seq_with_trailing_comma) TEST(emit_json, empty_val) { Tree t = parse_in_arena("a: \nb: \"\"\nc: !!tag\nd: !!tag e"); - EXPECT_EQ(emitrs_json(t), "{\n \"a\": null,\n \"b\": \"\",\n \"c\": \"\",\n \"d\": \"e\"\n}\n"); + test_emit_json_same_ints_(t, "{\n \"a\": null,\n \"b\": \"\",\n \"c\": \"\",\n \"d\": \"e\"\n}\n"); } -//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- struct SpecialScalarError { diff --git a/test/test_lib/string.hpp b/test/test_lib/string.hpp deleted file mode 100644 index 6da49f7e2..000000000 --- a/test/test_lib/string.hpp +++ /dev/null @@ -1,425 +0,0 @@ -#ifndef C4_YML_EXTRA_STRING_HPP_ -#define C4_YML_EXTRA_STRING_HPP_ - -#ifndef RYML_SINGLE_HEADER -#ifndef C4_YML_COMMON_HPP_ -#include "c4/yml/common.hpp" -#endif -#endif - -#include - -C4_SUPPRESS_WARNING_GCC_CLANG_PUSH -C4_SUPPRESS_WARNING_GCC_CLANG("-Wold-style-cast") -C4_SUPPRESS_WARNING_GCC("-Wuseless-cast") - -#ifndef RYML_STRING_SSO_SIZE -#define RYML_STRING_SSO_SIZE 128 -#endif - -#ifndef RYML_STRING_LIST_SSO_SIZE -#define RYML_STRING_LIST_SSO_SIZE 66 -#endif - -namespace c4 { -namespace yml { -namespace extra { - -/** an owning string class used by the yaml std event handler (and the - * YamlScript handler). we use this instead of std::string because: - * 1) this spares the dependency on the standard library - * 2) enables possibility of adding borrowing semantics (in the future) */ -struct string -{ - enum : id_type { sso_size = RYML_STRING_SSO_SIZE }; - char m_buf[sso_size]; - char *C4_RESTRICT m_str; - id_type m_size; - id_type m_capacity; - -public: - - string() - : m_buf() - , m_str(m_buf) - , m_size(0) - , m_capacity(sso_size) - {} - ~string() noexcept - { - _free(); - } - - string(string const& that) RYML_NOEXCEPT : string() - { - resize(that.m_size); - _cp(&that); - } - - string(string &&that) noexcept : string() - { - _mv(&that); - } - - string& operator= (string const& that) RYML_NOEXCEPT - { - resize(that.m_size); - _cp(&that); - return *this; - } - - string& operator= (string &&that) noexcept - { - _mv(&that); - return *this; - } - -public: - - C4_ALWAYS_INLINE C4_HOT operator csubstr() const noexcept { return {m_str, m_size}; } - C4_ALWAYS_INLINE C4_HOT operator substr() noexcept { return {m_str, m_size}; } - -public: - - const char* data() const noexcept { return m_str; } - id_type size() const noexcept { return m_size; } - id_type capacity() const noexcept { return m_capacity; } - - void clear() - { - m_size = 0; - } - - void resize(id_type sz) - { - reserve(sz); - m_size = sz; - } - - void reserve(id_type sz) - { - if(sz <= m_capacity) - return; - id_type cap = m_capacity < string::sso_size ? string::sso_size : 2 * m_capacity; - cap = cap > sz ? cap : sz; - if(cap <= sso_size) - return; - Callbacks cb = get_callbacks(); - char *buf = (char*) RYML_CB_ALLOC_(cb, char, cap); - if(m_size) - memcpy(buf, m_str, (size_t)m_size); - if(m_str != m_buf) - { - RYML_CB_FREE_(cb, m_str, char, m_size); - } - m_str = buf; - m_capacity = cap; - } - -public: - - C4_ALWAYS_INLINE C4_HOT void append(char c) - { - if C4_UNLIKELY(m_size == m_capacity) - reserve(m_size + 1); - m_str[m_size++] = c; - } - C4_ALWAYS_INLINE C4_HOT void append(csubstr cs) - { - if(cs.len) - { - const id_type ilen = (id_type)cs.len; - if C4_UNLIKELY(m_size + ilen > m_capacity) - reserve(m_size + ilen); - memcpy(m_str + m_size, cs.str, cs.len); - m_size += ilen; - } - } - C4_ALWAYS_INLINE void insert(char c, id_type pos) - { - RYML_ASSERT_BASIC_(pos <= m_size); - if(pos < m_size) - { - if C4_UNLIKELY(m_size == m_capacity) - reserve(m_size + 1); - char *C4_RESTRICT src = m_str + pos; - memmove(src + 1, src, m_size - pos); - *src = c; - ++m_size; - } - else - { - append(c); - } - } - C4_NO_INLINE void insert(csubstr cs, id_type pos) - { - RYML_ASSERT_BASIC_(pos <= m_size); - if(cs.len) - { - if(pos < m_size) - { - const id_type ilen = (id_type)cs.len; - if C4_UNLIKELY(m_size + ilen > m_capacity) - reserve(m_size + ilen); - char *C4_RESTRICT src = m_str + pos; - memmove(src + cs.len, src, m_size - pos); - memcpy(src, cs.str, cs.len); - m_size += ilen; - } - else - { - append(cs); - } - } - } - C4_NO_INLINE size_t find_last(csubstr pattern) RYML_NOEXCEPT - { - RYML_ASSERT_BASIC_(pattern.len); - if(m_size >= pattern.len) - { - for(size_t i = m_size - pattern.len; i != (size_t)-1; --i) - { - if(m_str[i] == pattern[0]) - { - bool gotit = true; - for(size_t j = 1; j < pattern.len; ++j) - { - if(m_str[i + j] != pattern[j]) - { - gotit = false; - break; - } - } - if(gotit) - return i; - } - } - } - return npos; - } - -public: - - void _free() - { - RYML_ASSERT_BASIC_(m_str != nullptr); // this structure cannot be memset() to zero - if(m_str != m_buf) - { - RYML_CB_FREE_(get_callbacks(), m_str, char, (size_t)m_capacity); - m_str = m_buf; - m_capacity = sso_size; - } - RYML_ASSERT_BASIC_(m_capacity == sso_size); - m_size = 0; - } - - void _cp(string const* C4_RESTRICT that) - { - #if RYML_USE_ASSERT - if(that->m_str != that->m_buf) - { - RYML_ASSERT_BASIC_(that->m_capacity > sso_size); - RYML_ASSERT_BASIC_(that->m_size <= that->m_capacity); - } - else - { - RYML_ASSERT_BASIC_(that->m_capacity <= sso_size); - RYML_ASSERT_BASIC_(that->m_size <= that->m_capacity); - } - #endif - memcpy(m_str, that->m_str, that->m_size); - m_size = that->m_size; - m_capacity = that->m_size < sso_size ? sso_size : that->m_size; - } - - void _mv(string *C4_RESTRICT that) - { - if(that->m_str != that->m_buf) - { - RYML_ASSERT_BASIC_(that->m_capacity > sso_size); - RYML_ASSERT_BASIC_(that->m_size <= that->m_capacity); - m_str = that->m_str; - } - else - { - RYML_ASSERT_BASIC_(that->m_capacity <= sso_size); - RYML_ASSERT_BASIC_(that->m_size <= that->m_capacity); - memcpy(m_buf, that->m_buf, that->m_size); - m_str = m_buf; - } - m_size = that->m_size; - m_capacity = that->m_capacity; - // make sure no deallocation happens on destruction - RYML_ASSERT_BASIC_(that->m_str != this->m_buf); - that->m_str = that->m_buf; - that->m_capacity = sso_size; - that->m_size = 0; - } -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -/** a string collection used by the event handler. using this instead of - * std::vector spares the dependency on the standard library. */ -struct string_vector -{ - enum : id_type { sso_size = RYML_STRING_LIST_SSO_SIZE }; - union { - alignas(string) string m_buf[sso_size]; - alignas(string) char m_buf_bytes[sso_size * sizeof(string)]; - }; - string *C4_RESTRICT m_arr; - id_type m_size; - id_type m_capacity; - -public: - - string_vector() - : m_arr(m_buf) - , m_size(0) - , m_capacity(sso_size) - {} - ~string_vector() noexcept - { - _free(); - } - - string_vector(string_vector const& that) RYML_NOEXCEPT : string_vector() - { - reserve(that.m_size); - m_size = that.m_size; - for(id_type i = 0; i < that.m_size; ++i) - new ((void*)(m_arr+i)) string(that.m_arr[i]); - } - - string_vector(string_vector &&that) noexcept : string_vector() - { - reserve(that.m_size); - m_size = that.m_size; - for(id_type i = 0; i < that.m_size; ++i) - new ((void*)(m_arr+i)) string(std::move(that.m_arr[i])); - that.~string_vector(); - } - - string_vector& operator= (string_vector const& that) RYML_NOEXCEPT - { - _free(); - reserve(that.m_size); - for(id_type i = 0; i < that.m_size; ++i) - m_arr[i].operator=(that.m_arr[i]); - m_size = that.m_size; - return *this; - } - - string_vector& operator= (string_vector &&that) noexcept - { - _free(); - reserve(that.m_size); - for(id_type i = 0; i < that.m_size; ++i) - m_arr[i].operator=(std::move(that.m_arr[i])); - m_size = that.m_size; - that.~string_vector(); - return *this; - } - - void _free() - { - RYML_ASSERT_BASIC_(m_arr != nullptr); // this structure cannot be memset() to zero - for(id_type i = 0; i < m_size; ++i) - m_arr[i].~string(); - if(m_arr != m_buf) - { - RYML_CB_FREE_(get_callbacks(), m_arr, string, (size_t)m_capacity); - m_arr = m_buf; - m_capacity = sso_size; - } - RYML_ASSERT_BASIC_(m_capacity == sso_size); - m_size = 0; - } - -public: - - id_type size() const noexcept { return m_size; } - id_type capacity() const noexcept { return m_capacity; } - - void clear() - { - resize(0); - } - - void resize(id_type sz) - { - reserve(sz); - if(sz >= m_size) - { - for(id_type i = m_size; i < sz; ++i) - new ((void*)(m_arr + i)) string(); - } - else - { - for(id_type i = sz; i < m_size; ++i) - m_arr[i].~string(); - } - m_size = sz; - } - - void reserve(id_type sz) - { - if(sz <= m_capacity) - return; - id_type cap = m_capacity < string::sso_size ? string::sso_size : 2 * m_capacity; - cap = cap > sz ? cap : sz; - if(cap <= sso_size) - return; - Callbacks cb = get_callbacks(); - string *buf = (string*) RYML_CB_ALLOC_(cb, string, cap); - for(id_type i = 0; i < m_size; ++i) - new ((void*)(buf + i)) string(std::move(m_arr[i])); - if(m_arr != m_buf) - { - RYML_CB_FREE_(cb, m_arr, string, m_size); - } - m_arr = buf; - m_capacity = cap; - } - -public: - - string& emplace_back() - { - RYML_ASSERT_BASIC_(m_size < m_capacity); - if(m_size == m_capacity) - reserve(m_size + 1); - string& ret = m_arr[m_size++]; - new ((void*)&ret) string(); - return ret; - } - string& operator[] (id_type i) - { - RYML_ASSERT_BASIC_(m_size <= m_capacity); - RYML_ASSERT_BASIC_(i < m_size); - return m_arr[i]; - } - string const& operator[] (id_type i) const - { - RYML_ASSERT_BASIC_(m_size <= m_capacity); - RYML_ASSERT_BASIC_(i < m_size); - return m_arr[i]; - } -}; - -} // namespace extra -} // namespace yml - -template struct is_string; // fwd-declare -template<> struct is_string : std::true_type {}; - -} // namespace c4 - -C4_SUPPRESS_WARNING_GCC_POP - -#endif /* C4_YML_EXTRA_STRING_HPP_ */ diff --git a/test/test_lib/test_case.cpp b/test/test_lib/test_case.cpp index 9df0e8df6..b4fbabf93 100644 --- a/test/test_lib/test_case.cpp +++ b/test/test_lib/test_case.cpp @@ -418,9 +418,15 @@ void ExpectError::check_success(Tree *tree, fntestref fn) fn(); _c4dbgp("check expected success: success!"); } - C4_IF_EXCEPTIONS_(catch(...), else) + C4_IF_EXCEPTIONS_(catch(ExpectedErrorBasic const& e), else) { - FAIL() << "check expected success: failed!"; + C4_IF_EXCEPTIONS_( , ExpectedErrorBasic const& e = s_jmp_err_basic); + (void)e; + #if defined(RYML_WITH_EXCEPTIONS_) + FAIL() << "exception:\n" << e.what(); + #else + FAIL() << "exception:\n" << e.smsg; + #endif } EXPECT_EQ(context.m_error, ExpectedErrorType::err_none); } @@ -637,55 +643,6 @@ void ExpectError::check_assert_visit(Tree *tree, fntestref fn, id_type id) //----------------------------------------------------------------------------- -void print_path(ConstNodeRef const& n) -{ - size_t len = 0; - char buf[1024]; - ConstNodeRef p = n; - while(p.readable()) - { - if(p.has_key()) - { - len += 1 + p.key().len; - } - else - { - int ret = snprintf(buf, sizeof(buf), "/%zu", p.has_parent() ? (size_t)p.parent().child_pos(p) : (size_t)0); - RYML_ASSERT_BASIC_(ret >= 0); - len += static_cast(ret); - } - p = p.parent(); - }; - C4_ASSERT(len < sizeof(buf)); - size_t pos = len; - p = n; - while(p.readable()) - { - if(p.has_key()) - { - size_t tl = p.key().len; - int ret = snprintf(buf + pos - tl, tl, "%.*s", (int)tl, p.key().str); - RYML_ASSERT_BASIC_(ret >= 0); - pos -= static_cast(ret); - } - else if(p.has_parent()) - { - pos = (size_t)p.parent().child_pos(p); - int ret = snprintf(buf, 0, "/%zu", pos); - RYML_ASSERT_BASIC_(ret >= 0); - size_t tl = static_cast(ret); - RYML_ASSERT_BASIC_(pos >= tl); - ret = snprintf(buf + static_cast(pos - tl), tl, "/%zu", pos); - RYML_ASSERT_BASIC_(ret >= 0); - pos -= static_cast(ret); - } - p = p.parent(); - }; - printf("%.*s", (int)len, buf); -} - - - void print_test_node(TestCaseNode const& p, int level) { printf("%*s%p", (2*level), "", (void const*)&p); @@ -839,19 +796,19 @@ void test_invariants(NodeType ty) EXPECT_NONE(ty, VAL); if(ty & FLOW_SL) { - EXPECT_ONE(ty, CONTAINER_STYLE, FLOW_SL); + EXPECT_ONE(ty, CONTAINER_STYLE & ~FLOW_SPC, FLOW_SL); } if(ty & FLOW_ML1) { - EXPECT_ONE(ty, CONTAINER_STYLE, FLOW_ML1); + EXPECT_ONE(ty, CONTAINER_STYLE & ~FLOW_SPC, FLOW_ML1); } if(ty & FLOW_MLN) { - EXPECT_ONE(ty, CONTAINER_STYLE, FLOW_MLN); + EXPECT_ONE(ty, CONTAINER_STYLE & ~FLOW_SPC, FLOW_MLN); } if(ty & FLOW_SPC) { - EXPECT_ANY(ty, FLOW_MLX); + EXPECT_ANY(ty, FLOW_MLX|FLOW_SL); } if(ty & BLOCK) { @@ -1125,13 +1082,13 @@ void test_invariants(Tree const& t) test_invariants(t.rootref()); check_invariants(t); - if(!testing::UnitTest::GetInstance()->current_test_info()->result()->Passed()) + if(testing::Test::HasFailure()) { print_tree(t); } return; -#if 0 == 1 +#if 0 == 1 // TODO for(size_t i = 0; i < t.m_size; ++i) { auto n = t.get(i); @@ -1185,31 +1142,17 @@ void test_invariants(Tree const& t) CaseData* get_data(csubstr name) { static std::map m; - auto it = m.find(name); - CaseData *cd; - if(it == m.end()) - { - cd = &m[name]; - Case const* c = get_case(name); - RYML_CHECK_BASIC_(c->src.find("\n\r") == csubstr::npos); - { - std::string tmp; - replace_all("\r", "", c->src, &tmp); - cd->unix_style.assign(to_csubstr(tmp)); - cd->unix_style_json.assign(to_csubstr(tmp)); - } - { - std::string tmp; - replace_all("\n", "\r\n", cd->unix_style.src, &tmp); - cd->windows_style.assign(to_csubstr(tmp)); - cd->windows_style_json.assign(to_csubstr(tmp)); - } - } - else - { - cd = &it->second; - } + if(it != m.end()) + return &it->second; + CaseData *cd = &m[name]; + Case const* c = get_case(name); + RYML_CHECK_BASIC_(c->src.find("\n\r") == csubstr::npos); + txtbuf tmp; + replace_all("\r", "", c->src, &tmp); + cd->unix_style.assign(tmp); + replace_all("\n", "\r\n", cd->unix_style.src, &tmp); + cd->windows_style.assign(tmp); return cd; } diff --git a/test/test_lib/test_case.hpp b/test/test_lib/test_case.hpp index 2792e42a0..8b3fa0872 100644 --- a/test/test_lib/test_case.hpp +++ b/test/test_lib/test_case.hpp @@ -11,38 +11,29 @@ #include #include #include +#include #endif #include "c4/span.hpp" - +#include #include #include // no pragma push for these warnings! they will be suppressed in the // files including this header (most test files) -#ifdef __clang__ -# pragma clang diagnostic ignored "-Wold-style-cast" -#elif defined(__GNUC__) -# pragma GCC diagnostic ignored "-Wold-style-cast" -#endif +C4_SUPPRESS_WARNING_GCC_CLANG("-Wold-style-cast") #if defined(__clang__) && (__clang_major__ >= 13) C4_SUPPRESS_WARNING_CLANG("-Wreserved-identifier") #endif -#ifdef __clang__ -# pragma clang diagnostic push -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wtype-limits" -#elif defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable: 4296/*expression is always 'boolean_value'*/) -# pragma warning(disable: 4389/*'==': signed/unsigned mismatch*/) -# pragma warning(disable: 4702/*unreachable code*/) -# if C4_MSVC_VERSION != C4_MSVC_VERSION_2017 -# pragma warning(disable: 4800/*'int': forcing value to bool 'true' or 'false' (performance warning)*/) -# endif +C4_SUPPRESS_WARNING_PUSH +C4_SUPPRESS_WARNING_GCC_CLANG("-Wtype-limits") +C4_SUPPRESS_WARNING_MSVC(4296/*expression is always 'boolean_value'*/) +C4_SUPPRESS_WARNING_MSVC(4389/*'==': signed/unsigned mismatch*/) +C4_SUPPRESS_WARNING_MSVC(4702/*unreachable code*/) +#if defined(_MSC_VER) && (C4_MSVC_VERSION != C4_MSVC_VERSION_2017) +C4_SUPPRESS_WARNING_MSVC(4800/*'int': forcing value to bool 'true' or 'false' (performance warning)*/) #endif #ifdef RYML_DBG @@ -148,7 +139,6 @@ void test_invariants(ConstNodeRef const& n); void print_test_node(TestCaseNode const& t, int level=0); void print_test_tree(TestCaseNode const& p, int level=0); void print_test_tree(const char *message, TestCaseNode const& t); -void print_path(ConstNodeRef const& p); //----------------------------------------------------------------------------- @@ -158,31 +148,45 @@ void print_path(ConstNodeRef const& p); template void test_check_emit_check_with_parser(Tree const& t, Parser &parser, CheckFn &&check_fn) { - #ifdef RYML_DBG - print_tree(t); - #endif { SCOPED_TRACE("original yaml"); test_invariants(t); std::forward(check_fn)(t, parser); + if(testing::Test::HasFailure()) + { + print_tree(t); + } } - auto emit_and_parse = [&](Tree const& tp, const char* identifier){ + auto emit_and_parse = [&](Tree const& tp, Tree *out, const char* identifier){ SCOPED_TRACE(identifier); std::string emitted = emitrs_yaml(tp); - #ifdef RYML_DBG - printf("~~~%s~~~[%zu]\n%.*s", identifier, emitted.size(), (int)emitted.size(), emitted.data()); - #endif - Tree cp = parse_in_arena(&parser, to_csubstr(emitted)); - #ifdef RYML_DBG - print_tree(cp); - #endif - test_invariants(cp); - std::forward(check_fn)(cp, parser); - return cp; + parse_in_arena(&parser, to_csubstr(emitted), out); + test_invariants(*out); + std::forward(check_fn)(*out, parser); + if(testing::Test::HasFailure()) + { + printf("~~~%s~~~[%zu]\n%.*s", identifier, emitted.size(), (int)emitted.size(), emitted.data()); + print_tree(*out); + } }; - Tree cp = emit_and_parse(t, "emitted 1"); - cp = emit_and_parse(cp, "emitted 2"); - cp = emit_and_parse(cp, "emitted 3"); + if(!testing::Test::HasFailure()) + { + Tree cp1; + SCOPED_TRACE("level 1"); + emit_and_parse(t, &cp1, "level 1"); + if(!testing::Test::HasFailure()) + { + Tree cp2; + SCOPED_TRACE("level 2"); + emit_and_parse(cp1, &cp2, "level 2"); + if(!testing::Test::HasFailure()) + { + Tree cp3; + SCOPED_TRACE("level 3"); + emit_and_parse(cp2, &cp3, "level 3"); + } + } + } } template void test_check_emit_check(Tree const& t, Parser &parser, CheckFn &&check_fn) @@ -216,7 +220,7 @@ void test_check_emit_check_with_parser(Tree const& t, CheckFn &&check_fn) { Parser::handler_type evt_handler = {}; Parser parser(&evt_handler, ParserOptions()); - test_check_emit_check_with_parser(t, parser, check_fn); + test_check_emit_check_with_parser(t, parser, std::forward(check_fn)); } template void test_check_emit_check(Tree const& t, CheckFn &&check_fn) @@ -329,6 +333,8 @@ typedef enum { HAS_CONTAINER_KEYS = (1<<5), HAS_MULTILINE_SCALAR = (1<<6), NO_COMPARE_EMITTED = (1<<7), + NO_COMPARE_EMITTED_INTS = (1<<8), + NO_COMPARE_EMITTED_INTS_JSON = (1<<9), } TestCaseFlags_e; @@ -350,52 +356,117 @@ struct Case Case(csubstr file, int line, const char *name_, int f_, const char *src_, TestCaseNode&& node) : /* */filelinebuf(catrs(file, ':', line)), fileline(to_csubstr(filelinebuf)), name(to_csubstr(name_)), src(to_csubstr(src_)), root(std::move(node)), flags((TestCaseFlags_e)f_), expected_location() {} }; + //----------------------------------------------------------------------------- +struct txtbuf : std::string +{ + operator c4::substr() noexcept { return c4::substr{&(*this)[0], size()}; }//NOLINT + operator c4::csubstr() const noexcept { return c4::csubstr{&(*this)[0], size()}; }//NOLINT +}; + +template +struct resultdep +{ + T result; + bool done = false; + template + bool ensure(Fn && fn) + { + if(done) + return false; + std::forward(fn)(); + done = true; + return true; + } +}; +template +struct src_and_val +{ + resultdep orig; // original source + resultdep src; // mutated by the parse + resultdep val; + void reset() { orig.done = src.done = val.done = false; } + void assign(csubstr src_) + { + if(src.ensure([&]{ src.result.assign(src_.begin(), src_.end()); })) + orig = src; + } +}; +using SrcTree = src_and_val; +using SrcInts = src_and_val; + + // a persistent data store to avoid repeating operations on every test struct CaseDataLineEndings { void assign(csubstr src_orig) { - parse_buf_ints.assign(src_orig.begin(), src_orig.end()); - src_buf.assign(src_orig.begin(), src_orig.end()); - src = to_substr(src_buf); + if(src_orig == src && src_orig.len) + return; + tree.reset(); + tree_roundtrip_yaml.reset(); + tree_roundtrip_json.reset(); + tree.val.result.clear(); + tree_roundtrip_yaml.val.result.clear(); + tree_roundtrip_json.val.result.clear(); + ints_resize.reset(); + ints_resize_roundtrip_yaml.reset(); + ints_resize_roundtrip_json.reset(); + ints_noresize.reset(); + ints_noresize_roundtrip_yaml.reset(); + ints_noresize_roundtrip_json.reset(); + const char *b = src_orig.begin(); + const char *e = src_orig.end(); + src.assign(b, e); + tree.assign(src_orig); + ints_resize.assign(src_orig); + ints_noresize.assign(src_orig); } - std::vector src_buf; - substr src; - - Tree parsed_tree{0}; + txtbuf src; - std::string emit_buf; - csubstr emitted_yml; + SrcTree tree; + SrcTree tree_roundtrip_yaml; + SrcTree tree_roundtrip_json; - std::string emitjson_buf; - csubstr emitted_json; + SrcInts ints_resize; + SrcInts ints_resize_roundtrip_yaml; + SrcInts ints_resize_roundtrip_json; - std::string parse_buf; - substr parsed_yml; + SrcInts ints_noresize; + SrcInts ints_noresize_roundtrip_yaml; + SrcInts ints_noresize_roundtrip_json; - std::string parse_buf_json; - substr parsed_json; + void ensure_tree_parse(Case const *c); + void ensure_tree_emit_yaml(Case const *c); + void ensure_tree_emit_json(Case const *c); + void ensure_tree_roundtrip_yaml(Case const *c); + void ensure_tree_roundtrip_json(Case const *c); - Tree emitted_tree{0}; - Tree emitted_tree_json{0}; + void ensure_ints_parse(Case const *c, SrcInts *dst); + void ensure_ints_emit(Case const *c, SrcInts *ints, SrcInts *roundtrip, EmitType_e type); + void ensure_ints_roundtrip(Case const *c, SrcInts *ints, SrcInts *roundtrip, EmitType_e type); - Tree recreated{0}; + void ensure_ints_resize_emit_yaml(Case const *c); + void ensure_ints_resize_emit_json(Case const *c); + void ensure_ints_resize_roundtrip_yaml(Case const *c); + void ensure_ints_resize_roundtrip_json(Case const *c); - std::string parse_buf_ints; - std::vector parsed_ints; - std::vector arena_ints; + void ensure_ints_noresize_emit_yaml(Case const *c); + void ensure_ints_noresize_emit_json(Case const *c); + void ensure_ints_noresize_roundtrip_yaml(Case const *c); + void ensure_ints_noresize_roundtrip_json(Case const *c); }; struct CaseData { CaseDataLineEndings unix_style; - CaseDataLineEndings unix_style_json; CaseDataLineEndings windows_style; - CaseDataLineEndings windows_style_json; + + resultdep reftree; + void ensure_reftree(Case const *c); }; @@ -424,12 +495,6 @@ inline std::string namefor(bomspec const& param) } // namespace yml } // namespace c4 -#ifdef __clang__ -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#elif defined(_MSC_VER) -# pragma warning(pop) -#endif +C4_SUPPRESS_WARNING_POP #endif /* TEST_CASE_HPP_ */ diff --git a/test/test_lib/test_case_node.cpp b/test/test_lib/test_case_node.cpp index da9d8e9c9..0942f2950 100644 --- a/test/test_lib/test_case_node.cpp +++ b/test/test_lib/test_case_node.cpp @@ -117,10 +117,7 @@ void TestCaseNode::compare_child(yml::ConstNodeRef const& n, id_type pos) const else { printf("error: node should have child with key [%zu]~~~%.*s~~~: ", expectedch.key.len, (int)expectedch.key.len, expectedch.key.str); - fflush(stdout); - print_path(n); - fflush(stdout); - printf("\n"); + (void)fflush(stdout); print_node(n); GTEST_FAIL(); } @@ -243,10 +240,10 @@ void TestCaseNode::compare(yml::ConstNodeRef const& actual, bool ignore_quote) c C4_SUPPRESS_WARNING_GCC_POP } -void TestCaseNode::recreate(yml::NodeRef *n) const +void TestCaseNode::recreate(Tree *tree, id_type node) const { - C4_ASSERT( ! n->has_children()); - NodeData *nd = n->get(); + C4_ASSERT( ! tree->has_children(node)); + NodeData *nd = tree->get(node); nd->m_type = type|key_anchor.type|val_anchor.type; nd->m_key.scalar = key; nd->m_key.tag = (key_tag); @@ -254,14 +251,8 @@ void TestCaseNode::recreate(yml::NodeRef *n) const nd->m_val.scalar = val; nd->m_val.tag = (val_tag); nd->m_val.anchor = val_anchor.str; - Tree &tree = *n->tree(); - id_type nid = n->id(); // don't use node from now on for(TestCaseNode const& ch : children) - { - id_type id = tree.append_child(nid); - NodeRef chn(n->tree(), id); - ch.recreate(&chn); - } + ch.recreate(tree, tree->append_child(node)); } C4_SUPPRESS_WARNING_GCC_CLANG_PUSH diff --git a/test/test_lib/test_case_node.hpp b/test/test_lib/test_case_node.hpp index 1354f3416..eeb59c09a 100644 --- a/test/test_lib/test_case_node.hpp +++ b/test/test_lib/test_case_node.hpp @@ -289,7 +289,8 @@ struct TestCaseNode return c; } - void recreate(yml::NodeRef *n) const; + void recreate(Tree *tree, id_type node) const; + void recreate(yml::NodeRef n) const { recreate(n.tree(), n.id()); } }; diff --git a/test/test_lib/test_compare_events.cpp b/test/test_lib/test_compare_events.cpp new file mode 100644 index 000000000..64ff86e9d --- /dev/null +++ b/test/test_lib/test_compare_events.cpp @@ -0,0 +1,164 @@ +#include "test_lib/test_compare_events.hpp" +#include "test_lib/test_case.hpp" + +namespace c4 { +namespace yml { + +csubstr parse_anchor_and_tag(csubstr tokens, OptionalScalar *anchor, OptionalScalar *tag) +{ + *anchor = OptionalScalar{}; + *tag = OptionalScalar{}; + if(tokens.begins_with('&')) + { + size_t pos = tokens.first_of(' '); + if(pos == (size_t)csubstr::npos) + { + *anchor = tokens.sub(1); + tokens = {}; + } + else + { + *anchor = tokens.first(pos).sub(1); + tokens = tokens.right_of(pos); + } + _c4dbgpf("anchor: {}", anchor->get()); + } + if(tokens.begins_with('<')) + { + size_t pos = tokens.find('>'); + RYML_ASSERT_BASIC_(pos != (size_t)csubstr::npos); + *tag = tokens.first(pos + 1); + tokens = tokens.right_of(pos).triml(' '); + _c4dbgpf("tag: {}", tag->maybe_get()); + } + return tokens; +} + +void test_compare_events(csubstr ref_evts, + csubstr emt_evts, + bool ignore_doc_style, + bool ignore_container_style, + bool ignore_scalar_style, + bool ignore_tag_normalization) +{ + RYML_TRACE_FMT("actual=~~~\n{}~~~", emt_evts); + RYML_TRACE_FMT("expected=~~~\n{}~~~", ref_evts); + auto test_anchor_tag = [&](csubstr &ref, csubstr &emt){ + OptionalScalar reftag = {}, refanchor = {}; + OptionalScalar emttag = {}, emtanchor = {}; + ref = parse_anchor_and_tag(ref, &refanchor, &reftag).triml(' '); + emt = parse_anchor_and_tag(emt, &emtanchor, &emttag).triml(' '); + EXPECT_EQ(bool(refanchor), bool(emtanchor)); + if(bool(refanchor) && bool(emtanchor)) + { + EXPECT_EQ(refanchor.get(), emtanchor.get()); + } + EXPECT_EQ(bool(reftag), bool(emttag)); + if(reftag && emttag) + { + if(!ignore_tag_normalization) + { + EXPECT_EQ(reftag.get(), emttag.get()); + } + } + }; + auto test_doc = [&](csubstr ref, csubstr emt){ + EXPECT_TRUE(ref.begins_with("+DOC") || ref.begins_with("-DOC")); + EXPECT_TRUE(emt.begins_with("+DOC") || emt.begins_with("-DOC")); + EXPECT_EQ(emt.begins_with("+DOC"), ref.begins_with("+DOC")); + EXPECT_EQ(emt.begins_with("-DOC"), ref.begins_with("-DOC")); + if(ignore_doc_style) + { + if(ref.begins_with("+DOC")) + { + ref = ref.stripr("---").trimr(' '); + emt = emt.stripr("---").trimr(' '); + } + else + { + ASSERT_TRUE(ref.begins_with("-DOC")); + ref = ref.stripr("...").trimr(' '); + emt = emt.stripr("...").trimr(' '); + } + } + EXPECT_EQ(ref, emt); + }; + auto test_container = [&](csubstr ref, csubstr emt){ + RYML_TRACE_FMT("expected={}", ref); + RYML_TRACE_FMT("actual={}", emt); + EXPECT_TRUE(ref.begins_with("+MAP") || ref.begins_with("+SEQ")); + EXPECT_TRUE(emt.begins_with("+MAP") || emt.begins_with("+SEQ")); + EXPECT_EQ(emt.begins_with("+MAP"), ref.begins_with("+MAP")); + EXPECT_EQ(emt.begins_with("+SEQ"), ref.begins_with("+SEQ")); + csubstr rest_ref = ref.sub(4).triml(' '); + csubstr rest_emt = emt.sub(4).triml(' '); + if(rest_ref.begins_with("{}")) + { + if(!ignore_container_style) + { + EXPECT_TRUE(rest_emt.begins_with("{}")); + } + } + else if(rest_ref.begins_with("[]")) + { + if(!ignore_container_style) + { + EXPECT_TRUE(rest_emt.begins_with("[]")); + } + } + test_anchor_tag(ref, emt); + }; + auto test_val_with_scalar_wildcard = [&](csubstr ref, csubstr emt){ + ASSERT_TRUE(ref.begins_with("=VAL ")); + ASSERT_TRUE(emt.begins_with("=VAL ")); + ref = ref.sub(5); + emt = emt.sub(5); + test_anchor_tag(ref, emt); + ASSERT_GE(ref.len, 0); + ASSERT_GE(emt.len, 0); + EXPECT_TRUE(ref[0] == ':' || ref[0] == '\'' || ref[0] == '"' || ref[0] == '|' || ref[0] == '>'); + EXPECT_TRUE(emt[0] == ':' || emt[0] == '\'' || emt[0] == '"' || emt[0] == '|' || emt[0] == '>'); + if(!ignore_scalar_style) + { + EXPECT_EQ(ref[0], emt[0]); + } + ref = ref.sub(1); + emt = emt.sub(1); + EXPECT_EQ(ref, emt); + }; + EXPECT_EQ(bool(ref_evts.len), bool(emt_evts.len)); + size_t posref = 0; + size_t posemt = 0; + while(posref < ref_evts.len && posemt < emt_evts.len) + { + const size_t endref = ref_evts.find('\n', posref); + const size_t endemt = emt_evts.find('\n', posemt); + ASSERT_FALSE((endref == npos || endemt == npos) && (endref != endemt)); + csubstr ref = ref_evts.range(posref, endref); + csubstr emt = emt_evts.range(posemt, endemt); + if(ref != emt) + { + if(ref.begins_with("+DOC") || emt.begins_with("-DOC")) + { + test_doc(ref, emt); + } + else if(ref.begins_with("+MAP") || ref.begins_with("+SEQ")) + { + test_container(ref, emt); + } + else if(ref.begins_with("=VAL")) + { + test_val_with_scalar_wildcard(ref, emt); + } + else + { + ASSERT_EQ(ref, emt); + } + } + posref = endref + 1u; + posemt = endemt + 1u; + } +} + +} // namespace yml +} // namespace c4 diff --git a/test/test_lib/test_compare_events.hpp b/test/test_lib/test_compare_events.hpp new file mode 100644 index 000000000..6ef534d5d --- /dev/null +++ b/test/test_lib/test_compare_events.hpp @@ -0,0 +1,37 @@ +#ifndef C4_YML_TEST_COMPARE_EVENTS_HPP_ +#define C4_YML_TEST_COMPARE_EVENTS_HPP_ + +#ifdef RYML_SINGLE_HEADER +#include +#else +#include +#endif + +namespace c4 { +namespace yml { + +struct OptionalScalar +{ + csubstr val = {}; + bool was_set = false; + operator csubstr() const { return get(); } + operator bool() const { return was_set; } + void operator= (csubstr v) { val = v; was_set = true; } // NOLINT + csubstr get() const { RYML_ASSERT_BASIC_(was_set); return val; } + csubstr maybe_get() const { return was_set ? val : csubstr(""); } +}; + +csubstr parse_anchor_and_tag(csubstr tokens, OptionalScalar *anchor, OptionalScalar *tag); + +void test_compare_events(csubstr ref_evts, + csubstr emt_evts, + bool ignore_doc_style, + bool ignore_container_style, + bool ignore_scalar_style, + bool ignore_tag_normalization); + +} // namespace yml +} // namespace c4 + + +#endif /* C4_YML_TEST_COMPARE_EVENTS_HPP_ */ diff --git a/test/test_lib/test_engine.cpp b/test/test_lib/test_engine.cpp index 789258db0..26e029fe2 100644 --- a/test/test_lib/test_engine.cpp +++ b/test/test_lib/test_engine.cpp @@ -1,8 +1,8 @@ #include "./test_engine.hpp" +#include "./test_events_ints_helpers.hpp" #include "c4/yml/extra/ints_to_testsuite.hpp" - namespace c4 { namespace yml { @@ -19,70 +19,66 @@ void print_handler_info_(EventHandlerTree const& ps, csubstr stmt, const char *f print_tree(*ps.m_tree); } -void print_handler_info_(extra::EventHandlerInts const& ps, csubstr stmt, const char *file, int line) +template +void print_handler_info_(extra::ievt::EventHandlerInts const& ps, csubstr stmt, const char *file, int line) { dbg_printf_("{}:{}: {}\n", file, line, stmt); (void)ps; } +template void print_handler_info_(extra::ievt::EventHandlerInts const& ps, csubstr stmt, const char *file, int line); +template void print_handler_info_(extra::ievt::EventHandlerInts const& ps, csubstr stmt, const char *file, int line); #endif //----------------------------------------------------------------------------- namespace { -struct IntsBuffers -{ - // prefer std::vector to std::string because g++ 4.8 - // sometimes fails the assignment operator - std::vector src; - std::vector arena; - std::vector ints; +struct EngineTestIntBuffers +{ + extra::ievt::TestBuffers buf; public: - void prepare_yaml(extra::EventHandlerInts &handler, - EngineEvtTestCase const& test_case, std::string const& parsed_yaml, - extra::ievt::evt_bits ints_size=-1, size_t arena_size=npos) - { - if(ints_size == -1) - ints_size = extra::estimate_events_ints_size(to_csubstr(parsed_yaml)); - if(arena_size == npos) - arena_size = test_case.expected_emitted.size(); - _c4dbgpf("ints: setting buffer sizes: src={} emitted={} ints={} arena={}", parsed_yaml.size(), test_case.expected_emitted.size(), ints_size, arena_size); - ints.resize((size_t)ints_size); - arena.resize(arena_size); - src.assign(parsed_yaml.begin(), parsed_yaml.end()); - handler.reset(to_substr(src), to_substr(arena), ints.data(), (int)ints.size()); - } - bool resize_post_yaml(extra::EventHandlerInts &handler, std::string const& parsed_yaml) - { - bool ret = false; - ints.resize((size_t)handler.required_size_events()); - if(!handler.fits_buffers()) - { - ints.resize((size_t)handler.required_size_events()); - arena.resize(handler.required_size_arena()); - src.assign(parsed_yaml.begin(), parsed_yaml.end()); - handler.reset(to_substr(src), to_substr(arena), ints.data(), (int)ints.size()); - ret = true; - } - return ret; + template + void prepare_parse(extra::ievt::EventHandlerInts &handler, + substr parsed_yaml, + extra::ievt::evt_bits ints_size=-1, size_t arena_size=npos) + { + buf.prepare_parse(handler, parsed_yaml, ints_size, arena_size); + } + + template + bool resize_post_parse(extra::ievt::EventHandlerInts &handler, substr parsed_yaml) + { + return buf.resize_post_parse(handler, parsed_yaml); + } + + template + void get_buffers(extra::ievt::EventHandlerInts &handler) + { + bool transfer_ownership = resize_buffers; + handler.get_buffers(&buf, transfer_ownership); } public: - void prepare_events(EventHandlerIntsTr &handler_tr, - EngineEvtTestCase const& test_case, std::string const& parsed_yaml, - extra::ievt::evt_bits ints_size=-1, size_t arena_size=npos) + template + void prepare_events(EventHandlerIntsTr &handler_tr, + substr parsed_yaml, + extra::ievt::evt_bits ints_size=-1, + size_t arena_size=npos) { - prepare_yaml(handler_tr.handler, test_case, parsed_yaml, ints_size, arena_size); - handler_tr.transformer.src = to_csubstr(src); + prepare_parse(handler_tr.handler, parsed_yaml, ints_size, arena_size); + handler_tr.transformer.src = to_csubstr(buf.src); } - bool resize_post_events(EventHandlerIntsTr &events_tr, std::string const& parsed_yaml) + + template + bool resize_post_events(EventHandlerIntsTr &events_tr, + substr parsed_yaml) { - if(resize_post_yaml(events_tr.handler, parsed_yaml)) + if(resize_post_parse(events_tr.handler, parsed_yaml)) { - events_tr.transformer.src = to_csubstr(src); + events_tr.transformer.src = to_csubstr(buf.src); return true; } return false; @@ -90,139 +86,248 @@ struct IntsBuffers public: - void print(bool print_all=true) const - { - size_t sz = print_all ? ints.size() : num_ints(); - extra::events_ints_print(to_csubstr(src), to_csubstr(arena), ints.data(), (int)sz); - } - void test(const EngineEvtTestCase& test_case) const + void test(EngineEvtTestCase const& test_case, bool ignore_doc_style=false) const { { SCOPED_TRACE("test_invariants"); - extra::test_events_ints_invariants(to_csubstr(src), to_csubstr(arena), ints.data(), (int)ints.size()); + buf.test_invariants(); } if(test_case.expected_ints_enabled) { SCOPED_TRACE("compare_ints"); - extra::test_events_ints(test_case.expected_ints.data(), test_case.expected_ints.size(), - ints.data(), ints.size(), - to_csubstr(test_case.yaml), - to_csubstr(src), - to_csubstr(arena)); + buf.test_expected_evts(to_csubstr(test_case.yaml), + test_case.expected_ints.data(), + (extra::ievt::evt_size)test_case.expected_ints.size()); } { - std::string actual_testsuite_events = extra::events_ints_to_testsuite(to_csubstr(src), to_csubstr(arena), ints.data(), (int)ints.size()); - _c4dbgpf("~~~\n{}~~~\n", actual_testsuite_events); - test_compare_events(to_csubstr(test_case.expected_events), - to_csubstr(actual_testsuite_events), - /*ignore_doc_style*/false, - /*ignore_container_style*/false, - /*ignore_scalar_style*/false, - /*ignore_tag_normalization*/true); + SCOPED_TRACE("compare_testsuite"); + buf.test_expected_testsuite(to_csubstr(test_case.expected_events), ignore_doc_style); } if(testing::Test::HasFailure()) { - print(); + buf.print(); } } - size_t num_ints() const - { - size_t sz = ints.size(); - for(size_t i = 0; i < sz; ++i) - { - if(ints[i] & extra::ievt::WSTR) // NOLINT - i += 2; // NOLINT - else if(!ints[i]) - return i; - } - return sz; - } }; + + +//----------------------------------------------------------------------------- + } // namespace -void test_engine_error_ints_from_events(const EngineEvtTestCase& test_case, EventProducerInts event_producer) +//----------------------------------------------------------------------------- + +template +static void test_engine_error_ints_from_events(const EngineEvtTestCase& test_case, + EventProducerInts event_producer) { SCOPED_TRACE("error_ints_from_events"); - IntsBuffers buffers; + EngineTestIntBuffers buffers; + std::vector yaml(test_case.yaml.begin(), test_case.yaml.end()); ExpectError::check_error_parse([&]{ - EventHandlerIntsTr events_tr; - buffers.prepare_events(events_tr, test_case, test_case.yaml, -1, test_case.expected_emitted.size()); + EventHandlerIntsTr events_tr; + buffers.prepare_events(events_tr, to_substr(yaml), -1, test_case.expected_emitted.size()); event_producer(events_tr); }); if(testing::Test::HasFailure()) - buffers.print(); + buffers.buf.print(); } +void test_engine_error_ints_from_events_resize(const EngineEvtTestCase& test_case, EventProducerIntsResize fn) +{ + SCOPED_TRACE("error_ints_from_events_resize"); + test_engine_error_ints_from_events(test_case, fn); +} +void test_engine_error_ints_from_events_noresize(const EngineEvtTestCase& test_case, EventProducerIntsNoResize fn) +{ + SCOPED_TRACE("error_ints_from_events_noresize"); + test_engine_error_ints_from_events(test_case, fn); +} + -void test_engine_ints_from_events(EngineEvtTestCase const& test_case, EventProducerInts event_producer) +//----------------------------------------------------------------------------- + +template +static void test_engine_ints_from_events(EngineEvtTestCase const& test_case, + EventProducerInts event_producer, + EngineTestIntBuffers &buffers, + std::vector &yaml) { SCOPED_TRACE("ints_from_events"); - EventHandlerIntsTr events_tr; - IntsBuffers buffers; - buffers.prepare_events(events_tr, test_case, test_case.yaml, -1, test_case.expected_emitted.size()); - event_producer(events_tr); - if(buffers.resize_post_events(events_tr, test_case.yaml)) + EventHandlerIntsTr events_tr; + yaml = {test_case.yaml.begin(), test_case.yaml.end()}; + if C4_IF_CONSTEXPR (resize_buffers) + { + SCOPED_TRACE("resize"); + buffers.prepare_events(events_tr, to_substr(yaml), -1, test_case.expected_emitted.size()); event_producer(events_tr); - ASSERT_TRUE(events_tr.handler.fits_buffers()); - buffers.test(test_case); + ASSERT_TRUE(events_tr.handler.fits_buffers()); + buffers.get_buffers(events_tr.handler); + EXPECT_TRUE(buffers.buf.owned); + buffers.test(test_case); + } + else + { + SCOPED_TRACE("noresize"); + buffers.prepare_events(events_tr, to_substr(yaml), -1, test_case.expected_emitted.size()); + EXPECT_FALSE(buffers.buf.owned); + event_producer(events_tr); + if(buffers.resize_post_events(events_tr, to_substr(yaml))) + { + ASSERT_TRUE(events_tr.handler.fits_buffers()); + EXPECT_FALSE(buffers.buf.owned); + event_producer(events_tr); + } + buffers.get_buffers(events_tr.handler); + EXPECT_FALSE(buffers.buf.owned); + buffers.test(test_case); + buffers.buf.owned = true; + } +} +template +static void test_engine_ints_from_events(EngineEvtTestCase const& test_case, + EventProducerInts event_producer) +{ + SCOPED_TRACE("ints_from_events"); + EngineTestIntBuffers buffers; + std::vector yaml; + test_engine_ints_from_events(test_case, event_producer, buffers, yaml); +} +void test_engine_ints_from_events_resize(EngineEvtTestCase const& test_case, EventProducerIntsResize event_producer) +{ + SCOPED_TRACE("ints_from_events_resize"); + test_engine_ints_from_events(test_case, event_producer); +} +void test_engine_ints_from_events_noresize(EngineEvtTestCase const& test_case, EventProducerIntsNoResize event_producer) +{ + SCOPED_TRACE("ints_from_events_noresize"); + test_engine_ints_from_events(test_case, event_producer); } -void test_expected_error_ints_from_yaml(EngineEvtTestCase const& test_case, ExpectedErrorType errtype) + +//----------------------------------------------------------------------------- + +template +static void test_expected_error_ints_from_yaml(EngineEvtTestCase const& test_case, ExpectedErrorType errtype) { SCOPED_TRACE("error_ints_from_yaml"); - IntsBuffers buffers; - ExpectError::check_error(errtype, [&]{ - extra::EventHandlerInts handler{}; - ParseEngine parser(&handler, test_case.opts); - buffers.prepare_yaml(handler, test_case, test_case.yaml); - parser.parse_in_place_ev(test_case.fileline, to_substr(buffers.src)); - }, test_case.expected_error_location); + EngineTestIntBuffers buffers; + std::vector yaml(test_case.yaml.begin(), test_case.yaml.end()); + RYML_EXPECT_ERROR(check_error(errtype, [&]{ + extra::ievt::EventHandlerInts handler{}; + ParseEngine> parser(&handler, test_case.opts); + buffers.prepare_parse(handler, to_substr(yaml)); + parser.parse_in_place_ev(to_csubstr(test_case.fileline), buffers.buf.src); + }, test_case.expected_error_location)); if(testing::Test::HasFailure()) - buffers.print(/*all*/false); + buffers.buf.print(); + if(!resize_buffers) buffers.buf.owned = true; +} +void test_expected_error_ints_from_yaml_resize(EngineEvtTestCase const& test_case, ExpectedErrorType errtype) +{ + SCOPED_TRACE("error_ints_from_yaml_resize"); + test_expected_error_ints_from_yaml(test_case, errtype); } +void test_expected_error_ints_from_yaml_noresize(EngineEvtTestCase const& test_case, ExpectedErrorType errtype) +{ + SCOPED_TRACE("error_ints_from_yaml_noresize"); + test_expected_error_ints_from_yaml(test_case, errtype); +} + -void test_engine_ints_from_yaml(EngineEvtTestCase const& test_case, std::string const& parsed_yaml) +//----------------------------------------------------------------------------- + +template +static void test_engine_ints_from_yaml(EngineTestIntBuffers& buffers, substr parsed_yaml_buf, + EngineEvtTestCase const& test_case, std::string const& yaml_src, + bool ignore_doc_style=false) { SCOPED_TRACE("test_engine_ints_from_yaml"); - extra::EventHandlerInts handler{}; - ParseEngine parser(&handler, test_case.opts); - IntsBuffers buffers; - int size_estimated = extra::estimate_events_ints_size(to_csubstr(parsed_yaml)); - int reqsz_evts = 0; - size_t reqsz_arena = 0; - { - SCOPED_TRACE("empty buffers"); - // try first with empty buffers - buffers.prepare_yaml(handler, test_case, parsed_yaml, 0, 0); - parser.parse_in_place_ev(test_case.fileline, to_substr(buffers.src)); - EXPECT_GE(size_estimated, handler.required_size_events()); - } - reqsz_evts = handler.required_size_events(); - reqsz_arena = handler.required_size_arena(); - { - SCOPED_TRACE("small buffers"); - buffers.prepare_yaml(handler, test_case, parsed_yaml, reqsz_evts / 2, reqsz_arena / 2); - parser.parse_in_place_ev(test_case.fileline, to_substr(buffers.src)); - EXPECT_EQ(handler.required_size_events(), reqsz_evts); - EXPECT_EQ(handler.required_size_arena(), reqsz_arena); - } - if(test_case.expected_ints_enabled) - { - size_t size_reference = num_ints(test_case.expected_ints.data(), test_case.expected_ints.size()); - EXPECT_EQ(size_reference, handler.required_size_events()); - } - EXPECT_TRUE(buffers.resize_post_yaml(handler, parsed_yaml)); - { - SCOPED_TRACE("buffers ok"); - parser.parse_in_place_ev(test_case.fileline, to_substr(buffers.src)); - EXPECT_FALSE(buffers.resize_post_yaml(handler, parsed_yaml)); - EXPECT_EQ(handler.required_size_events(), reqsz_evts); - EXPECT_EQ(handler.required_size_arena(), reqsz_arena); + substr parsed_yaml; + auto reset_parsed_yaml = [&]{ + ASSERT_GE(parsed_yaml_buf.len, yaml_src.size()); + if(yaml_src.size()) + memcpy(parsed_yaml_buf.str, yaml_src.data(), yaml_src.size()); + parsed_yaml = parsed_yaml_buf.first(yaml_src.size()); + }; + extra::ievt::EventHandlerInts handler{}; + ParseEngine> parser(&handler, test_case.opts); + if C4_IF_CONSTEXPR (resize_buffers) + { + reset_parsed_yaml(); + buffers.prepare_parse(handler, parsed_yaml, 0, 0); + ASSERT_EQ(buffers.buf.src.str, parsed_yaml.str); + ASSERT_EQ(buffers.buf.src.len, parsed_yaml.len); + parser.parse_in_place_ev(to_csubstr(test_case.fileline), buffers.buf.src); ASSERT_TRUE(handler.fits_buffers()); - buffers.test(test_case); + buffers.get_buffers(handler); + ASSERT_TRUE(buffers.buf.owned); + buffers.test(test_case, ignore_doc_style); + } + else + { + int size_estimated = extra::ievt::estimate_events_size(to_csubstr(yaml_src)); + int reqsz_evts = 0; + size_t reqsz_arena = 0; + reset_parsed_yaml(); + { + SCOPED_TRACE("empty buffers"); + buffers.prepare_parse(handler, to_substr(parsed_yaml), 0, 0); + ASSERT_EQ(buffers.buf.evts.len, 0); + ASSERT_EQ(buffers.buf.arena.len, 0); + parser.parse_in_place_ev(to_csubstr(test_case.fileline), buffers.buf.src); + EXPECT_GE(size_estimated, handler.required_size_events()); + } + reqsz_evts = handler.required_size_events(); + reqsz_arena = handler.required_size_arena(); + reset_parsed_yaml(); + { + SCOPED_TRACE("small buffers"); + buffers.prepare_parse(handler, parsed_yaml, reqsz_evts / 2, reqsz_arena / 2); + parser.parse_in_place_ev(to_csubstr(test_case.fileline), buffers.buf.src); + EXPECT_EQ(handler.required_size_events(), reqsz_evts); + EXPECT_EQ(handler.required_size_arena(), reqsz_arena); + } + if(test_case.expected_ints_enabled) + { + size_t size_reference = num_ints(test_case.expected_ints.data(), test_case.expected_ints.size()); + EXPECT_EQ(size_reference, handler.required_size_events()); + } + buffers.buf.owned = true; + buffers.buf.destroy(); + reset_parsed_yaml(); + EXPECT_TRUE(buffers.resize_post_parse(handler, to_substr(parsed_yaml))); + { + SCOPED_TRACE("buffers ok"); + parser.parse_in_place_ev(to_csubstr(test_case.fileline), buffers.buf.src); + EXPECT_FALSE(buffers.resize_post_parse(handler, to_substr(parsed_yaml))); + buffers.buf.owned = true; + EXPECT_EQ(handler.required_size_events(), reqsz_evts); + EXPECT_EQ(handler.required_size_arena(), reqsz_arena); + buffers.get_buffers(handler); + buffers.buf.owned = true; + ASSERT_TRUE(handler.fits_buffers()); + buffers.test(test_case, ignore_doc_style); + } } } +template +static void test_engine_ints_from_yaml(EngineEvtTestCase const& test_case, std::string const& yaml_src, bool ignore_doc_style=false) +{ + EngineTestIntBuffers buffers; + std::vector parsed_yaml{yaml_src.begin(), yaml_src.end()}; + test_engine_ints_from_yaml(buffers, to_substr(parsed_yaml), test_case, yaml_src, ignore_doc_style); +} +void test_engine_ints_from_yaml_resize(EngineEvtTestCase const& test_case, std::string const& parsed_yaml, bool ignore_doc_style) +{ + test_engine_ints_from_yaml(test_case, parsed_yaml, ignore_doc_style); +} +void test_engine_ints_from_yaml_noresize(EngineEvtTestCase const& test_case, std::string const& parsed_yaml, bool ignore_doc_style) +{ + test_engine_ints_from_yaml(test_case, parsed_yaml, ignore_doc_style); +} + //----------------------------------------------------------------------------- @@ -276,7 +381,7 @@ void test_expected_error_tree_from_yaml(EngineEvtTestCase const& test_case, Expe ParseEngine parser(&handler, test_case.opts); ASSERT_EQ(&handler, parser.m_evt_handler); ASSERT_EQ(&tree, parser.m_evt_handler->m_tree); - parser.parse_in_place_ev(test_case.fileline, to_substr(copy)); + parser.parse_in_place_ev(to_csubstr(test_case.fileline), to_substr(copy)); }, test_case.expected_error_location); } } @@ -296,7 +401,7 @@ void test_engine_tree_from_yaml(EngineEvtTestCase const& test_case, std::string ASSERT_EQ(&handler, parser.m_evt_handler); ASSERT_EQ(&parsed_tree, parser.m_evt_handler->m_tree); std::vector copy(yaml.begin(), yaml.end()); // g++ 4.8 fails with std::string - parser.parse_in_place_ev(test_case.fileline, to_substr(copy)); + parser.parse_in_place_ev(to_csubstr(test_case.fileline), to_substr(copy)); std::string actual_emitted = emitrs_yaml(parsed_tree); auto show_info = [&]{ printf("source: ~~~\n%.*s~~~\n", (int)test_case.yaml.size(), test_case.yaml.data()); @@ -328,7 +433,7 @@ void test_engine_tree_from_yaml(EngineEvtTestCase const& test_case, std::string EventHandlerTree unresolved_handler(&unresolved_tree, unresolved_tree.root_id()); ParseEngine unresolved_parser(&unresolved_handler, unresolved_opts); std::vector unresolved_copy(yaml.begin(), yaml.end()); // g++ 4.8 fails with std::string - unresolved_parser.parse_in_place_ev(test_case.fileline, to_substr(unresolved_copy)); + unresolved_parser.parse_in_place_ev(to_csubstr(test_case.fileline), to_substr(unresolved_copy)); TagCache tag_cache; Tree resolved_tree = unresolved_tree; resolved_tree.resolve_tags(tag_cache, resolve_all); @@ -356,11 +461,11 @@ void test_engine_tree_from_yaml(EngineEvtTestCase const& test_case, std::string //----------------------------------------------------------------------------- -void test_engine_roundtrip_from_events(EngineEvtTestCase const& test_case, EventProducerTree event_producer) +void test_engine_roundtrip_tree_from_events(EngineEvtTestCase const& test_case, EventProducerTree event_producer) { if(test_case.test_case_flags & HAS_CONTAINER_KEYS) return; - SCOPED_TRACE("roundtrip_from_events"); + SCOPED_TRACE("roundtrip_tree_from_events"); Tree event_tree = {}; EventHandlerTree handler(&event_tree, event_tree.root_id()); event_producer(handler); @@ -371,7 +476,7 @@ void test_engine_roundtrip_from_events(EngineEvtTestCase const& test_case, Event const std::string emitted0 = emitrs_yaml(event_tree); EXPECT_EQ(test_case.expected_emitted, emitted0); std::string copy = emitted0; - Tree after_roundtrip = parse_in_place(test_case.fileline, to_substr(copy), test_case.opts); + Tree after_roundtrip = parse_in_place(to_csubstr(test_case.fileline), to_substr(copy), test_case.opts); { SCOPED_TRACE("test_invariants_after_roundtrip"); test_invariants(after_roundtrip); @@ -392,13 +497,68 @@ void test_engine_roundtrip_from_events(EngineEvtTestCase const& test_case, Event } } -void test_engine_roundtrip_from_yaml(EngineEvtTestCase const& test_case, std::string const& yaml) +template +static void test_engine_roundtrip_ints_from_events(EngineEvtTestCase const& test_case, EventProducerInts event_producer) +{ + SCOPED_TRACE("roundtrip_ints_from_events"); + EngineTestIntBuffers buffers1, buffers2; + std::vector parsed_yaml1; + std::string emitted1, emitted2; + { + SCOPED_TRACE("ints_from_events"); + test_engine_ints_from_events(test_case, event_producer, buffers1, parsed_yaml1); + buffers1.buf.emitrs_yaml(&emitted1); + if(!(test_case.test_case_flags & NO_COMPARE_EMITTED)) + extra::ievt::test_compare_emitted_yaml_ints(emitted1, test_case.expected_emitted); + } + std::vector parsed_yaml2{emitted1.begin(), emitted1.end()}; + if(!testing::Test::HasFailure()) + { + SCOPED_TRACE("roundtrip_parse2"); + test_engine_ints_from_yaml(buffers2, to_substr(parsed_yaml2), test_case, emitted1, + /*ignore_doc_style*/true); + buffers2.buf.emitrs_yaml(&emitted2); + if(!(test_case.test_case_flags & NO_COMPARE_EMITTED)) + extra::ievt::test_compare_emitted_yaml_ints(emitted2, test_case.expected_emitted); + } + if(!testing::Test::HasFailure()) + { + SCOPED_TRACE("roundtrip_compare"); + test_events_ints_compare(buffers1.buf, buffers2.buf); + EXPECT_EQ(emitted1, emitted2); + } + if(testing::Test::HasFailure()) + { + printf("source: ~~~\n%.*s~~~\n", (int)test_case.yaml.size(), test_case.yaml.data()); + printf("parsed1:\n"); + buffers1.buf.print(); + printf("parsed1_emitted: ~~~\n%.*s~~~\n", (int)emitted1.size(), emitted1.data()); + printf("parsed2 (after roundtrip):\n"); + buffers2.buf.print(); + printf("parsed2_emitted: ~~~\n%.*s~~~\n", (int)emitted2.size(), emitted2.data()); + } +} +void test_engine_roundtrip_ints_from_events_resize(EngineEvtTestCase const& test_case, EventProducerIntsResize evts) +{ + SCOPED_TRACE("roundtrip_ints_from_events_resize"); + test_engine_roundtrip_ints_from_events(test_case, evts); +} +void test_engine_roundtrip_ints_from_events_noresize(EngineEvtTestCase const& test_case, EventProducerIntsNoResize evts) +{ + SCOPED_TRACE("roundtrip_ints_from_events_noresize"); + test_engine_roundtrip_ints_from_events(test_case, evts); +} + + +//----------------------------------------------------------------------------- + +void test_engine_roundtrip_tree_from_yaml(EngineEvtTestCase const& test_case, std::string const& yaml) { if(test_case.test_case_flags & HAS_CONTAINER_KEYS) // NOLINT return; - SCOPED_TRACE("test_engine_roundtrip_from_yaml"); + SCOPED_TRACE("roundtrip_tree_from_yaml"); std::string copy = yaml; - const Tree parsed_tree = parse_in_place(test_case.fileline, to_substr(copy), test_case.opts); + const Tree parsed_tree = parse_in_place(to_csubstr(test_case.fileline), to_substr(copy), test_case.opts); #ifdef RYML_DBG print_tree("parsed_tree", parsed_tree); #endif @@ -412,7 +572,7 @@ void test_engine_roundtrip_from_yaml(EngineEvtTestCase const& test_case, std::st EXPECT_EQ(test_case.expected_emitted, parsed_tree_emitted); } std::string emitted0_copy = parsed_tree_emitted; - const Tree after_roundtrip = parse_in_place(test_case.fileline, to_substr(emitted0_copy), test_case.opts); + const Tree after_roundtrip = parse_in_place(to_csubstr(test_case.fileline), to_substr(emitted0_copy), test_case.opts); { SCOPED_TRACE("invariants_after_roundtrip"); test_invariants(after_roundtrip); @@ -438,6 +598,62 @@ void test_engine_roundtrip_from_yaml(EngineEvtTestCase const& test_case, std::st } +template +static void test_engine_roundtrip_ints_from_yaml(EngineEvtTestCase const& test_case, std::string const& yaml) +{ + SCOPED_TRACE("roundtrip_ints_from_yaml"); + EngineTestIntBuffers buffers1 = {}, buffers2 = {}; + std::string emitted1, emitted2; + extra::ievt::evt_size num_ints = 0; + std::vector parsed_yaml1{yaml.begin(), yaml.end()}; + { + SCOPED_TRACE("roundtrip_parse1"); + test_engine_ints_from_yaml(buffers1, to_substr(parsed_yaml1), test_case, yaml); + num_ints = buffers1.buf.evts.len; + buffers1.buf.emitrs_yaml(&emitted1); + if(!(test_case.test_case_flags & NO_COMPARE_EMITTED)) + extra::ievt::test_compare_emitted_yaml_ints(emitted1, test_case.expected_emitted); + } + std::vector parsed_yaml2{emitted1.begin(), emitted1.end()}; + if(!testing::Test::HasFailure()) + { + SCOPED_TRACE("roundtrip_parse2"); + test_engine_ints_from_yaml(buffers2, to_substr(parsed_yaml2), test_case, emitted1, + /*ignore_doc_style*/true); + EXPECT_EQ(num_ints, buffers2.buf.evts.len); + buffers2.buf.emitrs_yaml(&emitted2); + if(!(test_case.test_case_flags & NO_COMPARE_EMITTED)) + extra::ievt::test_compare_emitted_yaml_ints(emitted2, test_case.expected_emitted); + } + if(!testing::Test::HasFailure()) + { + SCOPED_TRACE("roundtrip_compare"); + test_events_ints_compare(buffers1.buf, buffers2.buf); + EXPECT_EQ(emitted1, emitted2); + } + if(testing::Test::HasFailure()) + { + printf("source: ~~~\n%.*s~~~\n", (int)yaml.size(), yaml.data()); + printf("parsed1:\n"); + buffers1.buf.print(); + printf("parsed1_emitted: ~~~\n%.*s~~~\n", (int)emitted1.size(), emitted1.data()); + printf("parsed2 (after roundtrip):\n"); + buffers2.buf.print(); + printf("parsed2_emitted: ~~~\n%.*s~~~\n", (int)emitted2.size(), emitted2.data()); + } +} +void test_engine_roundtrip_ints_from_yaml_resize(EngineEvtTestCase const& test_case, std::string const& parsed_yaml) +{ + SCOPED_TRACE("roundtrip_ints_from_yaml_resize"); + test_engine_roundtrip_ints_from_yaml(test_case, parsed_yaml); +} +void test_engine_roundtrip_ints_from_yaml_noresize(EngineEvtTestCase const& test_case, std::string const& parsed_yaml) +{ + SCOPED_TRACE("roundtrip_ints_from_yaml_noresize"); + test_engine_roundtrip_ints_from_yaml(test_case, parsed_yaml); +} + + //----------------------------------------------------------------------------- namespace { @@ -472,7 +688,9 @@ std::vector inject_comments_in_src(std::string const& src_) } } // anon -void test_engine_ints_from_yaml_with_comments(EngineEvtTestCase const& test_case) + +template +static void test_engine_ints_from_yaml_with_comments(EngineEvtTestCase const& test_case) { SCOPED_TRACE("test_engine_ints_from_yaml_with_comments"); if(test_case.test_case_flags & HAS_MULTILINE_SCALAR) @@ -484,11 +702,22 @@ void test_engine_ints_from_yaml_with_comments(EngineEvtTestCase const& test_case RYML_TRACE_FMT("transformed[{}/{}]=~~~[{}]\n{}\n~~~", i, injected_comment_cases.size(), transformed_str.size(), to_csubstr(transformed_str)); SCOPED_TRACE(transformed_str); SCOPED_TRACE("commented"); - test_engine_ints_from_yaml(test_case, transformed_str); + test_engine_ints_from_yaml(test_case, transformed_str); if(testing::Test::HasFailure()) break; } } +void test_engine_ints_from_yaml_with_comments_resize(EngineEvtTestCase const& test_case) +{ + SCOPED_TRACE("test_engine_ints_from_yaml_with_comments_resize"); + test_engine_ints_from_yaml_with_comments(test_case); +} +void test_engine_ints_from_yaml_with_comments_noresize(EngineEvtTestCase const& test_case) +{ + SCOPED_TRACE("test_engine_ints_from_yaml_with_comments_noresize"); + test_engine_ints_from_yaml_with_comments(test_case); +} + void test_engine_tree_from_yaml_with_comments(EngineEvtTestCase const& test_case) { @@ -510,7 +739,7 @@ void test_engine_tree_from_yaml_with_comments(EngineEvtTestCase const& test_case } } -void test_engine_roundtrip_from_yaml_with_comments(EngineEvtTestCase const& test_case) +void test_engine_roundtrip_tree_from_yaml_with_comments(EngineEvtTestCase const& test_case) { SCOPED_TRACE("test_engine_roundtrip_from_yaml_with_comments"); if(test_case.test_case_flags & HAS_CONTAINER_KEYS) @@ -526,172 +755,43 @@ void test_engine_roundtrip_from_yaml_with_comments(EngineEvtTestCase const& test RYML_TRACE_FMT("transformed[{}/{}]=~~~[{}]\n{}\n~~~", i, injected_comment_cases.size(), transformed_str.size(), to_csubstr(transformed_str)); SCOPED_TRACE(transformed_str); SCOPED_TRACE("commented"); - test_engine_roundtrip_from_yaml(test_case, transformed_str); + test_engine_roundtrip_tree_from_yaml(test_case, transformed_str); if(testing::Test::HasFailure()) break; } } - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -csubstr parse_anchor_and_tag(csubstr tokens, OptionalScalar *anchor, OptionalScalar *tag) +template +static void test_engine_roundtrip_ints_from_yaml_with_comments(EngineEvtTestCase const& test_case) { - *anchor = OptionalScalar{}; - *tag = OptionalScalar{}; - if(tokens.begins_with('&')) + SCOPED_TRACE("test_engine_roundtrip_from_yaml_with_comments"); + if(test_case.test_case_flags & HAS_MULTILINE_SCALAR) + return; + if(test_case.test_case_flags & NO_COMPARE_EMITTED) + return; + const auto injected_comment_cases = inject_comments_in_src(test_case.yaml); + for(size_t i = 0; i < injected_comment_cases.size(); ++i) { - size_t pos = tokens.first_of(' '); - if(pos == (size_t)csubstr::npos) - { - *anchor = tokens.sub(1); - tokens = {}; - } - else - { - *anchor = tokens.first(pos).sub(1); - tokens = tokens.right_of(pos); - } - _c4dbgpf("anchor: {}", anchor->get()); - } - if(tokens.begins_with('<')) - { - size_t pos = tokens.find('>'); - RYML_ASSERT_BASIC_(pos != (size_t)csubstr::npos); - *tag = tokens.first(pos + 1); - tokens = tokens.right_of(pos).triml(' '); - _c4dbgpf("tag: {}", tag->maybe_get()); - } - return tokens; -} - -void test_compare_events(csubstr ref_evts, - csubstr emt_evts, - bool ignore_doc_style, - bool ignore_container_style, - bool ignore_scalar_style, - bool ignore_tag_normalization) -{ - RYML_TRACE_FMT("actual=~~~\n{}~~~", emt_evts); - RYML_TRACE_FMT("expected=~~~\n{}~~~", ref_evts); - auto test_anchor_tag = [&](csubstr &ref, csubstr &emt){ - OptionalScalar reftag = {}, refanchor = {}; - OptionalScalar emttag = {}, emtanchor = {}; - ref = parse_anchor_and_tag(ref, &refanchor, &reftag).triml(' '); - emt = parse_anchor_and_tag(emt, &emtanchor, &emttag).triml(' '); - EXPECT_EQ(bool(refanchor), bool(emtanchor)); - if(bool(refanchor) && bool(emtanchor)) - { - EXPECT_EQ(refanchor.get(), emtanchor.get()); - } - EXPECT_EQ(bool(reftag), bool(emttag)); - if(reftag && emttag) - { - if(!ignore_tag_normalization) - { - EXPECT_EQ(reftag.get(), emttag.get()); - } - } - }; - auto test_doc = [&](csubstr ref, csubstr emt){ - EXPECT_TRUE(ref.begins_with("+DOC") || ref.begins_with("-DOC")); - EXPECT_TRUE(emt.begins_with("+DOC") || emt.begins_with("-DOC")); - EXPECT_EQ(emt.begins_with("+DOC"), ref.begins_with("+DOC")); - EXPECT_EQ(emt.begins_with("-DOC"), ref.begins_with("-DOC")); - if(ignore_doc_style) - { - if(ref.begins_with("+DOC")) - { - ref = ref.stripr("---").trimr(' '); - emt = emt.stripr("---").trimr(' '); - } - else - { - ASSERT_TRUE(ref.begins_with("-DOC")); - ref = ref.stripr("...").trimr(' '); - emt = emt.stripr("...").trimr(' '); - } - } - EXPECT_EQ(ref, emt); - }; - auto test_container = [&](csubstr ref, csubstr emt){ - RYML_TRACE_FMT("expected={}", ref); - RYML_TRACE_FMT("actual={}", emt); - EXPECT_TRUE(ref.begins_with("+MAP") || ref.begins_with("+SEQ")); - EXPECT_TRUE(emt.begins_with("+MAP") || emt.begins_with("+SEQ")); - EXPECT_EQ(emt.begins_with("+MAP"), ref.begins_with("+MAP")); - EXPECT_EQ(emt.begins_with("+SEQ"), ref.begins_with("+SEQ")); - csubstr rest_ref = ref.sub(4).triml(' '); - csubstr rest_emt = emt.sub(4).triml(' '); - if(rest_ref.begins_with("{}")) - { - if(!ignore_container_style) - { - EXPECT_TRUE(rest_emt.begins_with("{}")); - } - } - else if(rest_ref.begins_with("[]")) - { - if(!ignore_container_style) - { - EXPECT_TRUE(rest_emt.begins_with("[]")); - } - } - test_anchor_tag(ref, emt); - }; - auto test_val_with_scalar_wildcard = [&](csubstr ref, csubstr emt){ - ASSERT_TRUE(ref.begins_with("=VAL ")); - ASSERT_TRUE(emt.begins_with("=VAL ")); - ref = ref.sub(5); - emt = emt.sub(5); - test_anchor_tag(ref, emt); - ASSERT_GE(ref.len, 0); - ASSERT_GE(emt.len, 0); - EXPECT_TRUE(ref[0] == ':' || ref[0] == '\'' || ref[0] == '"' || ref[0] == '|' || ref[0] == '>'); - EXPECT_TRUE(emt[0] == ':' || emt[0] == '\'' || emt[0] == '"' || emt[0] == '|' || emt[0] == '>'); - if(!ignore_scalar_style) - { - EXPECT_EQ(ref[0], emt[0]); - } - ref = ref.sub(1); - emt = emt.sub(1); - EXPECT_EQ(ref, emt); - }; - EXPECT_EQ(bool(ref_evts.len), bool(emt_evts.len)); - size_t posref = 0; - size_t posemt = 0; - while(posref < ref_evts.len && posemt < emt_evts.len) - { - const size_t endref = ref_evts.find('\n', posref); - const size_t endemt = emt_evts.find('\n', posemt); - ASSERT_FALSE((endref == npos || endemt == npos) && (endref != endemt)); - csubstr ref = ref_evts.range(posref, endref); - csubstr emt = emt_evts.range(posemt, endemt); - if(ref != emt) - { - if(ref.begins_with("+DOC") || emt.begins_with("-DOC")) - { - test_doc(ref, emt); - } - else if(ref.begins_with("+MAP") || ref.begins_with("+SEQ")) - { - test_container(ref, emt); - } - else if(ref.begins_with("=VAL")) - { - test_val_with_scalar_wildcard(ref, emt); - } - else - { - ASSERT_EQ(ref, emt); - } - } - posref = endref + 1u; - posemt = endemt + 1u; + const std::string& transformed_str = injected_comment_cases[i]; + RYML_TRACE_FMT("transformed[{}/{}]=~~~[{}]\n{}\n~~~", i, injected_comment_cases.size(), transformed_str.size(), to_csubstr(transformed_str)); + SCOPED_TRACE(transformed_str); + SCOPED_TRACE("commented"); + test_engine_roundtrip_ints_from_yaml(test_case, transformed_str); + if(testing::Test::HasFailure()) + break; } } +void test_engine_roundtrip_ints_from_yaml_with_comments_resize(EngineEvtTestCase const& test_case) +{ + SCOPED_TRACE("test_engine_roundtrip_from_yaml_with_comments_resize"); + test_engine_roundtrip_ints_from_yaml_with_comments(test_case); +} +void test_engine_roundtrip_ints_from_yaml_with_comments_noresize(EngineEvtTestCase const& test_case) +{ + SCOPED_TRACE("test_engine_roundtrip_from_yaml_with_comments_noresize"); + test_engine_roundtrip_ints_from_yaml_with_comments(test_case); +} + } // namespace yml } // namespace c4 diff --git a/test/test_lib/test_engine.hpp b/test/test_lib/test_engine.hpp index ad649943d..70e63c2ab 100644 --- a/test/test_lib/test_engine.hpp +++ b/test/test_lib/test_engine.hpp @@ -12,8 +12,6 @@ #include #include "./test_lib/test_case.hpp" #include "./test_lib/test_events_ints_helpers.hpp" -#include "./test_lib/string.hpp" -#include "c4/yml/extra/ints_to_testsuite.hpp" #include "c4/yml/extra/event_handler_ints.hpp" #if defined(__clang__) && (__clang_major__ >= 13) @@ -24,62 +22,32 @@ namespace c4 { namespace yml { -//----------------------------------------------------------------------------- - -struct OptionalScalar -{ - csubstr val = {}; - bool was_set = false; - operator csubstr() const { return get(); } - operator bool() const { return was_set; } - void operator= (csubstr v) { val = v; was_set = true; } // NOLINT - csubstr get() const { RYML_ASSERT_BASIC_(was_set); return val; } - csubstr maybe_get() const { return was_set ? val : csubstr(""); } -}; - -csubstr parse_anchor_and_tag(csubstr tokens, OptionalScalar *anchor, OptionalScalar *tag); - -void test_compare_events(csubstr ref_evts, - csubstr emt_evts, - bool ignore_doc_style, - bool ignore_container_style, - bool ignore_scalar_style, - bool ignore_tag_normalization); - - //----------------------------------------------------------------------------- struct EngineEvtTestCase { const char *file; int line; - extra::string fileline; + std::string fileline; ParserOptions opts; TestCaseFlags_e test_case_flags; Location expected_error_location; std::string yaml; std::string expected_emitted; std::string expected_events; - std::vector expected_ints; + std::vector expected_ints; bool expected_ints_enabled; public: - EngineEvtTestCase(const char *file_, int line_, ParserOptions opts_, std::string s , std::string ev) : file(file_), line(line_), opts(opts_), test_case_flags( ), expected_error_location( ), yaml(s ), expected_emitted(std::move(s)), expected_events(std::move(ev)), expected_ints(), expected_ints_enabled(false) { _mkfileline(); } - EngineEvtTestCase(const char *file_, int line_, ParserOptions opts_, std::string p, std::string e, std::string ev) : file(file_), line(line_), opts(opts_), test_case_flags( ), expected_error_location( ), yaml(std::move(p)), expected_emitted(std::move(e)), expected_events(std::move(ev)), expected_ints(), expected_ints_enabled(false) { _mkfileline(); } - EngineEvtTestCase(const char *file_, int line_, ParserOptions opts_, TestCaseFlags_e tf, std::string p, std::string e, std::string ev) : file(file_), line(line_), opts(opts_), test_case_flags(tf), expected_error_location( ), yaml(std::move(p)), expected_emitted(std::move(e)), expected_events(std::move(ev)), expected_ints(), expected_ints_enabled(false) { _mkfileline(); } - EngineEvtTestCase(const char *file_, int line_, ParserOptions opts_, TestCaseFlags_e tf, std::string p , std::string ev) : file(file_), line(line_), opts(opts_), test_case_flags(tf), expected_error_location( ), yaml(p ), expected_emitted(std::move(p)), expected_events(std::move(ev)), expected_ints(), expected_ints_enabled(false) { _mkfileline(); } - EngineEvtTestCase(const char *file_, int line_, ParserOptions opts_, Location linecol_, std::string p , std::string ev) : file(file_), line(line_), opts(opts_), test_case_flags( ), expected_error_location(linecol_), yaml(p ), expected_emitted(std::move(p)), expected_events(std::move(ev)), expected_ints(), expected_ints_enabled(false) { _mkfileline(); } - EngineEvtTestCase(const char *file_, int line_, ParserOptions opts_, TestCaseFlags_e tf, Location linecol_, std::string p, std::string e, std::string ev) : file(file_), line(line_), opts(opts_), test_case_flags(tf), expected_error_location(linecol_), yaml(std::move(p)), expected_emitted(std::move(e)), expected_events(std::move(ev)), expected_ints(), expected_ints_enabled(false) { _mkfileline(); } - EngineEvtTestCase(const char *file_, int line_, ParserOptions opts_, TestCaseFlags_e tf, Location linecol_, std::string p , std::string ev) : file(file_), line(line_), opts(opts_), test_case_flags(tf), expected_error_location(linecol_), yaml(p ), expected_emitted(std::move(p)), expected_events(std::move(ev)), expected_ints(), expected_ints_enabled(false) { _mkfileline(); } - - EngineEvtTestCase(const char *file_, int line_, ParserOptions opts_, std::string s , std::string ev, std::vector ints) : file(file_), line(line_), opts(opts_), test_case_flags( ), expected_error_location( ), yaml(s ), expected_emitted(std::move(s)), expected_events(std::move(ev)), expected_ints(std::move(ints)), expected_ints_enabled(true) { _mkfileline(); } - EngineEvtTestCase(const char *file_, int line_, ParserOptions opts_, std::string p, std::string e, std::string ev, std::vector ints) : file(file_), line(line_), opts(opts_), test_case_flags( ), expected_error_location( ), yaml(std::move(p)), expected_emitted(std::move(e)), expected_events(std::move(ev)), expected_ints(std::move(ints)), expected_ints_enabled(true) { _mkfileline(); } - EngineEvtTestCase(const char *file_, int line_, ParserOptions opts_, TestCaseFlags_e tf, std::string p, std::string e, std::string ev, std::vector ints) : file(file_), line(line_), opts(opts_), test_case_flags(tf), expected_error_location( ), yaml(std::move(p)), expected_emitted(std::move(e)), expected_events(std::move(ev)), expected_ints(std::move(ints)), expected_ints_enabled(true) { _mkfileline(); } - EngineEvtTestCase(const char *file_, int line_, ParserOptions opts_, TestCaseFlags_e tf, std::string p , std::string ev, std::vector ints) : file(file_), line(line_), opts(opts_), test_case_flags(tf), expected_error_location( ), yaml(p ), expected_emitted(std::move(p)), expected_events(std::move(ev)), expected_ints(std::move(ints)), expected_ints_enabled(true) { _mkfileline(); } - EngineEvtTestCase(const char *file_, int line_, ParserOptions opts_, Location linecol_, std::string p , std::string ev, std::vector ints) : file(file_), line(line_), opts(opts_), test_case_flags( ), expected_error_location(linecol_), yaml(p ), expected_emitted(std::move(p)), expected_events(std::move(ev)), expected_ints(std::move(ints)), expected_ints_enabled(true) { _mkfileline(); } - EngineEvtTestCase(const char *file_, int line_, ParserOptions opts_, TestCaseFlags_e tf, Location linecol_, std::string p, std::string e, std::string ev, std::vector ints) : file(file_), line(line_), opts(opts_), test_case_flags(tf), expected_error_location(linecol_), yaml(std::move(p)), expected_emitted(std::move(e)), expected_events(std::move(ev)), expected_ints(std::move(ints)), expected_ints_enabled(true) { _mkfileline(); } - EngineEvtTestCase(const char *file_, int line_, ParserOptions opts_, TestCaseFlags_e tf, Location linecol_, std::string p , std::string ev, std::vector ints) : file(file_), line(line_), opts(opts_), test_case_flags(tf), expected_error_location(linecol_), yaml( p), expected_emitted(std::move(p)), expected_events(std::move(ev)), expected_ints(std::move(ints)), expected_ints_enabled(true) { _mkfileline(); } + EngineEvtTestCase(const char *file_, int line_, ParserOptions opts_, std::string s , std::string ev, std::vector ints={}) : file(file_), line(line_), opts(opts_), test_case_flags( ), expected_error_location( ), yaml(s ), expected_emitted(std::move(s)), expected_events(std::move(ev)), expected_ints(std::move(ints)), expected_ints_enabled(!expected_ints.empty()) { _mkfileline(); } + EngineEvtTestCase(const char *file_, int line_, ParserOptions opts_, TestCaseFlags_e tf, std::string p , std::string ev, std::vector ints={}) : file(file_), line(line_), opts(opts_), test_case_flags(tf), expected_error_location( ), yaml(p ), expected_emitted(std::move(p)), expected_events(std::move(ev)), expected_ints(std::move(ints)), expected_ints_enabled(!expected_ints.empty()) { _mkfileline(); } + EngineEvtTestCase(const char *file_, int line_, ParserOptions opts_, std::string p, std::string e, std::string ev, std::vector ints={}) : file(file_), line(line_), opts(opts_), test_case_flags( ), expected_error_location( ), yaml(std::move(p)), expected_emitted(std::move(e)), expected_events(std::move(ev)), expected_ints(std::move(ints)), expected_ints_enabled(!expected_ints.empty()) { _mkfileline(); } + EngineEvtTestCase(const char *file_, int line_, ParserOptions opts_, TestCaseFlags_e tf, std::string p, std::string e, std::string ev, std::vector ints={}) : file(file_), line(line_), opts(opts_), test_case_flags(tf), expected_error_location( ), yaml(std::move(p)), expected_emitted(std::move(e)), expected_events(std::move(ev)), expected_ints(std::move(ints)), expected_ints_enabled(!expected_ints.empty()) { _mkfileline(); } + EngineEvtTestCase(const char *file_, int line_, ParserOptions opts_, Location linecol_, std::string p , std::string ev, std::vector ints={}) : file(file_), line(line_), opts(opts_), test_case_flags( ), expected_error_location(linecol_), yaml(p ), expected_emitted(std::move(p)), expected_events(std::move(ev)), expected_ints(std::move(ints)), expected_ints_enabled(!expected_ints.empty()) { _mkfileline(); } + EngineEvtTestCase(const char *file_, int line_, ParserOptions opts_, TestCaseFlags_e tf, Location linecol_, std::string p , std::string ev, std::vector ints={}) : file(file_), line(line_), opts(opts_), test_case_flags(tf), expected_error_location(linecol_), yaml( p), expected_emitted(std::move(p)), expected_events(std::move(ev)), expected_ints(std::move(ints)), expected_ints_enabled(!expected_ints.empty()) { _mkfileline(); } + EngineEvtTestCase(const char *file_, int line_, ParserOptions opts_, Location linecol_, std::string p, std::string e, std::string ev, std::vector ints={}) : file(file_), line(line_), opts(opts_), test_case_flags( ), expected_error_location(linecol_), yaml(std::move(p)), expected_emitted(std::move(e)), expected_events(std::move(ev)), expected_ints(std::move(ints)), expected_ints_enabled(!expected_ints.empty()) { _mkfileline(); } + EngineEvtTestCase(const char *file_, int line_, ParserOptions opts_, TestCaseFlags_e tf, Location linecol_, std::string p, std::string e, std::string ev, std::vector ints={}) : file(file_), line(line_), opts(opts_), test_case_flags(tf), expected_error_location(linecol_), yaml(std::move(p)), expected_emitted(std::move(e)), expected_events(std::move(ev)), expected_ints(std::move(ints)), expected_ints_enabled(!expected_ints.empty()) { _mkfileline(); } private: void _mkfileline() { c4::formatrs(&fileline, "{}:{}: (testyaml)", file, line); } @@ -106,10 +74,16 @@ static const EngineEvtTestCase test_case_err_##name( \ ""); \ \ \ -TEST(name, err_ints_from_yaml) \ +TEST(name, err_ints_from_yaml_resize) \ +{ \ + SCOPED_TRACE(#name ".err_ints_from_yaml_resize"); \ + test_expected_error_ints_from_yaml_resize(test_case_err_##name, \ + ExpectedErrorType::err_parse); \ +} \ +TEST(name, err_ints_from_yaml_noresize) \ { \ - SCOPED_TRACE(#name ".err_ints_from_yaml"); \ - test_expected_error_ints_from_yaml(test_case_err_##name, \ + SCOPED_TRACE(#name ".err_ints_from_yaml_noresize"); \ + test_expected_error_ints_from_yaml_noresize(test_case_err_##name, \ ExpectedErrorType::err_parse); \ } \ \ @@ -142,7 +116,8 @@ static void events_##name(EvtHandlerClass &handler); \ \ /* explicitly instantiate the event producers */ \ -template void events_##name(EventHandlerIntsTr&); \ +template void events_##name(EventHandlerIntsTrResize&); \ +template void events_##name(EventHandlerIntsTrNoResize&); \ template void events_##name(EventHandlerTree&); \ \ \ @@ -170,11 +145,17 @@ ENGINE_TEST_DECLARE_CASE(name, __VA_ARGS__) \ \ \ \ -TEST(name, ints_from_events) \ +TEST(name, ints_from_events_resize) \ { \ - SCOPED_TRACE(#name ".ints_from_events"); \ - test_engine_ints_from_events(test_case_##name, \ - &events_##name); \ + SCOPED_TRACE(#name ".ints_from_events_resize"); \ + test_engine_ints_from_events_resize(test_case_##name, \ + &events_##name); \ +} \ +TEST(name, ints_from_events_noresize) \ +{ \ + SCOPED_TRACE(#name ".ints_from_events_noresize"); \ + test_engine_ints_from_events_noresize(test_case_##name, \ + &events_##name); \ } \ \ TEST(name, tree_from_events) \ @@ -186,10 +167,15 @@ TEST(name, tree_from_events) \ \ \ \ -TEST(name, ints_from_yaml) \ +TEST(name, ints_from_yaml_resize) \ { \ - SCOPED_TRACE(#name ".event_ints_from_yaml"); \ - test_engine_ints_from_yaml(test_case_##name); \ + SCOPED_TRACE(#name ".event_ints_from_yaml_resize"); \ + test_engine_ints_from_yaml_resize(test_case_##name); \ +} \ +TEST(name, ints_from_yaml_noresize) \ +{ \ + SCOPED_TRACE(#name ".event_ints_from_yaml_noresize"); \ + test_engine_ints_from_yaml_noresize(test_case_##name); \ } \ \ TEST(name, tree_from_yaml) \ @@ -200,37 +186,82 @@ TEST(name, tree_from_yaml) \ \ \ \ -TEST(name, roundtrip_from_events) \ +TEST(name, roundtrip_ints_from_events_resize) \ +{ \ + SCOPED_TRACE(#name ".roundtrip_ints_from_events_resize"); \ + test_engine_roundtrip_ints_from_events_resize( \ + test_case_##name, \ + &events_##name); \ +} \ +TEST(name, roundtrip_ints_from_events_noresize) \ { \ - SCOPED_TRACE(#name ".roundtrip_from_events"); \ - test_engine_roundtrip_from_events(test_case_##name, \ - &events_##name); \ + SCOPED_TRACE(#name ".roundtrip_ints_from_events_noresize"); \ + test_engine_roundtrip_ints_from_events_noresize( \ + test_case_##name, \ + &events_##name); \ } \ \ -TEST(name, roundtrip_from_yaml) \ +TEST(name, roundtrip_tree_from_events) \ { \ - SCOPED_TRACE(#name ".tree_from_yaml"); \ - test_engine_roundtrip_from_yaml(test_case_##name); \ + SCOPED_TRACE(#name ".roundtrip_tree_from_events"); \ + test_engine_roundtrip_tree_from_events( \ + test_case_##name, \ + &events_##name); \ } \ \ \ \ -TEST(name, ints_from_yaml_with_comments) \ +TEST(name, roundtrip_ints_from_yaml_resize) \ { \ - SCOPED_TRACE(#name ".ints_from_yaml_with_comments"); \ - test_engine_ints_from_yaml_with_comments(test_case_##name); \ + SCOPED_TRACE(#name ".roundtrip_ints_from_yaml_resize"); \ + test_engine_roundtrip_ints_from_yaml_resize(test_case_##name); \ +} \ +TEST(name, roundtrip_ints_from_yaml_noresize) \ +{ \ + SCOPED_TRACE(#name ".roundtrip_ints_from_yaml_noresize"); \ + test_engine_roundtrip_ints_from_yaml_noresize(test_case_##name); \ +} \ + \ +TEST(name, roundtrip_tree_from_yaml) \ +{ \ + SCOPED_TRACE(#name ".roundtrip_tree_from_yaml"); \ + test_engine_roundtrip_tree_from_yaml(test_case_##name); \ +} \ + \ + \ + \ +TEST(name, ints_from_yaml_with_comments_resize) \ +{ \ + SCOPED_TRACE(#name ".ints_from_yaml_with_comments_resize"); \ + test_engine_ints_from_yaml_with_comments_resize(test_case_##name); \ +} \ +TEST(name, ints_from_yaml_with_comments_noresize) \ +{ \ + SCOPED_TRACE(#name ".ints_from_yaml_with_comments_noresize"); \ + test_engine_ints_from_yaml_with_comments_noresize(test_case_##name); \ } \ \ TEST(name, tree_from_yaml_with_comments) \ { \ - SCOPED_TRACE(#name ".tree_from_yaml"); \ + SCOPED_TRACE(#name ".tree_from_yaml_with_comments"); \ test_engine_tree_from_yaml_with_comments(test_case_##name); \ } \ \ -TEST(name, roundtrip_from_yaml_with_comments) \ +TEST(name, roundtrip_ints_from_yaml_with_comments_resize) \ { \ - SCOPED_TRACE(#name ".roundtrip_from_yaml"); \ - test_engine_roundtrip_from_yaml_with_comments(test_case_##name); \ + SCOPED_TRACE(#name ".roundtrip_ints_from_yaml_with_comments_resize"); \ + test_engine_roundtrip_ints_from_yaml_with_comments_resize(test_case_##name); \ +} \ +TEST(name, roundtrip_ints_from_yaml_with_comments_noresize) \ +{ \ + SCOPED_TRACE(#name ".roundtrip_ints_from_yaml_with_comments_noresize"); \ + test_engine_roundtrip_ints_from_yaml_with_comments_noresize(test_case_##name); \ +} \ + \ +TEST(name, roundtrip_tree_from_yaml_with_comments) \ +{ \ + SCOPED_TRACE(#name ".roundtrip_tree_from_yaml_with_comments"); \ + test_engine_roundtrip_tree_from_yaml_with_comments(test_case_##name); \ } \ \ \ @@ -242,9 +273,17 @@ ENGINE_TEST_DEFINE_CASE(name) \ template struct EventTransformer; template struct TransformToSourceBufferOrArena; -using EventHandlerIntsTr = EventTransformer>; - -using EventProducerInts = void (*)(EventHandlerIntsTr &); +template +using EventHandlerIntsTr = EventTransformer< + extra::ievt::EventHandlerInts, + TransformToSourceBufferOrArena>>; +using EventHandlerIntsTrResize = EventHandlerIntsTr; +using EventHandlerIntsTrNoResize = EventHandlerIntsTr; + +template +using EventProducerInts = void (*)(EventHandlerIntsTr &); +using EventProducerIntsResize = EventProducerInts; +using EventProducerIntsNoResize = EventProducerInts; using EventProducerTree = void (*)(EventHandlerTree &); @@ -252,34 +291,51 @@ using EventProducerTree = void (*)(EventHandlerTree &); //----------------------------------------------------------------------------- -void test_engine_ints_from_events(EngineEvtTestCase const& test_case, EventProducerInts evts); -void test_engine_error_ints_from_events(const EngineEvtTestCase& test_case, EventProducerInts fn); -void test_engine_ints_from_yaml(EngineEvtTestCase const& test_case, std::string const& parsed_yaml); -inline void test_engine_ints_from_yaml(EngineEvtTestCase const& test_case) { test_engine_ints_from_yaml(test_case, test_case.yaml); } -void test_engine_ints_from_yaml_with_comments(EngineEvtTestCase const& test_case); -void test_expected_error_ints_from_yaml(EngineEvtTestCase const& test_case, ExpectedErrorType errtype); +void test_engine_error_ints_from_events_resize(const EngineEvtTestCase& test_case, EventProducerIntsResize fn); +void test_engine_error_ints_from_events_noresize(const EngineEvtTestCase& test_case, EventProducerIntsNoResize fn); +void test_expected_error_ints_from_yaml_resize(EngineEvtTestCase const& test_case, ExpectedErrorType errtype); +void test_expected_error_ints_from_yaml_noresize(EngineEvtTestCase const& test_case, ExpectedErrorType errtype); + +void test_engine_ints_from_events_resize(EngineEvtTestCase const& test_case, EventProducerIntsResize evts); +void test_engine_ints_from_events_noresize(EngineEvtTestCase const& test_case, EventProducerIntsNoResize evts); +void test_engine_ints_from_yaml_resize(EngineEvtTestCase const& test_case, std::string const& parsed_yaml, bool ignore_doc_style=false); +void test_engine_ints_from_yaml_noresize(EngineEvtTestCase const& test_case, std::string const& parsed_yaml, bool ignore_doc_style=false); +inline void test_engine_ints_from_yaml_resize(EngineEvtTestCase const& test_case) { test_engine_ints_from_yaml_resize(test_case, test_case.yaml); } +inline void test_engine_ints_from_yaml_noresize(EngineEvtTestCase const& test_case) { test_engine_ints_from_yaml_noresize(test_case, test_case.yaml); } +void test_engine_ints_from_yaml_with_comments_resize(EngineEvtTestCase const& test_case); +void test_engine_ints_from_yaml_with_comments_noresize(EngineEvtTestCase const& test_case); + +void test_engine_roundtrip_ints_from_events_resize(EngineEvtTestCase const& test_case, EventProducerIntsResize evts); +void test_engine_roundtrip_ints_from_events_noresize(EngineEvtTestCase const& test_case, EventProducerIntsNoResize evts); +void test_engine_roundtrip_ints_from_yaml_resize(EngineEvtTestCase const& test_case, std::string const& parsed_yaml); +void test_engine_roundtrip_ints_from_yaml_noresize(EngineEvtTestCase const& test_case, std::string const& parsed_yaml); +inline void test_engine_roundtrip_ints_from_yaml_resize(EngineEvtTestCase const& test_case) { test_engine_roundtrip_ints_from_yaml_resize(test_case, test_case.yaml); } +inline void test_engine_roundtrip_ints_from_yaml_noresize(EngineEvtTestCase const& test_case) { test_engine_roundtrip_ints_from_yaml_noresize(test_case, test_case.yaml); } +void test_engine_roundtrip_ints_from_yaml_with_comments_resize(EngineEvtTestCase const& test_case); +void test_engine_roundtrip_ints_from_yaml_with_comments_noresize(EngineEvtTestCase const& test_case); //----------------------------------------------------------------------------- -void test_engine_tree_from_events(EngineEvtTestCase const& test_case, EventProducerTree evts); void test_engine_error_tree_from_events(const EngineEvtTestCase& test_case, EventProducerTree evts); +void test_expected_error_tree_from_yaml(EngineEvtTestCase const& test_case, ExpectedErrorType errtype); + +void test_engine_tree_from_events(EngineEvtTestCase const& test_case, EventProducerTree evts); void test_engine_tree_from_yaml(EngineEvtTestCase const& test_case, std::string const& parsed_yaml); inline void test_engine_tree_from_yaml(EngineEvtTestCase const& test_case) { test_engine_tree_from_yaml(test_case, test_case.yaml); } void test_engine_tree_from_yaml_with_comments(EngineEvtTestCase const& test_case); -void test_expected_error_tree_from_yaml(EngineEvtTestCase const& test_case, ExpectedErrorType errtype); - - -//----------------------------------------------------------------------------- -void test_engine_roundtrip_from_events(EngineEvtTestCase const& test_case, EventProducerTree evts); -void test_engine_roundtrip_from_yaml(EngineEvtTestCase const& test_case, std::string const& parsed_yaml); -inline void test_engine_roundtrip_from_yaml(EngineEvtTestCase const& test_case) { test_engine_roundtrip_from_yaml(test_case, test_case.yaml); } -void test_engine_roundtrip_from_yaml_with_comments(EngineEvtTestCase const& test_case); +void test_engine_roundtrip_tree_from_events(EngineEvtTestCase const& test_case, EventProducerTree evts); +void test_engine_roundtrip_tree_from_yaml(EngineEvtTestCase const& test_case, std::string const& parsed_yaml); +inline void test_engine_roundtrip_tree_from_yaml(EngineEvtTestCase const& test_case) { test_engine_roundtrip_tree_from_yaml(test_case, test_case.yaml); } +void test_engine_roundtrip_tree_from_yaml_with_comments(EngineEvtTestCase const& test_case); //----------------------------------------------------------------------------- +template +struct EventTransformer; + #if !defined(RYML_DBG) #define ___(stmt) stmt #else @@ -293,10 +349,8 @@ void test_engine_roundtrip_from_yaml_with_comments(EngineEvtTestCase const& test void print_handler_info_(EventHandlerTree const& ps, csubstr stmt, const char *file, int line); -void print_handler_info_(extra::EventHandlerInts const& ps, csubstr stmt, const char *file, int line); - -template -struct EventTransformer; +template +void print_handler_info_(extra::ievt::EventHandlerInts const& ps, csubstr stmt, const char *file, int line); template void print_handler_info_(EventTransformer const& ps, csubstr stmt, const char *file, int line) { diff --git a/test/test_lib/test_events_ints_helpers.cpp b/test/test_lib/test_events_ints_helpers.cpp index 5eaa23851..fdb3e09f6 100644 --- a/test/test_lib/test_events_ints_helpers.cpp +++ b/test/test_lib/test_events_ints_helpers.cpp @@ -6,6 +6,7 @@ namespace c4 { namespace yml { namespace extra { +namespace ievt { size_t num_ints(IntEventWithScalar const *evt, size_t evt_sz) { @@ -15,9 +16,49 @@ size_t num_ints(IntEventWithScalar const *evt, size_t evt_sz) return sz; } +void test_events_ints_compare(ievt::Buffers const& expected, ievt::Buffers const& actual) +{ + bool samelen = actual.evts.len == expected.evts.len; + int samemem = memcmp(actual.evts.ptr, expected.evts.ptr, (size_t)actual.evts.len * sizeof(actual.evts.ptr[0])); + if(samelen && samemem) + return; + EXPECT_EQ(actual.evts.len, expected.evts.len); + EXPECT_EQ(0, samemem); + const evt_size minsz = actual.evts.len < expected.evts.len ? actual.evts.len : expected.evts.len; + char abuf[200];(void)abuf; + char ebuf[200];(void)ebuf; + for(evt_size i = 0, count = 0; i < minsz; ++i, ++count) + { + const evt_bits ai = actual.evts.ptr[i]; + const evt_bits ei = expected.evts.ptr[i]; + if(ai != ei) + { + csubstr as = ievt::to_str_sub(abuf, ai); + csubstr es = ievt::to_str_sub(ebuf, ei); + EXPECT_EQ(ai, ei) << "\n" + << " evtid=" << count << "\n" + << " evtpos=" << i << "\n" + << " actual=" << (testing::Message() << as) << "\n" + << " expected=" << (testing::Message() << es) << "\n" + ; + break; + } + if(ai & ievt::WSTR) + { + const csubstr as = actual.getstr(i); + const csubstr es = expected.getstr(i); + if(as != es) + { + EXPECT_EQ(as, es); + break; + } + i += 2; + } + } +} void test_events_ints(IntEventWithScalar const* expected, size_t expected_sz, - ievt::evt_bits const* actual, size_t actual_sz, + evt_bits const* actual, size_t actual_sz, csubstr yaml, csubstr parsed_source, csubstr arena) @@ -35,14 +76,14 @@ void test_events_ints(IntEventWithScalar const* expected, size_t expected_sz, EXPECT_LT(ia, actual_sz); if (ia >= actual_sz) break; -#define _test_eq(lhs, rhs, fmt, ...) \ - do \ - { \ - _c4dbgpf("status={} cmp={} ie={} ia={}: {}={} == {}={} " fmt, \ - status, (lhs == rhs), ie, ia, #lhs, lhs, rhs, #rhs, __VA_ARGS__); \ - status &= int(lhs == rhs); \ - EXPECT_EQ(lhs, rhs); \ - } while(0) + #define _test_eq(lhs, rhs, fmt, ...) \ + do \ + { \ + _c4dbgpf("status={} cmp={} ie={} ia={}: {}={} == {}={} " fmt, \ + status, (lhs == rhs), ie, ia, #lhs, lhs, rhs, #rhs, __VA_ARGS__); \ + status &= int(lhs == rhs); \ + EXPECT_EQ(lhs, rhs); \ + } while(0) csubstr sactual = ievt::to_str_sub(actualbuf, actual[ia]); csubstr sexpect = ievt::to_str_sub(expectedbuf, expected[ie].flags); _test_eq(actual[ia], expected[ie].flags, "", 0); @@ -97,376 +138,534 @@ void test_events_ints(IntEventWithScalar const* expected, size_t expected_sz, #undef _test_eq } +enum : evt_bits { // NOLINT + style_scalar = ievt::PLAI|ievt::SQUO|ievt::DQUO|ievt::LITL|ievt::FOLD, + scope = ievt::MAP_|ievt::SEQ_|ievt::DOC_|ievt::STRM, + directives = ievt::YAML|ievt::TAGH|ievt::TAGP, + wstr = directives|ievt::SCLR|ievt::TAG_|ievt::ANCH|ievt::ALIA, +}; + +evt_size next_sibling(evt_bits const* evts, evt_size sz, evt_size pos) +{ + if(evts[pos] & ievt::BEG_) + { + evt_size close = detail::find_matching_close_(evts, sz, pos); + return ievt::nextpos(evts, close); + } + return ievt::nextpos(evts, pos); +} +template +static void iter_children(evt_bits const* evts, evt_size sz, evt_size pos, Fn const& fn) +{ + const evt_size close = detail::find_matching_close_(evts, sz, pos); + ++pos; + while(pos != close) + { + RYML_TRACE_FMT("child={}", pos); + fn(pos, evts[pos]); + if(testing::Test::HasFailure()) + break; + pos = next_sibling(evts, sz, pos); + } +} void test_events_ints_invariants(csubstr parsed_yaml, csubstr arena, - ievt::evt_bits const* evts, - ievt::evt_bits evts_sz) + evt_bits const* evts, + evt_bits evts_sz) { char bufpos[200]; char bufprev[200]; EXPECT_GT(evts_sz, 0); - for(ievt::evt_bits evtpos = 0, evtnumber = 0; + std::vector path; + path.reserve(32); + for(evt_bits evtpos = 0, evtnumber = 0; evtpos < evts_sz; ++evtnumber, evtpos += ((evts[evtpos] & ievt::WSTR) ? 3 : 1)) { - ievt::evt_bits evt = evts[evtpos]; - ievt::evt_bits prev = {}; - ievt::evt_bits nextpos = evtpos + ((evt & ievt::WSTR) ? 3 : 1); - ievt::evt_bits next = {}; - SCOPED_TRACE(evtpos); // position in the array - SCOPED_TRACE(evtnumber); // event number + bool ok = true; + evt_bits evt = evts[evtpos]; + evt_bits prev = {}; + evt_bits nextpos = evtpos + ((evt & ievt::WSTR) ? 3 : 1); + evt_bits next = {}; + evt_bits parentpos = path.empty() ? -1 : path.back(); + evt_bits parent = path.empty() ? evt_bits{} : evts[parentpos]; SCOPED_TRACE(ievt::to_str_sub(bufpos, evt)); + RYML_TRACE_FMT("evt #={} evtpos={} parentpos={}", evtnumber, evtpos, parentpos); if(evtpos) prev = (evt & ievt::PSTR) ? evts[evtpos - 3] : evts[evtpos - 1]; if(nextpos < evts_sz) next = evts[nextpos]; - #define _test_str_in_buffer(i) \ - do { \ - EXPECT_LE(i + 3, evts_sz); \ - if (i + 3 <= evts_sz) \ - { \ - bool in_arena = evts[i] & ievt::AREN; \ - csubstr buf = !in_arena ? parsed_yaml : arena; \ - EXPECT_GE(evts[i + 1], 0); \ - EXPECT_GE(evts[i + 2], 0); \ - if (evts[i + 1] >= 0 && evts[i + 2] >= 0) \ - { \ - size_t offset = (size_t)evts[i + 1]; \ - size_t len = (size_t)evts[i + 2]; \ - EXPECT_LE(offset, buf.len); \ - EXPECT_LE(len, buf.len); \ - EXPECT_LE(offset + len, buf.len); \ - } \ - } \ - } while(0) + if(evt & ievt::BEG_) + { + path.push_back(evtpos); + } + if(evt & ievt::END_) + { + ASSERT_TRUE(!path.empty()); + path.pop_back(); + } // check general rules + if(evt & ievt::WSTR) + { + EXPECT_NE(evt & wstr, 0) << (ok = false); + EXPECT_NE(next & ievt::PSTR, 0) << (ok = false); + EXPECT_LE(evtpos + 3, evts_sz) << (ok = false); + if(evtpos + 3 <= evts_sz) + { + bool in_arena = evts[evtpos] & ievt::AREN; + csubstr buf = !in_arena ? parsed_yaml : arena; + EXPECT_GE(evts[evtpos + 1], 0) << (ok = false); + EXPECT_GE(evts[evtpos + 2], 0) << (ok = false); + if(evts[evtpos + 1] >= 0 && + evts[evtpos + 2] >= 0) + { + size_t offset = (size_t)evts[evtpos + 1]; + size_t len = (size_t)evts[evtpos + 2]; + EXPECT_LE(offset, buf.len) << (ok = false); + EXPECT_LE(len, buf.len) << (ok = false); + EXPECT_LE(offset + len, buf.len) << (ok = false); + } + } + } if(evt & ievt::PSTR) { - EXPECT_GT(evtnumber, 0); - EXPECT_GE(evtpos, 3); SCOPED_TRACE(ievt::to_str_sub(bufprev, prev)); - EXPECT_NE(prev & ievt::WSTR, 0); + EXPECT_GT(evtnumber, 0) << (ok = false); + EXPECT_GE(evtpos, 3) << (ok = false); + EXPECT_NE(prev & ievt::WSTR, 0) << (ok = false); } - constexpr const ievt::evt_bits style = ievt::PLAI|ievt::SQUO|ievt::DQUO|ievt::LITL|ievt::FOLD; - constexpr const ievt::evt_bits scope = ievt::MAP_|ievt::SEQ_|ievt::DOC_|ievt::STRM; - constexpr const ievt::evt_bits directives = ievt::YAML|ievt::TAGH|ievt::TAGP; if(evt & (ievt::BEG_|ievt::END_)) { - EXPECT_NE(evt & scope, 0); - EXPECT_EQ(evt & style, 0); - EXPECT_EQ(evt & directives, 0); - EXPECT_EQ(evt & ievt::WSTR, 0); + EXPECT_NE(evt & scope, 0) << (ok = false); + EXPECT_EQ(evt & style_scalar, 0) << (ok = false); + EXPECT_EQ(evt & directives, 0) << (ok = false); + EXPECT_EQ(evt & ievt::WSTR, 0) << (ok = false); } if(evt & (ievt::EXPL)) { - EXPECT_EQ(evt & ievt::DOC_, ievt::DOC_); - EXPECT_EQ(evt & style, 0); + EXPECT_EQ(evt & ievt::DOC_, ievt::DOC_) << (ok = false); + EXPECT_EQ(evt & style_scalar, 0) << (ok = false); } if(evt & (ievt::AREN)) { - EXPECT_NE(evt & ievt::WSTR, 0); - EXPECT_EQ(evt & directives, 0); + EXPECT_NE(evt & ievt::WSTR, 0) << (ok = false); + EXPECT_EQ(evt & directives, 0) << (ok = false); } if(evt & (ievt::KEY_|ievt::VAL_)) { - EXPECT_EQ(evt & (ievt::DOC_|ievt::STRM), 0); - EXPECT_EQ(evt & directives, 0); + EXPECT_EQ(evt & (ievt::DOC_|ievt::STRM|ievt::TAGP|ievt::TAGH|ievt::YAML), 0) << (ok = false); + EXPECT_EQ(evt & directives, 0) << (ok = false); + EXPECT_NE(parent & (ievt::SEQ_|ievt::MAP_|ievt::DOC_), 0); + EXPECT_EQ(parent & ievt::BEG_, ievt::BEG_); + } + if(evt & ievt::KEY_) + { + EXPECT_EQ(parent & ievt::MAP_, ievt::MAP_); + } + if(evt & (ievt::FLOW|ievt::BLCK)) + { + EXPECT_EQ(evt & ievt::BEG_, ievt::BEG_) << (ok = false); + EXPECT_EQ(evt & ievt::END_, 0) << (ok = false); + EXPECT_NE(evt & (ievt::MAP_|ievt::SEQ_), 0) << (ok = false); } - if(evt & (ievt::FLOW)) + if(evt & (ievt::FSL_|ievt::FML1|ievt::FMLN|ievt::FMLX|ievt::FSPC)) { - EXPECT_EQ(evt & ievt::BEG_, ievt::BEG_); - EXPECT_EQ(evt & ievt::END_, 0); - EXPECT_NE(evt & (ievt::MAP_|ievt::SEQ_), 0); + EXPECT_EQ(evt & ievt::BLCK, 0) << (ok = false); + EXPECT_EQ(evt & ievt::FLOW, ievt::FLOW) << (ok = false); + EXPECT_EQ(evt & ievt::BEG_, ievt::BEG_) << (ok = false); + EXPECT_EQ(evt & ievt::END_, 0) << (ok = false); + EXPECT_NE(evt & (ievt::MAP_|ievt::SEQ_), 0) << (ok = false); } // now check each flag if(evt & ievt::YAML) { - EXPECT_EQ(evt & ievt::TAGH, 0); - EXPECT_EQ(evt & ievt::TAGP, 0); - EXPECT_EQ(evt & ievt::BSTR, 0); - EXPECT_EQ(evt & ievt::ESTR, 0); - EXPECT_EQ(evt & ievt::EXPL, 0); - EXPECT_EQ(evt & ievt::WSTR, ievt::YAML); - EXPECT_EQ(evt & ievt::SCLR, 0); - EXPECT_EQ(evt & ievt::ALIA, 0); - EXPECT_EQ(evt & ievt::ANCH, 0); - EXPECT_EQ(evt & ievt::TAG_, 0); - EXPECT_EQ(evt & ievt::KEY_, 0); - EXPECT_EQ(evt & ievt::VAL_, 0); - EXPECT_EQ(evt & (ievt::BDOC|ievt::EDOC), 0); - EXPECT_EQ(evt & (ievt::BMAP|ievt::EMAP), 0); - EXPECT_EQ(evt & (ievt::BSEQ|ievt::ESEQ), 0); - EXPECT_EQ(evt & (ievt::FLOW|ievt::BLCK), 0); - EXPECT_EQ(evt & (ievt::PLAI|ievt::SQUO|ievt::DQUO|ievt::LITL|ievt::FOLD), 0); - EXPECT_EQ(next & ievt::PSTR, ievt::PSTR); + EXPECT_EQ(parent & ievt::BSTR, ievt::BSTR); + EXPECT_EQ(parentpos, 0); + EXPECT_EQ(evt & ievt::TAGH, 0) << (ok = false); + EXPECT_EQ(evt & ievt::TAGP, 0) << (ok = false); + EXPECT_EQ(evt & ievt::BSTR, 0) << (ok = false); + EXPECT_EQ(evt & ievt::ESTR, 0) << (ok = false); + EXPECT_EQ(evt & ievt::EXPL, 0) << (ok = false); + EXPECT_EQ(evt & ievt::WSTR, ievt::YAML) << (ok = false); + EXPECT_EQ(evt & ievt::SCLR, 0) << (ok = false); + EXPECT_EQ(evt & ievt::ALIA, 0) << (ok = false); + EXPECT_EQ(evt & ievt::ANCH, 0) << (ok = false); + EXPECT_EQ(evt & ievt::TAG_, 0) << (ok = false); + EXPECT_EQ(evt & ievt::KEY_, 0) << (ok = false); + EXPECT_EQ(evt & ievt::VAL_, 0) << (ok = false); + EXPECT_EQ(evt & (ievt::BDOC|ievt::EDOC), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::BMAP|ievt::EMAP), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::BSEQ|ievt::ESEQ), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::FLOW|ievt::BLCK), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::PLAI|ievt::SQUO|ievt::DQUO|ievt::LITL|ievt::FOLD), 0) << (ok = false); + EXPECT_EQ(next & ievt::PSTR, ievt::PSTR) << (ok = false); } if(evt & ievt::TAGH) { - EXPECT_EQ(evt & ievt::YAML, 0); - EXPECT_EQ(evt & ievt::TAGP, 0); - EXPECT_EQ(evt & ievt::BSTR, 0); - EXPECT_EQ(evt & ievt::ESTR, 0); - EXPECT_EQ(evt & ievt::EXPL, 0); - EXPECT_EQ(evt & ievt::WSTR, ievt::TAGH); - EXPECT_EQ(evt & ievt::SCLR, 0); - EXPECT_EQ(evt & ievt::ALIA, 0); - EXPECT_EQ(evt & ievt::ANCH, 0); - EXPECT_EQ(evt & ievt::TAG_, 0); - EXPECT_EQ(evt & ievt::KEY_, 0); - EXPECT_EQ(evt & ievt::VAL_, 0); - EXPECT_EQ(evt & (ievt::BDOC|ievt::EDOC), 0); - EXPECT_EQ(evt & (ievt::BMAP|ievt::EMAP), 0); - EXPECT_EQ(evt & (ievt::BSEQ|ievt::ESEQ), 0); - EXPECT_EQ(evt & (ievt::FLOW|ievt::BLCK), 0); - EXPECT_EQ(evt & (ievt::PLAI|ievt::SQUO|ievt::DQUO|ievt::LITL|ievt::FOLD), 0); - EXPECT_EQ(next & ievt::PSTR, ievt::PSTR); + EXPECT_EQ(parent & ievt::BSTR, ievt::BSTR); + EXPECT_EQ(parentpos, 0); + EXPECT_EQ(evt & ievt::YAML, 0) << (ok = false); + EXPECT_EQ(evt & ievt::TAGP, 0) << (ok = false); + EXPECT_EQ(evt & ievt::BSTR, 0) << (ok = false); + EXPECT_EQ(evt & ievt::ESTR, 0) << (ok = false); + EXPECT_EQ(evt & ievt::EXPL, 0) << (ok = false); + EXPECT_EQ(evt & ievt::WSTR, ievt::TAGH) << (ok = false); + EXPECT_EQ(evt & ievt::SCLR, 0) << (ok = false); + EXPECT_EQ(evt & ievt::ALIA, 0) << (ok = false); + EXPECT_EQ(evt & ievt::ANCH, 0) << (ok = false); + EXPECT_EQ(evt & ievt::TAG_, 0) << (ok = false); + EXPECT_EQ(evt & ievt::KEY_, 0) << (ok = false); + EXPECT_EQ(evt & ievt::VAL_, 0) << (ok = false); + EXPECT_EQ(evt & (ievt::BDOC|ievt::EDOC), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::BMAP|ievt::EMAP), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::BSEQ|ievt::ESEQ), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::FLOW|ievt::BLCK), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::PLAI|ievt::SQUO|ievt::DQUO|ievt::LITL|ievt::FOLD), 0) << (ok = false); + EXPECT_EQ(next & ievt::PSTR, ievt::PSTR) << (ok = false); + EXPECT_EQ(next & ievt::TAGP, ievt::TAGP) << (ok = false); } if(evt & ievt::TAGP) { - EXPECT_EQ(evt & ievt::YAML, 0); - EXPECT_EQ(evt & ievt::TAGH, 0); - EXPECT_EQ(evt & ievt::BSTR, 0); - EXPECT_EQ(evt & ievt::ESTR, 0); - EXPECT_EQ(evt & ievt::EXPL, 0); - EXPECT_EQ(evt & ievt::WSTR, ievt::TAGP); - EXPECT_EQ(evt & ievt::SCLR, 0); - EXPECT_EQ(evt & ievt::ALIA, 0); - EXPECT_EQ(evt & ievt::ANCH, 0); - EXPECT_EQ(evt & ievt::TAG_, 0); - EXPECT_EQ(evt & ievt::KEY_, 0); - EXPECT_EQ(evt & ievt::VAL_, 0); - EXPECT_EQ(evt & (ievt::BDOC|ievt::EDOC), 0); - EXPECT_EQ(evt & (ievt::BMAP|ievt::EMAP), 0); - EXPECT_EQ(evt & (ievt::BSEQ|ievt::ESEQ), 0); - EXPECT_EQ(evt & (ievt::FLOW|ievt::BLCK), 0); - EXPECT_EQ(evt & (ievt::PLAI|ievt::SQUO|ievt::DQUO|ievt::LITL|ievt::FOLD), 0); - EXPECT_EQ(next & ievt::PSTR, ievt::PSTR); + EXPECT_EQ(parent & ievt::BSTR, ievt::BSTR); + EXPECT_EQ(parentpos, 0); + EXPECT_EQ(evt & ievt::YAML, 0) << (ok = false); + EXPECT_EQ(evt & ievt::TAGH, 0) << (ok = false); + EXPECT_EQ(evt & ievt::BSTR, 0) << (ok = false); + EXPECT_EQ(evt & ievt::ESTR, 0) << (ok = false); + EXPECT_EQ(evt & ievt::EXPL, 0) << (ok = false); + EXPECT_EQ(evt & ievt::WSTR, ievt::TAGP) << (ok = false); + EXPECT_EQ(evt & ievt::SCLR, 0) << (ok = false); + EXPECT_EQ(evt & ievt::ALIA, 0) << (ok = false); + EXPECT_EQ(evt & ievt::ANCH, 0) << (ok = false); + EXPECT_EQ(evt & ievt::TAG_, 0) << (ok = false); + EXPECT_EQ(evt & ievt::KEY_, 0) << (ok = false); + EXPECT_EQ(evt & ievt::VAL_, 0) << (ok = false); + EXPECT_EQ(evt & (ievt::BDOC|ievt::EDOC), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::BMAP|ievt::EMAP), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::BSEQ|ievt::ESEQ), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::FLOW|ievt::BLCK), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::PLAI|ievt::SQUO|ievt::DQUO|ievt::LITL|ievt::FOLD), 0) << (ok = false); + EXPECT_EQ(next & ievt::PSTR, ievt::PSTR) << (ok = false); + EXPECT_EQ(prev & ievt::TAGH, ievt::TAGH) << (ok = false); } if((evt & ievt::BSTR) == ievt::BSTR) { - EXPECT_EQ(evt & ievt::ESTR, ievt::STRM); - EXPECT_EQ(evt & ievt::EXPL, 0); - EXPECT_EQ(evt & ievt::WSTR, 0); - EXPECT_EQ(evt & ievt::SCLR, 0); - EXPECT_EQ(evt & ievt::ALIA, 0); - EXPECT_EQ(evt & ievt::ANCH, 0); - EXPECT_EQ(evt & ievt::TAG_, 0); - EXPECT_EQ(evt & ievt::KEY_, 0); - EXPECT_EQ(evt & ievt::VAL_, 0); - EXPECT_EQ(evt & (ievt::BDOC|ievt::EDOC), ievt::BEG_); - EXPECT_EQ(evt & (ievt::BMAP|ievt::EMAP), ievt::BEG_); - EXPECT_EQ(evt & (ievt::BSEQ|ievt::ESEQ), ievt::BEG_); - EXPECT_EQ(evt & (ievt::FLOW|ievt::BLCK), 0); - EXPECT_EQ(evt & (ievt::PLAI|ievt::SQUO|ievt::DQUO|ievt::LITL|ievt::FOLD), 0); - EXPECT_EQ(next & ievt::PSTR, 0); + EXPECT_EQ(evt & ievt::ESTR, ievt::STRM) << (ok = false); + EXPECT_EQ(evt & ievt::EXPL, 0) << (ok = false); + EXPECT_EQ(evt & ievt::WSTR, 0) << (ok = false); + EXPECT_EQ(evt & ievt::SCLR, 0) << (ok = false); + EXPECT_EQ(evt & ievt::ALIA, 0) << (ok = false); + EXPECT_EQ(evt & ievt::ANCH, 0) << (ok = false); + EXPECT_EQ(evt & ievt::TAG_, 0) << (ok = false); + EXPECT_EQ(evt & ievt::KEY_, 0) << (ok = false); + EXPECT_EQ(evt & ievt::VAL_, 0) << (ok = false); + EXPECT_EQ(evt & (ievt::BDOC|ievt::EDOC), ievt::BEG_) << (ok = false); + EXPECT_EQ(evt & (ievt::BMAP|ievt::EMAP), ievt::BEG_) << (ok = false); + EXPECT_EQ(evt & (ievt::BSEQ|ievt::ESEQ), ievt::BEG_) << (ok = false); + EXPECT_EQ(evt & (ievt::FLOW|ievt::BLCK), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::PLAI|ievt::SQUO|ievt::DQUO|ievt::LITL|ievt::FOLD), 0) << (ok = false); + EXPECT_EQ(next & ievt::PSTR, 0) << (ok = false); + iter_children(evts, evts_sz, evtpos, [&](evt_size, evt_bits child_evt){ + EXPECT_NE(child_evt & (ievt::DOC_|ievt::YAML|ievt::TAGH|ievt::TAGP), 0) << (ok = false); + EXPECT_EQ(child_evt & (ievt::SEQ_|ievt::MAP_|ievt::TAG_|ievt::ANCH|ievt::ALIA), 0) << (ok = false); + }); } if((evt & ievt::ESTR) == ievt::ESTR) { - EXPECT_EQ(evt & ievt::BSTR, ievt::STRM); - EXPECT_EQ(evt & ievt::EXPL, 0); - EXPECT_EQ(evt & ievt::WSTR, 0); - EXPECT_EQ(evt & ievt::SCLR, 0); - EXPECT_EQ(evt & ievt::ALIA, 0); - EXPECT_EQ(evt & ievt::ANCH, 0); - EXPECT_EQ(evt & ievt::TAG_, 0); - EXPECT_EQ(evt & ievt::KEY_, 0); - EXPECT_EQ(evt & ievt::VAL_, 0); - EXPECT_EQ(evt & (ievt::BDOC|ievt::EDOC), ievt::END_); - EXPECT_EQ(evt & (ievt::BMAP|ievt::EMAP), ievt::END_); - EXPECT_EQ(evt & (ievt::BSEQ|ievt::ESEQ), ievt::END_); - EXPECT_EQ(evt & (ievt::FLOW|ievt::BLCK), 0); - EXPECT_EQ(evt & (ievt::PLAI|ievt::SQUO|ievt::DQUO|ievt::LITL|ievt::FOLD), 0); - EXPECT_EQ(next & ievt::PSTR, 0); + EXPECT_EQ(evt & ievt::BSTR, ievt::STRM) << (ok = false); + EXPECT_EQ(evt & ievt::EXPL, 0) << (ok = false); + EXPECT_EQ(evt & ievt::WSTR, 0) << (ok = false); + EXPECT_EQ(evt & ievt::SCLR, 0) << (ok = false); + EXPECT_EQ(evt & ievt::ALIA, 0) << (ok = false); + EXPECT_EQ(evt & ievt::ANCH, 0) << (ok = false); + EXPECT_EQ(evt & ievt::TAG_, 0) << (ok = false); + EXPECT_EQ(evt & ievt::KEY_, 0) << (ok = false); + EXPECT_EQ(evt & ievt::VAL_, 0) << (ok = false); + EXPECT_EQ(evt & (ievt::BDOC|ievt::EDOC), ievt::END_) << (ok = false); + EXPECT_EQ(evt & (ievt::BMAP|ievt::EMAP), ievt::END_) << (ok = false); + EXPECT_EQ(evt & (ievt::BSEQ|ievt::ESEQ), ievt::END_) << (ok = false); + EXPECT_EQ(evt & (ievt::FLOW|ievt::BLCK), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::PLAI|ievt::SQUO|ievt::DQUO|ievt::LITL|ievt::FOLD), 0) << (ok = false); + EXPECT_EQ(next & ievt::PSTR, 0) << (ok = false); } if((evt & ievt::BDOC) == ievt::BDOC) { - EXPECT_EQ(evt & ievt::EDOC, ievt::DOC_); - EXPECT_EQ(evt & ievt::WSTR, 0); - EXPECT_EQ(evt & ievt::SCLR, 0); - EXPECT_EQ(evt & ievt::ALIA, 0); - EXPECT_EQ(evt & ievt::ANCH, 0); - EXPECT_EQ(evt & ievt::TAG_, 0); - EXPECT_EQ(evt & ievt::KEY_, 0); - EXPECT_EQ(evt & ievt::VAL_, 0); - EXPECT_EQ(evt & (ievt::BSTR|ievt::ESTR), ievt::BEG_); - EXPECT_EQ(evt & (ievt::BMAP|ievt::EMAP), ievt::BEG_); - EXPECT_EQ(evt & (ievt::BSEQ|ievt::ESEQ), ievt::BEG_); - EXPECT_EQ(evt & (ievt::FLOW|ievt::BLCK), 0); - EXPECT_EQ(evt & (ievt::PLAI|ievt::SQUO|ievt::DQUO|ievt::LITL|ievt::FOLD), 0); - EXPECT_EQ(next & ievt::PSTR, 0); + EXPECT_EQ(parentpos, 0); + EXPECT_EQ(parent & ievt::BSTR, ievt::BSTR); + EXPECT_EQ(evt & ievt::EDOC, ievt::DOC_) << (ok = false); + EXPECT_EQ(evt & ievt::WSTR, 0) << (ok = false); + EXPECT_EQ(evt & ievt::SCLR, 0) << (ok = false); + EXPECT_EQ(evt & ievt::ALIA, 0) << (ok = false); + EXPECT_EQ(evt & ievt::ANCH, 0) << (ok = false); + EXPECT_EQ(evt & ievt::TAG_, 0) << (ok = false); + EXPECT_EQ(evt & ievt::KEY_, 0) << (ok = false); + EXPECT_EQ(evt & ievt::VAL_, 0) << (ok = false); + EXPECT_EQ(evt & (ievt::BSTR|ievt::ESTR), ievt::BEG_) << (ok = false); + EXPECT_EQ(evt & (ievt::BMAP|ievt::EMAP), ievt::BEG_) << (ok = false); + EXPECT_EQ(evt & (ievt::BSEQ|ievt::ESEQ), ievt::BEG_) << (ok = false); + EXPECT_EQ(evt & (ievt::FLOW|ievt::BLCK), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::PLAI|ievt::SQUO|ievt::DQUO|ievt::LITL|ievt::FOLD), 0) << (ok = false); + EXPECT_EQ(next & ievt::PSTR, 0) << (ok = false); + iter_children(evts, evts_sz, evtpos, [&](evt_size, evt_bits child_evt){ + EXPECT_NE(child_evt & (ievt::SEQ_|ievt::MAP_|ievt::SCLR|ievt::TAG_|ievt::ANCH|ievt::ALIA), 0) << (ok = false); + }); } if((evt & ievt::EDOC) == ievt::EDOC) { - EXPECT_EQ(evt & ievt::BDOC, ievt::DOC_); - EXPECT_EQ(evt & ievt::WSTR, 0); - EXPECT_EQ(evt & ievt::SCLR, 0); - EXPECT_EQ(evt & ievt::ALIA, 0); - EXPECT_EQ(evt & ievt::ANCH, 0); - EXPECT_EQ(evt & ievt::TAG_, 0); - EXPECT_EQ(evt & ievt::KEY_, 0); - EXPECT_EQ(evt & ievt::VAL_, 0); - EXPECT_EQ(evt & (ievt::BSTR|ievt::ESTR), ievt::END_); - EXPECT_EQ(evt & (ievt::BMAP|ievt::EMAP), ievt::END_); - EXPECT_EQ(evt & (ievt::BSEQ|ievt::ESEQ), ievt::END_); - EXPECT_EQ(evt & (ievt::FLOW|ievt::BLCK), 0); - EXPECT_EQ(evt & (ievt::PLAI|ievt::SQUO|ievt::DQUO|ievt::LITL|ievt::FOLD), 0); - EXPECT_EQ(next & ievt::PSTR, 0); + EXPECT_EQ(parent & ievt::BDOC, ievt::BDOC); + EXPECT_EQ(evt & ievt::BDOC, ievt::DOC_) << (ok = false); + EXPECT_EQ(evt & ievt::WSTR, 0) << (ok = false); + EXPECT_EQ(evt & ievt::SCLR, 0) << (ok = false); + EXPECT_EQ(evt & ievt::ALIA, 0) << (ok = false); + EXPECT_EQ(evt & ievt::ANCH, 0) << (ok = false); + EXPECT_EQ(evt & ievt::TAG_, 0) << (ok = false); + EXPECT_EQ(evt & ievt::KEY_, 0) << (ok = false); + EXPECT_EQ(evt & ievt::VAL_, 0) << (ok = false); + EXPECT_EQ(evt & (ievt::BSTR|ievt::ESTR), ievt::END_) << (ok = false); + EXPECT_EQ(evt & (ievt::BMAP|ievt::EMAP), ievt::END_) << (ok = false); + EXPECT_EQ(evt & (ievt::BSEQ|ievt::ESEQ), ievt::END_) << (ok = false); + EXPECT_EQ(evt & (ievt::FLOW|ievt::BLCK), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::PLAI|ievt::SQUO|ievt::DQUO|ievt::LITL|ievt::FOLD), 0) << (ok = false); + EXPECT_EQ(next & ievt::PSTR, 0) << (ok = false); } if((evt & ievt::BSEQ) == ievt::BSEQ) { - EXPECT_EQ(evt & ievt::ESEQ, ievt::SEQ_); - EXPECT_EQ(evt & ievt::EMAP, 0); - EXPECT_EQ(evt & ievt::EXPL, 0); - EXPECT_EQ(evt & ievt::WSTR, 0); - EXPECT_EQ(evt & ievt::SCLR, 0); - EXPECT_EQ(evt & ievt::ALIA, 0); - EXPECT_EQ(evt & ievt::ANCH, 0); - EXPECT_EQ(evt & ievt::TAG_, 0); - EXPECT_EQ(evt & (ievt::BDOC|ievt::EDOC), ievt::BEG_); - EXPECT_EQ(evt & (ievt::BSTR|ievt::ESTR), ievt::BEG_); - EXPECT_EQ(evt & (ievt::BMAP|ievt::EMAP), ievt::BEG_); - EXPECT_NE(evt & (ievt::FLOW|ievt::BLCK), 0); - EXPECT_NE(evt & (ievt::FLOW|ievt::BLCK), ievt::FLOW|ievt::BLCK); - EXPECT_NE(evt & (ievt::KEY_|ievt::VAL_), 0); - EXPECT_NE(evt & (ievt::KEY_|ievt::VAL_), ievt::KEY_|ievt::VAL_); - EXPECT_EQ(evt & (ievt::PLAI|ievt::SQUO|ievt::DQUO|ievt::LITL|ievt::FOLD), 0); - EXPECT_EQ(next & ievt::PSTR, 0); + EXPECT_EQ(evt & ievt::ESEQ, ievt::SEQ_) << (ok = false); + EXPECT_EQ(evt & ievt::EMAP, 0) << (ok = false); + EXPECT_EQ(evt & ievt::EXPL, 0) << (ok = false); + EXPECT_EQ(evt & ievt::WSTR, 0) << (ok = false); + EXPECT_EQ(evt & ievt::SCLR, 0) << (ok = false); + EXPECT_EQ(evt & ievt::ALIA, 0) << (ok = false); + EXPECT_EQ(evt & ievt::ANCH, 0) << (ok = false); + EXPECT_EQ(evt & ievt::TAG_, 0) << (ok = false); + EXPECT_EQ(evt & (ievt::BDOC|ievt::EDOC), ievt::BEG_) << (ok = false); + EXPECT_EQ(evt & (ievt::BSTR|ievt::ESTR), ievt::BEG_) << (ok = false); + EXPECT_EQ(evt & (ievt::BMAP|ievt::EMAP), ievt::BEG_) << (ok = false); + EXPECT_NE(evt & (ievt::FLOW|ievt::BLCK), ievt::FLOW|ievt::BLCK) << (ok = false); + EXPECT_NE(evt & (ievt::KEY_|ievt::VAL_), 0) << (ok = false); + EXPECT_NE(evt & (ievt::KEY_|ievt::VAL_), ievt::KEY_|ievt::VAL_) << (ok = false); + EXPECT_EQ(evt & (ievt::PLAI|ievt::SQUO|ievt::DQUO|ievt::LITL|ievt::FOLD), 0) << (ok = false); + EXPECT_EQ(next & ievt::PSTR, 0) << (ok = false); + iter_children(evts, evts_sz, evtpos, [&](evt_size, evt_bits child_evt){ + EXPECT_NE(child_evt & (ievt::SEQ_|ievt::MAP_|ievt::SCLR|ievt::TAG_|ievt::ANCH|ievt::ALIA), 0) << (ok = false); + EXPECT_EQ(child_evt & ievt::KEY_, 0) << (ok = false); + }); } if((evt & ievt::ESEQ) == ievt::ESEQ) { - EXPECT_EQ(evt & ievt::BSEQ, ievt::SEQ_); - EXPECT_EQ(evt & ievt::EXPL, 0); - EXPECT_EQ(evt & ievt::WSTR, 0); - EXPECT_EQ(evt & ievt::SCLR, 0); - EXPECT_EQ(evt & ievt::ALIA, 0); - EXPECT_EQ(evt & ievt::ANCH, 0); - EXPECT_EQ(evt & ievt::TAG_, 0); - EXPECT_EQ(evt & ievt::KEY_, 0); - EXPECT_EQ(evt & ievt::VAL_, 0); - EXPECT_EQ(evt & (ievt::BDOC|ievt::EDOC), ievt::END_); - EXPECT_EQ(evt & (ievt::BSTR|ievt::ESTR), ievt::END_); - EXPECT_EQ(evt & (ievt::BMAP|ievt::EMAP), ievt::END_); - EXPECT_EQ(evt & (ievt::FLOW|ievt::BLCK), 0); - EXPECT_EQ(evt & (ievt::PLAI|ievt::SQUO|ievt::DQUO|ievt::LITL|ievt::FOLD), 0); - EXPECT_EQ(next & ievt::PSTR, 0); + EXPECT_EQ(evt & ievt::BSEQ, ievt::SEQ_) << (ok = false); + EXPECT_EQ(evt & ievt::EXPL, 0) << (ok = false); + EXPECT_EQ(evt & ievt::WSTR, 0) << (ok = false); + EXPECT_EQ(evt & ievt::SCLR, 0) << (ok = false); + EXPECT_EQ(evt & ievt::ALIA, 0) << (ok = false); + EXPECT_EQ(evt & ievt::ANCH, 0) << (ok = false); + EXPECT_EQ(evt & ievt::TAG_, 0) << (ok = false); + EXPECT_EQ(evt & ievt::KEY_, 0) << (ok = false); + EXPECT_EQ(evt & ievt::VAL_, 0) << (ok = false); + EXPECT_EQ(evt & (ievt::BDOC|ievt::EDOC), ievt::END_) << (ok = false); + EXPECT_EQ(evt & (ievt::BSTR|ievt::ESTR), ievt::END_) << (ok = false); + EXPECT_EQ(evt & (ievt::BMAP|ievt::EMAP), ievt::END_) << (ok = false); + EXPECT_EQ(evt & (ievt::FLOW|ievt::BLCK), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::PLAI|ievt::SQUO|ievt::DQUO|ievt::LITL|ievt::FOLD), 0) << (ok = false); + EXPECT_EQ(next & ievt::PSTR, 0) << (ok = false); } if((evt & ievt::BMAP) == ievt::BMAP) { - EXPECT_EQ(evt & ievt::EMAP, ievt::MAP_); - EXPECT_EQ(evt & ievt::EXPL, 0); - EXPECT_EQ(evt & ievt::WSTR, 0); - EXPECT_EQ(evt & ievt::SCLR, 0); - EXPECT_EQ(evt & ievt::ALIA, 0); - EXPECT_EQ(evt & ievt::ANCH, 0); - EXPECT_EQ(evt & ievt::TAG_, 0); - EXPECT_EQ(evt & (ievt::BDOC|ievt::EDOC), ievt::BEG_); - EXPECT_EQ(evt & (ievt::BSTR|ievt::ESTR), ievt::BEG_); - EXPECT_EQ(evt & (ievt::BSEQ|ievt::ESEQ), ievt::BEG_); - EXPECT_NE(evt & (ievt::FLOW|ievt::BLCK), 0); - EXPECT_NE(evt & (ievt::FLOW|ievt::BLCK), ievt::FLOW|ievt::BLCK); - EXPECT_NE(evt & (ievt::KEY_|ievt::VAL_), 0); - EXPECT_NE(evt & (ievt::KEY_|ievt::VAL_), ievt::KEY_|ievt::VAL_); - EXPECT_EQ(evt & (ievt::PLAI|ievt::SQUO|ievt::DQUO|ievt::LITL|ievt::FOLD), 0); - EXPECT_EQ(next & ievt::PSTR, 0); + EXPECT_EQ(evt & ievt::EMAP, ievt::MAP_) << (ok = false); + EXPECT_EQ(evt & ievt::EXPL, 0) << (ok = false); + EXPECT_EQ(evt & ievt::WSTR, 0) << (ok = false); + EXPECT_EQ(evt & ievt::SCLR, 0) << (ok = false); + EXPECT_EQ(evt & ievt::ALIA, 0) << (ok = false); + EXPECT_EQ(evt & ievt::ANCH, 0) << (ok = false); + EXPECT_EQ(evt & ievt::TAG_, 0) << (ok = false); + EXPECT_EQ(evt & (ievt::BDOC|ievt::EDOC), ievt::BEG_) << (ok = false); + EXPECT_EQ(evt & (ievt::BSTR|ievt::ESTR), ievt::BEG_) << (ok = false); + EXPECT_EQ(evt & (ievt::BSEQ|ievt::ESEQ), ievt::BEG_) << (ok = false); + EXPECT_NE(evt & (ievt::FLOW|ievt::BLCK), 0) << (ok = false); + EXPECT_NE(evt & (ievt::FLOW|ievt::BLCK), ievt::FLOW|ievt::BLCK) << (ok = false); + EXPECT_NE(evt & (ievt::KEY_|ievt::VAL_), 0) << (ok = false); + EXPECT_NE(evt & (ievt::KEY_|ievt::VAL_), ievt::KEY_|ievt::VAL_) << (ok = false); + EXPECT_EQ(evt & (ievt::PLAI|ievt::SQUO|ievt::DQUO|ievt::LITL|ievt::FOLD), 0) << (ok = false); + EXPECT_EQ(next & ievt::PSTR, 0) << (ok = false); + bool key_state = true; + iter_children(evts, evts_sz, evtpos, [&](evt_size, evt_bits child_evt){ + EXPECT_NE(child_evt & (ievt::SEQ_|ievt::MAP_|ievt::SCLR|ievt::TAG_|ievt::ANCH|ievt::ALIA), 0) << (ok = false); + if(key_state) + { + EXPECT_EQ(child_evt & ievt::KEY_, ievt::KEY_) << (ok = false); + EXPECT_EQ(child_evt & ievt::VAL_, 0) << (ok = false); + } + else + { + EXPECT_EQ(child_evt & ievt::KEY_, 0) << (ok = false); + EXPECT_EQ(child_evt & ievt::VAL_, ievt::VAL_) << (ok = false); + } + if(child_evt & (ievt::SEQ_|ievt::MAP_|ievt::SCLR|ievt::ALIA)) + key_state = !key_state; + }); } if((evt & ievt::EMAP) == ievt::EMAP) { - EXPECT_EQ(evt & ievt::BSEQ, 0); - EXPECT_EQ(evt & ievt::EXPL, 0); - EXPECT_EQ(evt & ievt::WSTR, 0); - EXPECT_EQ(evt & ievt::SCLR, 0); - EXPECT_EQ(evt & ievt::ALIA, 0); - EXPECT_EQ(evt & ievt::ANCH, 0); - EXPECT_EQ(evt & ievt::TAG_, 0); - EXPECT_EQ(evt & ievt::KEY_, 0); - EXPECT_EQ(evt & ievt::VAL_, 0); - EXPECT_EQ(evt & (ievt::BDOC|ievt::EDOC), ievt::END_); - EXPECT_EQ(evt & (ievt::BSTR|ievt::ESTR), ievt::END_); - EXPECT_EQ(evt & (ievt::BSEQ|ievt::ESEQ), ievt::END_); - EXPECT_EQ(evt & (ievt::FLOW|ievt::BLCK), 0); - EXPECT_EQ(evt & (ievt::PLAI|ievt::SQUO|ievt::DQUO|ievt::LITL|ievt::FOLD), 0); - EXPECT_EQ(next & ievt::PSTR, 0); + EXPECT_EQ(evt & ievt::BSEQ, 0) << (ok = false); + EXPECT_EQ(evt & ievt::EXPL, 0) << (ok = false); + EXPECT_EQ(evt & ievt::WSTR, 0) << (ok = false); + EXPECT_EQ(evt & ievt::SCLR, 0) << (ok = false); + EXPECT_EQ(evt & ievt::ALIA, 0) << (ok = false); + EXPECT_EQ(evt & ievt::ANCH, 0) << (ok = false); + EXPECT_EQ(evt & ievt::TAG_, 0) << (ok = false); + EXPECT_EQ(evt & ievt::KEY_, 0) << (ok = false); + EXPECT_EQ(evt & ievt::VAL_, 0) << (ok = false); + EXPECT_EQ(evt & (ievt::BDOC|ievt::EDOC), ievt::END_) << (ok = false); + EXPECT_EQ(evt & (ievt::BSTR|ievt::ESTR), ievt::END_) << (ok = false); + EXPECT_EQ(evt & (ievt::BSEQ|ievt::ESEQ), ievt::END_) << (ok = false); + EXPECT_EQ(evt & (ievt::FLOW|ievt::BLCK), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::PLAI|ievt::SQUO|ievt::DQUO|ievt::LITL|ievt::FOLD), 0) << (ok = false); + EXPECT_EQ(next & ievt::PSTR, 0) << (ok = false); } - if (evt & ievt::SCLR) + if(evt & ievt::SCLR) { - EXPECT_EQ(evt & ievt::EXPL, 0); - EXPECT_NE(evt & ievt::WSTR, 0); - EXPECT_EQ(evt & ievt::ALIA, 0); - EXPECT_EQ(evt & ievt::ANCH, 0); - EXPECT_EQ(evt & ievt::TAG_, 0); - EXPECT_NE(evt & (ievt::KEY_|ievt::VAL_), 0); - EXPECT_NE(evt & (ievt::KEY_|ievt::VAL_), ievt::KEY_|ievt::VAL_); - EXPECT_EQ(evt & (ievt::BSTR|ievt::ESTR), 0); - EXPECT_EQ(evt & (ievt::BDOC|ievt::EDOC), 0); - EXPECT_EQ(evt & (ievt::BSEQ|ievt::ESEQ), 0); - EXPECT_EQ(evt & (ievt::BMAP|ievt::EMAP), 0); - EXPECT_EQ(evt & (ievt::FLOW|ievt::BLCK), 0); - EXPECT_EQ(next & ievt::PSTR, ievt::PSTR); - ievt::evt_bits estyle = evt & style; - EXPECT_NE(estyle, 0); - EXPECT_EQ((estyle & (estyle << 1)), 0); - _test_str_in_buffer(evtpos); + EXPECT_EQ(evt & ievt::EXPL, 0) << (ok = false); + EXPECT_NE(evt & ievt::WSTR, 0) << (ok = false); + EXPECT_EQ(evt & ievt::ALIA, 0) << (ok = false); + EXPECT_EQ(evt & ievt::ANCH, 0) << (ok = false); + EXPECT_EQ(evt & ievt::TAG_, 0) << (ok = false); + EXPECT_NE(evt & (ievt::KEY_|ievt::VAL_), 0) << (ok = false); + EXPECT_NE(evt & (ievt::KEY_|ievt::VAL_), ievt::KEY_|ievt::VAL_) << (ok = false); + EXPECT_EQ(evt & (ievt::BSTR|ievt::ESTR), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::BDOC|ievt::EDOC), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::BSEQ|ievt::ESEQ), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::BMAP|ievt::EMAP), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::FLOW|ievt::BLCK), 0) << (ok = false); + EXPECT_EQ(next & ievt::PSTR, ievt::PSTR) << (ok = false); + evt_bits estyle = evt & style_scalar; + EXPECT_EQ((estyle & (estyle << 1)), 0) << (ok = false); } - if (evt & ievt::ALIA) + if(evt & ievt::ALIA) { - EXPECT_EQ(evt & ievt::EXPL, 0); - EXPECT_NE(evt & ievt::WSTR, 0); - EXPECT_EQ(evt & ievt::SCLR, 0); - EXPECT_EQ(evt & ievt::ANCH, 0); - EXPECT_EQ(evt & ievt::TAG_, 0); - EXPECT_NE(evt & (ievt::KEY_|ievt::VAL_), 0); - EXPECT_NE(evt & (ievt::KEY_|ievt::VAL_), ievt::KEY_|ievt::VAL_); - EXPECT_EQ(evt & (ievt::BSTR|ievt::ESTR), 0); - EXPECT_EQ(evt & (ievt::BDOC|ievt::EDOC), 0); - EXPECT_EQ(evt & (ievt::BSEQ|ievt::ESEQ), 0); - EXPECT_EQ(evt & (ievt::BMAP|ievt::EMAP), 0); - EXPECT_EQ(evt & (ievt::FLOW|ievt::BLCK), 0); - EXPECT_EQ(evt & (ievt::PLAI|ievt::SQUO|ievt::DQUO|ievt::LITL|ievt::FOLD), 0); - EXPECT_EQ(next & ievt::PSTR, ievt::PSTR); - _test_str_in_buffer(evtpos); + EXPECT_EQ(evt & ievt::EXPL, 0) << (ok = false); + EXPECT_NE(evt & ievt::WSTR, 0) << (ok = false); + EXPECT_EQ(evt & ievt::SCLR, 0) << (ok = false); + EXPECT_EQ(evt & ievt::ANCH, 0) << (ok = false); + EXPECT_EQ(evt & ievt::TAG_, 0) << (ok = false); + EXPECT_NE(evt & (ievt::KEY_|ievt::VAL_), 0) << (ok = false); + EXPECT_NE(evt & (ievt::KEY_|ievt::VAL_), ievt::KEY_|ievt::VAL_) << (ok = false); + EXPECT_EQ(evt & (ievt::BSTR|ievt::ESTR), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::BDOC|ievt::EDOC), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::BSEQ|ievt::ESEQ), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::BMAP|ievt::EMAP), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::FLOW|ievt::BLCK), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::PLAI|ievt::SQUO|ievt::DQUO|ievt::LITL|ievt::FOLD), 0) << (ok = false); + EXPECT_EQ(next & ievt::PSTR, ievt::PSTR) << (ok = false); } - if (evt & ievt::ANCH) + if(evt & ievt::ANCH) { - EXPECT_EQ(evt & ievt::EXPL, 0); - EXPECT_NE(evt & ievt::WSTR, 0); - EXPECT_EQ(evt & ievt::SCLR, 0); - EXPECT_EQ(evt & ievt::ALIA, 0); - EXPECT_EQ(evt & ievt::TAG_, 0); - EXPECT_NE(evt & (ievt::KEY_|ievt::VAL_), 0); - EXPECT_NE(evt & (ievt::KEY_|ievt::VAL_), ievt::KEY_|ievt::VAL_); - EXPECT_EQ(evt & (ievt::BSTR|ievt::ESTR), 0); - EXPECT_EQ(evt & (ievt::BDOC|ievt::EDOC), 0); - EXPECT_EQ(evt & (ievt::BSEQ|ievt::ESEQ), 0); - EXPECT_EQ(evt & (ievt::BMAP|ievt::EMAP), 0); - EXPECT_EQ(evt & (ievt::FLOW|ievt::BLCK), 0); - EXPECT_EQ(evt & (ievt::PLAI|ievt::SQUO|ievt::DQUO|ievt::LITL|ievt::FOLD), 0); - EXPECT_EQ(next & ievt::PSTR, ievt::PSTR); - _test_str_in_buffer(evtpos); + EXPECT_EQ(evt & ievt::EXPL, 0) << (ok = false); + EXPECT_NE(evt & ievt::WSTR, 0) << (ok = false); + EXPECT_EQ(evt & ievt::SCLR, 0) << (ok = false); + EXPECT_EQ(evt & ievt::ALIA, 0) << (ok = false); + EXPECT_EQ(evt & ievt::TAG_, 0) << (ok = false); + EXPECT_NE(evt & (ievt::KEY_|ievt::VAL_), 0) << (ok = false); + EXPECT_NE(evt & (ievt::KEY_|ievt::VAL_), ievt::KEY_|ievt::VAL_) << (ok = false); + EXPECT_EQ(evt & (ievt::BSTR|ievt::ESTR), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::BDOC|ievt::EDOC), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::BSEQ|ievt::ESEQ), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::BMAP|ievt::EMAP), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::FLOW|ievt::BLCK), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::PLAI|ievt::SQUO|ievt::DQUO|ievt::LITL|ievt::FOLD), 0) << (ok = false); + EXPECT_EQ(next & ievt::PSTR, ievt::PSTR) << (ok = false); } - if (evt & ievt::TAG_) + if(evt & ievt::TAG_) { - EXPECT_EQ(evt & ievt::EXPL, 0); - EXPECT_NE(evt & ievt::WSTR, 0); - EXPECT_EQ(evt & ievt::SCLR, 0); - EXPECT_EQ(evt & ievt::ALIA, 0); - EXPECT_EQ(evt & ievt::ANCH, 0); - EXPECT_NE(evt & (ievt::KEY_|ievt::VAL_), 0); - EXPECT_NE(evt & (ievt::KEY_|ievt::VAL_), ievt::KEY_|ievt::VAL_); - EXPECT_EQ(evt & (ievt::BSTR|ievt::ESTR), 0); - EXPECT_EQ(evt & (ievt::BDOC|ievt::EDOC), 0); - EXPECT_EQ(evt & (ievt::BSEQ|ievt::ESEQ), 0); - EXPECT_EQ(evt & (ievt::BMAP|ievt::EMAP), 0); - EXPECT_EQ(evt & (ievt::FLOW|ievt::BLCK), 0); - EXPECT_EQ(evt & (ievt::PLAI|ievt::SQUO|ievt::DQUO|ievt::LITL|ievt::FOLD), 0); - EXPECT_EQ(next & ievt::PSTR, ievt::PSTR); - _test_str_in_buffer(evtpos); + EXPECT_EQ(evt & ievt::EXPL, 0) << (ok = false); + EXPECT_NE(evt & ievt::WSTR, 0) << (ok = false); + EXPECT_EQ(evt & ievt::SCLR, 0) << (ok = false); + EXPECT_EQ(evt & ievt::ALIA, 0) << (ok = false); + EXPECT_EQ(evt & ievt::ANCH, 0) << (ok = false); + EXPECT_NE(evt & (ievt::KEY_|ievt::VAL_), 0) << (ok = false); + EXPECT_NE(evt & (ievt::KEY_|ievt::VAL_), ievt::KEY_|ievt::VAL_) << (ok = false); + EXPECT_EQ(evt & (ievt::BSTR|ievt::ESTR), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::BDOC|ievt::EDOC), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::BSEQ|ievt::ESEQ), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::BMAP|ievt::EMAP), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::FLOW|ievt::BLCK), 0) << (ok = false); + EXPECT_EQ(evt & (ievt::PLAI|ievt::SQUO|ievt::DQUO|ievt::LITL|ievt::FOLD), 0) << (ok = false); + EXPECT_EQ(next & ievt::PSTR, ievt::PSTR) << (ok = false); } - #undef _test_str_in_buffer + if(!ok) + break; } } + +namespace { +std::string filter_emitted_yaml_ints(csubstr em) +{ + std::string filtered; + filtered.reserve(em.len); + size_t line_start = 0; + size_t line_end = em.find('\n'); + while(true) + { + if(line_end != csubstr::npos) + ++line_end; + csubstr line = em.range(line_start, line_end); + // skip YAML directives + if(line.begins_with("%YAML ")) + goto skip; // NOLINT + // skip expl end docs if they're not followed by directives + else if(line == "...\n") + { + csubstr next_line = em.sub(line_end); + if(!next_line.begins_with("%TAG")) + goto skip; // NOLINT + } + filtered.append(line.str, line.len); + skip: + if(line_end == csubstr::npos || line_end >= em.len) + break; + line_start = line_end; + line_end = em.find('\n', line_start); + } + return filtered; +} + +bool compare_emitted_yaml_ints(csubstr emitted_, csubstr expected_) +{ + if(expected_.begins_with("---\n") || expected_.begins_with("--- ")) + { + if(expected_.sub(4) == emitted_) + return true; + } + if(emitted_.ends_with("...\n")) + { + if(expected_ == emitted_.offs(0, 4)) + return true; + } + return false; +} +} // namespace + +void test_compare_emitted_yaml_ints(std::string const& emitted, std::string const& expected) +{ + SCOPED_TRACE("compare_emitted_yaml_ints"); + if(emitted == expected) + return; + // they differ. work around some edge cases. + if(compare_emitted_yaml_ints(to_csubstr(emitted), to_csubstr(expected))) + return; + // remove internal ...\n + std::string filtered = filter_emitted_yaml_ints(to_csubstr(emitted)); + if(filtered == expected) + return; + if(compare_emitted_yaml_ints(to_csubstr(filtered), to_csubstr(expected))) + return; + RYML_TRACE_FMT("filtered=~~~\n{}~~~\n", filtered); + EXPECT_EQ(expected, emitted); +} + +} // namespace ievt } // namespace extra } // namespace yml } // namespace c4 diff --git a/test/test_lib/test_events_ints_helpers.hpp b/test/test_lib/test_events_ints_helpers.hpp index c7058aedb..ad9398ee3 100644 --- a/test/test_lib/test_events_ints_helpers.hpp +++ b/test/test_lib/test_events_ints_helpers.hpp @@ -1,25 +1,37 @@ #ifndef TEST_EVENTS_INTS_HPP_ #define TEST_EVENTS_INTS_HPP_ +#ifdef RYML_SINGLE_HEADER +#include +#else +#include +#include +#include +#include #include #include -#include - +#include +#include +#include +#endif +#include +#include namespace c4 { namespace yml { namespace extra { +namespace ievt { // provide a structured input for the event integers, grouping the // relevant data for the event in a single structure to simplify // specifying events in tests struct IntEventWithScalar { - ievt::evt_bits flags, str_start, str_len; + evt_bits flags, str_start, str_len; csubstr scalar; bool needs_filter; - IntEventWithScalar(ievt::evt_bits t, ievt::evt_bits start=0, ievt::evt_bits len=0, csubstr sclr={}, bool needs_filter_=false) + IntEventWithScalar(evt_bits t, evt_bits start=0, evt_bits len=0, csubstr sclr={}, bool needs_filter_=false) : flags(t) , str_start(start) , str_len(len) @@ -35,17 +47,249 @@ size_t num_ints(IntEventWithScalar const *evt, size_t evt_sz); void test_events_ints(IntEventWithScalar const* expected, size_t expected_sz, - ievt::evt_bits const* actual, size_t actual_sz, + evt_bits const* actual, size_t actual_sz, csubstr yaml, csubstr parsed_source, csubstr arena); +void test_events_ints_compare(ievt::Buffers const& expected, ievt::Buffers const& actual); + void test_events_ints_invariants( csubstr parsed_yaml, csubstr arena, - ievt::evt_bits const* evts_ints, - ievt::evt_bits evts_ints_sz); + evt_bits const* evts_ints, + evt_bits evts_ints_sz); + + +void test_compare_emitted_yaml_ints(std::string const& emitted, std::string const& expected); + + +//----------------------------------------------------------------------------- + +C4_SUPPRESS_WARNING_PUSH +C4_SUPPRESS_WARNING_GCC_CLANG("-Wold-style-cast") + + +inline void parse_ints(substr src, extra::ievt::Buffers *ints, ParserOptions const& opts={}) +{ + using Handler = extra::ievt::EventHandlerInts; + Handler handler; + ParseEngine parser(&handler, opts); + handler.reset(src); + parser.parse_in_place_ev("(testyaml)", src); + handler.get_buffers(ints, true); +} + +struct TestBuffers : public ievt::Buffers +{ +public: + + template + void prepare_parse(ievt::EventHandlerInts &handler, + substr parsed_yaml, + evt_size evts_cap=-1, size_t arena_size=npos) + { + if(evts_cap == -1) + evts_cap = ievt::estimate_events_size(to_csubstr(parsed_yaml)); + if(arena_size == npos) + arena_size = parsed_yaml.size(); + _c4dbgpf("ints: setting buffer sizes: src={} ints={} arena={}", parsed_yaml.size(), evts_cap, arena_size); + callbacks = handler.m_stack.m_callbacks; + ASSERT_NE(callbacks.m_allocate, nullptr); + ASSERT_NE(callbacks.m_free, nullptr); + ASSERT_NE(callbacks.m_error_basic, nullptr); + resize_(evts_cap, arena_size, parsed_yaml); + handler.reset(*this); + } + + template + bool resize_post_parse(ievt::EventHandlerInts &handler, substr parsed_yaml) + { + bool ret = false; + if C4_IF_CONSTEXPR (resize_buffers) + { + EXPECT_TRUE(handler.fits_buffers()); + } + else + { + if(!handler.fits_buffers()) + { + resize_(handler.required_size_events(), handler.required_size_arena(), parsed_yaml); + handler.reset(*this); + ret = true; + } + } + return ret; + } + + void resize_(evt_size evts_cap, size_t arena_size, substr parsed_yaml) + { + ASSERT_NE(callbacks.m_allocate, nullptr); + ASSERT_NE(callbacks.m_free, nullptr); + ASSERT_NE(callbacks.m_error_basic, nullptr); + src = parsed_yaml; + if(arena_size > arena.len) + { + arena = yml::detail::resize(arena, arena_size, callbacks); + } + ASSERT_GE(arena.len, arena_size); + if(evts_cap > evts.len) + { + evt_size prev_len = evts.len; + evts = yml::detail::resize(evts, evts_cap, callbacks); + EXPECT_EQ(prev_len, evts.len); + } + ASSERT_GE(evts.cap, evts_cap); + } + +public: + + void print(bool print_all=false) const + { + evt_size sz = print_all ? evts.cap : num_ints(); + ievt::events_ints_print(to_csubstr(src), to_csubstr(arena), evts.ptr, sz); + } + + evt_size num_ints() const + { + evt_size sz = evts.len; + for(evt_size i = 0; i < sz; ++i) + { + if(evts.ptr[i] & extra::ievt::WSTR) // NOLINT + i += 2; // NOLINT + else if(!evts.ptr[i]) + return i; + } + return sz; + } + +public: + + void test_invariants() const + { + SCOPED_TRACE("test_invariants"); + ievt::test_events_ints_invariants(src, arena, evts.ptr, evts.len); + } + + void test_compare(ievt::Buffers const& that) const + { + SCOPED_TRACE("test_compare"); + ievt::test_events_ints_compare(that, *this); + } + + void test_expected_evts(csubstr yaml, ievt::IntEventWithScalar const* expected, evt_size sz) const + { + SCOPED_TRACE("compare_ints"); + ievt::test_events_ints(expected, (size_t)sz, + evts.ptr, (size_t)evts.len, + yaml, + src, + arena); + } + + void test_expected_testsuite(csubstr expected_events, bool ignore_doc_style=false) const + { + SCOPED_TRACE("compare_testsuite"); + std::string actual_events = ievt::events_ints_to_testsuite( + src, arena, + evts.ptr, evts.len); + _c4dbgpf("~~~\n{}~~~\n", actual_events); + test_compare_events(expected_events, + to_csubstr(actual_events), + ignore_doc_style, + /*ignore_container_style*/false, + /*ignore_scalar_style*/false, + /*ignore_tag_normalization*/true); + } + +public: + + void emit_yaml(FILE* file, EmitOptions const& opts={}, evt_size pos=0) const + { + ASSERT_TRUE(pos <= evts.len); + ievt::EmitterInts emitter(opts, file); + emitter.emit_as(EMIT_YAML, evts.ptr, evts.len, pos, src, arena); + } + void emit_json(FILE* file, EmitOptions const& opts={}, evt_size pos=0) const + { + ASSERT_TRUE(pos <= evts.len); + ievt::EmitterInts emitter(opts, file); + emitter.emit_as(EMIT_JSON, evts.ptr, evts.len, pos, src, arena); + } + + template + void emit_yaml_stream(Stream &stream, EmitOptions const& opts={}, evt_size pos=0) const + { + ievt::EmitterInts> emitter(opts, &stream); + emitter.emit_as(EMIT_YAML, evts.ptr, evts.len, pos, src, arena); + } + template + void emit_json_stream(Stream &stream, EmitOptions const& opts={}, evt_size pos=0) const + { + ievt::EmitterInts> emitter(opts, &stream); + emitter.emit_as(EMIT_JSON, evts.ptr, evts.len, pos, src, arena); + } + + size_t emit_yaml(substr yaml, EmitOptions const& opts={}, evt_size pos=0) const + { + ievt::EmitterInts emitter(opts, yaml); + emitter.emit_as(EMIT_YAML, evts.ptr, evts.len, pos, src, arena); + return emitter.get_result(/*error_on_excess*/false).len; + } + size_t emit_json(substr json, EmitOptions const& opts={}, evt_size pos=0) const + { + ievt::EmitterInts emitter(opts, json); + emitter.emit_as(EMIT_JSON, evts.ptr, evts.len, pos, src, arena); + return emitter.get_result(/*error_on_excess*/false).len; + } + + template + void emitrs_yaml(CharContainer *cont, EmitOptions const& opts={}, evt_size pos=0) const + { + const size_t cap = cont->capacity(); + cont->resize(cap); + const size_t len = this->emit_yaml(to_substr(*cont), opts, pos); + cont->resize(len); + if(len > cap) + { + const size_t len2 = this->emit_yaml(to_substr(*cont), opts, pos); + ASSERT_EQ(len2, len); + } + } + template + void emitrs_json(CharContainer *cont, EmitOptions const& opts={}, evt_size pos=0) const + { + const size_t cap = cont->capacity(); + cont->resize(cap); + const size_t len = this->emit_json(to_substr(*cont), opts, pos); + cont->resize(len); + if(len > cap) + { + const size_t len2 = this->emit_json(to_substr(*cont), opts, pos); + ASSERT_EQ(len2, len); + } + } + + template + CharContainer emitrs_yaml(EmitOptions const& opts={}, evt_size pos=0) const + { + CharContainer c; + this->emitrs_yaml(&c, opts, pos); + return c; + } + template + CharContainer emitrs_json(EmitOptions const& opts={}, evt_size pos=0) const + { + CharContainer c; + this->emitrs_json(&c, opts, pos); + return c; + } + +}; + +C4_SUPPRESS_WARNING_POP +} // namespace ievt } // namespace extra } // namespace yml } // namespace c4 diff --git a/test/test_lib/test_group.cpp b/test/test_lib/test_group.cpp index ea93c880a..9523c7cd4 100644 --- a/test/test_lib/test_group.cpp +++ b/test/test_lib/test_group.cpp @@ -7,579 +7,562 @@ #include #include #include -#include #include -#include -//----------------------------------------------------------------------------- namespace c4 { namespace yml { -void YmlTestCase::_test_parse_using_ryml(CaseDataLineEndings *cd) +void CaseData::ensure_reftree(Case const *c) { - #ifdef RYML_DBG - if(dbg_enabled_()) - printf("---------------\n%.*s\n---------------\n", (int)c->src.len, c->src.str); - #endif - - if(c->flags & (EXPECT_PARSE_ERROR|HAS_CONTAINER_KEYS)) - { - ExpectError::check_error_parse(&cd->parsed_tree, [this, cd](){ - parse_in_place(c->fileline, cd->src, &cd->parsed_tree); - // if this point was reached, then it means that the expected - // error failed to occur. So print debugging info. - _c4dbg_tree("UNEXPECTED PARSED TREE", cd->parsed_tree); - }, c->expected_location); - return; - } - - cd->parsed_tree.clear(); - parse_in_place(c->fileline, cd->src, &cd->parsed_tree); - - #ifdef RYML_DBG - if(dbg_enabled_()) - { - print_test_tree("REF TREE", c->root); - _c4dbg_tree("PARSED TREE", cd->parsed_tree); - } - #endif - - if(!(c->flags & EXPECT_RESOLVE_ERROR)) - { - SCOPED_TRACE("checking tree invariants of unresolved parsed tree"); - test_invariants(cd->parsed_tree); - } - if(!(c->flags & EXPECT_RESOLVE_ERROR)) + SCOPED_TRACE("reftree"); + if(reftree.ensure([&]{ c->root.recreate(reftree.result); })) { - SCOPED_TRACE("checking node invariants of unresolved parsed tree"); - test_invariants(cd->parsed_tree.rootref()); + SCOPED_TRACE("checking tree invariants of recreated tree"); + test_invariants(reftree.result); } +} - if(c->flags & RESOLVE_REFS) - { - if(c->flags & EXPECT_RESOLVE_ERROR) - { - ExpectError::check_error(ExpectedErrorType::err_any, &cd->parsed_tree, [&]{ - cd->parsed_tree.resolve(); - // if this point was reached, then it means that the expected - // error failed to occur. So print debugging info. - _c4dbg_tree("UNEXPECTED RESOLVED TREE", cd->parsed_tree); - }, c->expected_location); - return; - } - - cd->parsed_tree.resolve(); - _c4dbg_tree("resolved tree!!!", cd->parsed_tree); +void CaseDataLineEndings::ensure_tree_parse(Case const *c) +{ + SCOPED_TRACE("tree parse"); + auto &dst = tree.val; + dst.ensure([&]{ + dst.result.clear(); + if(c->flags & (EXPECT_PARSE_ERROR|HAS_CONTAINER_KEYS)) // NOLINT { - SCOPED_TRACE("checking tree invariants of resolved parsed tree"); - test_invariants(cd->parsed_tree); + RYML_EXPECT_ERROR(check_error_parse(&dst.result, [&]{ + parse_in_place(c->fileline, tree.src.result, &dst.result); + }, c->expected_location)); + if(testing::Test::HasFailure()) + { + printf("---------------\n%.*s\n---------------\n", (int)c->src.len, c->src.str); + print_tree("PARSED TREE", dst.result); + return; + } } + else { - SCOPED_TRACE("checking node invariants of resolved parsed tree"); - test_invariants(cd->parsed_tree.rootref()); + bool parseok = false; + RYML_EXPECT_ERROR(check_success(&dst.result, [&]{ + parse_in_place(c->fileline, tree.src.result, &dst.result); + parseok = true; + })); + if(parseok && !(c->flags & EXPECT_RESOLVE_ERROR)) + { + SCOPED_TRACE("test invariants"); + test_invariants(dst.result); + } + if(testing::Test::HasFailure()) + { + printf("---------------\n%.*s\n---------------\n", (int)c->src.len, c->src.str); + print_tree("PARSED TREE", dst.result); + return; + } + if(c->flags & RESOLVE_REFS) + { + SCOPED_TRACE("resolve"); + if(c->flags & EXPECT_RESOLVE_ERROR) + { + RYML_EXPECT_ERROR(check_error(ExpectedErrorType::err_any, &dst.result, [&]{ + dst.result.resolve(); + }, c->expected_location)); + } + else + { + RYML_EXPECT_ERROR(check_success(&dst.result, [&]{ + dst.result.resolve(); + })); + { + SCOPED_TRACE("test invariants"); + test_invariants(dst.result); + } + { + SCOPED_TRACE("reorder"); + dst.result.reorder(); + test_invariants(dst.result); + } + } + if(testing::Test::HasFailure()) + { + printf("~~~\n%.*s\n~~~\n", (int)c->src.len, c->src.str); + print_tree("PARSED TREE", dst.result); + return; + } + } } - } + }); +} +void CaseDataLineEndings::ensure_tree_emit_yaml(Case const *c) +{ + SCOPED_TRACE("tree emit yaml"); + ensure_tree_parse(c); + if(c->flags & (EXPECT_PARSE_ERROR|HAS_CONTAINER_KEYS)) // NOLINT + return; + auto &dst = tree_roundtrip_yaml; + if(dst.src.ensure([&]{ + RYML_EXPECT_ERROR(check_success(&tree.val.result, [&]{ + emitrs_yaml(tree.val.result, &dst.src.result); + })); + })) { - SCOPED_TRACE("comparing parsed tree to ref tree"); - EXPECT_GE(cd->parsed_tree.capacity(), c->root.reccount()); - EXPECT_EQ(cd->parsed_tree.size(), c->root.reccount()); - c->root.compare(cd->parsed_tree.rootref()); + dst.orig = dst.src; } +} - if(c->flags & RESOLVE_REFS) +void CaseDataLineEndings::ensure_tree_emit_json(Case const *c) +{ + SCOPED_TRACE("tree emit json"); + ensure_tree_parse(c); + if(c->flags & (EXPECT_PARSE_ERROR|HAS_CONTAINER_KEYS)) // NOLINT + return; + auto &dst = tree_roundtrip_json; + if(dst.src.ensure([&]{ + RYML_EXPECT_ERROR(check_success(&tree.val.result, [&]{ + emitrs_json(tree.val.result, &dst.src.result); + })); + })) { - cd->parsed_tree.reorder(); - _c4dbg_tree("reordered tree!!!", cd->parsed_tree); - { - SCOPED_TRACE("checking tree invariants of reordered parsed tree after resolving"); - test_invariants(cd->parsed_tree); - } + dst.orig = dst.src; + } +} + + +void CaseDataLineEndings::ensure_tree_roundtrip_yaml(Case const *c) +{ + SCOPED_TRACE("tree roundtrip yaml"); + ensure_tree_emit_yaml(c); + if(c->flags & (EXPECT_PARSE_ERROR|HAS_CONTAINER_KEYS)) // NOLINT + return; + auto &dst = tree_roundtrip_yaml.val; + dst.ensure([&]{ + RYML_EXPECT_ERROR(check_success(&tree.val.result, [&]{ + parse_in_place(c->fileline, tree_roundtrip_yaml.src.result, &dst.result); + })); + if(!(c->flags & EXPECT_RESOLVE_ERROR)) // NOLINT { - SCOPED_TRACE("checking node invariants of reordered parsed tree after resolving"); - test_invariants(cd->parsed_tree.rootref()); + SCOPED_TRACE("test invariants: roundtrip"); + test_invariants(dst.result); } + }); +} + +void CaseDataLineEndings::ensure_tree_roundtrip_json(Case const *c) +{ + SCOPED_TRACE("tree roundtrip json"); + ensure_tree_emit_json(c); + if(c->flags & (EXPECT_PARSE_ERROR|HAS_CONTAINER_KEYS)) // NOLINT + return; + auto &dst = tree_roundtrip_json.val; + dst.ensure([&]{ + RYML_EXPECT_ERROR(check_success(&tree.val.result, [&]{ + parse_json_in_place(c->fileline, tree_roundtrip_json.src.result, &dst.result); + })); { - SCOPED_TRACE("comparing parsed tree to ref tree"); - EXPECT_GE(cd->parsed_tree.capacity(), c->root.reccount()); - EXPECT_EQ(cd->parsed_tree.size(), c->root.reccount()); - c->root.compare(cd->parsed_tree.rootref()); + SCOPED_TRACE("test invariants: roundtrip"); + test_invariants(tree_roundtrip_json.val.result); } - } + }); } -static void _parse_events_ints(csubstr name, substr src, std::vector *ints, std::vector *arena) + +//----------------------------------------------------------------------------- + +using LangType = EmitType_e; +const LangType as_yaml = EMIT_YAML; +const LangType as_json = EMIT_JSON; + +template +static void _parse_ints(csubstr name, substr src, extra::ievt::TestBuffers *ints, LangType type) { SCOPED_TRACE("parse_ints"); - using I = extra::ievt::evt_bits; - using Handler = extra::EventHandlerInts; - int estimated_size = extra::estimate_events_ints_size(src); - ints->resize((size_t)estimated_size); - arena->resize(src.len); + using Handler = extra::ievt::EventHandlerInts; Handler handler; - handler.reset(src, to_substr(*arena), ints->data(), (I)ints->size()); ParseEngine parser(&handler); - parser.parse_in_place_ev(name, src); - EXPECT_GT(handler.required_size_events(), 0); - ASSERT_GE(estimated_size, handler.required_size_events()); - ints->resize((size_t)handler.required_size_events()); + _c4dbgpf("parsing source:\n{}", prs_(src)); + if C4_IF_CONSTEXPR (resize_buffers) + { + ints->prepare_parse(handler, src); + if(type == as_yaml) + parser.parse_in_place_ev(name, src); + else + parser.parse_json_in_place_ev(name, src); + } + else + { + ints->prepare_parse(handler, src, + /*estimate*/-1, /*arena*/2 * src.len); + if(type == as_yaml) + parser.parse_in_place_ev(name, src); + else + parser.parse_json_in_place_ev(name, src); + } + ASSERT_GT(handler.required_size_events(), 0); ASSERT_TRUE(handler.fits_buffers()); + handler.get_buffers(ints, true); } -void YmlTestCase::_test_parse_using_ints(CaseDataLineEndings *cd) -{ - SCOPED_TRACE("test_parse_ints"); - - #ifdef RYML_DBG - if(dbg_enabled_()) - printf("---------------\n%.*s\n---------------\n", (int)c->src.len, c->src.str); - #endif - - substr s = to_substr(cd->parse_buf_ints); - auto printints = [&]{ - std::cout << extra::events_ints_to_testsuite(s, to_csubstr(cd->arena_ints), cd->parsed_ints.data(), (int)cd->parsed_ints.size()) << "\n"; - }; +template +static void _test_parse_to_ints(Case const* c, substr src, extra::ievt::TestBuffers *ints, LangType type) +{ if(c->flags & EXPECT_PARSE_ERROR) { SCOPED_TRACE("expect error"); - ExpectError::check_error_parse(&cd->parsed_tree, [&]{ - _parse_events_ints(c->fileline, s, &cd->parsed_ints, &cd->arena_ints); - printints(); // error failed to occur. So print debugging info. - }, c->expected_location); - return; + RYML_EXPECT_ERROR(check_error_parse([&]{ + _parse_ints(c->fileline, src, ints, type); + ints->print(); // error failed to occur. So print debugging info. + }, c->expected_location)); + if C4_IF_CONSTEXPR (!resize_buffers) + ints->owned = true; + } + else + { + SCOPED_TRACE("parse to ints"); + bool parseok = false; + RYML_EXPECT_ERROR(check_success([&]{ + _parse_ints(c->fileline, src, ints, type); + parseok = true; + })); + if(parseok) + ints->test_invariants(); + } + if(testing::Test::HasFailure()) + { + if(src != c->src) + printf("~~~[%zu]\n%.*s~~~\n", c->src.len, (int)c->src.len, c->src.str); + printf("~~~[%zu]\n%.*s~~~\n", src.len, (int)src.len, src.str); + ints->print(); } +} - _parse_events_ints(c->fileline, s, &cd->parsed_ints, &cd->arena_ints); +template +static void _ensure_ints_parse(Case const *c, SrcInts &ints, LangType type) +{ + SCOPED_TRACE("ensure_ints_parse"); + ASSERT_TRUE(ints.orig.done); + ASSERT_TRUE(ints.src.done); + auto &dst = ints.val; + dst.ensure([&]{ + _test_parse_to_ints(c, ints.src.result, &dst.result, type); + }); +} - #ifdef RYML_DBG - if(dbg_enabled_()) - printints(); - #endif +template +static void _ensure_ints_emit(Case const *c, SrcInts &from, SrcInts &to, LangType type) +{ + SCOPED_TRACE("ensure_ints_parse"); + _ensure_ints_parse(c, from, as_yaml);// first level parsed as yaml + ASSERT_TRUE(from.val.done); + if(c->flags & EXPECT_PARSE_ERROR) // NOLINT + return; + bool executed = to.src.ensure([&]{ + if(type == as_yaml) + from.val.result.emitrs_yaml(&to.src.result); + else + from.val.result.emitrs_json(&to.src.result); + }); + if(executed) + { + to.orig = to.src; + } +} +template +static void _ensure_ints_parse_roundtrip(Case const *c, SrcInts &from, SrcInts &to, LangType type) +{ + SCOPED_TRACE("ensure ints roundtrip"); + _ensure_ints_emit(c, from, to, type); { - SCOPED_TRACE("checking invariants"); - extra::test_events_ints_invariants(s, to_csubstr(cd->arena_ints), cd->parsed_ints.data(), (int)cd->parsed_ints.size()); + SCOPED_TRACE("roundtrip parse"); + _ensure_ints_parse(c, to, type); } } -//----------------------------------------------------------------------------- -void YmlTestCase::_test_emit_yml_stdout(CaseDataLineEndings *cd) +void CaseDataLineEndings::ensure_ints_resize_emit_yaml(Case const *c) { - if(c->flags & (EXPECT_PARSE_ERROR|HAS_CONTAINER_KEYS)) - return; - _ensure_parse(cd); - _ensure_emit(cd); - emit_yaml(cd->parsed_tree); + SCOPED_TRACE("ensure_ints_resize_emit_yaml"); + _ensure_ints_emit(c, ints_resize, ints_resize_roundtrip_yaml, as_yaml); } - -//----------------------------------------------------------------------------- -void YmlTestCase::_test_emit_json_stdout(CaseDataLineEndings *cd) +void CaseDataLineEndings::ensure_ints_resize_emit_json(Case const *c) { - if(!(c->flags & JSON_WRITE)) - return; - if(c->flags & (EXPECT_PARSE_ERROR|HAS_CONTAINER_KEYS)) - return; - _ensure_parse(cd); - _ensure_emit_json(cd); - emit_json(cd->parsed_tree); + SCOPED_TRACE("ensure_ints_resize_emit_json"); + _ensure_ints_emit(c, ints_resize, ints_resize_roundtrip_json, as_json); } -//----------------------------------------------------------------------------- -void YmlTestCase::_test_emit_yml_cout(CaseDataLineEndings *cd) +void CaseDataLineEndings::ensure_ints_noresize_emit_yaml(Case const *c) { - if(c->flags & (EXPECT_PARSE_ERROR|HAS_CONTAINER_KEYS)) - return; - _ensure_parse(cd); - _ensure_emit(cd); - std::cout << cd->parsed_tree; - std::cout << cd->parsed_tree.rootref(); + SCOPED_TRACE("ensure_ints_noresize_emit_yaml"); + _ensure_ints_emit(c, ints_noresize, ints_noresize_roundtrip_yaml, as_yaml); } - -//----------------------------------------------------------------------------- -void YmlTestCase::_test_emit_json_cout(CaseDataLineEndings *cd) +void CaseDataLineEndings::ensure_ints_noresize_emit_json(Case const *c) { - if(!(c->flags & JSON_WRITE)) - return; - if(c->flags & (EXPECT_PARSE_ERROR|HAS_CONTAINER_KEYS)) - return; - _ensure_parse(cd); - _ensure_emit_json(cd); - std::cout << as_json(cd->parsed_tree); - std::cout << as_json(cd->parsed_tree.rootref()); + SCOPED_TRACE("ensure_ints_noresize_emit_json"); + _ensure_ints_emit(c, ints_noresize, ints_noresize_roundtrip_json, as_json); } -//----------------------------------------------------------------------------- -void YmlTestCase::_test_emit_yml_stringstream(CaseDataLineEndings *cd) +void CaseDataLineEndings::ensure_ints_resize_roundtrip_yaml(Case const *c) { - if(c->flags & (EXPECT_PARSE_ERROR|HAS_CONTAINER_KEYS)) - return; - _ensure_parse(cd); - _ensure_emit(cd); - { - std::stringstream ss; - ss << cd->parsed_tree; - std::string actual = ss.str(); - EXPECT_EQ(actual, cd->emit_buf); - } - { - std::stringstream ss; - ss << cd->parsed_tree.rootref(); - std::string actual = ss.str(); - EXPECT_EQ(actual, cd->emit_buf); - } + SCOPED_TRACE("ensure_ints_resize_roundtrip_yaml"); + _ensure_ints_parse_roundtrip(c, ints_resize, ints_resize_roundtrip_yaml, as_yaml); +} +void CaseDataLineEndings::ensure_ints_resize_roundtrip_json(Case const *c) +{ + SCOPED_TRACE("ensure_ints_resize_roundtrip_json"); + _ensure_ints_parse_roundtrip(c, ints_resize, ints_resize_roundtrip_json, as_json); } -//----------------------------------------------------------------------------- -void YmlTestCase::_test_emit_json_stringstream(CaseDataLineEndings *cd) +void CaseDataLineEndings::ensure_ints_noresize_roundtrip_yaml(Case const *c) { - if(!(c->flags & JSON_WRITE)) - return; - if(c->flags & (EXPECT_PARSE_ERROR|HAS_CONTAINER_KEYS)) - return; - _ensure_parse(cd); - _ensure_emit_json(cd); - { - std::stringstream ss; - ss << as_json(cd->parsed_tree); - std::string actual = ss.str(); - EXPECT_EQ(actual, cd->emitjson_buf); - } - { - std::stringstream ss; - ss << as_json(cd->parsed_tree.rootref()); - std::string actual = ss.str(); - EXPECT_EQ(actual, cd->emitjson_buf); - } + SCOPED_TRACE("ensure_ints_noresize_roundtrip_yaml"); + _ensure_ints_parse_roundtrip(c, ints_noresize, ints_noresize_roundtrip_yaml, as_yaml); } +void CaseDataLineEndings::ensure_ints_noresize_roundtrip_json(Case const *c) +{ + SCOPED_TRACE("ensure_ints_noresize_roundtrip_json"); + _ensure_ints_parse_roundtrip(c, ints_noresize, ints_noresize_roundtrip_json, as_json); +} + //----------------------------------------------------------------------------- -void YmlTestCase::_test_emit_yml_ofstream(CaseDataLineEndings *cd) +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +using S = std::string const&; + +void YmlTestCase::_test_parse_yaml_to_tree(CaseDataLineEndings *cd) { - if(c->flags & (EXPECT_PARSE_ERROR|HAS_CONTAINER_KEYS)) + cd->ensure_tree_parse(c); + if(c->flags & (EXPECT_PARSE_ERROR|HAS_CONTAINER_KEYS|EXPECT_RESOLVE_ERROR)) // NOLINT return; - _ensure_parse(cd); - _ensure_emit(cd); + d->ensure_reftree(c); { - auto fn = fs::tmpnam(); - { - std::ofstream f(fn, std::ios::binary); - f << cd->parsed_tree; - } - auto actual = fs::file_get_contents(fn.c_str()); - EXPECT_EQ(actual, cd->emit_buf); - fs::rmfile(fn.c_str()); + SCOPED_TRACE("comparing parsed tree to ref tree"); + ASSERT_GE(cd->tree.val.result.capacity(), c->root.reccount()); + ASSERT_EQ(cd->tree.val.result.size(), c->root.reccount()); + c->root.compare(cd->tree.val.result.rootref()); } { - auto fn = fs::tmpnam(); - { - std::ofstream f(fn, std::ios::binary); - f << cd->parsed_tree.rootref(); - } - auto actual = fs::file_get_contents(fn.c_str()); - EXPECT_EQ(actual, cd->emit_buf); - fs::rmfile(fn.c_str()); + SCOPED_TRACE("comparing to recreated tree"); + test_compare(cd->tree.val.result, d->reftree.result); } } -//----------------------------------------------------------------------------- -void YmlTestCase::_test_emit_json_ofstream(CaseDataLineEndings *cd) +void YmlTestCase::_test_roundtrip_yaml_tree(CaseDataLineEndings *cd) { - if(!(c->flags & JSON_WRITE)) - return; - if(c->flags & (EXPECT_PARSE_ERROR|HAS_CONTAINER_KEYS)) + if(c->flags & (EXPECT_PARSE_ERROR|HAS_CONTAINER_KEYS|EXPECT_RESOLVE_ERROR)) // NOLINT return; - _ensure_parse(cd); - _ensure_emit_json(cd); + SCOPED_TRACE("test_roundtrip_yaml_tree"); + cd->ensure_tree_roundtrip_yaml(c); { - auto fn = fs::tmpnam(); - { - std::ofstream f(fn, std::ios::binary); - f << as_json(cd->parsed_tree); - } - auto actual = fs::file_get_contents(fn.c_str()); - EXPECT_EQ(actual, cd->emitjson_buf); - fs::rmfile(fn.c_str()); + SCOPED_TRACE("comparing roundtrip tree to ref tree"); + d->ensure_reftree(c); + EXPECT_GE(cd->tree_roundtrip_yaml.val.result.capacity(), c->root.reccount()); + EXPECT_EQ(cd->tree_roundtrip_yaml.val.result.size(), c->root.reccount()); + c->root.compare(cd->tree_roundtrip_yaml.val.result.rootref()); } { - auto fn = fs::tmpnam(); - { - std::ofstream f(fn, std::ios::binary); - f << as_json(cd->parsed_tree.rootref()); - } - auto actual = fs::file_get_contents(fn.c_str()); - EXPECT_EQ(actual, cd->emitjson_buf); - fs::rmfile(fn.c_str()); + SCOPED_TRACE("comparing roundtrip tree to recreated tree"); + test_compare(cd->tree_roundtrip_yaml.val.result, d->reftree.result); } } -//----------------------------------------------------------------------------- -void YmlTestCase::_test_emit_yml_string(CaseDataLineEndings *cd) +void YmlTestCase::_test_roundtrip_json_tree(CaseDataLineEndings *cd) { - if(c->flags & (EXPECT_PARSE_ERROR|HAS_CONTAINER_KEYS)) + if(c->flags & (EXPECT_PARSE_ERROR|HAS_CONTAINER_KEYS)) // NOLINT return; - _ensure_parse(cd); - _ensure_emit(cd); - csubstr emitted = emitrs_yaml(cd->parsed_tree, &cd->emit_buf); - EXPECT_EQ(emitted.len, cd->emit_buf.size()); - #ifdef RYML_DBG - printf("%.*s", (int)emitted.len, emitted.str); - #endif + SCOPED_TRACE("test_roundtrip_json_tree"); + cd->ensure_tree_roundtrip_json(c); + std::string json = emitrs_json(cd->tree_roundtrip_json.val.result); + EXPECT_EQ(json, (S)cd->tree_roundtrip_json.orig.result); } -//----------------------------------------------------------------------------- -void YmlTestCase::_test_emit_json_string(CaseDataLineEndings *cd) -{ - if(!(c->flags & JSON_WRITE)) - return; - if(c->flags & (EXPECT_PARSE_ERROR|HAS_CONTAINER_KEYS)) - return; - _ensure_parse(cd); - _ensure_emit_json(cd); - auto emitted = emitrs_json(cd->parsed_tree, &cd->emit_buf); - EXPECT_EQ(emitted.len, cd->emitjson_buf.size()); - #ifdef RYML_DBG - printf("%.*s", (int)emitted.len, emitted.str); - #endif -} //----------------------------------------------------------------------------- -void YmlTestCase::_test_emitrs(CaseDataLineEndings *cd) + +#define cmp_src_(ref, str) \ + { \ + SCOPED_TRACE("cmp_src_"); \ + ASSERT_TRUE((ref).orig.done); \ + ASSERT_TRUE((str).orig.done); \ + EXPECT_EQ((S)(ref).orig.result, (S)(str).orig.result); \ + } +#define cmp_src_str_(ref, str) \ + { \ + SCOPED_TRACE("cmp_src_str_"); \ + ASSERT_TRUE((ref).orig.done); \ + EXPECT_EQ((S)(ref).orig.result, (S)(str)); \ + } + +static void show_parse_info_(CaseDataLineEndings const* cd, + SrcTree const* tree, csubstr tree_emitted, + SrcInts const* ints, csubstr ints_emitted) { - if(c->flags & (EXPECT_PARSE_ERROR|HAS_CONTAINER_KEYS)) - return; - _ensure_parse(cd); - using vtype = std::vector; - using stype = std::string; - vtype vv, v = emitrs_yaml(cd->parsed_tree); - stype ss, s = emitrs_yaml(cd->parsed_tree); - EXPECT_EQ(to_csubstr(v), to_csubstr(s)); - csubstr svv = emitrs_yaml(cd->parsed_tree, &vv); - csubstr sss = emitrs_yaml(cd->parsed_tree, &ss); - EXPECT_EQ(svv, sss); + csubstr src = cd->src; + printf("------\nsrc\n------\n%.*s\n", (int)src.len, src.str); + printf("------\nints\n------\n"); + ints->val.result.print(); + printf("------\nints emitted\n------\n%.*s\n", (int)ints_emitted.len, ints_emitted.str); + print_tree("tree", tree->val.result); + printf("------\ntree emitted\n------\n%.*s\n", (int)tree_emitted.len, tree_emitted.str); } - -//----------------------------------------------------------------------------- -void YmlTestCase::_test_emitrs_json(CaseDataLineEndings *cd) +void YmlTestCase::_test_parse_yaml_to_ints_resize(CaseDataLineEndings *cd) { - if(!(c->flags & JSON_WRITE)) + SCOPED_TRACE("test_parse_ints_resize"); + _ensure_ints_parse(c, cd->ints_resize, as_yaml); + if(c->flags & EXPECT_PARSE_ERROR) // NOLINT return; - if(c->flags & (EXPECT_PARSE_ERROR|HAS_CONTAINER_KEYS)) + cd->ensure_ints_resize_emit_yaml(c); + if(c->flags & (HAS_CONTAINER_KEYS|RESOLVE_REFS)) // NOLINT return; - _ensure_parse(cd); - using vtype = std::vector; - using stype = std::string; - vtype vv, v = emitrs_json(cd->parsed_tree); - stype ss, s = emitrs_json(cd->parsed_tree); - EXPECT_EQ(to_csubstr(v), to_csubstr(s)); - csubstr svv = emitrs_json(cd->parsed_tree, &vv); - csubstr sss = emitrs_json(cd->parsed_tree, &ss); - EXPECT_EQ(svv, sss); -} - -//----------------------------------------------------------------------------- -void YmlTestCase::_test_emitrs_cfile(CaseDataLineEndings *cd) -{ - if(c->flags & (EXPECT_PARSE_ERROR|HAS_CONTAINER_KEYS)) + cd->ensure_tree_emit_yaml(c); + if(c->flags & NO_COMPARE_EMITTED_INTS) // NOLINT return; - _ensure_parse(cd); - auto s = emitrs_yaml(cd->parsed_tree); - std::string r; + extra::ievt::test_compare_emitted_yaml_ints(cd->ints_resize_roundtrip_yaml.orig.result, + cd->tree_roundtrip_yaml.orig.result); + if(testing::Test::HasFailure()) { - c4::fs::ScopedTmpFile f; - emit_yaml(cd->parsed_tree, f.m_file); - fflush(f.m_file); - r = f.contents(); + show_parse_info_(cd, + &cd->tree, cd->tree_roundtrip_yaml.orig.result, + &cd->ints_resize, cd->ints_resize_roundtrip_yaml.orig.result); } - EXPECT_EQ(s, r); } - -//----------------------------------------------------------------------------- -void YmlTestCase::_test_emitrs_json_cfile(CaseDataLineEndings *cd) +void YmlTestCase::_test_parse_yaml_to_ints_noresize(CaseDataLineEndings *cd) { - if(!(c->flags & JSON_WRITE)) + SCOPED_TRACE("test_parse_ints_noresize"); + _ensure_ints_parse(c, cd->ints_noresize, as_yaml); + if(c->flags & EXPECT_PARSE_ERROR) // NOLINT + return; + cd->ensure_ints_noresize_emit_yaml(c); + if(c->flags & (HAS_CONTAINER_KEYS|RESOLVE_REFS)) // NOLINT return; - if(c->flags & (EXPECT_PARSE_ERROR|HAS_CONTAINER_KEYS)) + cd->ensure_tree_emit_yaml(c); + if(c->flags & NO_COMPARE_EMITTED_INTS) // NOLINT return; - _ensure_parse(cd); - auto s = emitrs_json(cd->parsed_tree); - std::string r; + extra::ievt::test_compare_emitted_yaml_ints(cd->ints_noresize_roundtrip_yaml.orig.result, + cd->tree_roundtrip_yaml.orig.result); + if(testing::Test::HasFailure()) { - c4::fs::ScopedTmpFile f; - emit_json(cd->parsed_tree, f.m_file); - fflush(f.m_file); - r = f.contents(); + show_parse_info_(cd, + &cd->tree, cd->tree_roundtrip_yaml.orig.result, + &cd->ints_noresize, cd->ints_noresize_roundtrip_yaml.orig.result); } - EXPECT_EQ(s, r); } -//----------------------------------------------------------------------------- -void YmlTestCase::_test_complete_round_trip(CaseDataLineEndings *cd) +static void show_roundtrip_info_(CaseDataLineEndings const* cd, + SrcTree const* tree, + SrcInts const* level0, SrcInts const* level1, + csubstr tree_emitted, csubstr actual) +{ + csubstr src = cd->src; + csubstr ints_emitted = level1->orig.result; + csubstr roundtrip_ints_emitted = to_csubstr(actual); + printf("------\nsrc\n------\n%.*s\n", (int)src.len, src.str); + printf("------\nints\n------\n"); + level0->val.result.print(); + printf("------\nints emitted\n------\n%.*s\n", (int)ints_emitted.len, ints_emitted.str); + printf("------\nroundtrip ints\n------\n"); + level1->val.result.print(); + printf("------\nints roundtrip emitted\n------\n%.*s\n", (int)roundtrip_ints_emitted.len, roundtrip_ints_emitted.str); + print_tree("roundtrip tree", tree->val.result); + printf("------\ntree emitted\n------\n%.*s\n", (int)tree_emitted.len, tree_emitted.str); +} +static void _test_roundtrip_yaml_ints(Case const *c, CaseDataLineEndings *cd, + SrcInts *level0, SrcInts *level1) { - if(c->flags & (EXPECT_PARSE_ERROR|HAS_CONTAINER_KEYS|EXPECT_RESOLVE_ERROR)) + if(testing::Test::HasFailure()) return; - _ensure_parse(cd); - _ensure_emit(cd); - #ifdef RYML_DBG - printf("~~~~~~~~~~~~~~ emitted yml:\n"); - _c4presc(cd->emitted_yml, /*keep_newlines*/true); - printf("~~~~~~~~~~~~~~\n"); - #endif - { - SCOPED_TRACE("parsing emitted yml"); - cd->parse_buf = cd->emit_buf; - cd->parsed_yml = to_substr(cd->parse_buf); - parse_in_place(c->fileline, cd->parsed_yml, &cd->emitted_tree); - } - #ifdef RYML_DBG - printf("~~~~~~~~~~~~~~ src yml:\n"); - _c4presc(cd->src, /*keep_newlines*/true); - printf("~~~~~~~~~~~~~~ parsed tree:\n"); - print_tree(cd->parsed_tree); - printf("~~~~~~~~~~~~~~ emitted yml:\n"); - _c4presc(cd->emitted_yml, /*keep_newlines*/true); - printf("~~~~~~~~~~~~~~ emitted tree:\n"); - print_tree(cd->emitted_tree); - printf("~~~~~~~~~~~~~~\n"); - #endif - { - SCOPED_TRACE("checking node invariants of emitted tree"); - test_invariants(cd->parsed_tree.rootref()); - } - { - SCOPED_TRACE("checking node invariants of emitted tree"); - test_invariants(cd->emitted_tree.rootref()); - } - { - SCOPED_TRACE("comparing emitted and parsed tree"); - test_compare(cd->emitted_tree, cd->parsed_tree); - } - { - SCOPED_TRACE("checking tree invariants of emitted tree"); - test_invariants(cd->emitted_tree); - } + if(c->flags & (EXPECT_PARSE_ERROR|HAS_CONTAINER_KEYS)) // NOLINT + return; + SCOPED_TRACE("test_roundtrip_yaml_ints"); + cd->ensure_tree_roundtrip_yaml(c); + ASSERT_TRUE(level0->val.done); + ASSERT_TRUE(level1->val.done); + ASSERT_TRUE(cd->tree_roundtrip_yaml.val.done); + level1->val.result.test_compare(level0->val.result); + txtbuf actual = level1->val.result.emitrs_yaml(); + if(!(c->flags & (NO_COMPARE_EMITTED_INTS|RESOLVE_REFS))) // NOLINT { - SCOPED_TRACE("comparing parsed tree to ref tree"); - EXPECT_GE(cd->parsed_tree.capacity(), c->root.reccount()); - EXPECT_EQ(cd->parsed_tree.size(), c->root.reccount()); - c->root.compare(cd->parsed_tree.rootref()); + { + SCOPED_TRACE("vs ints"); + cmp_src_str_(*level1, actual); + } + { + SCOPED_TRACE("vs tree"); + extra::ievt::test_compare_emitted_yaml_ints(actual, cd->tree_roundtrip_yaml.orig.result); + } } + if(testing::Test::HasFailure()) { - SCOPED_TRACE("comparing emitted tree to ref tree"); - EXPECT_GE(cd->emitted_tree.capacity(), c->root.reccount()); - EXPECT_EQ(cd->emitted_tree.size(), c->root.reccount()); - // in this case, we can ignore whether scalars are quoted. - // Because it can happen that a scalar was quoted in the - // original file, but the re-emitted data does not quote the - // scalars. FIXME! - c->root.compare(cd->emitted_tree.rootref(), true); + show_roundtrip_info_(cd, &cd->tree_roundtrip_yaml, + level0, level1, cd->tree_roundtrip_yaml.orig.result, actual); } } - - -//----------------------------------------------------------------------------- -void YmlTestCase::_test_complete_round_trip_json(CaseDataLineEndings *cd) +void YmlTestCase::_test_roundtrip_yaml_ints_resize(CaseDataLineEndings *cd) { - if(!(c->flags & JSON_WRITE)) + SCOPED_TRACE("test_roundtrip_yaml_ints_resize"); + if(c->flags & (EXPECT_PARSE_ERROR)) // NOLINT return; - if(c->flags & (EXPECT_PARSE_ERROR|HAS_CONTAINER_KEYS)) + cd->ensure_ints_resize_roundtrip_yaml(c); + if(testing::Test::HasFailure()) return; - _ensure_parse(cd); - _ensure_emit_json(cd); - #ifdef RYML_DBG - printf("~~~~~~~~~~~~~~ emitted json:\n"); - _c4presc(cd->emitted_json); - printf("~~~~~~~~~~~~~~\n"); - #endif - { - SCOPED_TRACE("parsing emitted json"); - cd->parse_buf_json = cd->emitjson_buf; - cd->parsed_json = to_substr(cd->parse_buf_json); - parse_json_in_place(c->fileline, cd->parsed_json, &cd->emitted_tree_json); - } - #ifdef RYML_DBG - printf("~~~~~~~~~~~~~~ src yml:\n"); - _c4presc(cd->src); - printf("~~~~~~~~~~~~~~ parsed tree:\n"); - print_tree(cd->parsed_tree); - printf("~~~~~~~~~~~~~~ emitted json:\n"); - _c4presc(cd->emitted_json); - printf("~~~~~~~~~~~~~~ emitted json tree:\n"); - print_tree(cd->emitted_tree_json); - printf("~~~~~~~~~~~~~~\n"); - #endif - { - SCOPED_TRACE("checking node invariants of emitted tree"); - test_invariants(cd->parsed_tree.rootref()); - } - { - SCOPED_TRACE("checking node invariants of emitted json tree"); - test_invariants(cd->emitted_tree_json.rootref()); - } - { - SCOPED_TRACE("comparing emitted json and parsed tree"); - test_compare(cd->emitted_tree_json, cd->parsed_tree); - } - { - SCOPED_TRACE("checking tree invariants of emitted json tree"); - test_invariants(cd->emitted_tree_json); - } - { - SCOPED_TRACE("comparing parsed tree to ref tree"); - EXPECT_GE(cd->parsed_tree.capacity(), c->root.reccount()); - EXPECT_EQ(cd->parsed_tree.size(), c->root.reccount()); - c->root.compare(cd->parsed_tree.rootref()); - } - { - SCOPED_TRACE("comparing emitted tree to ref tree"); - EXPECT_GE(cd->emitted_tree_json.capacity(), c->root.reccount()); - EXPECT_EQ(cd->emitted_tree_json.size(), c->root.reccount()); - // in this case, we can ignore whether scalars are quoted. - // Because it can happen that a scalar was quoted in the - // original file, but the re-emitted data does not quote the - // scalars. - c->root.compare(cd->emitted_tree_json.rootref(), true); - } + _test_roundtrip_yaml_ints(c, cd, &cd->ints_resize, &cd->ints_resize_roundtrip_yaml); +} +void YmlTestCase::_test_roundtrip_yaml_ints_noresize(CaseDataLineEndings *cd) +{ + if(c->flags & (EXPECT_PARSE_ERROR)) // NOLINT + return; + SCOPED_TRACE("test_roundtrip_yaml_ints_noresize"); + cd->ensure_ints_noresize_roundtrip_yaml(c); + _test_roundtrip_yaml_ints(c, cd, &cd->ints_noresize, &cd->ints_noresize_roundtrip_yaml); } -//----------------------------------------------------------------------------- -void YmlTestCase::_test_recreate_from_ref(CaseDataLineEndings *cd) + +void _test_roundtrip_json_ints(Case const *c, CaseDataLineEndings *cd, + SrcInts *level0, SrcInts *level1) { - if(c->flags & (EXPECT_PARSE_ERROR|HAS_CONTAINER_KEYS)) + if(testing::Test::HasFailure()) return; - if(cd->parsed_tree.empty()) - parse_in_place(c->fileline, cd->src, &cd->parsed_tree); - if(cd->emit_buf.empty()) - cd->emitted_yml = emitrs_yaml(cd->parsed_tree, &cd->emit_buf); - { - SCOPED_TRACE("recreating a new tree from the ref tree"); - cd->recreated.reserve(cd->parsed_tree.size()); - NodeRef r = cd->recreated.rootref(); - c->root.recreate(&r); - } - #ifdef RYML_DBG - printf("REF TREE:\n"); - print_test_tree(c->root); - printf("RECREATED TREE:\n"); - print_tree(cd->recreated); - #endif - { - SCOPED_TRACE("checking node invariants of recreated tree"); - test_invariants(cd->recreated.rootref()); - } + SCOPED_TRACE("test_roundtrip_json_ints"); + cd->ensure_tree_emit_json(c); + txtbuf actual = level1->val.result.emitrs_json(); + if(!(c->flags & (NO_COMPARE_EMITTED_INTS|NO_COMPARE_EMITTED_INTS_JSON|RESOLVE_REFS))) // NOLINT { - SCOPED_TRACE("checking tree invariants of recreated tree"); - test_invariants(cd->recreated); + { + SCOPED_TRACE("vs ints"); + cmp_src_str_(*level1, actual); + } + { + SCOPED_TRACE("vs tree"); + cmp_src_str_(cd->tree_roundtrip_json, actual); + } } + if(testing::Test::HasFailure()) { - SCOPED_TRACE("comparing recreated tree to ref tree"); - c->root.compare(cd->recreated.rootref()); + show_roundtrip_info_(cd, &cd->tree_roundtrip_json, + level0, level1, cd->tree_roundtrip_json.orig.result, actual); } } +void YmlTestCase::_test_roundtrip_json_ints_resize(CaseDataLineEndings *cd) +{ + SCOPED_TRACE("test_roundtrip_json_ints_resize"); + if(c->flags & (EXPECT_PARSE_ERROR|HAS_CONTAINER_KEYS)) // NOLINT + return; + cd->ensure_ints_resize_roundtrip_json(c); + _test_roundtrip_json_ints(c, cd, &cd->ints_resize, &cd->ints_resize_roundtrip_json); +} +void YmlTestCase::_test_roundtrip_json_ints_noresize(CaseDataLineEndings *cd) +{ + SCOPED_TRACE("test_roundtrip_json_ints_noresize"); + if(c->flags & (EXPECT_PARSE_ERROR|HAS_CONTAINER_KEYS)) // NOLINT + return; + cd->ensure_ints_noresize_roundtrip_json(c); + _test_roundtrip_json_ints(c, cd, &cd->ints_noresize, &cd->ints_noresize_roundtrip_json); +} } // namespace yml } // namespace c4 diff --git a/test/test_lib/test_group.def.hpp b/test/test_lib/test_group.def.hpp index 13c5806fb..510f15819 100644 --- a/test/test_lib/test_group.def.hpp +++ b/test/test_lib/test_group.def.hpp @@ -1,238 +1,162 @@ #ifndef C4_YML_TEST_TEST_GROUP_TEST_GROUP_DEF_HPP_ #define C4_YML_TEST_TEST_GROUP_TEST_GROUP_DEF_HPP_ +#ifndef C4_RYML_TEST_GROUP_HPP_ +#include "./test_lib/test_group.hpp" +#endif + namespace c4 { namespace yml { -int YmlTestCaseDefsWereIncluded() { return 42; } +inline int YmlTestCaseDefsWereIncluded() { return 42; } -//----------------------------------------------------------------------------- -TEST_P(YmlTestCase, parse_unix) -{ - SCOPED_TRACE("unix style\n" + c->filelinebuf + ": case"); - _test_parse_using_ryml(&d->unix_style); -} +//----------------------------------------------------------------------------- -TEST_P(YmlTestCase, parse_windows) +TEST_P(YmlTestCase, recreate_from_ref) { - SCOPED_TRACE("windows style\n" + c->filelinebuf + ": case"); - _test_parse_using_ryml(&d->windows_style); + SCOPED_TRACE("\n" + c->filelinebuf + ": case"); + d->ensure_reftree(c); } //----------------------------------------------------------------------------- -TEST_P(YmlTestCase, parse_ints_unix) +TEST_P(YmlTestCase, parse_yaml_tree_unix) { SCOPED_TRACE("unix style\n" + c->filelinebuf + ": case"); - _test_parse_using_ints(&d->unix_style); + _test_parse_yaml_to_tree(&d->unix_style); + { + SCOPED_TRACE("redo parse to existing tree"); + SrcTree &tree = d->unix_style.tree; + tree.val.result.clear(); + tree.src.result = tree.orig.result; + tree.reset(); + _test_parse_yaml_to_tree(&d->unix_style); + } } -TEST_P(YmlTestCase, parse_ints_windows) +TEST_P(YmlTestCase, parse_yaml_tree_windows) { SCOPED_TRACE("windows style\n" + c->filelinebuf + ": case"); - _test_parse_using_ints(&d->windows_style); + _test_parse_yaml_to_tree(&d->windows_style); } //----------------------------------------------------------------------------- -TEST_P(YmlTestCase, emit_yml_unix_stdout) + +TEST_P(YmlTestCase, parse_yaml_ints_resize_unix) { SCOPED_TRACE("unix style\n" + c->filelinebuf + ": case"); - _test_emit_yml_stdout(&d->unix_style); -} -TEST_P(YmlTestCase, emit_json_unix_stdout) -{ - SCOPED_TRACE("unix style json\n" + c->filelinebuf + ": case"); - _test_emit_json_stdout(&d->unix_style_json); + _test_parse_yaml_to_ints_resize(&d->unix_style); } -TEST_P(YmlTestCase, emit_yml_windows_stdout) +TEST_P(YmlTestCase, parse_yaml_ints_resize_windows) { SCOPED_TRACE("windows style\n" + c->filelinebuf + ": case"); - _test_emit_yml_stdout(&d->windows_style); -} -TEST_P(YmlTestCase, emit_json_windows_stdout) -{ - SCOPED_TRACE("windows style json\n" + c->filelinebuf + ": case"); - _test_emit_json_stdout(&d->windows_style_json); + _test_parse_yaml_to_ints_noresize(&d->windows_style); } -//----------------------------------------------------------------------------- -TEST_P(YmlTestCase, emit_yml_unix_cout) + +TEST_P(YmlTestCase, parse_yaml_ints_noresize_unix) { SCOPED_TRACE("unix style\n" + c->filelinebuf + ": case"); - _test_emit_yml_cout(&d->unix_style); -} -TEST_P(YmlTestCase, emit_json_unix_cout) -{ - SCOPED_TRACE("unix style json\n" + c->filelinebuf + ": case"); - _test_emit_json_cout(&d->unix_style_json); + _test_parse_yaml_to_ints_noresize(&d->unix_style); } -TEST_P(YmlTestCase, emit_yml_windows_cout) +TEST_P(YmlTestCase, parse_yaml_ints_noresize_windows) { SCOPED_TRACE("windows style\n" + c->filelinebuf + ": case"); - _test_emit_yml_cout(&d->windows_style); -} -TEST_P(YmlTestCase, emit_json_windows_cout) -{ - SCOPED_TRACE("windows style json\n" + c->filelinebuf + ": case"); - _test_emit_json_cout(&d->windows_style_json); + _test_parse_yaml_to_ints_noresize(&d->windows_style); } + //----------------------------------------------------------------------------- -TEST_P(YmlTestCase, emit_yml_unix_stringstream) + +TEST_P(YmlTestCase, roundtrip_yaml_tree_unix) { SCOPED_TRACE("unix style\n" + c->filelinebuf + ": case"); - _test_emit_yml_stringstream(&d->unix_style); -} -TEST_P(YmlTestCase, emit_json_unix_stringstream) -{ - SCOPED_TRACE("unix style json\n" + c->filelinebuf + ": case"); - _test_emit_json_stringstream(&d->unix_style_json); + _test_roundtrip_yaml_tree(&d->unix_style); } -TEST_P(YmlTestCase, emit_yml_windows_stringstream) +TEST_P(YmlTestCase, roundtrip_yaml_tree_windows) { SCOPED_TRACE("windows style\n" + c->filelinebuf + ": case"); - _test_emit_yml_stringstream(&d->windows_style); -} -TEST_P(YmlTestCase, emit_json_windows_stringstream) -{ - SCOPED_TRACE("windows style json\n" + c->filelinebuf + ": case"); - _test_emit_json_stringstream(&d->windows_style_json); + _test_roundtrip_yaml_tree(&d->windows_style); } + //----------------------------------------------------------------------------- -TEST_P(YmlTestCase, emit_yml_unix_ofstream) + +TEST_P(YmlTestCase, roundtrip_yaml_ints_resize_unix) { SCOPED_TRACE("unix style\n" + c->filelinebuf + ": case"); - _test_emit_yml_ofstream(&d->unix_style); -} -TEST_P(YmlTestCase, emit_json_unix_ofstream) -{ - SCOPED_TRACE("unix style json\n" + c->filelinebuf + ": case"); - _test_emit_json_ofstream(&d->unix_style_json); + _test_roundtrip_yaml_ints_resize(&d->unix_style); } -TEST_P(YmlTestCase, emit_yml_windows_ofstream) +TEST_P(YmlTestCase, roundtrip_yaml_ints_resize_windows) { SCOPED_TRACE("windows style\n" + c->filelinebuf + ": case"); - _test_emit_yml_ofstream(&d->windows_style); -} -TEST_P(YmlTestCase, emit_json_windows_ofstream) -{ - SCOPED_TRACE("windows style json\n" + c->filelinebuf + ": case"); - _test_emit_json_ofstream(&d->windows_style_json); + _test_roundtrip_yaml_ints_resize(&d->windows_style); } -//----------------------------------------------------------------------------- -TEST_P(YmlTestCase, emit_yml_unix_string) + +TEST_P(YmlTestCase, roundtrip_yaml_ints_noresize_unix) { SCOPED_TRACE("unix style\n" + c->filelinebuf + ": case"); - _test_emit_yml_string(&d->unix_style); -} -TEST_P(YmlTestCase, emit_json_unix_string) -{ - SCOPED_TRACE("unix style json\n" + c->filelinebuf + ": case"); - _test_emit_json_string(&d->unix_style_json); + _test_roundtrip_yaml_ints_noresize(&d->unix_style); } -TEST_P(YmlTestCase, emit_yml_windows_string) +TEST_P(YmlTestCase, roundtrip_yaml_ints_noresize_windows) { SCOPED_TRACE("windows style\n" + c->filelinebuf + ": case"); - _test_emit_yml_string(&d->windows_style); -} -TEST_P(YmlTestCase, emit_json_windows_string) -{ - SCOPED_TRACE("windows style json\n" + c->filelinebuf + ": case"); - _test_emit_json_string(&d->windows_style_json); + _test_roundtrip_yaml_ints_noresize(&d->windows_style); } + //----------------------------------------------------------------------------- -TEST_P(YmlTestCase, unix_emitrs) + +TEST_P(YmlTestCase, roundtrip_json_tree_unix) { SCOPED_TRACE("unix style\n" + c->filelinebuf + ": case"); - _test_emitrs(&d->unix_style); -} -TEST_P(YmlTestCase, unix_emitrs_json) -{ - SCOPED_TRACE("unix style json\n" + c->filelinebuf + ": case"); - _test_emitrs_json(&d->unix_style_json); + _test_roundtrip_json_tree(&d->unix_style); } -TEST_P(YmlTestCase, windows_emitrs) +TEST_P(YmlTestCase, roundtrip_json_tree_windows) { SCOPED_TRACE("windows style\n" + c->filelinebuf + ": case"); - _test_emitrs(&d->windows_style); -} -TEST_P(YmlTestCase, windows_emitrs_json) -{ - SCOPED_TRACE("windows style json\n" + c->filelinebuf + ": case"); - _test_emitrs_json(&d->windows_style_json); + _test_roundtrip_json_tree(&d->windows_style); } + //----------------------------------------------------------------------------- -TEST_P(YmlTestCase, unix_emitrs_cfile) + +TEST_P(YmlTestCase, roundtrip_json_ints_resize_unix) { SCOPED_TRACE("unix style\n" + c->filelinebuf + ": case"); - _test_emitrs_cfile(&d->unix_style); -} -TEST_P(YmlTestCase, unix_emitrs_json_cfile) -{ - SCOPED_TRACE("unix style json\n" + c->filelinebuf + ": case"); - _test_emitrs_json_cfile(&d->unix_style_json); + _test_roundtrip_json_ints_resize(&d->unix_style); } -TEST_P(YmlTestCase, windows_emitrs_cfile) +TEST_P(YmlTestCase, roundtrip_json_ints_resize_windows) { SCOPED_TRACE("windows style\n" + c->filelinebuf + ": case"); - _test_emitrs_cfile(&d->windows_style); -} -TEST_P(YmlTestCase, windows_emitrs_json_cfile) -{ - SCOPED_TRACE("windows style json\n" + c->filelinebuf + ": case"); - _test_emitrs_json_cfile(&d->windows_style_json); + _test_roundtrip_json_ints_resize(&d->windows_style); } -//----------------------------------------------------------------------------- -TEST_P(YmlTestCase, complete_unix_round_trip) -{ - SCOPED_TRACE("unix style:\n" + c->filelinebuf + ": case"); - _test_complete_round_trip(&d->unix_style); -} -TEST_P(YmlTestCase, complete_unix_round_trip_json) -{ - SCOPED_TRACE("unix style json\n" + c->filelinebuf + ": case"); - _test_complete_round_trip_json(&d->unix_style_json); -} -TEST_P(YmlTestCase, complete_windows_round_trip) -{ - SCOPED_TRACE("windows style\n" + c->filelinebuf + ": case"); - _test_complete_round_trip(&d->windows_style); -} -TEST_P(YmlTestCase, complete_windows_round_trip_json) -{ - SCOPED_TRACE("windows style json\n" + c->filelinebuf + ": case"); - _test_complete_round_trip_json(&d->windows_style_json); -} - -//----------------------------------------------------------------------------- -TEST_P(YmlTestCase, unix_recreate_from_ref) +TEST_P(YmlTestCase, roundtrip_json_ints_noresize_unix) { SCOPED_TRACE("unix style\n" + c->filelinebuf + ": case"); - _test_recreate_from_ref(&d->unix_style); + _test_roundtrip_json_ints_noresize(&d->unix_style); } -TEST_P(YmlTestCase, windows_recreate_from_ref) +TEST_P(YmlTestCase, roundtrip_json_ints_noresize_windows) { SCOPED_TRACE("windows style\n" + c->filelinebuf + ": case"); - _test_recreate_from_ref(&d->windows_style); + _test_roundtrip_json_ints_noresize(&d->windows_style); } + } // namespace c4 } // namespace yml diff --git a/test/test_lib/test_group.hpp b/test/test_lib/test_group.hpp index d338c7ed0..5c43dca26 100644 --- a/test/test_lib/test_group.hpp +++ b/test/test_lib/test_group.hpp @@ -6,20 +6,14 @@ #include "c4/span.hpp" #include -#if defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable: 4068/*unknown pragma*/) -# pragma warning(disable: 4702/*unreachable code*/) -#elif defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wunknown-pragmas" -# if __GNUC__ > 5 -# pragma GCC diagnostic ignored "-Wunused-const-variable" -# endif -//# pragma GCC diagnostic ignored "-Wpragma-system-header-outside-header" +C4_SUPPRESS_WARNING_PUSH +C4_SUPPRESS_WARNING_MSVC(4068/*unknown pragma*/) +C4_SUPPRESS_WARNING_MSVC(4702/*unreachable code*/) +C4_SUPPRESS_WARNING_CLANG("-Wgnu-zero-variadic-macro-arguments") +C4_SUPPRESS_WARNING_GCC("-Wunknown-pragmas") +#if defined(__GNUC__) && (__GNUC__ > 5) +C4_SUPPRESS_WARNING_GCC("-Wunused-const-variable") +//C4_SUPPRESS_WARNING_GCC("-Wpragma-system-header-outside-header") #endif #if defined(RYML_WITH_TAB_TOKENS) @@ -70,66 +64,18 @@ struct YmlTestCase : public ::testing::TestWithParam std::cout << "-------------------------------------------\n"; } - void _test_parse_using_ryml(CaseDataLineEndings *cd); - void _test_parse_using_ints(CaseDataLineEndings *cd); - - void _test_emit_yml_stdout(CaseDataLineEndings *cd); - void _test_emit_json_stdout(CaseDataLineEndings *cd); - - void _test_emit_yml_cout(CaseDataLineEndings *cd); - void _test_emit_json_cout(CaseDataLineEndings *cd); - - void _test_emit_yml_stringstream(CaseDataLineEndings *cd); - void _test_emit_json_stringstream(CaseDataLineEndings *cd); - - void _test_emit_yml_ofstream(CaseDataLineEndings *cd); - void _test_emit_json_ofstream(CaseDataLineEndings *cd); - - void _test_emit_yml_string(CaseDataLineEndings *cd); - void _test_emit_json_string(CaseDataLineEndings *cd); - - void _test_emitrs(CaseDataLineEndings *cd); - void _test_emitrs_json(CaseDataLineEndings *cd); - - void _test_emitrs_cfile(CaseDataLineEndings *cd); - void _test_emitrs_json_cfile(CaseDataLineEndings *cd); + void _test_parse_yaml_to_tree(CaseDataLineEndings *cd); + void _test_parse_yaml_to_ints_noresize(CaseDataLineEndings *cd); + void _test_parse_yaml_to_ints_resize(CaseDataLineEndings *cd); - void _test_complete_round_trip(CaseDataLineEndings *cd); - void _test_complete_round_trip_json(CaseDataLineEndings *cd); + void _test_roundtrip_yaml_tree(CaseDataLineEndings *cd); + void _test_roundtrip_yaml_ints_resize(CaseDataLineEndings *cd); + void _test_roundtrip_yaml_ints_noresize(CaseDataLineEndings *cd); - void _test_recreate_from_ref(CaseDataLineEndings *cd); + void _test_roundtrip_json_tree(CaseDataLineEndings *cd); + void _test_roundtrip_json_ints_resize(CaseDataLineEndings *cd); + void _test_roundtrip_json_ints_noresize(CaseDataLineEndings *cd); - void _ensure_parse(CaseDataLineEndings *cd) - { - if(cd->parsed_tree.empty()) - parse_in_place(c->fileline, cd->src, &cd->parsed_tree); - } - void _ensure_emit(CaseDataLineEndings *cd) - { - _ensure_parse(cd); - if(cd->emit_buf.empty()) - { - cd->emitted_yml = emitrs_yaml(cd->parsed_tree, &cd->emit_buf); - ASSERT_EQ(cd->emitted_yml.size(), cd->emit_buf.size()); - if(cd->emitted_yml.size()) - { - ASSERT_EQ(cd->emitted_yml.data(), cd->emit_buf.data()); - } - } - } - void _ensure_emit_json(CaseDataLineEndings *cd) - { - _ensure_parse(cd); - if(cd->emitjson_buf.empty()) - { - cd->emitted_json = emitrs_json(cd->parsed_tree, &cd->emitjson_buf); - ASSERT_EQ(cd->emitted_json.size(), cd->emitjson_buf.size()); - if(cd->emitted_json.size()) - { - ASSERT_EQ(cd->emitted_json.data(), cd->emitjson_buf.data()); - } - } - } }; @@ -200,6 +146,7 @@ struct CaseAdderGcc4_8 } }; + /* all arguments are to the constructor of Case */ #define ADD_CASE_TO_GROUP CaseAdderGcc4_8{group_cases__, csubstr(__FILE__), __LINE__+1} @@ -273,13 +220,6 @@ void add_cases_##group_name(std::vector *group_cases__) } // namespace yml } // namespace c4 -#if defined(_MSC_VER) -# pragma warning(pop) -# pragma warning(disable: 4702/*unreachable code*/) -#elif defined(__clang__) -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#endif +C4_SUPPRESS_WARNING_PUSH #endif // C4_RYML_TEST_GROUP_HPP_ diff --git a/test/test_lib/tree_and_ints.hpp b/test/test_lib/tree_and_ints.hpp new file mode 100644 index 000000000..7691b729a --- /dev/null +++ b/test/test_lib/tree_and_ints.hpp @@ -0,0 +1,259 @@ +#ifndef TEST_TREE_AND_INTS_HPP_ +#define TEST_TREE_AND_INTS_HPP_ + +#include +#ifdef RYML_SINGLE_HEADER +#include +#else +#include +#include +#include +#endif + +#include +#include + +namespace c4 { +namespace yml { + +using IntBufs = extra::ievt::TestBuffers; +using IntBufsCR = IntBufs const&; + +struct TreeAndInts +{ + Tree tree; + IntBufs ints; + std::string src_ints; +}; + +inline TreeAndInts parse_tree_and_ints(csubstr src, ParserOptions const& opts={}) +{ + TreeAndInts ret; + parse_in_arena(src, &ret.tree, opts); + ret.src_ints.assign(src.str, src.len); + parse_ints(to_substr(ret.src_ints), &ret.ints, opts); + return ret; +} + + +inline void test_emit_yaml_tree(ConstNodeRef n, std::string const& expected, EmitOptions const& opts={}) +{ + if(!testing::Test::HasFailure()) + { + RYML_TRACE_FMT("tree: id={}", n.id()); + EXPECT_EQ(emitrs_yaml(n, opts), expected); + if(testing::Test::HasFailure()) + print_tree(*n.tree()); + } +} +inline void test_emit_yaml_tree(ConstNodeRef n, EmitOptions const& opts, std::string const& expected) +{ + test_emit_yaml_tree(n, expected, opts); +} + + +inline void test_emit_yaml_ints(IntBufsCR ints, extra::ievt::evt_size pos, std::string const& expected, EmitOptions const& opts={}) +{ + if(!testing::Test::HasFailure()) + { + RYML_TRACE_FMT("ints: pos={}", pos); + EXPECT_EQ(ints.emitrs_yaml(opts, pos), expected); + if(testing::Test::HasFailure()) + ints.print(); + } +} +inline void test_emit_yaml_ints(IntBufsCR ints, extra::ievt::evt_size pos, EmitOptions const& opts, std::string const& expected) +{ + test_emit_yaml_ints(ints, pos, expected, opts); +} + + +inline void test_emit_yaml_same_ints(ConstNodeRef n, std::string const& expected, EmitOptions const& opts={}) +{ + if(!testing::Test::HasFailure()) + { + RYML_TRACE_FMT("tree: id={}", n.id()); + std::string emitted_tree = emitrs_yaml(n, opts); + EXPECT_EQ(emitted_tree, expected); + if(testing::Test::HasFailure()) + { + print_tree(*n.tree()); + return; + } + { + SCOPED_TRACE("here"); + IntBufs ints; + parse_ints(to_substr(emitted_tree), &ints); + test_emit_yaml_ints(ints, 0, expected, opts); + } + } +} + +inline void test_emit_yaml(ConstNodeRef n, IntBufsCR ints, extra::ievt::evt_size pos, std::string const& expected, EmitOptions const& opts={}) +{ + test_emit_yaml_tree(n, expected, opts); + test_emit_yaml_ints(ints, pos, expected, opts); +} +inline void test_emit_yaml(ConstNodeRef n, IntBufsCR ints, extra::ievt::evt_size pos, EmitOptions const& opts, std::string const& expected) +{ + test_emit_yaml(n, ints, pos, expected, opts); +} +inline void test_emit_yaml(TreeAndInts const& ti, std::string const& expected, EmitOptions const& opts={}) +{ + test_emit_yaml(ti.tree.rootref(), ti.ints, 0, expected, opts); +} +inline void test_emit_yaml(TreeAndInts const& ti, EmitOptions const& opts, std::string const& expected) +{ + test_emit_yaml(ti.tree.rootref(), ti.ints, 0, expected, opts); +} + + +inline void test_emit_json_tree(ConstNodeRef n, std::string const& expected, EmitOptions const& opts={}) +{ + if(!testing::Test::HasFailure()) + { + RYML_TRACE_FMT("tree: id={}", n.id()); + EXPECT_EQ(emitrs_json(n, opts), expected); + if(testing::Test::HasFailure()) + print_tree(*n.tree()); + } +} +inline void test_emit_json_ints(IntBufsCR ints, extra::ievt::evt_size pos, std::string const& expected, EmitOptions const& opts={}) +{ + if(!testing::Test::HasFailure()) + { + RYML_TRACE_FMT("ints: pos={}", pos); + EXPECT_EQ(ints.emitrs_json(opts, pos), expected); + if(testing::Test::HasFailure()) + ints.print(); + } +} +inline void test_emit_json_same_ints(ConstNodeRef n, std::string const& expected, EmitOptions const& opts={}) +{ + if(!testing::Test::HasFailure()) + { + RYML_TRACE_FMT("tree: id={}", n.id()); + std::string emitted_tree = emitrs_json(n, opts); + EXPECT_EQ(emitted_tree, expected); + if(testing::Test::HasFailure()) + { + print_tree(*n.tree()); + return; + } + { + SCOPED_TRACE("here"); + IntBufs ints; + parse_ints(to_substr(emitted_tree), &ints); + test_emit_json_ints(ints, 0, expected, opts); + } + } +} +inline void test_emit_json_tree(ConstNodeRef n, EmitOptions const& opts, std::string const& expected) +{ + test_emit_json_tree(n, expected, opts); +} +inline void test_emit_json(IntBufsCR ints, extra::ievt::evt_size pos, EmitOptions const& opts, std::string const& expected) +{ + test_emit_json_ints(ints, pos, expected, opts); +} +inline void test_emit_json(ConstNodeRef n, IntBufsCR ints, extra::ievt::evt_size pos, std::string const& expected, EmitOptions const& opts={}) +{ + test_emit_json_tree(n, expected, opts); + test_emit_json_ints(ints, pos, expected, opts); +} +inline void test_emit_json(ConstNodeRef n, IntBufsCR ints, extra::ievt::evt_size pos, EmitOptions const& opts, std::string const& expected) +{ + test_emit_json(n, ints, pos, expected, opts); +} +inline void test_emit_json(TreeAndInts const& ti, std::string const& expected, EmitOptions const& opts={}) +{ + test_emit_json(ti.tree.rootref(), ti.ints, 0, expected, opts); +} +inline void test_emit_json(TreeAndInts const& ti, EmitOptions const& opts, std::string const& expected) +{ + test_emit_json(ti.tree.rootref(), ti.ints, 0, opts, expected); +} + + + +inline void test_emit_error_yaml_tree(NodeRef n, EmitOptions const& opts={}) +{ + RYML_TRACE_FMT("tree: id={}", n.id()); + RYML_EXPECT_ERROR(check_error_visit(n.tree(), [&]{ + emitrs_yaml(n, opts); + // if we reach this, it's a failure + GTEST_FAIL(); + print_tree(*n.tree()); + })); +} +inline void test_emit_error_yaml_ints(IntBufsCR ints, extra::ievt::evt_size pos, EmitOptions const& opts={}) +{ + RYML_TRACE_FMT("ints: pos={}", pos); + RYML_EXPECT_ERROR(check_error_basic([&]{ + ints.emitrs_yaml(opts, pos); + // if we reach this, it's a failure + GTEST_FAIL(); + ints.print(); + })); +} +inline void test_emit_error_yaml_ints(IntBufsCR ints, EmitOptions const& opts={}) +{ + test_emit_error_yaml_ints(ints, 0, opts); +} + +inline void test_emit_error_yaml(NodeRef n, IntBufsCR ints, extra::ievt::evt_size pos, EmitOptions const& opts={}) +{ + test_emit_error_yaml_tree(n, opts); + test_emit_error_yaml_ints(ints, pos, opts); +} +inline void test_emit_error_yaml(NodeRef n, IntBufsCR ints, EmitOptions const& opts={}) +{ + test_emit_error_yaml(n, ints, 0, opts); +} +inline void test_emit_error_yaml(TreeAndInts & ti, EmitOptions const& opts={}) +{ + test_emit_error_yaml(ti.tree.rootref(), ti.ints, 0, opts); +} + +inline void test_emit_error_json_tree(NodeRef n, EmitOptions const& opts={}) +{ + RYML_TRACE_FMT("tree: id={}", n.id()); + RYML_EXPECT_ERROR(check_error_visit(n.tree(), [&]{ + emitrs_json(n, opts); + // if we reach this, it's a failure + print_tree(*n.tree()); + })); +} +inline void test_emit_error_json_ints(IntBufsCR ints, extra::ievt::evt_size pos, EmitOptions const& opts={}) +{ + RYML_TRACE_FMT("ints: pos={}", pos); + RYML_EXPECT_ERROR(check_error_basic([&]{ + ints.emitrs_json(opts, pos); + // if we reach this, it's a failure + ints.print(); + })); +} +inline void test_emit_error_json_ints(IntBufsCR ints, EmitOptions const& opts={}) +{ + test_emit_error_json_ints(ints, 0, opts); +} + +inline void test_emit_error_json(NodeRef n, IntBufsCR ints, extra::ievt::evt_size pos, EmitOptions const& opts={}) +{ + test_emit_error_json_tree(n, opts); + test_emit_error_json_ints(ints, pos, opts); +} +inline void test_emit_error_json(NodeRef n, IntBufsCR ints, EmitOptions const& opts={}) +{ + test_emit_error_json(n, ints, 0, opts); +} +inline void test_emit_error_json(TreeAndInts & ti, EmitOptions const& opts={}) +{ + test_emit_error_json(ti.tree.rootref(), ti.ints, 0, opts); +} + + +} // namespace yml +} // namespace c4 + +#endif /* TEST_TREE_AND_INTS_HPP_ */ diff --git a/test/test_map.cpp b/test/test_map.cpp index e79b215a2..90d8d9929 100644 --- a/test/test_map.cpp +++ b/test/test_map.cpp @@ -827,7 +827,7 @@ R"( N(MB, L{N(KP|VP, "key", "value")}) ); -ADD_CASE_TO_GROUP("simple map, null values", +ADD_CASE_TO_GROUP("simple map, null values", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"( key: val a: @@ -842,12 +842,12 @@ foo: bar N(MB, L{N(KP|VP, "key", "val"), N(KP|VN, "a", {}), N(KP|VN, "b", {}), N(KP|VN, "c", {}), N(KP|VN, "d", {}), N(KP|VN, "e", {}), N(KP|VN, "f", {}), N(KP|VN, "g", {}), N(KP|VP, "foo", "bar"),}) ); -ADD_CASE_TO_GROUP("simple map expl, null values 1", +ADD_CASE_TO_GROUP("simple map expl, null values 1", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"({key: val, a, b, c, d, e: , f: , g: , foo: bar})", N(MFS, L{N(KP|VP, "key", "val"), N(KP|VN, "a", {}), N(KP|VN, "b", {}), N(KP|VN, "c", {}), N(KP|VN, "d", {}), N(KP|VN, "e", {}), N(KP|VN, "f", {}), N(KP|VN, "g", {}), N(KP|VP, "foo", "bar"),}) ); -ADD_CASE_TO_GROUP("simple map expl, null values 2", +ADD_CASE_TO_GROUP("simple map expl, null values 2", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"( - {a} - {a, b, c} @@ -864,7 +864,7 @@ N(SB, L{ }) ); -ADD_CASE_TO_GROUP("simple map expl, null values 3, 4ABK", +ADD_CASE_TO_GROUP("simple map expl, null values 3, 4ABK", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"( - {foo: , bar: , baz: } - {foo:, bar:, baz:} @@ -1102,7 +1102,7 @@ N(MB, L{ }) ); -ADD_CASE_TO_GROUP("simple map expl, scalars with special chars, comma", +ADD_CASE_TO_GROUP("simple map expl, scalars with special chars, comma", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"({ a0,b0: val0,0000 c0,d0: val0, 0000 diff --git a/test/test_map_set.cpp b/test/test_map_set.cpp index fe99578bf..752f46bf9 100644 --- a/test/test_map_set.cpp +++ b/test/test_map_set.cpp @@ -50,7 +50,7 @@ TEST(simple_set, emit_doc) CASE_GROUP(SIMPLE_SET) { -ADD_CASE_TO_GROUP("doc as set, missing value", +ADD_CASE_TO_GROUP("doc as set, missing value", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"(!!set ? a ? b @@ -59,7 +59,7 @@ R"(!!set N(MB, TL("!!set", L{N(KP|VN, "a", {}), N(KP|VN, "b", {}), N(KN|VN, {}, "")})) ); -ADD_CASE_TO_GROUP("doc as set, implicit", +ADD_CASE_TO_GROUP("doc as set, implicit", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"(!!set ? a ? b @@ -67,7 +67,7 @@ R"(!!set N(MB, TL("!!set", L{N(KP|VN, "a", {}), N(KP|VN, "b", {})})) ); -ADD_CASE_TO_GROUP("doc as set", +ADD_CASE_TO_GROUP("doc as set", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"(--- !!set ? aa ? bb @@ -82,7 +82,7 @@ N(STREAM, L{ }) ); -ADD_CASE_TO_GROUP("sets 2XXW", +ADD_CASE_TO_GROUP("sets 2XXW", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"( --- !!set ? Mark McGwire @@ -98,7 +98,7 @@ N(STREAM, L{ }) ); -ADD_CASE_TO_GROUP("sets 2XXW, no set", +ADD_CASE_TO_GROUP("sets 2XXW, no set", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"( --- ? Mark McGwire @@ -114,7 +114,7 @@ N(STREAM, L{ }) ); -ADD_CASE_TO_GROUP("sets 2XXW, no doc", +ADD_CASE_TO_GROUP("sets 2XXW, no doc", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"(!!set ? Mark McGwire ? Sammy Sosa @@ -127,7 +127,7 @@ N(MB, TL("!!set", L{ })) ); -ADD_CASE_TO_GROUP("sets 2XXW, no doc, no set", +ADD_CASE_TO_GROUP("sets 2XXW, no doc, no set", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"( ? Mark McGwire ? Sammy Sosa diff --git a/test/test_qmrk.cpp b/test/test_qmrk.cpp index 690e18f80..a58349e3d 100644 --- a/test/test_qmrk.cpp +++ b/test/test_qmrk.cpp @@ -145,7 +145,7 @@ TEST(qmrk, test_suite_FRK4) CASE_GROUP(QMRK) { -ADD_CASE_TO_GROUP("explicit key, last value missing", +ADD_CASE_TO_GROUP("explicit key, last value missing", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"( ? a ? b @@ -176,7 +176,7 @@ N(STREAM, L{ }) ); -ADD_CASE_TO_GROUP("explicit key, all values missing", +ADD_CASE_TO_GROUP("explicit key, all values missing", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"( ? ? @@ -189,7 +189,7 @@ N(MB, L{ }) ); -ADD_CASE_TO_GROUP("explicit key, last value missing, end doc", +ADD_CASE_TO_GROUP("explicit key, last value missing, end doc", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"( ? a ? b @@ -407,7 +407,7 @@ N(MB, L{ }) ); -ADD_CASE_TO_GROUP("explicit key, missing val 7W2P", +ADD_CASE_TO_GROUP("explicit key, missing val 7W2P", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"( ? a ? b @@ -424,7 +424,7 @@ N(MB, L{ }) ); -ADD_CASE_TO_GROUP("explicit key, missing val ZWK4", +ADD_CASE_TO_GROUP("explicit key, missing val ZWK4", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"( a: 1 ? b diff --git a/test/test_scalar_dquoted.cpp b/test/test_scalar_dquoted.cpp index 8bf576471..f41625e5b 100644 --- a/test/test_scalar_dquoted.cpp +++ b/test/test_scalar_dquoted.cpp @@ -997,7 +997,7 @@ Newlines can also be added by leaving a blank line. N(VD, "Several lines of text, containing 'single quotes' and \"double quotes\". Escapes (like \\n) work.\nIn addition, newlines can be escaped to prevent them from being converted to a space.\nNewlines can also be added by leaving a blank line. Leading whitespace on lines is ignored.") ); -ADD_CASE_TO_GROUP("dquoted, empty", +ADD_CASE_TO_GROUP("dquoted, empty", NO_COMPARE_EMITTED_INTS,//FIXME R"("")", N(VD, "") ); diff --git a/test/test_scalar_null.cpp b/test/test_scalar_null.cpp index 0ca9f0c82..05580b581 100644 --- a/test/test_scalar_null.cpp +++ b/test/test_scalar_null.cpp @@ -1069,12 +1069,12 @@ TEST(empty_scalar, build_zero_length_string) CASE_GROUP(NULL_VAL) { -ADD_CASE_TO_GROUP("empty scalar, single quoted", +ADD_CASE_TO_GROUP("empty scalar, single quoted", NO_COMPARE_EMITTED_INTS,//FIXME "''", N(VS, "") ); -ADD_CASE_TO_GROUP("all null", +ADD_CASE_TO_GROUP("all null", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"( - - # with space @@ -1105,13 +1105,13 @@ N(MB, L{N(KP|VP, "null", "~")}), }) ); -ADD_CASE_TO_GROUP("null map vals, expl", +ADD_CASE_TO_GROUP("null map vals, expl", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"({foo: , bar: , baz: } )", N(MFS, L{N(KP|VN, "foo", nullptr), N(KP|VN, "bar", nullptr), N(KP|VN, "baz", nullptr)}) ); -ADD_CASE_TO_GROUP("null map vals, impl", +ADD_CASE_TO_GROUP("null map vals, impl", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"( foo: bar: @@ -1120,7 +1120,7 @@ R"( N(MB, L{N(KP|VN, "foo", nullptr), N(KP|VN, "bar", nullptr), N(KP|VN, "baz", nullptr)}) ); -ADD_CASE_TO_GROUP("null seq vals, impl", +ADD_CASE_TO_GROUP("null seq vals, impl", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"(- - - @@ -1128,7 +1128,7 @@ R"(- N(SB, L{N(VN, nullptr), N(VN, nullptr), N(VN, nullptr)}) ); -ADD_CASE_TO_GROUP("null seq vals in map, impl, mixed 1", +ADD_CASE_TO_GROUP("null seq vals in map, impl, mixed 1", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"( foo: - @@ -1140,7 +1140,7 @@ R"( N(MB, L{N(KP|SB, "foo", L{VN, VN, VN}), N(KP|VN, "bar", nullptr), N(KP|VN, "baz", nullptr)}) ); -ADD_CASE_TO_GROUP("null seq vals in map, impl, mixed 2", +ADD_CASE_TO_GROUP("null seq vals in map, impl, mixed 2", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"( foo: bar: @@ -1152,7 +1152,7 @@ R"( N(MB, L{N(KP|VN, "foo", nullptr), N(KP|SB, "bar", L{VN, VN, VN}), N(KP|VN, "baz", nullptr)}) ); -ADD_CASE_TO_GROUP("null seq vals in map, impl, mixed 3", +ADD_CASE_TO_GROUP("null seq vals in map, impl, mixed 3", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"( foo: bar: @@ -1164,7 +1164,7 @@ R"( N(MB, L{N(KP|VN, "foo", nullptr), N(KP|VN, "bar", nullptr), N(KP|SB, "baz", L{VN, VN, VN})}) ); -ADD_CASE_TO_GROUP("null map vals in seq, impl, mixed 1", +ADD_CASE_TO_GROUP("null map vals in seq, impl, mixed 1", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"( - foo: bar: @@ -1183,7 +1183,7 @@ N(SB, L{ }) ); -ADD_CASE_TO_GROUP("null map vals in seq, impl, mixed 2", +ADD_CASE_TO_GROUP("null map vals in seq, impl, mixed 2", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"( - - foo: @@ -1202,7 +1202,7 @@ N(SB, L{ }) ); -ADD_CASE_TO_GROUP("null map vals in seq, impl, mixed 3", +ADD_CASE_TO_GROUP("null map vals in seq, impl, mixed 3", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"( - - @@ -1221,7 +1221,7 @@ N(SB, L{ }) ); -ADD_CASE_TO_GROUP("issue84.1", +ADD_CASE_TO_GROUP("issue84.1", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"( fixed case: foo: a @@ -1238,7 +1238,7 @@ N(MB, L{ }) ); -ADD_CASE_TO_GROUP("issue84.2", +ADD_CASE_TO_GROUP("issue84.2", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"( version: 0 type: xml @@ -1279,7 +1279,7 @@ N(MB, L{ }) ); -ADD_CASE_TO_GROUP("issue84.3", +ADD_CASE_TO_GROUP("issue84.3", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"( version: 10 type: test diff --git a/test/test_scalar_plain.cpp b/test/test_scalar_plain.cpp index 2ed1279ce..c8bac195e 100644 --- a/test/test_scalar_plain.cpp +++ b/test/test_scalar_plain.cpp @@ -839,7 +839,7 @@ N(SB, L{N(VP, "Several lines of text, with special:characters, like:this-or-this )}) ); -ADD_CASE_TO_GROUP("plain scalar, special characters 3MYT", +ADD_CASE_TO_GROUP("plain scalar, special characters 3MYT", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"(--- # ZWK4 a: 1 ? b @@ -1240,14 +1240,14 @@ N(MB, L{ ); -ADD_CASE_TO_GROUP("plain scalar trailing column 1, flow, seq", +ADD_CASE_TO_GROUP("plain scalar trailing column 1, flow, seq", NO_COMPARE_EMITTED_INTS_JSON,//FIXME "[plain:]", N(SFS, L{ N(MFS, L{N(KP|VP|VALNIL, "plain", "")}), }) ); -ADD_CASE_TO_GROUP("plain scalar trailing column 1, flow, seqimap", +ADD_CASE_TO_GROUP("plain scalar trailing column 1, flow, seqimap", NO_COMPARE_EMITTED_INTS_JSON,//FIXME "[{plain:}]", N(SFS, L{ N(MFS, L{N(KP|VP|VALNIL, "plain", "")}), @@ -1255,14 +1255,14 @@ ADD_CASE_TO_GROUP("plain scalar trailing column 1, flow, seqimap", ); -ADD_CASE_TO_GROUP("plain scalar trailing column 2, flow, seq", +ADD_CASE_TO_GROUP("plain scalar trailing column 2, flow, seq", NO_COMPARE_EMITTED_INTS_JSON,//FIXME "[plain: ]", N(SFS, L{ N(MFS, L{N(KP|VP|VALNIL, "plain", "")}), }) ); -ADD_CASE_TO_GROUP("plain scalar trailing column 2, flow, seqimap", +ADD_CASE_TO_GROUP("plain scalar trailing column 2, flow, seqimap", NO_COMPARE_EMITTED_INTS_JSON,//FIXME "[{plain: }]", N(SFS, L{ N(MFS, L{N(KP|VP|VALNIL, "plain", "")}), @@ -1270,14 +1270,14 @@ ADD_CASE_TO_GROUP("plain scalar trailing column 2, flow, seqimap", ); -ADD_CASE_TO_GROUP("plain scalar trailing column 3, flow, seq", +ADD_CASE_TO_GROUP("plain scalar trailing column 3, flow, seq", NO_COMPARE_EMITTED_INTS_JSON,//FIXME "[plain:\r\n]", N(SFM, L{ N(MFM, L{N(KP|VP|VALNIL, "plain", "")}), }) ); -ADD_CASE_TO_GROUP("plain scalar trailing column 3, flow, seqimap", +ADD_CASE_TO_GROUP("plain scalar trailing column 3, flow, seqimap", NO_COMPARE_EMITTED_INTS_JSON,//FIXME "[{plain:\r\n}]", N(SFM, L{ N(MFM, L{N(KP|VP|VALNIL, "plain", "")}), @@ -1285,14 +1285,14 @@ ADD_CASE_TO_GROUP("plain scalar trailing column 3, flow, seqimap", ); -ADD_CASE_TO_GROUP("plain scalar trailing column 4, flow, seq", +ADD_CASE_TO_GROUP("plain scalar trailing column 4, flow, seq", NO_COMPARE_EMITTED_INTS_JSON,//FIXME "[plain:\n]", N(SFM, L{ N(MFM, L{N(KP|VP|VALNIL, "plain", "")}), }) ); -ADD_CASE_TO_GROUP("plain scalar trailing column 4, flow, seqimap", +ADD_CASE_TO_GROUP("plain scalar trailing column 4, flow, seqimap", NO_COMPARE_EMITTED_INTS_JSON,//FIXME "[{plain:\n}]", N(SFM, L{ N(MFM, L{N(KP|VP|VALNIL, "plain", "")}), diff --git a/test/test_scalar_squoted.cpp b/test/test_scalar_squoted.cpp index 1317f36d2..17c293c27 100644 --- a/test/test_scalar_squoted.cpp +++ b/test/test_scalar_squoted.cpp @@ -453,7 +453,7 @@ Newlines can be added by leaving a blank line. N(VS, "Several lines of text, containing 'single quotes' and \"double quotes\". Escapes (like \\n) don't do anything.\nNewlines can be added by leaving a blank line. Leading whitespace on lines is ignored.") ); -ADD_CASE_TO_GROUP("squoted, empty", +ADD_CASE_TO_GROUP("squoted, empty", NO_COMPARE_EMITTED_INTS,//FIXME R"('')", N(VS, "") ); diff --git a/test/test_seq.cpp b/test/test_seq.cpp index e947a05c1..b47881fd2 100644 --- a/test/test_seq.cpp +++ b/test/test_seq.cpp @@ -343,7 +343,7 @@ R"( N(SB, L{N{VP, "0"}, N{VP, "1"}, N{VP, "2"}, N{VP, "3"}}) ); -ADD_CASE_TO_GROUP("simple seq, empty elements", +ADD_CASE_TO_GROUP("simple seq, empty elements", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"(- - - @@ -354,7 +354,7 @@ R"(- N(SB, L{VN, VN, VN, VN, VN, VN}) ); -ADD_CASE_TO_GROUP("simple seq, empty elements with non-empty first", +ADD_CASE_TO_GROUP("simple seq, empty elements with non-empty first", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"( - non-empty - @@ -564,7 +564,7 @@ N(SFM, L{ }) ); -ADD_CASE_TO_GROUP("simple seq flow, scalars with special chars, colon", +ADD_CASE_TO_GROUP("simple seq flow, scalars with special chars, colon", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"([ :a, :0, @@ -644,7 +644,7 @@ N(SFM, L{ }) ); -ADD_CASE_TO_GROUP("simple seq blck, scalars with special chars, colon", +ADD_CASE_TO_GROUP("simple seq blck, scalars with special chars, colon", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"(- :a - :0 - :: diff --git a/test/test_seq_of_map.cpp b/test/test_seq_of_map.cpp index 1b8b913d9..3dfd3f0dc 100644 --- a/test/test_seq_of_map.cpp +++ b/test/test_seq_of_map.cpp @@ -270,7 +270,7 @@ N(MB, L{ ); -ADD_CASE_TO_GROUP("seq of maps, implicit map in seq, missing scalar", +ADD_CASE_TO_GROUP("seq of maps, implicit map in seq, missing scalar", NO_COMPARE_EMITTED_INTS_JSON, R"({a : [ : foo ], @@ -307,7 +307,7 @@ N(SB, L{ ); -ADD_CASE_TO_GROUP("seq of maps, implicit with anchors, resolved", RESOLVE_REFS, +ADD_CASE_TO_GROUP("seq of maps, implicit with anchors, resolved", RESOLVE_REFS|NO_COMPARE_EMITTED_INTS, R"( - &a1 a1: v1 &a2 a2: v2 diff --git a/test/test_style.cpp b/test/test_style.cpp index 6e3bab57f..233cd0b83 100644 --- a/test/test_style.cpp +++ b/test/test_style.cpp @@ -5,25 +5,95 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include #endif +#include "./test_lib/tree_and_ints.hpp" #include "./test_lib/test_case.hpp" +#include "./test_lib/test_events_ints_helpers.hpp" #include RYML_DEFINE_TEST_MAIN() +// NOLINTBEGIN(hicpp-signed-bitwise,*avoid-c-style-cast) + namespace c4 { namespace yml { +namespace xievt = extra::ievt; + +using xievt::evt_size; +using xievt::evt_bits; +constexpr const xievt::evt_bits all_styles_container = xievt::BLCK|xievt::FLOW|xievt::FSL_|xievt::FML1|xievt::FMLN|xievt::FSPC; // NOLINT +constexpr const xievt::evt_bits all_styles_scalar = xievt::PLAI|xievt::SQUO|xievt::DQUO|xievt::LITL|xievt::FOLD; // NOLINT +constexpr const xievt::evt_bits all_styles_ievt = all_styles_container|all_styles_scalar; +constexpr const xievt::evt_bits all_styles_ievtkv = all_styles_ievt|xievt::SCLR|xievt::KEY_|xievt::VAL_; + +EmitOptions maxcols(id_type max) +{ + return EmitOptions{}.max_cols(max); +} +size_t emit2buf(substr s, IntBufs const& buf, EmitOptions const& opts={}) +{ + xievt::EmitterInts e(opts, s); + e.emit_as(EMIT_YAML, buf.evts.ptr, buf.evts.len, buf.src, buf.arena); + return e.m_pos; +} +std::string emit2str(IntBufs const& buf, EmitOptions const& opts={}) +{ + std::string s; + s.resize((3 * buf.src.len) / 2); +again: + size_t len = emit2buf(to_substr(s), buf, opts); + bool ok = len <= s.size(); + s.resize(len); + if(!ok) + goto again; // NOLINT + return s; +} std::string emit2str(Tree const& t, EmitOptions const& opts={}) { return emitrs_yaml(t, opts); } -EmitOptions maxcols(id_type max) + + +//----------------------------------------------------------------------------- + + +void set_style(TreeAndInts *ti, + NodeRef which_node, NodeType node_style, + evt_size which_evt, evt_bits evt_style) { - return EmitOptions{}.max_cols(max); + ASSERT_LT(which_evt, ti->ints.evts.len); + which_node.set_container_style(node_style); + (ti->ints.evts.ptr[which_evt] &= ~all_styles_container) |= evt_style; } +void add_style(TreeAndInts *ti, + NodeRef which_node, NodeType node_style, + evt_size which_evt, evt_bits evt_style) +{ + ASSERT_LT(which_evt, ti->ints.evts.len); + which_node.tree()->_add_flags(which_node.id(), node_style); + ti->ints.evts.ptr[which_evt] |= evt_style; +} +void rem_style(TreeAndInts *ti, + NodeRef which_node, NodeType node_style, + evt_size which_evt, evt_bits evt_style) +{ + ASSERT_LT(which_evt, ti->ints.evts.len); + which_node.tree()->_rem_flags(which_node.id(), node_style); + ti->ints.evts.ptr[which_evt] &= ~evt_style; +} + + +//----------------------------------------------------------------------------- inline void test_container_nostyle(ConstNodeRef n) { @@ -46,6 +116,10 @@ inline void test_container_block(ConstNodeRef n) EXPECT_FALSE(n.type().is_flow_mln()); EXPECT_FALSE(n.type().is_flow_mlx()); } +inline void test_container_block(IntBufsCR buf, evt_size pos) +{ + EXPECT_EQ(buf.evts.ptr[pos] & (all_styles_ievt|xievt::BEG_), xievt::BLCK|xievt::BEG_); +} inline void test_container_flow_sl(ConstNodeRef n) { @@ -57,6 +131,10 @@ inline void test_container_flow_sl(ConstNodeRef n) EXPECT_FALSE(n.type().is_flow_mln()); EXPECT_FALSE(n.type().is_flow_mlx()); } +inline void test_container_flow_sl(IntBufsCR buf, evt_size pos) +{ + EXPECT_EQ(buf.evts.ptr[pos] & (all_styles_ievt|xievt::BEG_), xievt::FLOW|xievt::FSL_); +} inline void test_container_flow_ml(ConstNodeRef n) { @@ -68,6 +146,24 @@ inline void test_container_flow_ml(ConstNodeRef n) n.type().is_flow_mln()); EXPECT_TRUE(n.type().is_flow_mlx()); } +inline void test_container_flow_ml(IntBufsCR buf, evt_size pos) +{ + const evt_bits bits = buf.evts.ptr[pos] & (all_styles_ievt|xievt::BEG_); + EXPECT_TRUE((bits == (xievt::FLOW|xievt::FML1)) + || + (bits == (xievt::FLOW|xievt::FMLN))); +} + +#define test_int_bits(buf, pos, mask, expected) \ + do { \ + RYML_TRACE_FMT("pos={} len={}", pos, buf.evts.len); \ + ASSERT_LE(pos, buf.evts.len); \ + if((buf.evts.ptr[pos] & (mask)) != (expected)) \ + { \ + EXPECT_EQ(buf.evts.ptr[pos] & (mask), expected); \ + buf.print(); \ + } \ + } while(0) inline void test_key_plain(ConstNodeRef n) { @@ -78,6 +174,10 @@ inline void test_key_plain(ConstNodeRef n) EXPECT_FALSE(n.type().is_key_literal()); EXPECT_FALSE(n.type().is_key_folded()); } +inline void test_key_plain(IntBufsCR buf, evt_size pos) +{ + test_int_bits(buf, pos, all_styles_ievtkv, xievt::KEY_|xievt::SCLR|xievt::PLAI); +} inline void test_val_plain(ConstNodeRef n) { EXPECT_TRUE(n.type().is_val_styled()); @@ -87,6 +187,10 @@ inline void test_val_plain(ConstNodeRef n) EXPECT_FALSE(n.type().is_val_literal()); EXPECT_FALSE(n.type().is_val_folded()); } +inline void test_val_plain(IntBufsCR buf, evt_size pos) +{ + test_int_bits(buf, pos, all_styles_ievtkv, xievt::VAL_|xievt::SCLR|xievt::PLAI); +} inline void test_key_squo(ConstNodeRef n) { @@ -97,6 +201,10 @@ inline void test_key_squo(ConstNodeRef n) EXPECT_FALSE(n.type().is_key_literal()); EXPECT_FALSE(n.type().is_key_folded()); } +inline void test_key_squo(IntBufsCR buf, evt_size pos) +{ + test_int_bits(buf, pos, all_styles_ievtkv, xievt::KEY_|xievt::SCLR|xievt::SQUO); +} inline void test_val_squo(ConstNodeRef n) { EXPECT_TRUE(n.type().is_val_styled()); @@ -106,6 +214,10 @@ inline void test_val_squo(ConstNodeRef n) EXPECT_FALSE(n.type().is_val_literal()); EXPECT_FALSE(n.type().is_val_folded()); } +inline void test_val_squo(IntBufsCR buf, evt_size pos) +{ + test_int_bits(buf, pos, all_styles_ievtkv, xievt::VAL_|xievt::SCLR|xievt::SQUO); +} inline void test_key_dquo(ConstNodeRef n) { @@ -116,6 +228,10 @@ inline void test_key_dquo(ConstNodeRef n) EXPECT_FALSE(n.type().is_key_literal()); EXPECT_FALSE(n.type().is_key_folded()); } +inline void test_key_dquo(IntBufsCR buf, evt_size pos) +{ + test_int_bits(buf, pos, all_styles_ievtkv, xievt::KEY_|xievt::SCLR|xievt::DQUO); +} inline void test_val_dquo(ConstNodeRef n) { EXPECT_TRUE(n.type().is_val_styled()); @@ -125,6 +241,10 @@ inline void test_val_dquo(ConstNodeRef n) EXPECT_FALSE(n.type().is_val_literal()); EXPECT_FALSE(n.type().is_val_folded()); } +inline void test_val_dquo(IntBufsCR buf, evt_size pos) +{ + test_int_bits(buf, pos, all_styles_ievtkv, xievt::VAL_|xievt::SCLR|xievt::DQUO); +} inline void test_key_literal(ConstNodeRef n) { @@ -135,6 +255,10 @@ inline void test_key_literal(ConstNodeRef n) EXPECT_TRUE(n.type().is_key_literal()); EXPECT_FALSE(n.type().is_key_folded()); } +inline void test_key_literal(IntBufsCR buf, evt_size pos) +{ + test_int_bits(buf, pos, all_styles_ievtkv, xievt::KEY_|xievt::SCLR|xievt::LITL); +} inline void test_val_literal(ConstNodeRef n) { EXPECT_TRUE(n.type().is_val_styled()); @@ -144,6 +268,11 @@ inline void test_val_literal(ConstNodeRef n) EXPECT_TRUE(n.type().is_val_literal()); EXPECT_FALSE(n.type().is_val_folded()); } +inline void test_val_literal(IntBufsCR buf, evt_size pos) +{ + test_int_bits(buf, pos, all_styles_ievtkv, xievt::VAL_|xievt::SCLR|xievt::LITL); +} + inline void test_key_folded(ConstNodeRef n) { @@ -154,6 +283,10 @@ inline void test_key_folded(ConstNodeRef n) EXPECT_FALSE(n.type().is_key_literal()); EXPECT_TRUE(n.type().is_key_folded()); } +inline void test_key_folded(IntBufsCR buf, evt_size pos) +{ + test_int_bits(buf, pos, all_styles_ievtkv, xievt::KEY_|xievt::SCLR|xievt::FOLD); +} inline void test_val_folded(ConstNodeRef n) { EXPECT_TRUE(n.type().is_val_styled()); @@ -163,6 +296,10 @@ inline void test_val_folded(ConstNodeRef n) EXPECT_FALSE(n.type().is_val_literal()); EXPECT_TRUE(n.type().is_val_folded()); } +inline void test_val_folded(IntBufsCR buf, evt_size pos) +{ + test_int_bits(buf, pos, all_styles_ievtkv, xievt::VAL_|xievt::SCLR|xievt::FOLD); +} inline void test_key_nostyle(ConstNodeRef n) { @@ -268,52 +405,161 @@ this is the key: >- 'empty' lines )"; -void check_same_emit(Tree const& expected) -{ - #ifndef RYML_DBG - #define _showtrees(num) - #else - #define _showtrees(num) \ - { \ - std::cout << "--------\nEMITTED" #num "\n--------\n"; \ - std::cout << ws ## num; \ - std::cout << "--------\nACTUAL" #num "\n--------\n"; \ - print_tree(actual ## num); \ - std::cout << "--------\nEXPECTED" #num "\n--------\n"; \ - print_tree(expected); \ - } - #endif - +void check_same_emit4(Tree const& expected, std::string const* expected_yaml=nullptr) +{ std::string ws1, ws2, ws3, ws4; + Tree actual1, actual2, actual3, actual4; + bool did2 = false, did3 = false, did4 = false; emitrs_yaml(expected, &ws1); + if(expected_yaml) { EXPECT_EQ(*expected_yaml, ws1); } { SCOPED_TRACE("actual1"); - Tree actual1 = parse_in_arena(to_csubstr(ws1)); - _showtrees(1); + parse_in_arena(to_csubstr(ws1), &actual1); test_compare(actual1, expected); emitrs_yaml(actual1, &ws2); + if(expected_yaml) { EXPECT_EQ(*expected_yaml, ws2); } } + if(!testing::Test::HasFailure()) { SCOPED_TRACE("actual2"); - Tree actual2 = parse_in_arena(to_csubstr(ws2)); - _showtrees(2); + parse_in_arena(to_csubstr(ws2), &actual2); test_compare(actual2, expected); emitrs_yaml(actual2, &ws3); + if(expected_yaml) { EXPECT_EQ(*expected_yaml, ws3); } + did2 = true; } + if(!testing::Test::HasFailure()) { SCOPED_TRACE("actual3"); - Tree actual3 = parse_in_arena(to_csubstr(ws3)); - _showtrees(3); + parse_in_arena(to_csubstr(ws3), &actual3); test_compare(actual3, expected); emitrs_yaml(actual3, &ws4); + if(expected_yaml) { EXPECT_EQ(*expected_yaml, ws4); } + did3 = true; } + if(!testing::Test::HasFailure()) { SCOPED_TRACE("actual4"); - Tree actual4 = parse_in_arena(to_csubstr(ws4)); - _showtrees(4); + parse_in_arena(to_csubstr(ws4), &actual4); test_compare(actual4, expected); + did4 = true; + } + if(testing::Test::HasFailure()) + { + auto showtrees_ = [&expected](size_t num, std::string const& ws, Tree const& actual) + { + std::cout << "--------\nEMITTED" << num << "\n--------\n"; + std::cout << ws; + std::cout << "--------\nACTUAL" << num << "\n--------\n"; + print_tree(actual); + std::cout << "--------\nEXPECTED" << num << "\n--------\n"; + print_tree(expected); + }; + showtrees_(1, ws1, actual1); + if(did2) showtrees_(2, ws2, actual2); + if(did3) showtrees_(3, ws3, actual3); + if(did4) showtrees_(4, ws4, actual4); } } +void check_same_emit4(IntBufsCR& expected, std::string const* expected_yaml=nullptr) +{ + std::string ws1, ws2, ws3, ws4; + IntBufs actual1, actual2, actual3, actual4; + bool did2 = false, did3 = false, did4 = false; + ws1 = emit2str(expected); + if(expected_yaml) { EXPECT_EQ(*expected_yaml, ws1); } + { + SCOPED_TRACE("actual1"); + parse_ints(to_substr(ws1), &actual1); + xievt::test_events_ints_compare(expected, actual1); + ws2 = emit2str(actual1); + if(expected_yaml) { EXPECT_EQ(*expected_yaml, ws2); } + } + if(!testing::Test::HasFailure()) + { + SCOPED_TRACE("actual2"); + parse_ints(to_substr(ws2), &actual2); + xievt::test_events_ints_compare(expected, actual2); + ws3 = emit2str(actual2); + if(expected_yaml) { EXPECT_EQ(*expected_yaml, ws3); } + did2 = true; + } + if(!testing::Test::HasFailure()) + { + SCOPED_TRACE("actual3"); + parse_ints(to_substr(ws3), &actual3); + xievt::test_events_ints_compare(expected, actual3); + ws4 = emit2str(actual3); + if(expected_yaml) { EXPECT_EQ(*expected_yaml, ws4); } + did3 = true; + } + if(!testing::Test::HasFailure()) + { + SCOPED_TRACE("actual4"); + parse_ints(to_substr(ws4), &actual4); + xievt::test_events_ints_compare(expected, actual4); + did4 = true; + } + if(testing::Test::HasFailure()) + { + auto showtrees_ = [&expected](size_t num, std::string const& ws, IntBufsCR actual) + { + std::cout << "--------\nEMITTED" << num << "\n--------\n"; + std::cout << ws; + std::cout << "--------\nACTUAL" << num << "\n--------\n"; + actual.print(); + std::cout << "--------\nEXPECTED" << num << "\n--------\n"; + expected.print(); + }; + showtrees_(1, ws1, actual1); + if(did2) showtrees_(2, ws2, actual2); + if(did3) showtrees_(3, ws3, actual3); + if(did4) showtrees_(4, ws4, actual4); + } +} +void check_same_emit4(TreeAndInts const& ti, std::string const* expected_yaml) +{ + check_same_emit4(ti.tree, expected_yaml); + check_same_emit4(ti.ints, expected_yaml); +} +void check_same_emit4(TreeAndInts const& ti, std::string const& expected_yaml={}) +{ + check_same_emit4(ti.tree, &expected_yaml); + check_same_emit4(ti.ints, &expected_yaml); +} + +void check_same_emit1(Tree const& tree, std::string const& expected, EmitOptions const& opts={}) +{ + SCOPED_TRACE("check_same_emit1"); + test_invariants(tree); + std::string actual; + emitrs_yaml(tree, opts, &actual); + EXPECT_EQ(expected, actual); + if(testing::Test::HasFailure()) + print_tree(tree); +} +void check_same_emit1(IntBufsCR& ints, std::string const& expected, EmitOptions const& opts={}) +{ + SCOPED_TRACE("check_same_emit1"); + std::string actual = emit2str(ints, opts); + xievt::test_events_ints_invariants(ints.src, ints.arena, ints.evts.ptr, ints.evts.len); + EXPECT_EQ(expected, actual); + if(testing::Test::HasFailure()) + ints.print(); +} +void check_same_emit1(TreeAndInts const& ti, std::string const& expected, EmitOptions const& opts={}) +{ + SCOPED_TRACE("check_same_emit1"); + check_same_emit1(ti.tree, expected, opts); + check_same_emit1(ti.ints, expected, opts); +} +void check_same_emit1(TreeAndInts const& ti, EmitOptions const& opts, std::string const& expected) +{ + SCOPED_TRACE("check_same_emit1"); + check_same_emit1(ti.tree, expected, opts); + check_same_emit1(ti.ints, expected, opts); +} + //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- @@ -389,50 +635,72 @@ TEST(style, noflags) TEST(style, scalar_retains_style_after_parse__plain) { - const Tree t = parse_in_arena("foo"); - test_val_plain(t.rootref()); - EXPECT_EQ(emitrs_yaml(t), std::string("foo\n")); + csubstr yaml = "foo"; + RYML_TRACE_FMT("yaml={}", yaml); + TreeAndInts ti = parse_tree_and_ints(yaml); + test_val_plain(ti.tree.rootref()); + test_val_plain(ti.ints, 2); + test_emit_yaml(ti, "foo\n"); } TEST(style, scalar_retains_style_after_parse__squo) { - const Tree t = parse_in_arena("'foo'"); - test_val_squo(t.rootref()); - EXPECT_EQ(emitrs_yaml(t), std::string("'foo'\n")); + csubstr yaml = "'foo'"; + RYML_TRACE_FMT("yaml={}", yaml); + TreeAndInts ti = parse_tree_and_ints(yaml); + test_val_squo(ti.tree.rootref()); + test_val_squo(ti.ints, 2); + test_emit_yaml(ti, "'foo'\n"); } TEST(style, scalar_retains_style_after_parse__dquo) { - const Tree t = parse_in_arena("\"foo\""); - test_val_dquo(t.rootref()); - EXPECT_EQ(emitrs_yaml(t), std::string("\"foo\"\n")); + csubstr yaml = "\"foo\""; + RYML_TRACE_FMT("yaml={}", yaml); + TreeAndInts ti = parse_tree_and_ints(yaml); + test_val_dquo(ti.tree.rootref()); + test_val_dquo(ti.ints, 2); + test_emit_yaml(ti, "\"foo\"\n"); } TEST(style, scalar_retains_style_after_parse__literal) { - const Tree t = parse_in_arena("|\n foo"); - test_val_literal(t.rootref()); - EXPECT_EQ(emitrs_yaml(t), std::string("|\n foo\n")); + csubstr yaml = "|\n foo"; + RYML_TRACE_FMT("yaml={}", yaml); + TreeAndInts ti = parse_tree_and_ints(yaml); + test_val_literal(ti.tree.rootref()); + test_val_literal(ti.ints, 2); + test_emit_yaml(ti, "|\n foo\n"); } TEST(style, scalar_retains_style_after_parse__folded) { - const Tree t = parse_in_arena(">\n foo"); - test_val_folded(t.rootref()); - EXPECT_EQ(emitrs_yaml(t), std::string(">\n foo\n")); + csubstr yaml = ">\n foo"; + RYML_TRACE_FMT("yaml={}", yaml); + TreeAndInts ti = parse_tree_and_ints(yaml); + test_val_folded(ti.tree.rootref()); + test_val_folded(ti.ints, 2); + test_emit_yaml(ti, ">\n foo\n"); } TEST(style, scalar_retains_style_after_parse__mixed) { std::string yaml = "- foo\n- 'baz'\n- \"bat\"\n- |\n baq\n- >\n bax\n"; - const Tree t = parse_in_arena(to_csubstr(yaml)); - test_container_block(t.rootref()); - test_val_plain(t[0]); - test_val_squo(t[1]); - test_val_dquo(t[2]); - test_val_literal(t[3]); - test_val_folded(t[4]); - EXPECT_EQ(emitrs_yaml(t), yaml); + RYML_TRACE_FMT("yaml=~~~\n{}~~~", yaml); + TreeAndInts ti = parse_tree_and_ints(to_csubstr(yaml)); + test_container_block(ti.tree.rootref()); + test_container_block(ti.ints, 2); + test_val_plain(ti.tree[0]); + test_val_plain(ti.ints, 3); + test_val_squo(ti.tree[1]); + test_val_squo(ti.ints, 6); + test_val_dquo(ti.tree[2]); + test_val_dquo(ti.ints, 9); + test_val_literal(ti.tree[3]); + test_val_literal(ti.ints, 12); + test_val_folded(ti.tree[4]); + test_val_folded(ti.ints, 15); + test_emit_yaml(ti, yaml); } @@ -442,17 +710,20 @@ TEST(style, scalar_retains_style_after_parse__mixed) TEST(scalar, base) { - const Tree tree = parse_in_arena(scalar_yaml); - test_key_plain(tree[0]); - test_val_folded(tree[0]); - EXPECT_EQ(tree[0].key(), csubstr("this is the key")); - EXPECT_EQ(tree[0].val(), csubstr("this is the multiline \"val\" with\n'empty' lines")); - EXPECT_EQ(emit2str(tree), R"(this is the key: >- + TreeAndInts ti = parse_tree_and_ints(scalar_yaml); + test_key_plain(ti.tree[0]); + test_key_plain(ti.ints, 3); + test_val_folded(ti.tree[0]); + test_val_folded(ti.ints, 6); + EXPECT_EQ(ti.tree[0].key(), csubstr("this is the key")); + EXPECT_EQ(ti.ints.getstr(3), csubstr("this is the key")); + EXPECT_EQ(ti.tree[0].val(), csubstr("this is the multiline \"val\" with\n'empty' lines")); + EXPECT_EQ(ti.ints.getstr(6), csubstr("this is the multiline \"val\" with\n'empty' lines")); + check_same_emit4(ti, R"(this is the key: >- this is the multiline "val" with 'empty' lines )"); - check_same_emit(tree); } @@ -460,53 +731,67 @@ TEST(scalar, base) TEST(scalar, block_literal__key) { - Tree tree = parse_in_arena(scalar_yaml); - test_key_plain(tree[0]); - test_val_folded(tree[0]); - tree[0].set_key_style(KEY_LITERAL); - test_key_literal(tree[0]); - test_val_folded(tree[0]); - EXPECT_EQ(emit2str(tree), R"(? |- + TreeAndInts ti = parse_tree_and_ints(scalar_yaml); + test_key_plain(ti.tree[0]); + test_key_plain(ti.ints, 3); + test_val_folded(ti.tree[0]); + test_val_folded(ti.ints, 6); + ti.tree[0].set_key_style(KEY_LITERAL); + (ti.ints.evts.ptr[3] &= ~all_styles_scalar) |= xievt::LITL; + test_key_literal(ti.tree[0]); + test_key_literal(ti.ints, 3); + test_val_folded(ti.tree[0]); + test_val_folded(ti.ints, 6); + check_same_emit4(ti, R"(? |- this is the key : >- this is the multiline "val" with 'empty' lines )"); - check_same_emit(tree); } TEST(scalar, block_literal__val) { - Tree tree = parse_in_arena(scalar_yaml); - test_key_plain(tree[0]); - test_val_folded(tree[0]); - tree[0].set_val_style(VAL_LITERAL); - test_key_plain(tree[0]); - test_val_literal(tree[0]); - EXPECT_EQ(emit2str(tree), R"(this is the key: |- + TreeAndInts ti = parse_tree_and_ints(scalar_yaml); + test_key_plain(ti.tree[0]); + test_key_plain(ti.ints, 3); + test_val_folded(ti.tree[0]); + test_val_folded(ti.ints, 6); + ti.tree[0].set_val_style(VAL_LITERAL); + (ti.ints.evts.ptr[6] &= ~all_styles_scalar) |= xievt::LITL; + test_key_plain(ti.tree[0]); + test_key_plain(ti.ints, 3); + test_val_literal(ti.tree[0]); + test_val_literal(ti.ints, 6); + check_same_emit4(ti, R"(this is the key: |- this is the multiline "val" with 'empty' lines )"); - check_same_emit(tree); } TEST(scalar, block_literal__key_val) { - Tree tree = parse_in_arena(scalar_yaml); - test_key_plain(tree[0]); - test_val_folded(tree[0]); - tree[0].set_key_style(KEY_LITERAL); - tree[0].set_val_style(VAL_LITERAL); - test_key_literal(tree[0]); - test_val_literal(tree[0]); - EXPECT_EQ(emit2str(tree), R"(? |- + TreeAndInts ti = parse_tree_and_ints(scalar_yaml); + test_key_plain(ti.tree[0]); + test_key_plain(ti.ints, 3); + test_val_folded(ti.tree[0]); + test_val_folded(ti.ints, 6); + ti.tree[0].set_key_style(KEY_LITERAL); + ti.tree[0].set_val_style(VAL_LITERAL); + (ti.ints.evts.ptr[3] &= ~all_styles_scalar) |= xievt::LITL; + (ti.ints.evts.ptr[6] &= ~all_styles_scalar) |= xievt::LITL; + test_key_literal(ti.tree[0]); + test_key_literal(ti.ints, 3); + test_key_literal(ti.ints, 3); + test_val_literal(ti.tree[0]); + test_val_literal(ti.ints, 6); + check_same_emit4(ti, R"(? |- this is the key : |- this is the multiline "val" with 'empty' lines )"); - check_same_emit(tree); } @@ -514,55 +799,71 @@ TEST(scalar, block_literal__key_val) TEST(scalar, block_folded__key) { - Tree tree = parse_in_arena(scalar_yaml); - test_key_plain(tree[0]); - test_val_folded(tree[0]); - tree[0].set_key_style(KEY_FOLDED); - test_key_folded(tree[0]); - test_val_folded(tree[0]); - EXPECT_EQ(emit2str(tree), R"(? >- + TreeAndInts ti = parse_tree_and_ints(scalar_yaml); + test_key_plain(ti.tree[0]); + test_key_plain(ti.ints, 3); + test_val_folded(ti.tree[0]); + test_val_folded(ti.ints, 6); + ti.tree[0].set_key_style(KEY_FOLDED); + (ti.ints.evts.ptr[3] &= ~all_styles_scalar) |= xievt::FOLD; + test_key_folded(ti.tree[0]); + test_key_folded(ti.ints, 3); + test_val_folded(ti.tree[0]); + test_val_folded(ti.ints, 6); + const std::string expected_yaml = R"(? >- this is the key : >- this is the multiline "val" with 'empty' lines -)"); - check_same_emit(tree); +)"; + check_same_emit4(ti, &expected_yaml); } TEST(scalar, block_folded__val) { - Tree tree = parse_in_arena(scalar_yaml); - test_key_plain(tree[0]); - test_val_folded(tree[0]); - tree[0].set_val_style(VAL_FOLDED); - test_key_plain(tree[0]); - test_val_folded(tree[0]); - EXPECT_EQ(emit2str(tree), R"(this is the key: >- + TreeAndInts ti = parse_tree_and_ints(scalar_yaml); + test_key_plain(ti.tree[0]); + test_key_plain(ti.ints, 3); + test_val_folded(ti.tree[0]); + test_val_folded(ti.ints, 6); + ti.tree[0].set_val_style(VAL_FOLDED); + (ti.ints.evts.ptr[6] &= ~all_styles_scalar) |= xievt::FOLD; + test_key_plain(ti.tree[0]); + test_key_plain(ti.ints, 3); + test_val_folded(ti.tree[0]); + test_val_folded(ti.ints, 6); + const std::string expected_yaml = R"(this is the key: >- this is the multiline "val" with 'empty' lines -)"); - check_same_emit(tree); +)"; + check_same_emit4(ti, &expected_yaml); } TEST(scalar, block_folded__key_val) { - Tree tree = parse_in_arena(scalar_yaml); - test_key_plain(tree[0]); - test_val_folded(tree[0]); - tree[0].set_key_style(KEY_FOLDED); - tree[0].set_val_style(VAL_FOLDED); - test_key_folded(tree[0]); - test_val_folded(tree[0]); - EXPECT_EQ(emit2str(tree), R"(? >- + TreeAndInts ti = parse_tree_and_ints(scalar_yaml); + test_key_plain(ti.tree[0]); + test_key_plain(ti.ints, 3); + test_val_folded(ti.tree[0]); + test_val_folded(ti.ints, 6); + ti.tree[0].set_key_style(KEY_FOLDED); + ti.tree[0].set_val_style(VAL_FOLDED); + (ti.ints.evts.ptr[3] &= ~all_styles_scalar) |= xievt::FOLD; + (ti.ints.evts.ptr[6] &= ~all_styles_scalar) |= xievt::FOLD; + test_key_folded(ti.tree[0]); + test_key_folded(ti.ints, 3); + test_val_folded(ti.tree[0]); + test_val_folded(ti.ints, 6); + const std::string expected_yaml = R"(? >- this is the key : >- this is the multiline "val" with 'empty' lines -)"); - check_same_emit(tree); +)"; + check_same_emit4(ti, &expected_yaml); } @@ -570,49 +871,65 @@ TEST(scalar, block_folded__key_val) TEST(scalar, squo__key) { - Tree tree = parse_in_arena(scalar_yaml); - test_key_plain(tree[0]); - test_val_folded(tree[0]); - tree[0].set_key_style(KEY_SQUO); - test_key_squo(tree[0]); - test_val_folded(tree[0]); - EXPECT_EQ(emit2str(tree), R"('this is the key': >- + TreeAndInts ti = parse_tree_and_ints(scalar_yaml); + test_key_plain(ti.tree[0]); + test_key_plain(ti.ints, 3); + test_val_folded(ti.tree[0]); + test_val_folded(ti.ints, 6); + ti.tree[0].set_key_style(KEY_SQUO); + (ti.ints.evts.ptr[3] &= ~all_styles_scalar) |= xievt::SQUO; + test_key_squo(ti.tree[0]); + test_key_squo(ti.ints, 3); + test_val_folded(ti.tree[0]); + test_val_folded(ti.ints, 6); + const std::string expected_yaml = R"('this is the key': >- this is the multiline "val" with 'empty' lines -)"); - check_same_emit(tree); +)"; + check_same_emit4(ti, &expected_yaml); } TEST(scalar, squo__val) { - Tree tree = parse_in_arena(scalar_yaml); - test_key_plain(tree[0]); - test_val_folded(tree[0]); - tree[0].set_val_style(VAL_SQUO); - test_key_plain(tree[0]); - test_val_squo(tree[0]); - EXPECT_EQ(emit2str(tree), R"(this is the key: 'this is the multiline "val" with + TreeAndInts ti = parse_tree_and_ints(scalar_yaml); + test_key_plain(ti.tree[0]); + test_key_plain(ti.ints, 3); + test_val_folded(ti.tree[0]); + test_val_folded(ti.ints, 6); + ti.tree[0].set_val_style(VAL_SQUO); + (ti.ints.evts.ptr[6] &= ~all_styles_scalar) |= xievt::SQUO; + test_key_plain(ti.tree[0]); + test_key_plain(ti.ints, 3); + test_val_squo(ti.tree[0]); + test_val_squo(ti.ints, 6); + const std::string expected_yaml = R"(this is the key: 'this is the multiline "val" with ''empty'' lines' -)"); - check_same_emit(tree); +)"; + check_same_emit4(ti, &expected_yaml); } TEST(scalar, squo__key_val) { - Tree tree = parse_in_arena(scalar_yaml); - test_key_plain(tree[0]); - test_val_folded(tree[0]); - tree[0].set_key_style(KEY_SQUO); - tree[0].set_val_style(VAL_SQUO); - test_key_squo(tree[0]); - test_val_squo(tree[0]); - EXPECT_EQ(emit2str(tree), R"('this is the key': 'this is the multiline "val" with + TreeAndInts ti = parse_tree_and_ints(scalar_yaml); + test_key_plain(ti.tree[0]); + test_key_plain(ti.ints, 3); + test_val_folded(ti.tree[0]); + test_val_folded(ti.ints, 6); + ti.tree[0].set_key_style(KEY_SQUO); + ti.tree[0].set_val_style(VAL_SQUO); + (ti.ints.evts.ptr[3] &= ~all_styles_scalar) |= xievt::SQUO; + (ti.ints.evts.ptr[6] &= ~all_styles_scalar) |= xievt::SQUO; + test_key_squo(ti.tree[0]); + test_key_squo(ti.ints, 3); + test_val_squo(ti.tree[0]); + test_val_squo(ti.ints, 6); + const std::string expected_yaml = R"('this is the key': 'this is the multiline "val" with ''empty'' lines' -)"); - check_same_emit(tree); +)"; + check_same_emit4(ti, &expected_yaml); } @@ -622,7 +939,7 @@ TEST(scalar, squo__key_val) TEST(stream, block) { - Tree tree = parse_in_arena(R"( + TreeAndInts ti = parse_tree_and_ints(R"( --- scalar %YAML 1.2 @@ -631,13 +948,14 @@ foo --- bar )"); - EXPECT_TRUE(tree.rootref().is_stream()); - EXPECT_TRUE(tree.docref(0).is_doc()); - EXPECT_TRUE(tree.docref(0).is_val()); - EXPECT_EQ(emit2str(tree), "--- scalar %YAML 1.2\n--- foo\n--- bar\n"); - NodeRef r = tree; + EXPECT_TRUE(ti.tree.rootref().is_stream()); + EXPECT_TRUE(ti.tree.docref(0).is_doc()); + EXPECT_TRUE(ti.tree.docref(0).is_val()); + std::string expected = "--- scalar %YAML 1.2\n--- foo\n--- bar\n"; + check_same_emit4(ti, &expected); + NodeRef r = ti.tree; r.set_container_style(FLOW_SL); - EXPECT_EQ(emit2str(tree), "--- scalar %YAML 1.2\n--- foo\n--- bar\n"); + check_same_emit4(ti, &expected); } @@ -647,10 +965,12 @@ bar TEST(seq, block) { - Tree tree = parse_in_arena("[1, 2, 3, 4, 5, 6]"); - NodeRef r = tree; + TreeAndInts ti = parse_tree_and_ints("[1, 2, 3, 4, 5, 6]"); + check_same_emit4(ti, "[1,2,3,4,5,6]"); + NodeRef r = ti.tree; r.set_container_style(BLOCK); - EXPECT_EQ(emit2str(tree), R"(- 1 + (ti.ints.evts.ptr[2] &= ~all_styles_container) |= xievt::BLCK; + check_same_emit4(ti, R"(- 1 - 2 - 3 - 4 @@ -659,22 +979,66 @@ TEST(seq, block) )"); } +TEST(seq, block_picks_default_style) +{ + TreeAndInts ti = parse_tree_and_ints("['ab', [2,3]]"); + check_same_emit1(ti, "['ab',[2,3]]"); + set_style(&ti, ti.tree, BLOCK, 2, xievt::BLCK); + check_same_emit1(ti, R"(- 'ab' +- [2,3] +)"); + rem_style(&ti, ti.tree[0], SCALAR_STYLE, 3, all_styles_scalar); + rem_style(&ti, ti.tree[1], CONTAINER_STYLE, 6, all_styles_container); + check_same_emit1(ti, R"(- ab +- - 2 + - 3 +)"); +} + TEST(seq, flow_sl) { - Tree tree = parse_in_arena("[1, 2, 3, 4, 5, 6]"); - NodeRef r = tree; - r.set_container_style(FLOW_SL); - EXPECT_EQ(emit2str(tree), R"([1,2,3,4,5,6])"); - r.set_container_style(FLOW_SL|FLOW_SPC); - EXPECT_EQ(emit2str(tree), R"([1, 2, 3, 4, 5, 6])"); + TreeAndInts ti = parse_tree_and_ints("[1, 2, 3, 4, 5, 6]"); + NodeRef r = ti.tree; + { + SCOPED_TRACE("flow_sl"); + r.set_container_style(FLOW_SL); + (ti.ints.evts.ptr[2] &= ~all_styles_container) |= xievt::FLOW|xievt::FSL_; + check_same_emit1(ti, R"([1,2,3,4,5,6])"); + } + { + SCOPED_TRACE("flow_sl|flow_spc"); + r.set_container_style(FLOW_SL|FLOW_SPC); + (ti.ints.evts.ptr[2] &= ~all_styles_container) |= xievt::FLOW|xievt::FSL_|xievt::FSPC; + check_same_emit1(ti, R"([1, 2, 3, 4, 5, 6])"); + } } -static void test_seq_flow_ml1(NodeType extra={}) // NOLINT +TEST(seq, flow_sl_picks_default_style) { - Tree tree = parse_in_arena("[1, 2, 3, 4, 5, 6]"); - NodeRef r = tree; + TreeAndInts ti = parse_tree_and_ints("['ab', [2,3]]"); + check_same_emit1(ti, "['ab',[2,3]]"); + rem_style(&ti, ti.tree[0], SCALAR_STYLE, 3, all_styles_scalar); + rem_style(&ti, ti.tree[1], CONTAINER_STYLE, 6, all_styles_container); + check_same_emit1(ti, R"([ab,[2,3]])"); +} + +TEST(seq, flow_ml_picks_default_style) +{ + TreeAndInts ti = parse_tree_and_ints("[\n 'ab',\n [2,3]\n]\n"); + check_same_emit1(ti, "[\n 'ab',\n [2,3]\n]\n"); + rem_style(&ti, ti.tree[0], SCALAR_STYLE, 3, all_styles_scalar); + rem_style(&ti, ti.tree[1], CONTAINER_STYLE, 6, all_styles_container); + check_same_emit1(ti, "[\n ab,\n [2,3]\n]\n"); +} + + +static void test_seq_flow_ml1(NodeType extra={}, evt_bits extra_bits={}) // NOLINT +{ + TreeAndInts ti = parse_tree_and_ints("[1, 2, 3, 4, 5, 6]"); + NodeRef r = ti.tree; r.set_container_style(FLOW_ML1|extra); - EXPECT_EQ(emit2str(tree), + (ti.ints.evts.ptr[2] &= ~all_styles_container) |= xievt::FLOW|xievt::FML1|extra_bits; + check_same_emit1(ti, "[\n" " 1,\n" " 2,\n" @@ -683,7 +1047,7 @@ static void test_seq_flow_ml1(NodeType extra={}) // NOLINT " 5,\n" " 6\n" "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(0)), + check_same_emit1(ti, maxcols(0), "[\n" " 1,\n" " 2,\n" @@ -692,7 +1056,7 @@ static void test_seq_flow_ml1(NodeType extra={}) // NOLINT " 5,\n" " 6\n" "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(1)), + check_same_emit1(ti, maxcols(1), "[\n" " 1,\n" " 2,\n" @@ -701,7 +1065,7 @@ static void test_seq_flow_ml1(NodeType extra={}) // NOLINT " 5,\n" " 6\n" "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(10)), + check_same_emit1(ti, maxcols(10), "[\n" " 1,\n" " 2,\n" @@ -710,7 +1074,7 @@ static void test_seq_flow_ml1(NodeType extra={}) // NOLINT " 5,\n" " 6\n" "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(100)), + check_same_emit1(ti, maxcols(100), "[\n" " 1,\n" " 2,\n" @@ -731,14 +1095,15 @@ TEST(seq, flow_ml1_spc) TEST(seq, flow_mln) { - Tree tree = parse_in_arena("[1, 2, 3, 4, 5, 6]"); - NodeRef r = tree; + TreeAndInts ti = parse_tree_and_ints("[1, 2, 3, 4, 5, 6]"); + NodeRef r = ti.tree; r.set_container_style(FLOW_MLN); - EXPECT_EQ(emit2str(tree), + (ti.ints.evts.ptr[2] &= ~all_styles_container) |= xievt::FLOW|xievt::FMLN; + check_same_emit1(ti, "[\n" " 1,2,3,4,5,6\n" "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(3)), + check_same_emit1(ti, maxcols(3), "[\n" " 1,\n" " 2,\n" @@ -747,7 +1112,7 @@ TEST(seq, flow_mln) " 5,\n" " 6\n" "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(4)), + check_same_emit1(ti, maxcols(4), "[\n" " 1,\n" " 2,\n" @@ -756,49 +1121,49 @@ TEST(seq, flow_mln) " 5,\n" " 6\n" "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(5)), + check_same_emit1(ti, maxcols(5), "[\n" " 1,2,\n" " 3,4,\n" " 5,6\n" "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(6)), + check_same_emit1(ti, maxcols(6), "[\n" " 1,2,\n" " 3,4,\n" " 5,6\n" "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(7)), + check_same_emit1(ti, maxcols(7), "[\n" " 1,2,3,\n" " 4,5,6\n" "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(8)), + check_same_emit1(ti, maxcols(8), "[\n" " 1,2,3,\n" " 4,5,6\n" "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(9)), + check_same_emit1(ti, maxcols(9), "[\n" " 1,2,3,4,\n" " 5,6\n" "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(10)), + check_same_emit1(ti, maxcols(10), "[\n" " 1,2,3,4,\n" " 5,6\n" "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(11)), + check_same_emit1(ti, maxcols(11), "[\n" " 1,2,3,4,5,\n" " 6\n" "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(12)), + check_same_emit1(ti, maxcols(12), "[\n" " 1,2,3,4,5,\n" " 6\n" "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(13)), + check_same_emit1(ti, maxcols(13), "[\n" " 1,2,3,4,5,6\n" "]\n"); @@ -806,14 +1171,15 @@ TEST(seq, flow_mln) TEST(seq, flow_mln_spc) { - Tree tree = parse_in_arena("[1, 2, 3, 4, 5, 6]"); - NodeRef r = tree; + TreeAndInts ti = parse_tree_and_ints("[1, 2, 3, 4, 5, 6]"); + NodeRef r = ti.tree; r.set_container_style(FLOW_MLN|FLOW_SPC); - EXPECT_EQ(emit2str(tree), + (ti.ints.evts.ptr[2] &= ~all_styles_container) |= xievt::FLOW|xievt::FMLN|xievt::FSPC; + check_same_emit1(ti, "[\n" " 1, 2, 3, 4, 5, 6\n" "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(4)), + check_same_emit1(ti, maxcols(4), "[\n" " 1,\n" " 2,\n" @@ -822,34 +1188,34 @@ TEST(seq, flow_mln_spc) " 5,\n" " 6\n" "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(6)), + check_same_emit1(ti, maxcols(6), "[\n" " 1, 2,\n" " 3, 4,\n" " 5, 6\n" "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(8)), + check_same_emit1(ti, maxcols(8), "[\n" " 1, 2,\n" " 3, 4,\n" " 5, 6\n" "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(9)), + check_same_emit1(ti, maxcols(9), "[\n" " 1, 2, 3,\n" " 4, 5, 6\n" "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(12)), + check_same_emit1(ti, maxcols(12), "[\n" " 1, 2, 3, 4,\n" " 5, 6\n" "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(15)), + check_same_emit1(ti, maxcols(15), "[\n" " 1, 2, 3, 4, 5,\n" " 6\n" "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(18)), + check_same_emit1(ti, maxcols(18), "[\n" " 1, 2, 3, 4, 5, 6\n" "]\n"); @@ -857,173 +1223,184 @@ TEST(seq, flow_mln_spc) TEST(seq, flow_ml_nested_1_ml1) { - Tree tree = parse_in_arena("[[1, 2, 3, 4, 5, 6], 10, 20, 25, [100, 200, 300, 400], 30, 40, 50, [7, 8, 9, 10, 11, 12]]"); - NodeRef r = tree; - EXPECT_EQ(emit2str(tree), "[[1,2,3,4,5,6],10,20,25,[100,200,300,400],30,40,50,[7,8,9,10,11,12]]"); - r.set_container_style(FLOW_SL|FLOW_SPC); - EXPECT_EQ(emit2str(tree), "[[1,2,3,4,5,6], 10, 20, 25, [100,200,300,400], 30, 40, 50, [7,8,9,10,11,12]]"); - r.set_container_style(FLOW_SL); - r[0].set_container_style(FLOW_SL|FLOW_SPC); - r[4].set_container_style(FLOW_SL|FLOW_SPC); - r[8].set_container_style(FLOW_SL|FLOW_SPC); - EXPECT_EQ(emit2str(tree), "[[1, 2, 3, 4, 5, 6],10,20,25,[100, 200, 300, 400],30,40,50,[7, 8, 9, 10, 11, 12]]"); - r[0].set_container_style(FLOW_SL); - r[4].set_container_style(FLOW_SL); - r[8].set_container_style(FLOW_SL); - r.set_container_style(FLOW_ML1); - EXPECT_EQ(emit2str(tree), - "[\n" - " [1,2,3,4,5,6],\n" - " 10,\n" - " 20,\n" - " 25,\n" - " [100,200,300,400],\n" - " 30,\n" - " 40,\n" - " 50,\n" - " [7,8,9,10,11,12]\n" - "]\n"); - r.set_container_style(FLOW_ML1|FLOW_SPC); - EXPECT_EQ(emit2str(tree), - "[\n" - " [1,2,3,4,5,6],\n" - " 10,\n" - " 20,\n" - " 25,\n" - " [100,200,300,400],\n" - " 30,\n" - " 40,\n" - " 50,\n" - " [7,8,9,10,11,12]\n" - "]\n"); + TreeAndInts ti = parse_tree_and_ints("[[1, 2, 3, 4, 5, 6], 10, 20, 25, [100, 200, 300, 400], 30, 40, 50, [7, 8, 9, 10, 11, 12]]"); + NodeRef r = ti.tree; + { + SCOPED_TRACE("base"); + check_same_emit1(ti, "[[1,2,3,4,5,6],10,20,25,[100,200,300,400],30,40,50,[7,8,9,10,11,12]]"); + } + { + SCOPED_TRACE("1"); + set_style(&ti, r, FLOW_SL|FLOW_SPC, 2, xievt::FLOW|xievt::FSL_|xievt::FSPC); + check_same_emit1(ti, "[[1,2,3,4,5,6], 10, 20, 25, [100,200,300,400], 30, 40, 50, [7,8,9,10,11,12]]"); + } + { + SCOPED_TRACE("2"); + set_style(&ti, r, FLOW_SL, 2, xievt::FLOW|xievt::FSL_); + set_style(&ti, r[0], FLOW_SL|FLOW_SPC, 3, xievt::FLOW|xievt::FSL_|xievt::FSPC); + set_style(&ti, r[4], FLOW_SL|FLOW_SPC, 32, xievt::FLOW|xievt::FSL_|xievt::FSPC); + set_style(&ti, r[8], FLOW_SL|FLOW_SPC, 55, xievt::FLOW|xievt::FSL_|xievt::FSPC); + check_same_emit1(ti, "[[1, 2, 3, 4, 5, 6],10,20,25,[100, 200, 300, 400],30,40,50,[7, 8, 9, 10, 11, 12]]"); + } + { + SCOPED_TRACE("3"); + set_style(&ti, r, FLOW_ML1, 2, xievt::FLOW|xievt::FML1); + set_style(&ti, r[0], FLOW_SL, 3, xievt::FLOW|xievt::FSL_); + set_style(&ti, r[4], FLOW_SL, 32, xievt::FLOW|xievt::FSL_); + set_style(&ti, r[8], FLOW_SL, 55, xievt::FLOW|xievt::FSL_); + check_same_emit1(ti, + "[\n" + " [1,2,3,4,5,6],\n" + " 10,\n" + " 20,\n" + " 25,\n" + " [100,200,300,400],\n" + " 30,\n" + " 40,\n" + " 50,\n" + " [7,8,9,10,11,12]\n" + "]\n"); + } + { + SCOPED_TRACE("4"); + set_style(&ti, r, FLOW_ML1|FLOW_SPC, 2, xievt::FLOW|xievt::FML1|xievt::FSPC); + check_same_emit1(ti, + "[\n" + " [1,2,3,4,5,6],\n" + " 10,\n" + " 20,\n" + " 25,\n" + " [100,200,300,400],\n" + " 30,\n" + " 40,\n" + " 50,\n" + " [7,8,9,10,11,12]\n" + "]\n"); + } } TEST(seq, flow_ml_nested_2_mln) { - Tree tree = parse_in_arena("[[1, 2, 3, 4, 5, 6], 10, 20, 25, [100, 200, 300, 400], 30, 40, 50, [7, 8, 9, 10, 11, 12]]"); - NodeRef r = tree; - r.set_container_style(FLOW_MLN); - EXPECT_EQ(emit2str(tree, maxcols(0)), - "[\n" - " [1,\n" - " 2,\n" - " 3,\n" - " 4,\n" - " 5,\n" - " 6],\n" - " 10,\n" - " 20,\n" - " 25,\n" - " [100,\n" - " 200,\n" - " 300,\n" - " 400],\n" - " 30,\n" - " 40,\n" - " 50,\n" - " [7,\n" - " 8,\n" - " 9,\n" - " 10,\n" - " 11,\n" - " 12]\n" - "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(1)), - "[\n" - " [1,\n" - " 2,\n" - " 3,\n" - " 4,\n" - " 5,\n" - " 6],\n" - " 10,\n" - " 20,\n" - " 25,\n" - " [100,\n" - " 200,\n" - " 300,\n" - " 400],\n" - " 30,\n" - " 40,\n" - " 50,\n" - " [7,\n" - " 8,\n" - " 9,\n" - " 10,\n" - " 11,\n" - " 12]\n" - "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(10)), - "[\n" - " [1,2,3,4,\n" - " 5,6],10,\n" - " 20,25,[100,\n" - " 200,300,\n" - " 400],30,\n" - " 40,50,[7,\n" - " 8,9,10,11,\n" - " 12]\n" - "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(16)), - "[\n" - " [1,2,3,4,5,6],\n" - " 10,20,25,[100,\n" - " 200,300,400],30,\n" - " 40,50,[7,8,9,10,\n" - " 11,12]\n" - "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(20)), - "[\n" - " [1,2,3,4,5,6],10,20,\n" - " 25,[100,200,300,400],\n" - " 30,40,50,[7,8,9,10,\n" - " 11,12]\n" - "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(24)), - "[\n" - " [1,2,3,4,5,6],10,20,25,\n" - " [100,200,300,400],30,40,\n" - " 50,[7,8,9,10,11,12]\n" - "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(30)), - "[\n" - " [1,2,3,4,5,6],10,20,25,[100,\n" - " 200,300,400],30,40,50,[7,8,9,\n" - " 10,11,12]\n" - "]\n"); + TreeAndInts ti = parse_tree_and_ints("[[1, 2, 3, 4, 5, 6], 10, 20, 25, [100, 200, 300, 400], 30, 40, 50, [7, 8, 9, 10, 11, 12]]"); + set_style(&ti, ti.tree, FLOW_MLN, 2, xievt::FLOW|xievt::FMLN); + { + SCOPED_TRACE("0"); + check_same_emit1(ti, maxcols(0), + "[\n" + " [1,\n" + " 2,\n" + " 3,\n" + " 4,\n" + " 5,\n" + " 6],\n" + " 10,\n" + " 20,\n" + " 25,\n" + " [100,\n" + " 200,\n" + " 300,\n" + " 400],\n" + " 30,\n" + " 40,\n" + " 50,\n" + " [7,\n" + " 8,\n" + " 9,\n" + " 10,\n" + " 11,\n" + " 12]\n" + "]\n"); + } + { + SCOPED_TRACE("1"); + check_same_emit1(ti, maxcols(1), + "[\n" + " [1,\n" + " 2,\n" + " 3,\n" + " 4,\n" + " 5,\n" + " 6],\n" + " 10,\n" + " 20,\n" + " 25,\n" + " [100,\n" + " 200,\n" + " 300,\n" + " 400],\n" + " 30,\n" + " 40,\n" + " 50,\n" + " [7,\n" + " 8,\n" + " 9,\n" + " 10,\n" + " 11,\n" + " 12]\n" + "]\n"); + } + { + SCOPED_TRACE("10"); + check_same_emit1(ti, maxcols(10), + "[\n" + " [1,2,3,4,\n" + " 5,6],10,\n" + " 20,25,[100,\n" + " 200,300,\n" + " 400],30,\n" + " 40,50,[7,\n" + " 8,9,10,11,\n" + " 12]\n" + "]\n"); + } + { + SCOPED_TRACE("16"); + check_same_emit1(ti, maxcols(16), + "[\n" + " [1,2,3,4,5,6],\n" + " 10,20,25,[100,\n" + " 200,300,400],30,\n" + " 40,50,[7,8,9,10,\n" + " 11,12]\n" + "]\n"); + } + { + SCOPED_TRACE("20"); + check_same_emit1(ti, maxcols(20), + "[\n" + " [1,2,3,4,5,6],10,20,\n" + " 25,[100,200,300,400],\n" + " 30,40,50,[7,8,9,10,\n" + " 11,12]\n" + "]\n"); + } + { + SCOPED_TRACE("24"); + check_same_emit1(ti, maxcols(24), + "[\n" + " [1,2,3,4,5,6],10,20,25,\n" + " [100,200,300,400],30,40,\n" + " 50,[7,8,9,10,11,12]\n" + "]\n"); + } + { + SCOPED_TRACE("30"); + check_same_emit1(ti, maxcols(30), + "[\n" + " [1,2,3,4,5,6],10,20,25,[100,\n" + " 200,300,400],30,40,50,[7,8,9,\n" + " 10,11,12]\n" + "]\n"); + } } TEST(seq, flow_ml_nested_2_mln_spc) { - Tree tree = parse_in_arena("[[1, 2, 3, 4, 5, 6], 10, 20, 25, [100, 200, 300, 400], 30, 40, 50, [7, 8, 9, 10, 11, 12]]"); - NodeRef r = tree; - r.set_container_style(FLOW_MLN|FLOW_SPC); - EXPECT_EQ(emit2str(tree, maxcols(0)), - "[\n" - " [1,\n" - " 2,\n" - " 3,\n" - " 4,\n" - " 5,\n" - " 6],\n" - " 10,\n" - " 20,\n" - " 25,\n" - " [100,\n" - " 200,\n" - " 300,\n" - " 400],\n" - " 30,\n" - " 40,\n" - " 50,\n" - " [7,\n" - " 8,\n" - " 9,\n" - " 10,\n" - " 11,\n" - " 12]\n" - "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(1)), + TreeAndInts ti = parse_tree_and_ints("[[1, 2, 3, 4, 5, 6], 10, 20, 25, [100, 200, 300, 400], 30, 40, 50, [7, 8, 9, 10, 11, 12]]"); + set_style(&ti, ti.tree, FLOW_MLN|FLOW_SPC, 2, xievt::FLOW|xievt::FMLN|xievt::FSPC); + { + SCOPED_TRACE("0"); + check_same_emit1(ti, maxcols(0), "[\n" " [1,\n" " 2,\n" @@ -1048,7 +1425,38 @@ TEST(seq, flow_ml_nested_2_mln_spc) " 11,\n" " 12]\n" "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(10)), + } + { + SCOPED_TRACE("1"); + check_same_emit1(ti, maxcols(1), + "[\n" + " [1,\n" + " 2,\n" + " 3,\n" + " 4,\n" + " 5,\n" + " 6],\n" + " 10,\n" + " 20,\n" + " 25,\n" + " [100,\n" + " 200,\n" + " 300,\n" + " 400],\n" + " 30,\n" + " 40,\n" + " 50,\n" + " [7,\n" + " 8,\n" + " 9,\n" + " 10,\n" + " 11,\n" + " 12]\n" + "]\n"); + } + { + SCOPED_TRACE("10"); + check_same_emit1(ti, maxcols(10), "[\n" " [1, 2, 3,\n" " 4, 5, 6],\n" @@ -1061,7 +1469,10 @@ TEST(seq, flow_ml_nested_2_mln_spc) " 10, 11,\n" " 12]\n" "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(16)), + } + { + SCOPED_TRACE("16"); + check_same_emit1(ti, maxcols(16), "[\n" " [1, 2, 3, 4, 5,\n" " 6], 10, 20, 25,\n" @@ -1070,7 +1481,10 @@ TEST(seq, flow_ml_nested_2_mln_spc) " 50, [7, 8, 9,\n" " 10, 11, 12]\n" "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(20)), + } + { + SCOPED_TRACE("20"); + check_same_emit1(ti, maxcols(20), "[\n" " [1, 2, 3, 4, 5, 6],\n" " 10, 20, 25, [100,\n" @@ -1078,30 +1492,38 @@ TEST(seq, flow_ml_nested_2_mln_spc) " 40, 50, [7, 8, 9,\n" " 10, 11, 12]\n" "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(24)), + } + { + SCOPED_TRACE("24"); + check_same_emit1(ti, maxcols(24), "[\n" " [1, 2, 3, 4, 5, 6], 10,\n" " 20, 25, [100, 200, 300,\n" " 400], 30, 40, 50, [7,\n" " 8, 9, 10, 11, 12]\n" "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(30)), + } + { + SCOPED_TRACE("30"); + check_same_emit1(ti, maxcols(30), "[\n" " [1, 2, 3, 4, 5, 6], 10, 20,\n" " 25, [100, 200, 300, 400], 30,\n" " 40, 50, [7, 8, 9, 10, 11, 12]\n" "]\n"); + } } TEST(seq, flow_ml_nested_2_mln_spc_nested) { - Tree tree = parse_in_arena("[[1, 2, 3, 4, 5, 6], 10, 20, 25, [100, 200, 300, 400], 30, 40, 50, [7, 8, 9, 10, 11, 12]]"); - NodeRef r = tree; - r.set_container_style(FLOW_MLN|FLOW_SPC); - r[0].set_container_style(FLOW_MLN|FLOW_SPC); - r[4].set_container_style(FLOW_MLN|FLOW_SPC); - r[8].set_container_style(FLOW_MLN|FLOW_SPC); - EXPECT_EQ(emit2str(tree, maxcols(0)), + TreeAndInts ti = parse_tree_and_ints("[[1, 2, 3, 4, 5, 6], 10, 20, 25, [100, 200, 300, 400], 30, 40, 50, [7, 8, 9, 10, 11, 12]]"); + set_style(&ti, ti.tree, FLOW_MLN|FLOW_SPC, 2, xievt::FLOW|xievt::FMLN|xievt::FSPC); + set_style(&ti, ti.tree[0], FLOW_MLN|FLOW_SPC, 3, xievt::FLOW|xievt::FMLN|xievt::FSPC); + set_style(&ti, ti.tree[4], FLOW_MLN|FLOW_SPC, 32, xievt::FLOW|xievt::FMLN|xievt::FSPC); + set_style(&ti, ti.tree[8], FLOW_MLN|FLOW_SPC, 55, xievt::FLOW|xievt::FMLN|xievt::FSPC); + { + SCOPED_TRACE("0"); + check_same_emit1(ti, maxcols(0), "[\n" " [\n" " 1,\n" @@ -1132,7 +1554,10 @@ TEST(seq, flow_ml_nested_2_mln_spc_nested) " 12\n" " ]\n" "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(1)), + } + { + SCOPED_TRACE("1"); + check_same_emit1(ti, maxcols(1), "[\n" " [\n" " 1,\n" @@ -1163,7 +1588,10 @@ TEST(seq, flow_ml_nested_2_mln_spc_nested) " 12\n" " ]\n" "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(10)), + } + { + SCOPED_TRACE("10"); + check_same_emit1(ti, maxcols(10), "[\n" " [\n" " 1, 2,\n" @@ -1180,7 +1608,10 @@ TEST(seq, flow_ml_nested_2_mln_spc_nested) " 11, 12\n" " ]\n" "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(16)), + } + { + SCOPED_TRACE("16"); + check_same_emit1(ti, maxcols(16), "[\n" " [\n" " 1, 2, 3, 4,\n" @@ -1195,7 +1626,10 @@ TEST(seq, flow_ml_nested_2_mln_spc_nested) " 11, 12\n" " ]\n" "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(20)), + } + { + SCOPED_TRACE("20"); + check_same_emit1(ti, maxcols(20), "[\n" " [\n" " 1, 2, 3, 4, 5, 6\n" @@ -1206,7 +1640,10 @@ TEST(seq, flow_ml_nested_2_mln_spc_nested) " 12\n" " ]\n" "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(24)), + } + { + SCOPED_TRACE("24"); + check_same_emit1(ti, maxcols(24), "[\n" " [\n" " 1, 2, 3, 4, 5, 6\n" @@ -1216,7 +1653,10 @@ TEST(seq, flow_ml_nested_2_mln_spc_nested) " 7, 8, 9, 10, 11, 12\n" " ]\n" "]\n"); - EXPECT_EQ(emit2str(tree, maxcols(30)), + } + { + SCOPED_TRACE("30"); + check_same_emit1(ti, maxcols(30), "[\n" " [\n" " 1, 2, 3, 4, 5, 6\n" @@ -1226,6 +1666,7 @@ TEST(seq, flow_ml_nested_2_mln_spc_nested) " 7, 8, 9, 10, 11, 12\n" " ]\n" "]\n"); + } } @@ -1235,17 +1676,23 @@ TEST(seq, flow_ml_nested_2_mln_spc_nested) TEST(keyseq, block) { - Tree tree = parse_in_arena("{foo: [1, 2, 3, 4, 5, 6]}"); - tree._rem_flags(tree.root_id(), CONTAINER_STYLE); - tree._add_flags(tree.root_id(), BLOCK); - EXPECT_EQ(emit2str(tree), R"(foo: [1,2,3,4,5,6] + TreeAndInts ti = parse_tree_and_ints("{foo: [1, 2, 3, 4, 5, 6]}"); + { + SCOPED_TRACE("1"); + set_style(&ti, ti.tree, BLOCK, 2, xievt::BLCK); + check_same_emit1(ti, R"(foo: [1,2,3,4,5,6] )"); - tree._add_flags(tree["foo"].id(), FLOW_SPC); - EXPECT_EQ(emit2str(tree), R"(foo: [1, 2, 3, 4, 5, 6] + } + { + SCOPED_TRACE("2"); + set_style(&ti, ti.tree["foo"], FLOW_SL|FLOW_SPC, 6, xievt::FLOW|xievt::FSL_|xievt::FSPC); + check_same_emit1(ti, R"(foo: [1, 2, 3, 4, 5, 6] )"); - tree._rem_flags(tree["foo"].id(), CONTAINER_STYLE); - tree._add_flags(tree["foo"].id(), BLOCK); - EXPECT_EQ(emit2str(tree), R"(foo: + } + { + SCOPED_TRACE("3"); + set_style(&ti, ti.tree["foo"], BLOCK, 6, xievt::BLCK); + check_same_emit1(ti, R"(foo: - 1 - 2 - 3 @@ -1253,78 +1700,113 @@ TEST(keyseq, block) - 5 - 6 )"); - tree = parse_in_arena("{foo: [1, [2, 3], 4, [5, 6]]}"); - tree._rem_flags(tree.root_id(), CONTAINER_STYLE); - tree._add_flags(tree.root_id(), BLOCK); - EXPECT_EQ(emit2str(tree), R"(foo: [1,[2,3],4,[5,6]] + } +} + +TEST(keyseq, block_nested) +{ + TreeAndInts ti = parse_tree_and_ints("{foo: [1, [2, 3], 4, [5, 6]]}"); + { + SCOPED_TRACE("1"); + set_style(&ti, ti.tree, BLOCK, 2, xievt::BLCK); + check_same_emit1(ti, R"(foo: [1,[2,3],4,[5,6]] +)"); + } + { + SCOPED_TRACE("2"); + set_style(&ti, ti.tree["foo"], FLOW_SL, 6, xievt::FLOW|xievt::FSL_); + check_same_emit1(ti, R"(foo: [1,[2,3],4,[5,6]] )"); - tree._add_flags(tree["foo"].id(), FLOW_SPC); - EXPECT_EQ(emit2str(tree), R"(foo: [1, [2,3], 4, [5,6]] + } + { + SCOPED_TRACE("3"); + add_style(&ti, ti.tree["foo"], FLOW_SPC, 6, xievt::FSPC); + check_same_emit1(ti, R"(foo: [1, [2,3], 4, [5,6]] )"); - tree._add_flags(tree["foo"][1].id(), FLOW_SPC); - tree._add_flags(tree["foo"][3].id(), FLOW_SPC); - EXPECT_EQ(emit2str(tree), R"(foo: [1, [2, 3], 4, [5, 6]] + } + { + SCOPED_TRACE("3"); + add_style(&ti, ti.tree["foo"][1], FLOW_SPC, 10, xievt::FSPC); + add_style(&ti, ti.tree["foo"][3], FLOW_SPC, 21, xievt::FSPC); + check_same_emit1(ti, R"(foo: [1, [2, 3], 4, [5, 6]] )"); - tree._rem_flags(tree["foo"].id(), CONTAINER_STYLE); - tree._add_flags(tree["foo"].id(), BLOCK); - EXPECT_EQ(emit2str(tree), R"(foo: + } + { + SCOPED_TRACE("4"); + set_style(&ti, ti.tree["foo"], BLOCK, 6, xievt::BLCK); + check_same_emit1(ti, R"(foo: - 1 - [2, 3] - 4 - [5, 6] )"); - tree._rem_flags(tree["foo"][1].id(), FLOW_SPC); - tree._rem_flags(tree["foo"][3].id(), FLOW_SPC); - EXPECT_EQ(emit2str(tree), R"(foo: + } + { + SCOPED_TRACE("5"); + rem_style(&ti, ti.tree["foo"][1], FLOW_SPC, 10, xievt::FSPC); + rem_style(&ti, ti.tree["foo"][3], FLOW_SPC, 21, xievt::FSPC); + check_same_emit1(ti, R"(foo: - 1 - [2,3] - 4 - [5,6] )"); + } } TEST(keyseq, flow_sl) { - Tree tree = parse_in_arena("foo: [1, 2, 3, 4, 5, 6]"); - tree._rem_flags(tree.root_id(), CONTAINER_STYLE); - tree._add_flags(tree.root_id(), FLOW_SL); - EXPECT_EQ(emit2str(tree), R"({foo: [1,2,3,4,5,6]})"); - // - tree = parse_in_arena("foo: [1, [2, 3], 4, [5, 6]]"); - tree._rem_flags(tree.root_id(), CONTAINER_STYLE); - tree._add_flags(tree.root_id(), FLOW_SL); - EXPECT_EQ(emit2str(tree), R"({foo: [1,[2,3],4,[5,6]]})"); - // - tree._rem_flags(tree.root_id(), CONTAINER_STYLE); - tree._add_flags(tree.root_id(), BLOCK); - tree._rem_flags(tree["foo"].id(), CONTAINER_STYLE); - tree._add_flags(tree["foo"].id(), BLOCK); - tree._add_flags(tree["foo"][1].id(), FLOW_SL); - tree._add_flags(tree["foo"][3].id(), FLOW_SL); - EXPECT_EQ(emit2str(tree), R"(foo: + TreeAndInts ti = parse_tree_and_ints("foo: [1, 2, 3, 4, 5, 6]"); + set_style(&ti, ti.tree, FLOW_SL, 2, xievt::FLOW|xievt::FSL_); + check_same_emit1(ti, R"({foo: [1,2,3,4,5,6]})"); +} + +TEST(keyseq, flow_sl_nested) +{ + TreeAndInts ti = parse_tree_and_ints("foo: [1, [2, 3], 4, [5, 6]]"); + { + SCOPED_TRACE("1"); + set_style(&ti, ti.tree, FLOW_SL, 2, xievt::FLOW|xievt::FSL_); + check_same_emit1(ti, R"({foo: [1,[2,3],4,[5,6]]})"); + } + { + SCOPED_TRACE("2"); + set_style(&ti, ti.tree, BLOCK, 2, xievt::BLCK); + set_style(&ti, ti.tree["foo"], BLOCK, 6, xievt::BLCK); + set_style(&ti, ti.tree["foo"][1], FLOW_SL, 10, xievt::FLOW|xievt::FSL_); + set_style(&ti, ti.tree["foo"][3], FLOW_SL, 21, xievt::FLOW|xievt::FSL_); + check_same_emit1(ti, R"(foo: - 1 - [2,3] - 4 - [5,6] )"); + } } TEST(keyseq, flow_ml1) { - Tree tree = parse_in_arena("foo: [1, 2, 3, 4, 5, 6]"); - NodeRef r = tree; - r.set_container_style(FLOW_ML1); - EXPECT_EQ(emit2str(tree), + TreeAndInts ti = parse_tree_and_ints("foo: [1, 2, 3, 4, 5, 6]"); + { + SCOPED_TRACE("1"); + set_style(&ti, ti.tree, FLOW_ML1, 2, xievt::FLOW|xievt::FML1); + check_same_emit1(ti, "{\n" " foo: [1,2,3,4,5,6]\n" "}\n"); - r.set_container_style(FLOW_ML1|FLOW_SPC); - EXPECT_EQ(emit2str(tree), + } + { + SCOPED_TRACE("2"); + add_style(&ti, ti.tree, FLOW_SPC, 2, xievt::FSPC); + check_same_emit1(ti, "{\n" " foo: [1,2,3,4,5,6]\n" "}\n"); - r["foo"].set_container_style(FLOW_ML1); - EXPECT_EQ(emit2str(tree), + } + { + SCOPED_TRACE("3"); + set_style(&ti, ti.tree["foo"], FLOW_ML1, 6, xievt::FLOW|xievt::FML1); + check_same_emit1(ti, "{\n" " foo: [\n" " 1,\n" @@ -1335,42 +1817,54 @@ TEST(keyseq, flow_ml1) " 6\n" " ]\n" "}\n"); - r["foo"].set_container_style(FLOW_MLN); - EXPECT_EQ(emit2str(tree), + } + { + SCOPED_TRACE("4"); + set_style(&ti, ti.tree["foo"], FLOW_MLN, 6, xievt::FLOW|xievt::FMLN); + check_same_emit1(ti, "{\n" " foo: [\n" " 1,2,3,4,5,6\n" " ]\n" "}\n"); - r["foo"].set_container_style(FLOW_MLN|FLOW_SPC); - EXPECT_EQ(emit2str(tree), + } + { + SCOPED_TRACE("5"); + add_style(&ti, ti.tree["foo"], FLOW_SPC, 6, xievt::FSPC); + check_same_emit1(ti, "{\n" " foo: [\n" " 1, 2, 3, 4, 5, 6\n" " ]\n" "}\n"); + } } -TEST(keyseq, flow_mln_0) +TEST(keyseq, flow_mln) { - Tree tree = parse_in_arena("foo: [1, 2, 3, 4, 5, 6]"); - NodeRef r = tree; - r.set_container_style(FLOW_ML1); - r["foo"].set_container_style(FLOW_MLN|FLOW_SPC); - EXPECT_EQ(emit2str(tree), + TreeAndInts ti = parse_tree_and_ints("foo: [1, 2, 3, 4, 5, 6]"); + { + SCOPED_TRACE("1"); + set_style(&ti, ti.tree, FLOW_ML1, 2, xievt::FLOW|xievt::FML1); + set_style(&ti, ti.tree["foo"], FLOW_MLN|FLOW_SPC, 6, xievt::FLOW|xievt::FMLN|xievt::FSPC); + check_same_emit1(ti, "{\n" " foo: [\n" " 1, 2, 3, 4, 5, 6\n" " ]\n" "}\n"); - r["foo"].set_container_style(FLOW_MLN); - EXPECT_EQ(emit2str(tree), + } + { + SCOPED_TRACE("2"); + set_style(&ti, ti.tree["foo"], FLOW_MLN, 6, xievt::FLOW|xievt::FMLN); + check_same_emit1(ti, "{\n" " foo: [\n" " 1,2,3,4,5,6\n" " ]\n" "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(5)), + } + check_same_emit1(ti, maxcols(5), "{\n" " foo: [\n" " 1,\n" @@ -1381,7 +1875,7 @@ TEST(keyseq, flow_mln_0) " 6\n" " ]\n" "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(6)), + check_same_emit1(ti, maxcols(6), "{\n" " foo: [\n" " 1,\n" @@ -1392,7 +1886,7 @@ TEST(keyseq, flow_mln_0) " 6\n" " ]\n" "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(7)), + check_same_emit1(ti, maxcols(7), "{\n" " foo: [\n" " 1,2,\n" @@ -1400,7 +1894,7 @@ TEST(keyseq, flow_mln_0) " 5,6\n" " ]\n" "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(8)), + check_same_emit1(ti, maxcols(8), "{\n" " foo: [\n" " 1,2,\n" @@ -1408,55 +1902,55 @@ TEST(keyseq, flow_mln_0) " 5,6\n" " ]\n" "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(9)), + check_same_emit1(ti, maxcols(9), "{\n" " foo: [\n" " 1,2,3,\n" " 4,5,6\n" " ]\n" "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(10)), + check_same_emit1(ti, maxcols(10), "{\n" " foo: [\n" " 1,2,3,\n" " 4,5,6\n" " ]\n" "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(11)), + check_same_emit1(ti, maxcols(11), "{\n" " foo: [\n" " 1,2,3,4,\n" " 5,6\n" " ]\n" "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(12)), + check_same_emit1(ti, maxcols(12), "{\n" " foo: [\n" " 1,2,3,4,\n" " 5,6\n" " ]\n" "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(13)), + check_same_emit1(ti, maxcols(13), "{\n" " foo: [\n" " 1,2,3,4,5,\n" " 6\n" " ]\n" "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(14)), + check_same_emit1(ti, maxcols(14), "{\n" " foo: [\n" " 1,2,3,4,5,\n" " 6\n" " ]\n" "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(15)), + check_same_emit1(ti, maxcols(15), "{\n" " foo: [\n" " 1,2,3,4,5,6\n" " ]\n" "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(20)), + check_same_emit1(ti, maxcols(20), "{\n" " foo: [\n" " 1,2,3,4,5,6\n" @@ -1464,19 +1958,18 @@ TEST(keyseq, flow_mln_0) "}\n"); } -TEST(keyseq, flow_mln_1) +TEST(keyseq, flow_mln_spc) { - Tree tree = parse_in_arena("foo: [1, 2, 3, 4, 5, 6]"); - NodeRef r = tree; - r.set_container_style(FLOW_ML1); - r["foo"].set_container_style(FLOW_MLN|FLOW_SPC); - EXPECT_EQ(emit2str(tree), + TreeAndInts ti = parse_tree_and_ints("foo: [1, 2, 3, 4, 5, 6]"); + set_style(&ti, ti.tree, FLOW_ML1, 2, xievt::FLOW|xievt::FML1); + set_style(&ti, ti.tree["foo"], FLOW_MLN|FLOW_SPC, 6, xievt::FLOW|xievt::FMLN|xievt::FSPC); + check_same_emit1(ti, "{\n" " foo: [\n" " 1, 2, 3, 4, 5, 6\n" " ]\n" "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(5)), + check_same_emit1(ti, maxcols(5), "{\n" " foo: [\n" " 1,\n" @@ -1487,7 +1980,7 @@ TEST(keyseq, flow_mln_1) " 6\n" " ]\n" "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(6)), + check_same_emit1(ti, maxcols(6), "{\n" " foo: [\n" " 1,\n" @@ -1498,7 +1991,7 @@ TEST(keyseq, flow_mln_1) " 6\n" " ]\n" "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(7)), + check_same_emit1(ti, maxcols(7), "{\n" " foo: [\n" " 1,\n" @@ -1509,7 +2002,7 @@ TEST(keyseq, flow_mln_1) " 6\n" " ]\n" "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(8)), + check_same_emit1(ti, maxcols(8), "{\n" " foo: [\n" " 1, 2,\n" @@ -1517,7 +2010,7 @@ TEST(keyseq, flow_mln_1) " 5, 6\n" " ]\n" "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(9)), + check_same_emit1(ti, maxcols(9), "{\n" " foo: [\n" " 1, 2,\n" @@ -1525,7 +2018,7 @@ TEST(keyseq, flow_mln_1) " 5, 6\n" " ]\n" "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(10)), + check_same_emit1(ti, maxcols(10), "{\n" " foo: [\n" " 1, 2,\n" @@ -1533,42 +2026,42 @@ TEST(keyseq, flow_mln_1) " 5, 6\n" " ]\n" "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(11)), + check_same_emit1(ti, maxcols(11), "{\n" " foo: [\n" " 1, 2, 3,\n" " 4, 5, 6\n" " ]\n" "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(12)), + check_same_emit1(ti, maxcols(12), "{\n" " foo: [\n" " 1, 2, 3,\n" " 4, 5, 6\n" " ]\n" "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(13)), + check_same_emit1(ti, maxcols(13), "{\n" " foo: [\n" " 1, 2, 3,\n" " 4, 5, 6\n" " ]\n" "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(14)), + check_same_emit1(ti, maxcols(14), "{\n" " foo: [\n" " 1, 2, 3, 4,\n" " 5, 6\n" " ]\n" "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(17)), + check_same_emit1(ti, maxcols(17), "{\n" " foo: [\n" " 1, 2, 3, 4, 5,\n" " 6\n" " ]\n" "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(20)), + check_same_emit1(ti, maxcols(20), "{\n" " foo: [\n" " 1, 2, 3, 4, 5, 6\n" @@ -1578,23 +2071,33 @@ TEST(keyseq, flow_mln_1) TEST(keyseq, flow_mln_nested) { - Tree tree = parse_in_arena("foo: [1, [2, 3], 4, [5, 6]]"); - NodeRef r = tree; - r.set_container_style(FLOW_SL); - EXPECT_EQ(emit2str(tree), R"({foo: [1,[2,3],4,[5,6]]})"); - r.set_container_style(FLOW_ML1); - EXPECT_EQ(emit2str(tree), - "{\n" - " foo: [1,[2,3],4,[5,6]]\n" - "}\n"); - r["foo"].set_container_style(FLOW_MLN); - EXPECT_EQ(emit2str(tree), - "{\n" - " foo: [\n" - " 1,[2,3],4,[5,6]\n" - " ]\n" - "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(5)), + TreeAndInts ti = parse_tree_and_ints("foo: [1, [2, 3], 4, [5, 6]]"); + { + SCOPED_TRACE("1"); + set_style(&ti, ti.tree, FLOW_SL, 2, xievt::FLOW|xievt::FSL_); + check_same_emit1(ti, R"({foo: [1,[2,3],4,[5,6]]})"); + } + { + SCOPED_TRACE("2"); + set_style(&ti, ti.tree, FLOW_ML1, 2, xievt::FLOW|xievt::FML1); + check_same_emit1(ti, + "{\n" + " foo: [1,[2,3],4,[5,6]]\n" + "}\n"); + } + { + SCOPED_TRACE("3"); + set_style(&ti, ti.tree["foo"], FLOW_MLN, 6, xievt::FLOW|xievt::FMLN); + check_same_emit1(ti, + "{\n" + " foo: [\n" + " 1,[2,3],4,[5,6]\n" + " ]\n" + "}\n"); + } + { + SCOPED_TRACE("4"); + check_same_emit1(ti, maxcols(5), "{\n" " foo: [\n" " 1,\n" @@ -1605,7 +2108,10 @@ TEST(keyseq, flow_mln_nested) " 6]\n" " ]\n" "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(7)), + } + { + SCOPED_TRACE("5"); + check_same_emit1(ti, maxcols(7), "{\n" " foo: [\n" " 1,[2,\n" @@ -1614,38 +2120,49 @@ TEST(keyseq, flow_mln_nested) " 6]\n" " ]\n" "}\n"); - // - r.set_container_style(BLOCK); - r["foo"].set_container_style(BLOCK); - r["foo"][1].set_container_style(FLOW_SL); - r["foo"][3].set_container_style(FLOW_SL); - EXPECT_EQ(emit2str(tree), R"(foo: + } + { + SCOPED_TRACE("6"); + set_style(&ti, ti.tree, BLOCK, 2, xievt::BLCK); + set_style(&ti, ti.tree["foo"], BLOCK, 6, xievt::BLCK); + set_style(&ti, ti.tree["foo"][1], FLOW_SL, 10, xievt::FLOW|xievt::FSL_); + set_style(&ti, ti.tree["foo"][3], FLOW_SL, 21, xievt::FLOW|xievt::FSL_); + check_same_emit1(ti, R"(foo: - 1 - [2,3] - 4 - [5,6] )"); + } } TEST(keyseq, flow_mln_nested_2) { - Tree tree = parse_in_arena("foo: [1, [2, 3, 20, 30, 40], 4, [5, 6, 70, 80, 90]]"); - NodeRef r = tree; - r.set_container_style(FLOW_SL); - EXPECT_EQ(emit2str(tree), R"({foo: [1,[2,3,20,30,40],4,[5,6,70,80,90]]})"); - r.set_container_style(FLOW_ML1); - EXPECT_EQ(emit2str(tree), - "{\n" - " foo: [1,[2,3,20,30,40],4,[5,6,70,80,90]]\n" - "}\n"); - r["foo"].set_container_style(FLOW_MLN); - EXPECT_EQ(emit2str(tree), + TreeAndInts ti = parse_tree_and_ints("foo: [1, [2, 3, 20, 30, 40], 4, [5, 6, 70, 80, 90]]"); + { + SCOPED_TRACE("1"); + set_style(&ti, ti.tree, FLOW_SL, 2, xievt::FLOW|xievt::FSL_); + check_same_emit1(ti, R"({foo: [1,[2,3,20,30,40],4,[5,6,70,80,90]]})"); + } + { + SCOPED_TRACE("2"); + set_style(&ti, ti.tree, FLOW_ML1, 2, xievt::FLOW|xievt::FML1); + check_same_emit1(ti, + "{\n" + " foo: [1,[2,3,20,30,40],4,[5,6,70,80,90]]\n" + "}\n"); + } + { + SCOPED_TRACE("3"); + set_style(&ti, ti.tree["foo"], FLOW_MLN, 6, xievt::FLOW|xievt::FMLN); + check_same_emit1(ti, "{\n" " foo: [\n" " 1,[2,3,20,30,40],4,[5,6,70,80,90]\n" " ]\n" "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(5)), + } + check_same_emit1(ti, maxcols(5), "{\n" " foo: [\n" " 1,\n" @@ -1662,7 +2179,7 @@ TEST(keyseq, flow_mln_nested_2) " 90]\n" " ]\n" "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(7)), + check_same_emit1(ti, maxcols(7), "{\n" " foo: [\n" " 1,[2,\n" @@ -1675,7 +2192,7 @@ TEST(keyseq, flow_mln_nested_2) " 90]\n" " ]\n" "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(12)), + check_same_emit1(ti, maxcols(12), "{\n" " foo: [\n" " 1,[2,3,20,\n" @@ -1684,14 +2201,14 @@ TEST(keyseq, flow_mln_nested_2) " 80,90]\n" " ]\n" "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(20)), + check_same_emit1(ti, maxcols(20), "{\n" " foo: [\n" " 1,[2,3,20,30,40],\n" " 4,[5,6,70,80,90]\n" " ]\n" "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(25)), + check_same_emit1(ti, maxcols(25), "{\n" " foo: [\n" " 1,[2,3,20,30,40],4,[5,\n" @@ -1707,10 +2224,9 @@ TEST(keyseq, flow_mln_nested_2) TEST(map, block) { - Tree tree = parse_in_arena("{1: 10, 2: 10, 3: 10, 4: 10, 5: 10, 6: 10}"); - NodeRef r = tree; - r.set_container_style(BLOCK); - EXPECT_EQ(emit2str(tree), R"(1: 10 + TreeAndInts ti = parse_tree_and_ints("{1: 10, 2: 10, 3: 10, 4: 10, 5: 10, 6: 10}"); + set_style(&ti, ti.tree, BLOCK, 2, xievt::BLCK); + check_same_emit1(ti, R"(1: 10 2: 10 3: 10 4: 10 @@ -1719,27 +2235,71 @@ TEST(map, block) )"); } +TEST(map, block_picks_default_style) +{ + TreeAndInts ti = parse_tree_and_ints("'ab': [2,3]\n"); + { + SCOPED_TRACE("1"); + check_same_emit1(ti, "'ab': [2,3]\n"); + } + { + SCOPED_TRACE("2"); + rem_style(&ti, ti.tree[0], SCALAR_STYLE, 3, all_styles_scalar); + rem_style(&ti, ti.tree[0], CONTAINER_STYLE, 6, all_styles_container); + check_same_emit1(ti, "ab:\n - 2\n - 3\n"); + } +} + +TEST(map, flow_sl_picks_default_style) +{ + TreeAndInts ti = parse_tree_and_ints("{'ab': [2,3]}"); + { + SCOPED_TRACE("1"); + check_same_emit1(ti, "{'ab': [2,3]}"); + } + { + SCOPED_TRACE("2"); + rem_style(&ti, ti.tree[0], SCALAR_STYLE, 3, all_styles_scalar); + rem_style(&ti, ti.tree[0], CONTAINER_STYLE, 6, all_styles_container); + check_same_emit1(ti, "{ab: [2,3]}"); + } +} + +TEST(map, flow_ml_picks_default_style) +{ + TreeAndInts ti = parse_tree_and_ints("{\n 'ab': [\n 2,\n 3]\n}"); + { + SCOPED_TRACE("1"); + check_same_emit1(ti, "{\n 'ab': [\n 2,\n 3\n ]\n}\n"); + } + { + SCOPED_TRACE("2"); + rem_style(&ti, ti.tree[0], SCALAR_STYLE, 3, all_styles_scalar); + rem_style(&ti, ti.tree[0], CONTAINER_STYLE, 6, all_styles_container); + check_same_emit1(ti, "{\n ab: [2,3]\n}\n"); + } +} + TEST(map, flow_sl) { - Tree tree = parse_in_arena(R"(1: 10 + TreeAndInts ti = parse_tree_and_ints(R"(1: 10 2: 10 3: 10 4: 10 5: 10 6: 10 )"); - NodeRef r = tree; - r.set_container_style(FLOW_SL); - EXPECT_EQ(emit2str(tree), R"({1: 10,2: 10,3: 10,4: 10,5: 10,6: 10})"); - r.set_container_style(FLOW_SL|FLOW_SPC); - EXPECT_EQ(emit2str(tree), R"({1: 10, 2: 10, 3: 10, 4: 10, 5: 10, 6: 10})"); - r.set_container_style(FLOW_SL); - EXPECT_EQ(emit2str(tree), R"({1: 10,2: 10,3: 10,4: 10,5: 10,6: 10})"); + set_style(&ti, ti.tree, FLOW_SL, 2, xievt::FLOW|xievt::FSL_); + check_same_emit1(ti, R"({1: 10,2: 10,3: 10,4: 10,5: 10,6: 10})"); + add_style(&ti, ti.tree, FLOW_SPC, 2, xievt::FSPC); + check_same_emit1(ti, R"({1: 10, 2: 10, 3: 10, 4: 10, 5: 10, 6: 10})"); + rem_style(&ti, ti.tree, FLOW_SPC, 2, xievt::FSPC); + check_same_emit1(ti, R"({1: 10,2: 10,3: 10,4: 10,5: 10,6: 10})"); } TEST(map, flow_ml_1) { - Tree tree = parse_in_arena(R"(1: 10 + TreeAndInts ti = parse_tree_and_ints(R"(1: 10 2: 10 3: 10 4: 10 @@ -1752,9 +2312,8 @@ TEST(map, flow_ml_1) 11: 10 12: 10 )"); - NodeRef r = tree; - r.set_container_style(FLOW_ML1); - EXPECT_EQ(emit2str(tree), "" + set_style(&ti, ti.tree, FLOW_ML1, 2, xievt::FLOW|xievt::FML1); + check_same_emit1(ti, "" "{\n" " 1: 10,\n" " 2: 10,\n" @@ -1769,8 +2328,8 @@ TEST(map, flow_ml_1) " 11: 10,\n" " 12: 10\n" "}\n"); - r.set_container_style(FLOW_ML1|FLOW_SPC); - EXPECT_EQ(emit2str(tree), "" + add_style(&ti, ti.tree, FLOW_SPC, 2, xievt::FSPC); + check_same_emit1(ti, "" "{\n" " 1: 10,\n" " 2: 10,\n" @@ -1789,7 +2348,7 @@ TEST(map, flow_ml_1) TEST(map, flow_ml_n) { - Tree tree = parse_in_arena(R"(1: 10 + TreeAndInts ti = parse_tree_and_ints(R"(1: 10 2: 10 3: 10 4: 10 @@ -1802,36 +2361,35 @@ TEST(map, flow_ml_n) 11: 10 12: 10 )"); - NodeRef r = tree; - r.set_container_style(FLOW_MLN); - EXPECT_EQ(emit2str(tree), "" + set_style(&ti, ti.tree, FLOW_MLN, 2, xievt::FLOW|xievt::FMLN); + check_same_emit1(ti, "" "{\n" " 1: 10,2: 10,3: 10,4: 10,5: 10,6: 10,7: 10,8: 10,9: 10,10: 10,11: 10,12: 10\n" "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(40)), "" + check_same_emit1(ti, maxcols(40), "" "{\n" " 1: 10,2: 10,3: 10,4: 10,5: 10,6: 10,7: 10,\n" " 8: 10,9: 10,10: 10,11: 10,12: 10\n" "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(20)), "" + check_same_emit1(ti, maxcols(20), "" "{\n" " 1: 10,2: 10,3: 10,\n" " 4: 10,5: 10,6: 10,\n" " 7: 10,8: 10,9: 10,\n" " 10: 10,11: 10,12: 10\n" "}\n"); - r.set_container_style(FLOW_MLN|FLOW_SPC); - EXPECT_EQ(emit2str(tree), "" + add_style(&ti, ti.tree, FLOW_SPC, 2, xievt::FSPC); + check_same_emit1(ti, "" "{\n" " 1: 10, 2: 10, 3: 10, 4: 10, 5: 10, 6: 10, 7: 10, 8: 10, 9: 10, 10: 10, 11: 10,\n" " 12: 10\n" "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(40)), "" + check_same_emit1(ti, maxcols(40), "" "{\n" " 1: 10, 2: 10, 3: 10, 4: 10, 5: 10, 6: 10,\n" " 7: 10, 8: 10, 9: 10, 10: 10, 11: 10, 12: 10\n" "}\n"); - EXPECT_EQ(emit2str(tree, maxcols(20)), "" + check_same_emit1(ti, maxcols(20), "" "{\n" " 1: 10, 2: 10, 3: 10,\n" " 4: 10, 5: 10, 6: 10,\n" @@ -1847,14 +2405,15 @@ TEST(map, flow_ml_n) TEST(keymap, block) { - Tree tree = parse_in_arena("{foo: {1: 10, 2: 10, 3: 10, 4: 10, 5: 10, 6: 10}}"); - NodeRef r = tree; - r.set_container_style(BLOCK); - EXPECT_EQ(emit2str(tree), "foo: {1: 10,2: 10,3: 10,4: 10,5: 10,6: 10}\n"); - r["foo"].set_container_style(FLOW_SL|FLOW_SPC); - EXPECT_EQ(emit2str(tree), "foo: {1: 10, 2: 10, 3: 10, 4: 10, 5: 10, 6: 10}\n"); - r["foo"].set_container_style(BLOCK); - EXPECT_EQ(emit2str(tree), R"(foo: + TreeAndInts ti = parse_tree_and_ints("{foo: {1: 10, 2: 10, 3: 10, 4: 10, 5: 10, 6: 10}}"); + set_style(&ti, ti.tree, BLOCK, 2, xievt::BLCK); + check_same_emit1(ti, "" + "foo: {1: 10,2: 10,3: 10,4: 10,5: 10,6: 10}\n"); + set_style(&ti, ti.tree["foo"], FLOW_SL|FLOW_SPC, 6, xievt::FLOW|xievt::FSL_|xievt::FSPC); + check_same_emit1(ti, "" + "foo: {1: 10, 2: 10, 3: 10, 4: 10, 5: 10, 6: 10}\n"); + set_style(&ti, ti.tree["foo"], BLOCK, 6, xievt::BLCK); + check_same_emit1(ti, R"(foo: 1: 10 2: 10 3: 10 @@ -1867,7 +2426,7 @@ TEST(keymap, block) TEST(keymap, flow_sl) { - Tree tree = parse_in_arena(R"(foo: + TreeAndInts ti = parse_tree_and_ints(R"(foo: 1: 10 2: 10 3: 10 @@ -1875,11 +2434,14 @@ TEST(keymap, flow_sl) 5: 10 6: 10 )"); - tree._rem_flags(tree.root_id(), CONTAINER_STYLE); - tree._add_flags(tree.root_id(), FLOW_SL); - EXPECT_EQ(emit2str(tree), R"({foo: {1: 10,2: 10,3: 10,4: 10,5: 10,6: 10}})"); - // - tree = parse_in_arena(R"(foo: + set_style(&ti, ti.tree, FLOW_SL, 2, xievt::FLOW|xievt::FSL_); + check_same_emit1(ti, R"({foo: {1: 10,2: 10,3: 10,4: 10,5: 10,6: 10}})"); +} + + +TEST(keymap, flow_sl_nested) +{ + TreeAndInts ti = parse_tree_and_ints(R"(foo: 1: 10 2: 2: 10 @@ -1889,29 +2451,35 @@ TEST(keymap, flow_sl) 5: 10 6: 10 )"); - tree._rem_flags(tree.root_id(), CONTAINER_STYLE); - tree._add_flags(tree.root_id(), FLOW_SL); - EXPECT_EQ(emit2str(tree), R"({foo: {1: 10,2: {2: 10,3: 10},4: 10,5: {5: 10,6: 10}}})"); - tree._rem_flags(tree.root_id(), CONTAINER_STYLE); - tree._add_flags(tree.root_id(), BLOCK); - tree._rem_flags(tree["foo"][1].id(), BLOCK); - tree._add_flags(tree["foo"][1].id(), FLOW_SL); - tree._rem_flags(tree["foo"][3].id(), BLOCK); - tree._add_flags(tree["foo"][3].id(), FLOW_SL); - EXPECT_EQ(emit2str(tree), R"(foo: + { + SCOPED_TRACE("1"); + set_style(&ti, ti.tree, FLOW_SL, 2, xievt::FLOW|xievt::FSL_); + check_same_emit1(ti, R"({foo: {1: 10,2: {2: 10,3: 10},4: 10,5: {5: 10,6: 10}}})"); + } + { + SCOPED_TRACE("2"); + set_style(&ti, ti.tree, BLOCK, 2, xievt::BLCK); + set_style(&ti, ti.tree["foo"], BLOCK, 6, xievt::BLCK); + set_style(&ti, ti.tree["foo"][1], FLOW_SL, 16, xievt::FLOW|xievt::FSL_); + set_style(&ti, ti.tree["foo"][3], FLOW_SL, 39, xievt::FLOW|xievt::FSL_); + check_same_emit1(ti, R"(foo: 1: 10 2: {2: 10,3: 10} 4: 10 5: {5: 10,6: 10} )"); - tree._add_flags(tree["foo"][1].id(), FLOW_SPC); - tree._add_flags(tree["foo"][3].id(), FLOW_SPC); - EXPECT_EQ(emit2str(tree), R"(foo: + } + { + SCOPED_TRACE("3"); + add_style(&ti, ti.tree["foo"][1], FLOW_SPC, 16, xievt::FSPC); + add_style(&ti, ti.tree["foo"][3], FLOW_SPC, 39, xievt::FSPC); + check_same_emit1(ti, R"(foo: 1: 10 2: {2: 10, 3: 10} 4: 10 5: {5: 10, 6: 10} )"); + } } @@ -1924,3 +2492,5 @@ Case const* get_case(csubstr /*name*/) } // namespace yml } // namespace c4 + +// NOLINTEND(hicpp-signed-bitwise,*avoid-c-style-cast) diff --git a/test/test_tag.cpp b/test/test_tag.cpp index 5ff839b3c..30a0a2e85 100644 --- a/test/test_tag.cpp +++ b/test/test_tag.cpp @@ -1988,7 +1988,7 @@ N(STREAM, L{ }) ); -ADD_CASE_TO_GROUP("tagged doc 8", +ADD_CASE_TO_GROUP("tagged doc 8", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"( --- !!set @@ -2000,7 +2000,7 @@ N(STREAM, L{ }) ); -ADD_CASE_TO_GROUP("tagged doc 9", +ADD_CASE_TO_GROUP("tagged doc 9", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"( --- !!set ? a @@ -2011,7 +2011,7 @@ N(STREAM, L{ }) ); -ADD_CASE_TO_GROUP("ambiguous tag in map, std tag", +ADD_CASE_TO_GROUP("ambiguous tag in map, std tag", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"(!!map !!str a0: !!xxx b0 !!str fooz: !!map @@ -2036,7 +2036,7 @@ N(MB, TL("!!map", L{ })) ); -ADD_CASE_TO_GROUP("ambiguous tag in map, usr tag", +ADD_CASE_TO_GROUP("ambiguous tag in map, usr tag", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"(!map !str a0: !xxx b0 !str fooz: !map @@ -2062,7 +2062,7 @@ N(MB, TL("!map", L{ ); -ADD_CASE_TO_GROUP("ambiguous tag in seq, std tag", +ADD_CASE_TO_GROUP("ambiguous tag in seq, std tag", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"(!!seq - !!str k1: v1 !!str k2: v2 @@ -2096,7 +2096,7 @@ N(SB, TL("!!seq", L{ N(SB, TL("!!seq", L{N(VP, "v70"), N(VP, "v80"), N(VP, "v90")})), }))); -ADD_CASE_TO_GROUP("ambiguous tag in seq, usr tag", +ADD_CASE_TO_GROUP("ambiguous tag in seq, usr tag", NO_COMPARE_EMITTED_INTS_JSON,//FIXME R"(!seq - !str k1: v1 !str k2: v2 diff --git a/test/test_tree.cpp b/test/test_tree.cpp index a10f61b65..cff6fad5a 100644 --- a/test/test_tree.cpp +++ b/test/test_tree.cpp @@ -981,6 +981,27 @@ TEST(Tree, issue564_relocate_arena_0) }); } +TEST(Tree, clear_empty) +{ + Tree t(0, 0); + EXPECT_EQ(t.capacity(), 0); + EXPECT_EQ(t.slack(), 0); + EXPECT_EQ(t.size(), 0); + EXPECT_EQ(t.arena_capacity(), 0); + EXPECT_EQ(t.arena_slack(), 0); + EXPECT_EQ(t.arena_size(), 0); + test_invariants(t); + + t.clear(); + EXPECT_EQ(t.capacity(), 0); + EXPECT_EQ(t.slack(), 0); + EXPECT_EQ(t.size(), 0); + EXPECT_EQ(t.arena_capacity(), 0); + EXPECT_EQ(t.arena_slack(), 0); + EXPECT_EQ(t.arena_size(), 0); + test_invariants(t); +} + TEST(Tree, clear) { Tree t(16, 64); @@ -1002,7 +1023,7 @@ TEST(Tree, clear) EXPECT_EQ(t.arena_size(), 0); test_invariants(t); - auto buf = t.m_buf; + NodeData *buf = t.m_buf; t.reserve(16); t.reserve_arena(64); EXPECT_EQ(t.m_buf, buf); diff --git a/test/testsuite.cpp b/test/testsuite.cpp index 80a46db4e..69edec665 100644 --- a/test/testsuite.cpp +++ b/test/testsuite.cpp @@ -13,6 +13,8 @@ #include "testsuite/testsuite_parts.hpp" #include "testsuite/testsuite_events.hpp" #include "c4/yml/extra/event_handler_ints.hpp" +#include "c4/yml/extra/emitter_ints.hpp" +#include "c4/yml/extra/emitter_ints.def.hpp" #include "c4/yml/extra/ints_to_testsuite.hpp" #include #include @@ -122,6 +124,9 @@ struct TestSuiteCaseEvents void compare_events(csubstr emitted_events, bool ignore_container_style, bool ignore_scalar_style) { + SCOPED_TRACE("compare events"); + EXPECT_FALSE(reference_events.empty()); + EXPECT_FALSE(emitted_events.empty()); test_compare_events(to_csubstr(reference_events), emitted_events, /*ignore_doc_style*/true, @@ -144,9 +149,14 @@ struct TestSequenceLevel std::string src_orig; std::string src_tree; std::string src_tree_json; - std::string src_evts; - std::string src_evts_ints; - std::string arena_evts_ints; + std::string src_ints_resize; + std::string src_ints_resize_json; + std::string src_ints_noresize; + std::string src_ints_noresize_json; + std::string src_ints_noresize_orig; + std::string src_ints_noresize_orig_json; + std::string arena_ints_noresize; + std::string arena_ints_noresize_json; ParserOptions parser_options; EventHandlerTree evt_handler_tree; EventHandlerTree evt_handler_tree_json; @@ -156,20 +166,44 @@ struct TestSequenceLevel Tree tree_parsed_from_src_json; std::string emitted_from_tree_parsed_from_src; std::string emitted_from_tree_parsed_from_src_json; - - extra::EventHandlerInts evt_handler_ints; - ParseEngine parser_ints; - std::vector buffer_ints; - std::string evts_test_suite_from_ints; - - bool immutable = false; + std::string evts_test_suite_from_tree; + std::string evts_test_suite_from_tree_json; + + std::string emitted_from_ints_resize_parsed_from_src; + std::string emitted_from_ints_resize_parsed_from_src_json; + std::string emitted_from_ints_noresize_parsed_from_src; + std::string emitted_from_ints_noresize_parsed_from_src_json; + + using EventHandlerIntsNoResize = extra::ievt::EventHandlerInts; + using EventHandlerIntsResize = extra::ievt::EventHandlerInts; + + EventHandlerIntsNoResize evt_handler_ints_noresize; + EventHandlerIntsNoResize evt_handler_ints_noresize_json; + EventHandlerIntsResize evt_handler_ints_resize; + EventHandlerIntsResize evt_handler_ints_resize_json; + ParseEngine parser_ints_noresize; + ParseEngine parser_ints_noresize_json; + ParseEngine parser_ints_resize; + ParseEngine parser_ints_resize_json; + std::vector buffer_ints_noresize; + std::vector buffer_ints_noresize_json; + extra::ievt::Buffers ints_resize; + extra::ievt::Buffers ints_resize_json; + std::string evts_test_suite_from_ints_noresize; + std::string evts_test_suite_from_ints_noresize_json; + std::string evts_test_suite_from_ints_resize; + std::string evts_test_suite_from_ints_resize_json; + + bool in_arena = false; bool reuse = false; bool tree_was_parsed = false; bool tree_was_parsed_json = false; bool tree_was_emitted = false; bool tree_was_emitted_json = false; - bool events_were_generated = false; - bool events_ints_were_generated = false; + bool ints_were_parsed = false; + bool ints_were_parsed_json = false; + bool ints_were_emitted = false; + bool ints_were_emitted_json = false; TestSequenceLevel() : parser_options(ParserOptions{}.resolve_tags(true).resolve_tags_all(true)) @@ -177,59 +211,75 @@ struct TestSequenceLevel , evt_handler_tree_json() , parser_tree(&evt_handler_tree, parser_options) , parser_tree_json(&evt_handler_tree_json, parser_options) - , evt_handler_ints() - , parser_ints(&evt_handler_ints, parser_options) - , buffer_ints() + , evt_handler_ints_noresize() + , evt_handler_ints_noresize_json() + , evt_handler_ints_resize() + , evt_handler_ints_resize_json() + , parser_ints_noresize(&evt_handler_ints_noresize, parser_options) + , parser_ints_noresize_json(&evt_handler_ints_noresize_json, parser_options) + , parser_ints_resize(&evt_handler_ints_resize, parser_options) + , parser_ints_resize_json(&evt_handler_ints_resize_json, parser_options) + , buffer_ints_noresize() + , buffer_ints_noresize_json() + , ints_resize() + , ints_resize_json() + , evts_test_suite_from_ints_noresize() + , evts_test_suite_from_ints_noresize_json() + , evts_test_suite_from_ints_resize() + , evts_test_suite_from_ints_resize_json() { } - void init(size_t level_, TestSequenceLevel *prev_, csubstr filename_, csubstr src_, bool immutable_, bool reuse_) + void init(size_t level_, TestSequenceLevel *prev_, csubstr filename_, csubstr src_, bool in_arena_, bool reuse_) { level = level_; prev = prev_; filename = filename_; src_tree.assign(src_.begin(), src_.end()); src_orig = src_tree; - src_evts = src_tree; - src_evts_ints = src_tree; - immutable = immutable_; + src_ints_resize = src_tree; + src_ints_noresize = src_tree; + src_ints_noresize_orig = src_tree; + in_arena = in_arena_; reuse = reuse_; tree_was_parsed = false; tree_was_parsed_json = false; tree_was_emitted = false; tree_was_emitted_json = false; - events_were_generated = false; - events_ints_were_generated = false; + ints_were_parsed = false; + ints_were_emitted = false; + ints_were_emitted_json = false; } - void receive_src(TestSequenceLevel & prev_) + // workaround for miscompilation in string assignment op + static void cpstr(std::string &dst, std::string const& src) noexcept + { + dst.resize(src.size()); + if(src.size()) + memcpy(&dst[0], &src[0], src.size()); // NOLINT + }; + + void receive_src_tree(TestSequenceLevel const& prev_) { RYML_ASSERT_BASIC_(&prev_ == prev); - if(!prev_.tree_was_emitted) - { - _nfo_logf("level[{}] not emitted. emit!", prev_.level); - prev_.emit_parsed_tree(); - } + ASSERT_TRUE(prev_.tree_was_parsed); + ASSERT_TRUE(prev_.tree_was_emitted); if(src_tree != prev_.emitted_from_tree_parsed_from_src) { tree_was_parsed = false; tree_was_emitted = false; - events_were_generated = false; - events_ints_were_generated = false; - src_tree = prev_.emitted_from_tree_parsed_from_src; - src_evts = src_tree; - src_evts_ints = src_tree; + cpstr(src_tree, prev_.emitted_from_tree_parsed_from_src); + cpstr(src_orig, prev_.emitted_from_tree_parsed_from_src); } + // check problem with string assignment op + ASSERT_EQ(src_tree, prev_.emitted_from_tree_parsed_from_src); + ASSERT_EQ(src_orig, prev_.emitted_from_tree_parsed_from_src); } - void receive_src_json(TestSequenceLevel & prev_) + void receive_src_tree_json(TestSequenceLevel const& prev_) { RYML_ASSERT_BASIC_(&prev_ == prev); - if(!prev_.tree_was_emitted_json) - { - _nfo_logf("level[{}] not emitted. emit!", prev_.level); - prev_.emit_parsed_tree_json(); - } + ASSERT_TRUE(prev_.tree_was_emitted_json); if(src_tree_json != prev_.emitted_from_tree_parsed_from_src_json) { tree_was_parsed_json = false; @@ -238,26 +288,69 @@ struct TestSequenceLevel } } + void receive_src_ints(TestSequenceLevel const& prev_) + { + RYML_ASSERT_BASIC_(&prev_ == prev); + ASSERT_TRUE(prev_.ints_were_parsed); + ASSERT_TRUE(prev_.ints_were_emitted); + if(src_ints_noresize != prev_.emitted_from_ints_noresize_parsed_from_src + || + src_ints_resize != prev_.emitted_from_ints_resize_parsed_from_src) + { + ints_were_parsed = false; + ints_were_emitted = false; + cpstr(src_ints_resize, prev_.emitted_from_ints_resize_parsed_from_src); + cpstr(src_ints_noresize, prev_.emitted_from_ints_noresize_parsed_from_src); + } + cpstr(src_ints_noresize_orig, prev_.emitted_from_ints_noresize_parsed_from_src); + // check problem with string assignment op + ASSERT_EQ(src_ints_resize, prev_.emitted_from_ints_resize_parsed_from_src); + ASSERT_EQ(src_ints_noresize, prev_.emitted_from_ints_noresize_parsed_from_src); + ASSERT_EQ(src_ints_noresize_orig, prev_.emitted_from_ints_noresize_parsed_from_src); + } + + void receive_src_ints_json(TestSequenceLevel const& prev_) + { + RYML_ASSERT_BASIC_(&prev_ == prev); + ASSERT_TRUE(prev_.ints_were_parsed_json); + ASSERT_TRUE(prev_.ints_were_emitted_json); + if(src_ints_noresize_json != prev_.emitted_from_ints_noresize_parsed_from_src_json + || + src_ints_resize_json != prev_.emitted_from_ints_resize_parsed_from_src_json) + { + ints_were_parsed_json = false; + ints_were_emitted_json = false; + cpstr(src_ints_resize_json, prev_.emitted_from_ints_resize_parsed_from_src_json); + cpstr(src_ints_noresize_json, prev_.emitted_from_ints_noresize_parsed_from_src_json); + } + cpstr(src_ints_noresize_orig_json, prev_.emitted_from_ints_noresize_parsed_from_src_json); + // check problem with string assignment op + ASSERT_EQ(src_ints_resize_json, prev_.emitted_from_ints_resize_parsed_from_src_json); + ASSERT_EQ(src_ints_noresize_json, prev_.emitted_from_ints_noresize_parsed_from_src_json); + ASSERT_EQ(src_ints_noresize_orig_json, prev_.emitted_from_ints_noresize_parsed_from_src_json); + } + void parse_yaml_to_tree() { if(tree_was_parsed) return; if(prev) - receive_src(*prev); + receive_src_tree(*prev); _nfo_logf("level[{}]: parsing source:\n{}", level, src_tree); if(reuse) { tree_parsed_from_src.clear(); + tree_parsed_from_src.clear_arena(); evt_handler_tree.m_stack.m_callbacks = get_callbacks(); tree_parsed_from_src.m_callbacks = get_callbacks(); - if(immutable) + if(in_arena) parse_in_arena(&parser_tree, filename, c4::to_csubstr(src_tree), &tree_parsed_from_src); else parse_in_place(&parser_tree, filename, c4::to_substr(src_tree), &tree_parsed_from_src); } else { - if(immutable) + if(in_arena) tree_parsed_from_src = parse_in_arena(filename, c4::to_csubstr(src_tree), parser_options); else tree_parsed_from_src = parse_in_place(filename, c4::to_substr(src_tree), parser_options); @@ -271,6 +364,7 @@ struct TestSequenceLevel } tree_parsed_from_src.normalize_tags_long(); tree_was_parsed = true; + emit_events_from_tree(&evts_test_suite_from_tree, tree_parsed_from_src); } void parse_json_to_tree() @@ -278,79 +372,155 @@ struct TestSequenceLevel if(tree_was_parsed_json) return; if(prev) - receive_src_json(*prev); + receive_src_tree_json(*prev); _nfo_logf("level[{}]: parsing source:\n{}", level, src_tree); if(reuse) { tree_parsed_from_src_json.clear(); evt_handler_tree_json.m_stack.m_callbacks = get_callbacks(); tree_parsed_from_src_json.m_callbacks = get_callbacks(); - if(immutable) - { + if(in_arena) parse_json_in_arena(&parser_tree_json, filename, c4::to_csubstr(src_tree_json), &tree_parsed_from_src_json); - } else - { parse_json_in_place(&parser_tree_json, filename, c4::to_substr(src_tree_json), &tree_parsed_from_src_json); - } } else { - if(immutable) - { + if(in_arena) tree_parsed_from_src_json = parse_json_in_arena(filename, c4::to_csubstr(src_tree_json), parser_options); - } else - { tree_parsed_from_src_json = parse_json_in_place(filename, c4::to_substr(src_tree_json), parser_options); - } } _nfo_print_tree("PARSED", tree_parsed_from_src_json); ASSERT_FALSE(tree_parsed_from_src_json.empty()); tree_was_parsed_json = true; + emit_events_from_tree(&evts_test_suite_from_tree_json, tree_parsed_from_src_json); } - void parse_yaml_to_events_ints() + void parse_yaml_to_ints() { + if(ints_were_parsed) + return; using I = extra::ievt::evt_bits; - if(events_ints_were_generated) + if(prev) + receive_src_ints(*prev); + ints_were_emitted = false; + { + SCOPED_TRACE("resize"); + _nfo_logf("level[{}]: parsing source to ints [resize]:\n{}", level, src_ints_resize); + evt_handler_ints_resize.m_stack.m_callbacks = get_callbacks(); + evt_handler_ints_resize.reset(to_substr(src_ints_resize), ints_resize.arena, ints_resize.evts.ptr, ints_resize.evts.len); + parser_ints_resize.parse_in_place_ev(filename, to_substr(src_ints_resize)); + ints_resize = evt_handler_ints_resize.get_buffers(); + #ifdef RYML_DBG + extra::ievt::events_ints_print(to_csubstr(src_ints_resize), ints_resize.arena, ints_resize.evts.ptr, ints_resize.evts.len); + #endif + extra::ievt::test_events_ints_invariants(to_csubstr(src_ints_resize), ints_resize.arena, ints_resize.evts.ptr, ints_resize.evts.len); + EXPECT_GT(evt_handler_ints_resize.required_size_events(), 0); + extra::ievt::events_ints_to_testsuite(to_csubstr(src_ints_resize), ints_resize.arena, ints_resize.evts.ptr, ints_resize.evts.len, + &evts_test_suite_from_ints_resize); + } + { + _nfo_logf("level[{}]: parsing source to ints [noresize]:\n{}", level, src_ints_noresize); + SCOPED_TRACE("noresize"); + buffer_ints_noresize.resize(32); + int size_estimated = extra::ievt::estimate_events_size(to_csubstr(src_ints_noresize)); + evt_handler_ints_noresize.m_stack.m_callbacks = get_callbacks(); + evt_handler_ints_noresize.reset(to_substr(src_ints_noresize), to_substr(arena_ints_noresize), buffer_ints_noresize.data(), (I)buffer_ints_noresize.size()); + parser_ints_noresize.parse_in_place_ev(filename, to_substr(src_ints_noresize)); + EXPECT_GE(size_estimated, evt_handler_ints_noresize.required_size_events()); + size_t szi = (size_t)evt_handler_ints_noresize.required_size_events(); + size_t sza = evt_handler_ints_noresize.required_size_arena(); + if (!evt_handler_ints_noresize.fits_buffers()) + { + buffer_ints_noresize.resize(szi); + arena_ints_noresize.resize(sza); + src_ints_noresize = src_ints_noresize_orig; + evt_handler_ints_noresize.reset(to_substr(src_ints_noresize), to_substr(arena_ints_noresize), buffer_ints_noresize.data(), (I)buffer_ints_noresize.size()); + parser_ints_noresize.parse_in_place_ev(filename, to_substr(src_ints_noresize)); + size_t szi2 = (size_t)evt_handler_ints_noresize.required_size_events(); + size_t sza2 = evt_handler_ints_noresize.required_size_arena(); + ASSERT_EQ(szi2, szi); + ASSERT_EQ(sza2, sza); + szi = szi2; + ASSERT_EQ((size_t)evt_handler_ints_noresize.required_size_events(), buffer_ints_noresize.size()); + ASSERT_EQ(evt_handler_ints_noresize.required_size_arena(), arena_ints_noresize.size()); + ASSERT_TRUE(evt_handler_ints_noresize.fits_buffers()); + } + ASSERT_LE(szi, buffer_ints_noresize.size()); + buffer_ints_noresize.resize(szi); + #ifdef RYML_DBG + extra::ievt::events_ints_print(to_csubstr(src_ints_noresize), to_csubstr(arena_ints_noresize), buffer_ints_noresize.data(), (I)szi); + #endif + extra::ievt::test_events_ints_invariants(to_csubstr(src_ints_noresize), to_csubstr(arena_ints_noresize), buffer_ints_noresize.data(), (I)szi); + EXPECT_GT(evt_handler_ints_noresize.required_size_events(), 0); + extra::ievt::events_ints_to_testsuite(to_csubstr(src_ints_noresize), to_csubstr(arena_ints_noresize), buffer_ints_noresize.data(), (I)buffer_ints_noresize.size(), + &evts_test_suite_from_ints_noresize); + } + ints_were_parsed = true; + } + + void parse_json_to_ints() + { + if(ints_were_parsed_json) return; + using I = extra::ievt::evt_bits; if(prev) - receive_src(*prev); - _nfo_logf("level[{}]: parsing source to ints:\n{}", level, src_evts_ints); - buffer_ints.resize(32); - int size_estimated = extra::estimate_events_ints_size(to_csubstr(src_evts_ints)); - evt_handler_ints.m_stack.m_callbacks = get_callbacks(); - evt_handler_ints.reset(to_substr(src_evts_ints), to_substr(arena_evts_ints), buffer_ints.data(), (I)buffer_ints.size()); - parser_ints.parse_in_place_ev(filename, to_substr(src_evts_ints)); - EXPECT_GE(size_estimated, evt_handler_ints.required_size_events()); - size_t sz = (size_t)evt_handler_ints.required_size_events(); - size_t sza = evt_handler_ints.required_size_arena(); - if (!evt_handler_ints.fits_buffers()) + receive_src_ints_json(*prev); + ints_were_emitted_json = false; { - buffer_ints.resize(sz); - arena_evts_ints.resize(sza); - src_evts_ints = src_tree; - evt_handler_ints.reset(to_substr(src_evts_ints), to_substr(arena_evts_ints), buffer_ints.data(), (I)buffer_ints.size()); - parser_ints.parse_in_place_ev(filename, to_substr(src_evts_ints)); - size_t sz2 = (size_t)evt_handler_ints.required_size_events(); - size_t sza2 = evt_handler_ints.required_size_arena(); - ASSERT_EQ(sz2, sz); - ASSERT_EQ(sza2, sza); - sz = sz2; - ASSERT_EQ((size_t)evt_handler_ints.required_size_events(), buffer_ints.size()); - ASSERT_EQ(evt_handler_ints.required_size_arena(), arena_evts_ints.size()); - ASSERT_TRUE(evt_handler_ints.fits_buffers()); + SCOPED_TRACE("resize"); + _nfo_logf("level[{}]: parsing source to ints [resize]:\n{}", level, src_ints_resize); + evt_handler_ints_resize_json.m_stack.m_callbacks = get_callbacks(); + evt_handler_ints_resize_json.reset(to_substr(src_ints_resize_json), ints_resize_json.arena, ints_resize_json.evts.ptr, ints_resize_json.evts.len); + parser_ints_resize_json.parse_json_in_place_ev(filename, to_substr(src_ints_resize_json)); + ints_resize_json = evt_handler_ints_resize_json.get_buffers(); + #ifdef RYML_DBG + extra::ievt::events_ints_print(to_csubstr(src_ints_resize_json), ints_resize_json.arena, ints_resize_json.evts.ptr, ints_resize_json.evts.len); + #endif + extra::ievt::test_events_ints_invariants(to_csubstr(src_ints_resize_json), ints_resize_json.arena, ints_resize_json.evts.ptr, ints_resize_json.evts.len); + EXPECT_GT(evt_handler_ints_resize_json.required_size_events(), 0); + extra::ievt::events_ints_to_testsuite(to_csubstr(src_ints_resize_json), ints_resize_json.arena, ints_resize_json.evts.ptr, ints_resize_json.evts.len, + &evts_test_suite_from_ints_resize_json); } - ASSERT_LE(sz, buffer_ints.size()); - buffer_ints.resize(sz); - #ifdef RYML_DBG - extra::events_ints_print(to_csubstr(src_evts_ints), to_csubstr(arena_evts_ints), buffer_ints.data(), (I)sz); - #endif - extra::test_events_ints_invariants(to_csubstr(src_evts_ints), to_csubstr(arena_evts_ints), buffer_ints.data(), (I)sz); - EXPECT_GT(evt_handler_ints.required_size_events(), 0); - extra::events_ints_to_testsuite(to_csubstr(src_evts_ints), to_csubstr(arena_evts_ints), buffer_ints.data(), (I)buffer_ints.size(), &evts_test_suite_from_ints); - events_ints_were_generated = true; + { + _nfo_logf("level[{}]: parsing source to ints [noresize]:\n{}", level, src_ints_noresize); + SCOPED_TRACE("noresize"); + buffer_ints_noresize_json.resize(32); + int size_estimated = extra::ievt::estimate_events_size(to_csubstr(src_ints_noresize_json)); + evt_handler_ints_noresize_json.m_stack.m_callbacks = get_callbacks(); + evt_handler_ints_noresize_json.reset(to_substr(src_ints_noresize_json), to_substr(arena_ints_noresize_json), buffer_ints_noresize_json.data(), (I)buffer_ints_noresize_json.size()); + parser_ints_noresize_json.parse_json_in_place_ev(filename, to_substr(src_ints_noresize_json)); + EXPECT_GE(size_estimated, evt_handler_ints_noresize_json.required_size_events()); + size_t szi = (size_t)evt_handler_ints_noresize_json.required_size_events(); + size_t sza = evt_handler_ints_noresize_json.required_size_arena(); + if (!evt_handler_ints_noresize_json.fits_buffers()) + { + buffer_ints_noresize_json.resize(szi); + arena_ints_noresize_json.resize(sza); + src_ints_noresize_json = src_ints_noresize_orig_json; + evt_handler_ints_noresize_json.reset(to_substr(src_ints_noresize_json), to_substr(arena_ints_noresize_json), buffer_ints_noresize_json.data(), (I)buffer_ints_noresize_json.size()); + parser_ints_noresize_json.parse_json_in_place_ev(filename, to_substr(src_ints_noresize_json)); + size_t szi2 = (size_t)evt_handler_ints_noresize_json.required_size_events(); + size_t sza2 = evt_handler_ints_noresize_json.required_size_arena(); + ASSERT_EQ(szi2, szi); + ASSERT_EQ(sza2, sza); + szi = szi2; + ASSERT_EQ((size_t)evt_handler_ints_noresize_json.required_size_events(), buffer_ints_noresize_json.size()); + ASSERT_EQ(evt_handler_ints_noresize_json.required_size_arena(), arena_ints_noresize_json.size()); + ASSERT_TRUE(evt_handler_ints_noresize_json.fits_buffers()); + } + ASSERT_LE(szi, buffer_ints_noresize_json.size()); + buffer_ints_noresize_json.resize(szi); + #ifdef RYML_DBG + extra::ievt::events_ints_print(to_csubstr(src_ints_noresize_json), to_csubstr(arena_ints_noresize_json), buffer_ints_noresize_json.data(), (I)szi); + #endif + extra::ievt::test_events_ints_invariants(to_csubstr(src_ints_noresize_json), to_csubstr(arena_ints_noresize_json), buffer_ints_noresize_json.data(), (I)szi); + EXPECT_GT(evt_handler_ints_noresize_json.required_size_events(), 0); + extra::ievt::events_ints_to_testsuite(to_csubstr(src_ints_noresize_json), to_csubstr(arena_ints_noresize_json), buffer_ints_noresize_json.data(), (I)buffer_ints_noresize_json.size(), + &evts_test_suite_from_ints_noresize_json); + } + ints_were_parsed_json = true; } void emit_parsed_tree() @@ -362,18 +532,12 @@ struct TestSequenceLevel _nfo_logf("level[{}] not parsed. parse!", level); parse_yaml_to_tree(); } - if(!tree_was_parsed_json) - { - _nfo_logf("level[{}] json not parsed. parse!", level); - parse_json_to_tree(); - } emitrs_yaml(tree_parsed_from_src, &emitted_from_tree_parsed_from_src); - emitrs_json(tree_parsed_from_src_json, &emitted_from_tree_parsed_from_src_json); csubstr ss = to_csubstr(emitted_from_tree_parsed_from_src); if(ss.ends_with("\n...\n")) emitted_from_tree_parsed_from_src.resize(emitted_from_tree_parsed_from_src.size() - 4); tree_was_emitted = true; - _nfo_logf("EMITTED:\n{}", emitted_from_tree_parsed_from_src); + _nfo_logf("EMITTED[tree]:\n{}", emitted_from_tree_parsed_from_src); } void emit_parsed_tree_json() @@ -387,23 +551,87 @@ struct TestSequenceLevel } emitrs_json(tree_parsed_from_src_json, &emitted_from_tree_parsed_from_src_json); tree_was_emitted_json = true; - _nfo_logf("EMITTED:\n{}", emitted_from_tree_parsed_from_src_json); + _nfo_logf("EMITTED[treejson]:\n{}", emitted_from_tree_parsed_from_src_json); } - void compare_trees(TestSequenceLevel & that) + void emit_ints() { - SCOPED_TRACE("compare trees"); - RYML_ASSERT_BASIC_(&that == prev); - if(!that.tree_was_parsed) + if(ints_were_emitted) + return; + if(!ints_were_parsed) { - _nfo_logf("level[{}] not parsed. parse!", that.level); - that.parse_yaml_to_tree(); + _nfo_logf("level[{}] not parsed. parse!", level); + parse_yaml_to_ints(); } - if(!this->tree_was_parsed) + emit_ints2str(&emitted_from_ints_resize_parsed_from_src, + ints_resize.evts.ptr, ints_resize.evts.len, + to_csubstr(src_ints_resize), + ints_resize.arena, + EMIT_YAML); + emit_ints2str(&emitted_from_ints_noresize_parsed_from_src, + buffer_ints_noresize.data(), (extra::ievt::evt_size)buffer_ints_noresize.size(), + to_csubstr(src_ints_noresize), + to_csubstr(arena_ints_noresize), + EMIT_YAML); + ints_were_emitted = true; + _nfo_logf("EMITTED[resize]:\n{}", emitted_from_ints_resize_parsed_from_src); + _nfo_logf("EMITTED[noresize]:\n{}", emitted_from_ints_noresize_parsed_from_src); + } + + void emit_ints_json() + { + if(ints_were_emitted_json) + return; + if(!ints_were_parsed_json) { _nfo_logf("level[{}] not parsed. parse!", level); - this->parse_yaml_to_tree(); + parse_json_to_ints(); } + emit_ints2str(&emitted_from_ints_resize_parsed_from_src_json, + ints_resize_json.evts.ptr, ints_resize_json.evts.len, + to_csubstr(src_ints_resize_json), + ints_resize_json.arena, + EMIT_JSON); + emit_ints2str(&emitted_from_ints_noresize_parsed_from_src_json, + buffer_ints_noresize_json.data(), (extra::ievt::evt_size)buffer_ints_noresize_json.size(), + to_csubstr(src_ints_noresize_json), + to_csubstr(arena_ints_noresize_json), + EMIT_JSON); + ints_were_emitted_json = true; + _nfo_logf("EMITTED[resize]:\n{}", emitted_from_ints_resize_parsed_from_src_json); + _nfo_logf("EMITTED[noresize]:\n{}", emitted_from_ints_noresize_parsed_from_src_json); + } + + static void emit_ints2str(std::string *s, + extra::ievt::evt_bits const* evts, extra::ievt::evt_size evts_size, + csubstr src, csubstr arena, + EmitType_e ety) + { + ASSERT_FALSE(src.overlaps(to_substr(*s))); + ASSERT_FALSE(arena.overlaps(to_substr(*s))); + auto doit = [&](std::string *ss) -> size_t { + extra::ievt::EmitterInts em(EmitOptions{}, to_substr(*ss)); + em.emit_as(ety, evts, evts_size, src, arena); + return em.m_pos; + }; + size_t needed = doit(s); + bool ok = needed <= s->size(); + s->resize(needed); + if(!ok) + { + size_t needed2 = doit(s); + ASSERT_EQ(needed2, needed); + } + } + + void compare_trees(TestSequenceLevel const& that) + { + SCOPED_TRACE("compare_trees"); + RYML_ASSERT_BASIC_(&that == prev); + ASSERT_TRUE(that.tree_was_parsed); + ASSERT_TRUE(that.tree_was_emitted); + ASSERT_TRUE(this->tree_was_parsed); + ASSERT_TRUE(this->tree_was_emitted); _nfo_print_tree("PREV_", that.tree_parsed_from_src); _nfo_print_tree("CURR", tree_parsed_from_src); EXPECT_FALSE(that.tree_parsed_from_src_json.empty()); @@ -411,20 +639,14 @@ struct TestSequenceLevel test_compare(that.tree_parsed_from_src, tree_parsed_from_src); } - void compare_trees_json(TestSequenceLevel & that) + void compare_trees_json(TestSequenceLevel const& that) { - SCOPED_TRACE("compare trees"); + SCOPED_TRACE("compare_trees_json"); RYML_ASSERT_BASIC_(&that == prev); - if(!that.tree_was_parsed_json) - { - _nfo_logf("level[{}] not parsed. parse!", that.level); - that.parse_json_to_tree(); - } - if(!this->tree_was_parsed_json) - { - _nfo_logf("level[{}] not parsed. parse!", level); - this->parse_json_to_tree(); - } + ASSERT_TRUE(that.tree_was_parsed_json); + ASSERT_TRUE(that.tree_was_emitted_json); + ASSERT_TRUE(this->tree_was_parsed_json); + ASSERT_TRUE(this->tree_was_emitted_json); _nfo_print_tree("PREV_", that.tree_parsed_from_src_json); _nfo_print_tree("CURR", tree_parsed_from_src_json); EXPECT_FALSE(that.tree_parsed_from_src_json.empty()); @@ -432,25 +654,19 @@ struct TestSequenceLevel test_compare(that.tree_parsed_from_src_json, tree_parsed_from_src_json); } - void compare_emitted_yaml(TestSequenceLevel & that) + void compare_emitted_yaml(TestSequenceLevel const& that) { - SCOPED_TRACE("compare emitted"); + SCOPED_TRACE("compare_emitted_yaml"); RYML_ASSERT_BASIC_(&that == prev); - if(!that.tree_was_emitted) - { - _nfo_logf("level[{}] not emitted. emit!", that.level); - that.emit_parsed_tree(); - } - if(!this->tree_was_emitted) - { - _nfo_logf("level[{}] not emitted. emit!", level); - this->emit_parsed_tree(); - } + ASSERT_TRUE(that.tree_was_parsed); + ASSERT_TRUE(that.tree_was_emitted); + ASSERT_TRUE(this->tree_was_parsed); + ASSERT_TRUE(this->tree_was_emitted); _nfo_logf("level[{}]: EMITTED:\n{}", that.level, that.emitted_from_tree_parsed_from_src); _nfo_logf("level[{}]: EMITTED:\n{}", level, emitted_from_tree_parsed_from_src); + // workaround for lack of idempotency in tag normalization. if(this->emitted_from_tree_parsed_from_src != that.emitted_from_tree_parsed_from_src) { - // workaround for lack of idempotency in tag normalization. Tree from_prev = parse_in_arena(to_csubstr(that.emitted_from_tree_parsed_from_src), parser_options); Tree from_this = parse_in_arena(to_csubstr(emitted_from_tree_parsed_from_src), parser_options); TagCache tag_cache; @@ -460,20 +676,14 @@ struct TestSequenceLevel } } - void compare_emitted_json(TestSequenceLevel & that) + void compare_emitted_json(TestSequenceLevel const& that) { SCOPED_TRACE("compare emitted"); RYML_ASSERT_BASIC_(&that == prev); - if(!that.tree_was_emitted_json) - { - _nfo_logf("level[{}] not emitted. emit!", that.level); - that.emit_parsed_tree_json(); - } - if(!this->tree_was_emitted_json) - { - _nfo_logf("level[{}] not emitted. emit!", level); - this->emit_parsed_tree_json(); - } + ASSERT_TRUE(that.tree_was_parsed_json); + ASSERT_TRUE(that.tree_was_emitted_json); + ASSERT_TRUE(this->tree_was_parsed_json); + ASSERT_TRUE(this->tree_was_emitted_json); _nfo_logf("level[{}]: EMITTED:\n{}", that.level, that.emitted_from_tree_parsed_from_src_json); _nfo_logf("level[{}]: EMITTED:\n{}", level, emitted_from_tree_parsed_from_src_json); if(this->emitted_from_tree_parsed_from_src_json != that.emitted_from_tree_parsed_from_src_json) @@ -495,6 +705,15 @@ struct TestSequenceLevel c4::log("{}:\n{}{}{}", context, sep, v, sep); #endif } + + void print_src_and_tree() const + { + printf("src_orig:\n~~~\n%s~~~\n", src_orig.c_str()); + if(tree_was_parsed) + print_tree(tree_parsed_from_src); + if(tree_was_emitted) + printf("emitted:\n~~~\n%s~~~\n", emitted_from_tree_parsed_from_src.c_str()); + } }; @@ -537,6 +756,8 @@ struct TestSequenceData { if(!has_container_keys && !expect_error) { + if(i) + levels[i-1].emit_parsed_tree(); levels[i].parse_yaml_to_tree(); } else @@ -548,7 +769,6 @@ struct TestSequenceData } } } - void parse_json_to_tree(size_t num) { SKIP_IF(allowed_failure); @@ -556,6 +776,8 @@ struct TestSequenceData { if(!has_container_keys && !expect_error) { + if(i) + levels[i-1].emit_parsed_tree_json(); levels[i].parse_json_to_tree(); } else @@ -568,7 +790,7 @@ struct TestSequenceData } } - void parse_yaml_to_events_ints(size_t num) + void parse_yaml_to_ints(size_t num) { SKIP_IF(allowed_failure); //SKIP_IF(has_container_keys); // DO IT! @@ -576,20 +798,66 @@ struct TestSequenceData { if(!expect_error) { - levels[i].parse_yaml_to_events_ints(); - if(has_container_keys) - break; + if(i) + levels[i-1].emit_ints(); + levels[i].parse_yaml_to_ints(); + } + else + { + ExpectError::check_error_parse([&]{ + levels[i].parse_yaml_to_ints(); + }); + break; // because we expect error,we cannot go on to the next + } + } + } + + void parse_json_to_ints(size_t num) + { + SKIP_IF(allowed_failure); + //SKIP_IF(has_container_keys); // DO IT! + for(size_t i = 0; i < num; ++i) + { + if(!expect_error) + { + if(i) + levels[i-1].emit_ints_json(); + levels[i].parse_json_to_ints(); } else { ExpectError::check_error_parse([&]{ - levels[i].parse_yaml_to_events_ints(); + levels[i].parse_json_to_ints(); }); break; // because we expect error,we cannot go on to the next } } } + void emit_ints_parsed_from_src(size_t num) + { + SKIP_IF(allowed_failure); + for(size_t i = 0; i < num; ++i) + { + if(!levels[i].ints_were_parsed) + levels[i].parse_yaml_to_ints(); + if(!levels[i].ints_were_emitted) + levels[i].emit_ints(); + } + } + + void emit_ints_parsed_from_src_json(size_t num) + { + SKIP_IF(allowed_failure); + for(size_t i = 0; i < num; ++i) + { + if(!levels[i].ints_were_parsed_json) + levels[i].parse_json_to_ints(); + if(!levels[i].ints_were_emitted_json) + levels[i].emit_ints_json(); + } + } + void emit_tree_parsed_from_src(size_t num) { SKIP_IF(allowed_failure); @@ -598,9 +866,8 @@ struct TestSequenceData { if(!levels[i].tree_was_parsed) levels[i].parse_yaml_to_tree(); - levels[i].emit_parsed_tree(); - if(i + 1 < num) - levels[i+1].receive_src(levels[i]); + if(!levels[i].tree_was_emitted) + levels[i].emit_parsed_tree(); } } @@ -610,11 +877,9 @@ struct TestSequenceData SKIP_IF(has_container_keys); for(size_t i = 0; i < num; ++i) { - if(!levels[i].tree_was_parsed) + if(!levels[i].tree_was_parsed_json) levels[i].parse_json_to_tree(); levels[i].emit_parsed_tree_json(); - if(i + 1 < num) - levels[i+1].receive_src_json(levels[i]); } } @@ -622,8 +887,22 @@ struct TestSequenceData { SKIP_IF(allowed_failure); SKIP_IF(has_container_keys); + emit_tree_parsed_from_src(num); for(size_t i = 1; i < num; ++i) + { + RYML_TRACE_FMT("compare_level_trees: {} vs {}", i, i-1); levels[i].compare_trees(levels[i-1]); + if(testing::Test::HasFailure()) + { + for(size_t j = 0; j <= i; ++j) + { + printf("level[%zu]:\n", j); + levels[j].print_src_and_tree(); + printf("(endlevel[%zu])\n", j); + } + break; + } + } } void compare_level_trees_json(size_t num) { @@ -693,33 +972,67 @@ struct TestSequenceData parse_yaml_to_tree(1); events->compare_event_tree_to_src_tree(src(), levels[0].tree_parsed_from_src); } - void compare_emitted_events_str(size_t num, TestSuiteCaseEvents *events) + + void compare_emitted_events_tree_str(size_t num, TestSuiteCaseEvents *events) { SKIP_IF(allowed_failure); SKIP_IF(has_container_keys); + SCOPED_TRACE("compare_emitted_events_tree_str"); events->parse_events(src()); parse_yaml_to_tree(num); for(size_t i = 0; i < num; ++i) { - levels[i].parse_yaml_to_events_ints(); - events->compare_events(to_csubstr(levels[i].evts_test_suite_from_ints), + RYML_TRACE_FMT("level={}", i); + ASSERT_TRUE(levels[i].tree_was_parsed); + events->compare_events(to_csubstr(levels[i].evts_test_suite_from_tree), /*ignore_container_style*/false, /*ignore_scalar_style*/(num>0)); } } - void compare_events_ints_str(size_t num, TestSuiteCaseEvents *events) + void compare_emitted_events_ints_str(size_t num, TestSuiteCaseEvents *events) { - ASSERT_EQ(num, 1); // FIXME SKIP_IF(allowed_failure); - parse_yaml_to_events_ints(1); - events->compare_events(to_csubstr(levels[0].evts_test_suite_from_ints), - /*ignore_container_style*/false, - /*ignore_scalar_style*/false); + SCOPED_TRACE("compare_emitted_events_ints_str"); + ASSERT_FALSE(events->reference_events.empty()); + parse_yaml_to_ints(num); + for(size_t i = 0; i < num; ++i) + { + RYML_TRACE_FMT("level={}", i); + ASSERT_TRUE(levels[i].ints_were_parsed); + { + SCOPED_TRACE("resize"); + events->compare_events(to_csubstr(levels[i].evts_test_suite_from_ints_resize), + /*ignore_container_style*/false, + /*ignore_scalar_style*/(num>0)); + if(testing::Test::HasFailure()) + { + extra::ievt::events_ints_print(to_csubstr(levels[i].src_ints_resize), + levels[i].ints_resize.arena, + levels[i].ints_resize.evts.ptr, + levels[i].ints_resize.evts.len); + break; + } + } + { + SCOPED_TRACE("noresize"); + events->compare_events(to_csubstr(levels[i].evts_test_suite_from_ints_noresize), + /*ignore_container_style*/false, + /*ignore_scalar_style*/(num>0)); + if(testing::Test::HasFailure()) + { + extra::ievt::events_ints_print(to_csubstr(levels[i].src_ints_noresize), + to_csubstr(levels[i].arena_ints_noresize), + levels[i].buffer_ints_noresize.data(), + (int)levels[i].buffer_ints_noresize.size()); + break; + } + } + } } bool m_expected_error_to_tree_checked = false; + bool m_expected_error_to_ints_checked = false; bool m_expected_error_to_events_checked = false; - bool m_expected_error_to_events_ints_checked = false; void check_expected_error() { SKIP_IF(allowed_failure); @@ -736,13 +1049,13 @@ struct TestSequenceData { SKIP_IF(allowed_failure); //SKIP_IF(has_container_keys); // DO IT! - if(m_expected_error_to_events_ints_checked) + if(m_expected_error_to_ints_checked) return; SCOPED_TRACE("check_expected_error_events"); ExpectError::check_error_parse([this]{ - levels[0].parse_yaml_to_events_ints(); + levels[0].parse_yaml_to_ints(); }); - m_expected_error_to_events_ints_checked = true; + m_expected_error_to_ints_checked = true; } }; @@ -885,19 +1198,6 @@ TEST(which##_errors, check_expected_error_src_to_events_ints) \ \ /*-----------------------------------------------*/ \ \ -TEST(which##_events_ints_from_src, parse_yaml_to_events_ints) \ -{ \ - g_suite_case->which.parse_yaml_to_events_ints(1); \ -} \ - \ -TEST(which##_events_ints_from_src, compare_events_ints_to_ref_events) \ -{ \ - g_suite_case->which.compare_events_ints_str(1, &g_suite_case->events); \ -} \ - \ - \ -/*-----------------------------------------------*/ \ - \ TEST(which##_events_from_tree, compare_actual_tree_to_events_tree) \ { \ SKIP_IF(g_suite_case->test_case_expects_error); \ @@ -917,13 +1217,18 @@ struct which : public ::testing::TestWithParam \ { \ }; \ \ -TEST_P(which, 0_parse_yaml_to_events_ints) \ +TEST_P(which, 0_parse_yaml_to_ints) \ { \ /*ALWAYS COMPARE.~SKIP_IF(g_suite_case->test_case_expects_error);*/ \ RYML_CHECK_BASIC_(GetParam() < NLEVELS); \ - g_suite_case->which.parse_yaml_to_events_ints(1 + GetParam()); \ + g_suite_case->which.parse_yaml_to_ints(1 + GetParam()); \ +} \ +TEST_P(which, 0_parse_json_to_ints) \ +{ \ + SKIP_IF( ! g_suite_case->test_case_is_json); \ + RYML_CHECK_BASIC_(GetParam() < NLEVELS); \ + g_suite_case->which.parse_json_to_ints(1 + GetParam()); \ } \ - \ TEST_P(which, 0_parse_yaml_to_tree) \ { \ SKIP_IF(g_suite_case->test_case_expects_error); \ @@ -938,13 +1243,34 @@ TEST_P(which, 0_parse_json_to_tree) \ g_suite_case->which.parse_json_to_tree(1 + GetParam()); \ } \ \ -TEST_P(which, 1_compare_emitted_events_to_ref_events) \ + \ +TEST_P(which, 1_compare_emitted_events_tree_to_ref_events) \ +{ \ + /*ALWAYS COMPARE.~SKIP_IF(g_suite_case->test_case_expects_error);*/ \ + SKIP_IF(g_suite_case->test_case_is_json); \ + RYML_CHECK_BASIC_(GetParam() < NLEVELS); \ + g_suite_case->which.compare_emitted_events_tree_str(1 + GetParam(), &g_suite_case->events); \ +} \ +TEST_P(which, 1_compare_emitted_events_ints_to_ref_events) \ { \ + SKIP_IF(g_suite_case->test_case_is_json); \ /*ALWAYS COMPARE.~SKIP_IF(g_suite_case->test_case_expects_error);*/ \ RYML_CHECK_BASIC_(GetParam() < NLEVELS); \ - g_suite_case->which.compare_emitted_events_str(1 + GetParam(), &g_suite_case->events); \ + g_suite_case->which.compare_emitted_events_ints_str(1 + GetParam(), &g_suite_case->events); \ } \ \ + \ +TEST_P(which, 2_emit_ints_parsed_from_src) \ +{ \ + RYML_CHECK_BASIC_(GetParam() < NLEVELS); \ + g_suite_case->which.emit_ints_parsed_from_src(1 + GetParam()); \ +} \ +TEST_P(which, 2_emit_ints_parsed_from_src_json) \ +{ \ + RYML_CHECK_BASIC_(GetParam() < NLEVELS); \ + SKIP_IF( ! g_suite_case->test_case_is_json); \ + g_suite_case->which.emit_ints_parsed_from_src_json(1 + GetParam()); \ +} \ TEST_P(which, 2_emit_tree_parsed_from_src) \ { \ SKIP_IF(g_suite_case->test_case_expects_error); \ @@ -953,8 +1279,8 @@ TEST_P(which, 2_emit_tree_parsed_from_src) \ } \ TEST_P(which, 2_emit_tree_parsed_from_src_json) \ { \ - SKIP_IF( ! g_suite_case->test_case_is_json); \ SKIP_IF(g_suite_case->test_case_expects_error); \ + SKIP_IF( ! g_suite_case->test_case_is_json); \ RYML_CHECK_BASIC_(GetParam() < NLEVELS); \ g_suite_case->which.emit_tree_parsed_from_src_json(1 + GetParam()); \ } \ @@ -979,7 +1305,7 @@ TEST_P(which, 4_compare_emitted_yaml) \ RYML_CHECK_BASIC_(GetParam() < NLEVELS); \ g_suite_case->which.compare_level_emitted(1 + GetParam()); \ } \ -TEST_P(which, 4_compare_emitted_yaml_json) \ +TEST_P(which, 4_compare_emitted_json) \ { \ SKIP_IF( ! g_suite_case->test_case_is_json); \ SKIP_IF(g_suite_case->test_case_expects_error); \ diff --git a/test/testsuite/testsuite_events.cpp b/test/testsuite/testsuite_events.cpp index f0dd45e0e..aded36181 100644 --- a/test/testsuite/testsuite_events.cpp +++ b/test/testsuite/testsuite_events.cpp @@ -1,6 +1,7 @@ #include "testsuite_events.hpp" #include "testsuite_common.hpp" -#include "test_lib/test_engine.hpp" +#include "test_lib/test_compare_events.hpp" + #ifdef RYML_SINGLE_HEADER #include #else @@ -94,7 +95,7 @@ struct Scalar OptionalScalar ref = {}; OptionalScalar tag = {}; NodeType flags = {}; - inline operator bool() const { if(anchor || tag) { RYML_ASSERT_BASIC_(scalar); } return scalar.was_set; } + operator bool() const { if(anchor || tag) { RYML_ASSERT_BASIC_(scalar); } return scalar.was_set; } void add_key_props(Tree *tree, id_type node) const { if(ref) @@ -563,6 +564,5 @@ void parse_events_to_tree(csubstr src, Tree *C4_RESTRICT tree_) } } - } // namespace yml } // namespace c4 diff --git a/tools/amalgamate.py b/tools/amalgamate.py index 94f486644..f55b8ce02 100644 --- a/tools/amalgamate.py +++ b/tools/amalgamate.py @@ -298,18 +298,22 @@ def has(*which): "src/c4/yml/file.hpp", "src/c4/yml/tag.hpp", am.onlyif(has(Event.tree), "src/c4/yml/resolve_options.hpp"), - am.onlyif(has(Event.tree), "src/c4/yml/scalar_charconv.hpp"), + "src/c4/yml/scalar_charconv.hpp", am.onlyif(has(Event.tree), "src/c4/yml/tree.hpp"), am.onlyif(has(Event.tree), "src/c4/yml/node.hpp"), - am.onlyif(has(Event.tree), "src/c4/yml/writer_buf.hpp"), - am.onlyif(has(Event.tree), "src/c4/yml/writer_file.hpp"), - am.onlyif(has(Event.tree), "src/c4/yml/writer_ostream.hpp"), - am.onlyif(has(Event.tree), "src/c4/yml/writer.hpp"), + am.onlyif(has(Event.ints), "src_extra/c4/yml/extra/event_ints.hpp"), + "src/c4/yml/writer_buf.hpp", + "src/c4/yml/writer_file.hpp", + "src/c4/yml/writer_ostream.hpp", + "src/c4/yml/writer.hpp", "src/c4/yml/detail/dbgprint.hpp", - am.onlyif(has(Event.tree), "src/c4/yml/emit_options.hpp"), - am.onlyif(has(Event.tree), "src/c4/yml/scalar_style.hpp"), + "src/c4/yml/detail/emit_scalar.hpp", + "src/c4/yml/emit_options.hpp", + "src/c4/yml/scalar_style.hpp", am.onlyif(has(Event.tree), "src/c4/yml/emitter.hpp"), am.onlyif(has(Event.tree), "src/c4/yml/emitter.def.hpp"), + am.onlyif(has(Event.ints), "src_extra/c4/yml/extra/emitter_ints.hpp"), + am.onlyif(has(Event.ints), "src_extra/c4/yml/extra/emitter_ints.def.hpp"), am.onlyif(has(Event.tree), "src/c4/yml/emit_buf.hpp"), am.onlyif(has(Event.tree), "src/c4/yml/emit_container.hpp"), am.onlyif(has(Event.tree), "src/c4/yml/emit_file.hpp"), @@ -341,13 +345,13 @@ def has(*which): "src/c4/yml/node_type.cpp", "src/c4/yml/tag.cpp", am.onlyif(not with_engine_def_on_hdr, "src/c4/yml/parse_engine.def.hpp"), - am.onlyif(has(Event.ints), "src_extra/c4/yml/extra/event_handler_ints.cpp"), + am.onlyif(has(Event.ints), "src_extra/c4/yml/extra/event_ints.cpp"), am.onlyif(has(Event.ints_utils), "src_extra/c4/yml/extra/ints_utils.cpp"), am.onlyif(has(Event.ints_to_testsuite), "src_extra/c4/yml/extra/ints_to_testsuite.cpp"), am.onlyif(has(Event.tree), "src/c4/yml/tree.cpp"), am.onlyif(has(Event.tree), "src/c4/yml/reference_resolver.cpp"), am.onlyif(has(Event.tree), "src/c4/yml/parse.cpp"), - am.onlyif(has(Event.tree), "src/c4/yml/scalar_style.cpp"), + "src/c4/yml/scalar_style.cpp", am.onlyif(has(Event.tree), "src/c4/yml/emit_buf.cpp"), am.onlyif(has(Event.tree), "src/c4/yml/emit_file.cpp"), ] diff --git a/tools/parse_emit.cpp b/tools/parse_emit.cpp index 8bfdab7fb..e51808708 100644 --- a/tools/parse_emit.cpp +++ b/tools/parse_emit.cpp @@ -361,15 +361,13 @@ void process_file_tree(Args const& args, ParserOptions opts, substr contents) } -void process_file_ints(Args const& args, ParserOptions opts, csubstr contents) +void process_file_ints(Args const& args, ParserOptions opts, substr contents) { TS(process_file_ints); - using evt_type = extra::ievt::evt_bits; - extra::EventHandlerInts handler; - ParseEngine parser(&handler, opts); - std::vector events; - std::vector src; - std::vector arena; + using handler_type = extra::ievt::EventHandlerInts; + handler_type handler; + ParseEngine parser(&handler, opts); + handler.reset(contents); if(args.reserve_size) { TSB(reserve, contents.len); @@ -377,46 +375,26 @@ void process_file_ints(Args const& args, ParserOptions opts, csubstr contents) if(args.reserve_size == 1) { TSB(estimate_size, contents.len); - cap = (id_type)extra::estimate_events_ints_size(to_csubstr(contents)); + cap = (id_type)extra::ievt::estimate_events_size(to_csubstr(contents)); } - events.reserve(cap); - arena.resize(contents.len); + handler.reserve_evts((extra::ievt::evt_size)cap); + handler.reserve_arena(contents.len); if(args.timed_sections) fprintf(stderr, "reserving capacity=%zu\n", (size_t)cap); // NOLINT } - again: - { - TS(reset); - { - TSB(copy_src, contents.len); - src.assign(contents.begin(), contents.end()); - } - { - TS(handler); - handler.reset(to_substr(src), to_substr(arena), events.data(), (evt_type)events.size()); - } - } - { - TSB(parse_yml, contents.len); - parser.parse_in_place_ev(args.filename, to_substr(src)); - } - events.resize((size_t)handler.required_size_events()); - if(!handler.fits_buffers()) - { - arena.resize(handler.required_size_arena()); - goto again; // NOLINT - } + parser.parse_in_place_ev(args.filename, contents); + extra::ievt::Buffers buf = handler.get_buffers(); if(!args.quiet && !args.testsuite) { TSB(print_events, contents.len); - extra::events_ints_print(to_csubstr(src), to_csubstr(arena), events.data(), (evt_type)events.size()); + extra::ievt::events_ints_print(buf.src, buf.arena, buf.evts.ptr, buf.evts.len); } if(args.testsuite) { std::vector tsevts; { TSB(tsevts, contents.len); - extra::events_ints_to_testsuite(to_csubstr(src), to_substr(arena), events.data(), (evt_type)events.size(), &tsevts); + extra::ievt::events_ints_to_testsuite(buf.src, buf.arena, buf.evts.ptr, buf.evts.len, &tsevts); } if(!args.quiet) {