diff --git a/src/c4/yml/parse_engine.def.hpp b/src/c4/yml/parse_engine.def.hpp index 0889abe5..2aebaa3c 100644 --- a/src/c4/yml/parse_engine.def.hpp +++ b/src/c4/yml/parse_engine.def.hpp @@ -3550,29 +3550,51 @@ csubstr ParseEngine::_filter_scalar_dquot(substr s) //----------------------------------------------------------------------------- + +template +csubstr ParseEngine::_move_scalar_left_and_add_newline(substr s) +{ + if(s.is_sub(m_buf)) + { + _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, s.str > m_buf.str); + _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, s.str-1 >= m_buf.str); + if(s.len) + memmove(s.str - 1, s.str, s.len); + --s.str; + s.str[s.len] = '\n'; + ++s.len; + return s; + } + else + { + substr dst = m_evt_handler->alloc_arena(s.len + 1); + if(s.len) + memcpy(dst.str, s.str, s.len); + dst[s.len] = '\n'; + return dst; + } +} + template csubstr ParseEngine::_filter_scalar_literal(substr s, size_t indentation, BlockChomp_e chomp) { _c4dbgpf("filtering block literal scalar: s=[{}]~~~{}~~~", s.len, s); FilterResult r = this->filter_scalar_block_literal_in_place(s, s.len, indentation, chomp); + csubstr result; if(C4_LIKELY(r.valid())) { - _c4dbgpf("filtering block literal scalar: success! s=[{}]~~~{}~~~", r.get().len, r.get()); - return r.get(); + result = r.get(); } else { _c4dbgpf("filtering block literal scalar: not enough space: needs {}, have {}", r.required_len(), s.len); - substr dst = m_evt_handler->alloc_arena(r.required_len(), &s); - if(dst.str) - { - FilterResult rsd = this->filter_scalar_block_literal(s, dst, indentation, chomp); - _RYML_CB_CHECK(m_evt_handler->m_stack.m_callbacks, rsd.valid()); - _c4dbgpf("filtering block literal scalar: success! s=[{}]~~~{}~~~", rsd.get().len, rsd.get()); - return rsd.get(); - } - return dst; + _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, r.required_len() == s.len + 1); + // this can only happen when adding a single newline in clip mode. + // so we shift left the scalar by one place + result = _move_scalar_left_and_add_newline(s); } + _c4dbgpf("filtering block literal scalar: success! s=[{}]~~~{}~~~", result.len, result); + return result; } @@ -3582,24 +3604,21 @@ csubstr ParseEngine::_filter_scalar_folded(substr s, size_t indent { _c4dbgpf("filtering block folded scalar: s=[{}]~~~{}~~~", s.len, s); FilterResult r = this->filter_scalar_block_folded_in_place(s, s.len, indentation, chomp); + csubstr result; if(C4_LIKELY(r.valid())) { - _c4dbgpf("filtering block folded scalar: success! s=[{}]~~~{}~~~", r.get().len, r.get()); - return r.get(); + result = r.get(); } else { _c4dbgpf("filtering block folded scalar: not enough space: needs {}, have {}", r.required_len(), s.len); - substr dst = m_evt_handler->alloc_arena(r.required_len(), &s); - if(dst.str) - { - FilterResult rsd = this->filter_scalar_block_folded(s, dst, indentation, chomp); - _RYML_CB_CHECK(m_evt_handler->m_stack.m_callbacks, rsd.valid()); - _c4dbgpf("filtering block folded scalar: success! s=[{}]~~~{}~~~", rsd.get().len, rsd.get()); - return rsd.get(); - } - return dst; + _RYML_CB_ASSERT(m_evt_handler->m_stack.m_callbacks, r.required_len() == s.len + 1); + // this can only happen when adding a single newline in clip mode. + // so we shift left the scalar by one place + result = _move_scalar_left_and_add_newline(s); } + _c4dbgpf("filtering block folded scalar: success! s=[{}]~~~{}~~~", result.len, result); + return result; } diff --git a/src/c4/yml/parse_engine.hpp b/src/c4/yml/parse_engine.hpp index 16af3621..656b87ea 100644 --- a/src/c4/yml/parse_engine.hpp +++ b/src/c4/yml/parse_engine.hpp @@ -536,6 +536,7 @@ public: // exposed for testing csubstr _filter_scalar_dquot(substr s); csubstr _filter_scalar_literal(substr s, size_t indentation, BlockChomp_e chomp); csubstr _filter_scalar_folded(substr s, size_t indentation, BlockChomp_e chomp); + csubstr _move_scalar_left_and_add_newline(substr s); csubstr _maybe_filter_key_scalar_plain(ScannedScalar const& sc, size_t indendation); csubstr _maybe_filter_val_scalar_plain(ScannedScalar const& sc, size_t indendation); diff --git a/test/test_extra_ints.cpp b/test/test_extra_ints.cpp index 5f7f9036..8968a0f4 100644 --- a/test/test_extra_ints.cpp +++ b/test/test_extra_ints.cpp @@ -541,7 +541,10 @@ const IntEventsCase test_cases[] = { { e(BSTR), e(BDOC), - e(VAL_|SCLR|LITL|AREN, 0, 4, "abc\n"), // result has additional newline + // instead of this (in the arena): + //e(VAL_|SCLR|LITL|AREN, 0, 4, "abc\n"), // result has additional newline + // we get this (shifted left by 1, in the source code) + e(VAL_|SCLR|LITL, 1, 4, "abc\n"), // result has additional newline e(EDOC|PSTR), e(ESTR), }), @@ -553,7 +556,10 @@ const IntEventsCase test_cases[] = { { e(BSTR), e(BDOC), - e(VAL_|SCLR|FOLD|AREN, 0, 4, "abc\n"), // result has additional newline + // instead of this (in the arena): + //e(VAL_|SCLR|FOLD|AREN, 0, 4, "abc\n"), // result has additional newline + // we get this (shifted left by 1, in the source code) + e(VAL_|SCLR|FOLD, 1, 4, "abc\n"), // result has additional newline e(EDOC|PSTR), e(ESTR), }),