diff --git a/test/test_lib/test_engine.cpp b/test/test_lib/test_engine.cpp index 5992f4ae..f2870ee2 100644 --- a/test/test_lib/test_engine.cpp +++ b/test/test_lib/test_engine.cpp @@ -72,8 +72,8 @@ void test_new_parser_events_from_yaml(ReferenceYaml const& yaml, std::string con ParseEngine parser(&handler); std::string copy = yaml.parsed; parser.parse_in_place_ev("(testyaml)", to_substr(copy)); - csubstr result = sink.get(); - _c4dbgpf("~~~\n{}~~~\n", sink.get()); + csubstr result = sink; + _c4dbgpf("~~~\n{}~~~\n", result); EXPECT_EQ(std::string(result.str, result.len), expected_events); } diff --git a/test/test_lib/test_engine.hpp b/test/test_lib/test_engine.hpp index e5118775..882ba166 100644 --- a/test/test_lib/test_engine.hpp +++ b/test/test_lib/test_engine.hpp @@ -42,7 +42,7 @@ C4_NO_INLINE void test_new_parser_str_from_events(std::string const& expected_ev handler.reset(); EventProducerFn event_producer; event_producer(handler); - csubstr result = sink.get(); + csubstr result = sink; _c4dbgpf("~~~\n{}~~~\n", result); EXPECT_EQ(std::string(result.str, result.len), expected_events); } diff --git a/test/test_suite.cpp b/test/test_suite.cpp index dbb917da..194998e8 100644 --- a/test/test_suite.cpp +++ b/test/test_suite.cpp @@ -299,11 +299,11 @@ struct TestSequenceLevel if(prev) receive_src(*prev); _nfo_logf("level[{}]: parsing source:\n{}", level, src_evts); - evt_str_sink.reset(); + evt_str_sink.clear(); evt_handler_str_sink.reset(); evt_handler_str_sink.m_stack.m_callbacks = get_callbacks(); parser_str_sink.parse_in_place_ev(filename, to_substr(src_evts)); - EXPECT_FALSE(evt_str_sink.get().empty()); + EXPECT_NE(evt_str_sink.size(), 0); events_were_generated = true; } @@ -655,7 +655,7 @@ struct TestSequenceData for(size_t i = 0; i < num; ++i) { levels[i].parse_yaml_to_events(); - csubstr result = levels[i].evt_str_sink.get(); + csubstr result = levels[i].evt_str_sink; events->compare_emitted_events_to_reference_events(std::string(result.str, result.len), /*ignore_container_style*/false, /*ignore_scalar_style*/(num>0)); diff --git a/test/test_suite/string.hpp b/test/test_suite/string.hpp new file mode 100644 index 00000000..4ef1b870 --- /dev/null +++ b/test/test_suite/string.hpp @@ -0,0 +1,426 @@ +#ifndef _C4_YML_EXTRA_STRING_HPP_ +#define _C4_YML_EXTRA_STRING_HPP_ + +#ifdef RYML_SINGLE_HEADER +#ifndef _RYML_SINGLE_HEADER_AMALGAMATED_HPP_ +#include +#endif +#else +#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). using this instead of std::string spares the + * dependency on the standard library. */ +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: + + 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); + 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(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(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(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(m_str != nullptr); // this structure cannot be memset() to zero + if(m_str != m_buf) + { + _RYML_CB_FREE(get_callbacks(), m_str, string, (size_t)m_capacity); + m_str = m_buf; + m_size = 0; + m_capacity = sso_size; + } + else + { + RYML_ASSERT(m_capacity == sso_size); + } + } + + void _cp(string const* C4_RESTRICT that) + { + #ifdef RYML_DBG + if(that->m_str != that->m_buf) + { + RYML_ASSERT(that->m_capacity > sso_size); + RYML_ASSERT(that->m_size <= that->m_capacity); + } + else + { + RYML_ASSERT(that->m_capacity <= sso_size); + RYML_ASSERT(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(that->m_capacity > sso_size); + RYML_ASSERT(that->m_size <= that->m_capacity); + m_str = that->m_str; + } + else + { + RYML_ASSERT(that->m_capacity <= sso_size); + RYML_ASSERT(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(that->m_str != m_buf); + that->m_str = that->m_buf; + that->m_capacity = sso_size; + that->m_size = 0; + } +}; + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +/** a string class used by the event handler. using this instead of + * std::string spares the dependency on the standard library. */ +struct string_vector +{ + enum : id_type { sso_size = RYML_STRING_LIST_SSO_SIZE }; + string m_buf[sso_size]; + string *C4_RESTRICT m_arr; + id_type m_size; + id_type m_capacity; + +public: + + string_vector() + : m_buf() + , 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(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; + } + else + { + RYML_ASSERT(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(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(m_size <= m_capacity); + RYML_ASSERT(i < m_size); + return m_arr[i]; + } + string const& operator[] (id_type i) const + { + RYML_ASSERT(m_size <= m_capacity); + RYML_ASSERT(i < m_size); + return m_arr[i]; + } +}; + +} // namespace extra +} // namespace yml +} // namespace c4 + +C4_SUPPRESS_WARNING_GCC_POP + +#endif /* _C4_YML_EXTRA_STRING_HPP_ */ diff --git a/test/test_suite/test_suite_event_handler.cpp b/test/test_suite/test_suite_event_handler.cpp index 5a11d97e..ec1fd180 100644 --- a/test/test_suite/test_suite_event_handler.cpp +++ b/test/test_suite/test_suite_event_handler.cpp @@ -12,49 +12,49 @@ namespace yml { // instantiate the template template class ParseEngine; -void append_escaped(evt_string *es, csubstr val) +void append_escaped(extra::string *es, csubstr val) { - #define _c4flush_use_instead(repl, skip) \ - do { \ - es->append(val.range(prev, i)); \ - es->append(repl); \ - prev = i + skip; \ - } \ + #define _c4flush_use_instead(i, repl, skip) \ + do { \ + es->append(val.range(prev, i)); \ + es->append(repl); \ + prev = i + skip; \ + } \ while(0) - uint8_t const* C4_RESTRICT s = reinterpret_cast(es->get().str); + uint8_t const* C4_RESTRICT s = reinterpret_cast(val.str); size_t prev = 0; for(size_t i = 0; i < val.len; ++i) { switch(s[i]) { case UINT8_C(0x0a): // \n - _c4flush_use_instead("\\n", 1); break; + _c4flush_use_instead(i, "\\n", 1); break; case UINT8_C(0x5c): // '\\' - _c4flush_use_instead("\\\\", 1); break; + _c4flush_use_instead(i, "\\\\", 1); break; case UINT8_C(0x09): // \t - _c4flush_use_instead("\\t", 1); break; + _c4flush_use_instead(i, "\\t", 1); break; case UINT8_C(0x0d): // \r - _c4flush_use_instead("\\r", 1); break; + _c4flush_use_instead(i, "\\r", 1); break; case UINT8_C(0x00): // \0 - _c4flush_use_instead("\\0", 1); break; + _c4flush_use_instead(i, "\\0", 1); break; case UINT8_C(0x0c): // \f (form feed) - _c4flush_use_instead("\\f", 1); break; + _c4flush_use_instead(i, "\\f", 1); break; case UINT8_C(0x08): // \b (backspace) - _c4flush_use_instead("\\b", 1); break; + _c4flush_use_instead(i, "\\b", 1); break; case UINT8_C(0x07): // \a (bell) - _c4flush_use_instead("\\a", 1); break; + _c4flush_use_instead(i, "\\a", 1); break; case UINT8_C(0x0b): // \v (vertical tab) - _c4flush_use_instead("\\v", 1); break; + _c4flush_use_instead(i, "\\v", 1); break; case UINT8_C(0x1b): // \e (escape) - _c4flush_use_instead("\\e", 1); break; + _c4flush_use_instead(i, "\\e", 1); break; case UINT8_C(0xc2): if(i+1 < val.len) { const uint8_t np1 = s[i+1]; if(np1 == UINT8_C(0xa0)) - _c4flush_use_instead("\\_", 2); + _c4flush_use_instead(i, "\\_", 2); else if(np1 == UINT8_C(0x85)) - _c4flush_use_instead("\\N", 2); + _c4flush_use_instead(i, "\\N", 2); } break; case UINT8_C(0xe2): @@ -63,9 +63,9 @@ void append_escaped(evt_string *es, csubstr val) if(s[i+1] == UINT8_C(0x80)) { if(s[i+2] == UINT8_C(0xa8)) - _c4flush_use_instead("\\L", 3); + _c4flush_use_instead(i, "\\L", 3); else if(s[i+2] == UINT8_C(0xa9)) - _c4flush_use_instead("\\P", 3); + _c4flush_use_instead(i, "\\P", 3); } } break; diff --git a/test/test_suite/test_suite_event_handler.hpp b/test/test_suite/test_suite_event_handler.hpp index 019fd541..5f499395 100644 --- a/test/test_suite/test_suite_event_handler.hpp +++ b/test/test_suite/test_suite_event_handler.hpp @@ -12,6 +12,10 @@ #endif #endif +#ifndef _C4_YML_EXTRA_STRING_HPP_ +#include "./string.hpp" +#endif + C4_SUPPRESS_WARNING_GCC_CLANG_PUSH C4_SUPPRESS_WARNING_GCC_CLANG("-Wold-style-cast") C4_SUPPRESS_WARNING_GCC("-Wuseless-cast") @@ -23,125 +27,7 @@ namespace yml { /** @addtogroup doc_event_handlers * @{ */ -struct evt_string : private detail::stack -{ - C4_ALWAYS_INLINE void reset() { m_size = 0; } - C4_ALWAYS_INLINE csubstr get() const noexcept { return {m_stack, m_size}; } - C4_ALWAYS_INLINE substr get() noexcept { return {m_stack, m_size}; } - C4_ALWAYS_INLINE C4_HOT void grow(id_type more) - { - const id_type next = m_size + more; - if(next >= m_capacity) - { - id_type cap = m_capacity == 0 ? evt_string::sso_size : 2 * m_capacity; - cap = cap > next ? cap : next; - reserve(cap); - } - } - C4_ALWAYS_INLINE C4_HOT void append(char c) - { - grow(1); - m_stack[m_size++] = c; - } - C4_ALWAYS_INLINE C4_HOT void append(csubstr cs) - { - if(cs.len) - { - const id_type ilen = (id_type)cs.len; - grow(ilen); - memcpy(m_stack + m_size, cs.str, cs.len); - m_size += ilen; - } - } - C4_ALWAYS_INLINE void insert(char c, id_type pos) - { - if(pos < m_size) - { - grow(1); - char *C4_RESTRICT src = m_stack + 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) - { - if(cs.len) - { - if(pos < m_size) - { - const id_type ilen = (id_type)cs.len; - grow(ilen); - char *C4_RESTRICT src = m_stack + 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(pattern.len); - if(m_size >= pattern.len) - { - for(size_t i = m_size - pattern.len; i != (size_t)-1; --i) - { - if(m_stack[i] == pattern[0]) - { - bool gotit = true; - for(size_t j = 1; j < pattern.len; ++j) - { - if(m_stack[i + j] != pattern[j]) - { - gotit = false; - break; - } - } - if(gotit) - return i; - } - } - } - return npos; - } - friend struct evt_string_stack; -}; -void append_escaped(evt_string *s, csubstr val); - - -struct evt_string_stack -{ - evt_string m_arr[32] = {}; - id_type m_size = 0; - static constexpr const id_type m_capacity = 32; - C4_ALWAYS_INLINE id_type size() const noexcept { return m_size; } - void reserve(id_type sz) { _RYML_CB_ASSERT(m_arr[0].m_callbacks, sz <= m_capacity); } - void clear() { m_size = 0; } - void resize(id_type sz) - { - _RYML_CB_ASSERT(m_arr[0].m_callbacks, sz <= m_capacity); - for(id_type i = m_size; i < sz; ++i) - m_arr[i].reset(); - m_size = sz; - } - evt_string& emplace_back() - { - _RYML_CB_ASSERT(m_arr[0].m_callbacks, m_size < m_capacity); - evt_string& ret = m_arr[m_size++]; - ret.reset(); - return ret; - } - evt_string& operator[] (id_type i) { _RYML_CB_ASSERT(m_arr[0].m_callbacks, m_size < m_capacity); return m_arr[i]; } - evt_string const& operator[] (id_type i) const { _RYML_CB_ASSERT(m_arr[0].m_callbacks, m_size < m_capacity); return m_arr[i]; } -}; +void append_escaped(extra::string *s, csubstr val); /** The stack state needed specifically by @ref EventHandlerYamlStd */ @@ -169,7 +55,7 @@ struct EventHandlerYamlStd : public EventHandlerStack() @@ -194,9 +80,9 @@ struct EventHandlerYamlStd : public EventHandlerStacknode_id, tag.len, tag); _enable_(KEYTAG); - m_curr->ev_data.m_key.tag = _transform_directive(tag, m_key_tag_buf); + m_curr->ev_data.m_key.tag = _transform_directive(tag, &m_key_tag_buf); } void set_val_tag(csubstr tag) { _c4dbgpf("node[{}]: set val tag: [{}]~~~{}~~~", m_curr->node_id, tag.len, tag); _enable_(VALTAG); - m_curr->ev_data.m_val.tag = _transform_directive(tag, m_val_tag_buf); + m_curr->ev_data.m_val.tag = _transform_directive(tag, &m_val_tag_buf); } /** @} */ @@ -673,7 +561,7 @@ struct EventHandlerYamlStd : public EventHandlerStackev_data = {}; _c4dbgpf("pushed! level={}", m_curr->level); } @@ -757,8 +645,8 @@ struct EventHandlerYamlStd : public EventHandlerStack output->size()) + { + _RYML_CB_CHECK(m_stack.m_callbacks, !retry); + retry = true; + output->resize(len); + output->resize(output->capacity()); + goto again1; + } + return csubstr(*output).first(len); } } if(tag.begins_with('!')) @@ -888,15 +785,23 @@ struct EventHandlerYamlStd : public EventHandlerStackpos); } } - csubstr result = normalize_tag_long(tag, output); - _RYML_CB_CHECK(m_stack.m_callbacks, result.len > 0); - _RYML_CB_CHECK(m_stack.m_callbacks, result.str); + bool retry = false; + again2: + csubstr result = normalize_tag_long(tag, *output); + if(!result.str) + { + _RYML_CB_CHECK(m_stack.m_callbacks, !retry); + retry = true; + output->resize(result.len); + output->resize(output->capacity()); + goto again2; + } return result; } -#undef _enable_ -#undef _disable_ -#undef _has_any_ + #undef _enable_ + #undef _disable_ + #undef _has_any_ /** @endcond */ }; diff --git a/test/test_suite/test_suite_events.cpp b/test/test_suite/test_suite_events.cpp index 162fc939..881fab34 100644 --- a/test/test_suite/test_suite_events.cpp +++ b/test/test_suite/test_suite_events.cpp @@ -15,7 +15,8 @@ std::string emit_events_from_source(substr src) EventHandlerYamlStd handler(&sink); ParseEngine parser(&handler); parser.parse_in_place_ev("(testyaml)", src); - return std::string(sink.get().str, sink.get().len); + csubstr result = sink; + return std::string(result.str, result.len); } diff --git a/test/test_yaml_events.cpp b/test/test_yaml_events.cpp index 8afe64ff..92f4cc8e 100644 --- a/test/test_yaml_events.cpp +++ b/test/test_yaml_events.cpp @@ -58,10 +58,11 @@ TEST_P(EventsTest, from_parser) ParseEngine parser(&handler); std::string src_copy(ec.src.str, ec.src.len); parser.parse_in_place_ev("(testyaml)", to_substr(src_copy)); - _c4dbgpf("~~~\n{}~~~\n", sink.result); + csubstr result = sink; + _c4dbgpf("~~~\n{}~~~\n", result); // use the diff from std::string which is nice std::string exp_copy(ec.expected_events_from_parser.str, ec.expected_events_from_parser.len); - std::string result_copy(sink.get().str, sink.get().len); + std::string result_copy(result.str, result.len); EXPECT_EQ(result_copy, exp_copy); } diff --git a/tools/yaml_events.cpp b/tools/yaml_events.cpp index 56ebe387..b8c849a5 100644 --- a/tools/yaml_events.cpp +++ b/tools/yaml_events.cpp @@ -118,7 +118,7 @@ std::string emit_events_direct(csubstr filename, substr filecontents) EventHandlerYamlStd handler(&sink, create_custom_callbacks()); ParseEngine parser(&handler); parser.parse_in_place_ev(filename, filecontents); - csubstr result = sink.get(); + csubstr result = sink; return std::string(result.str, result.len); }