Skip to content

Commit

Permalink
wip [ci skip]
Browse files Browse the repository at this point in the history
  • Loading branch information
biojppm committed May 25, 2024
1 parent a28b2c3 commit 0e9c853
Show file tree
Hide file tree
Showing 10 changed files with 163 additions and 53 deletions.
12 changes: 6 additions & 6 deletions src/c4/yml/detail/stack.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ namespace detail {
template<class T, id_type N=16>
class stack
{
static_assert(std::is_trivially_copyable<T>::value, "T must be trivially copyable");
//static_assert(std::is_trivially_copyable<T>::value, "T must be trivially copyable");
static_assert(std::is_trivially_destructible<T>::value, "T must be trivially destructible");

public:
Expand All @@ -34,11 +34,11 @@ class stack

public:

T m_buf[size_t(N)];
T * m_stack;
id_type m_size;
id_type m_capacity;
Callbacks m_callbacks;
T m_buf[size_t(N)];
T *C4_RESTRICT m_stack;
id_type m_size;
id_type m_capacity;
Callbacks m_callbacks;

public:

Expand Down
4 changes: 2 additions & 2 deletions test/test_fuzz/test_fuzz_common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ inline int fuzztest_yaml_events(uint32_t case_number, csubstr src)
{
_if_dbg(_dbg_printf("in[{}]: [{}]~~~\n{}\n~~~\n", case_number, src.len, src); fflush(NULL));
parser.parse_in_place_ev("input", c4::to_substr(str));
_if_dbg(_dbg_printf("evts[{}]: ~~~\n{}\n~~~\n", case_number, sink.result.c_str()); fflush(NULL));
C4_DONT_OPTIMIZE(sink.result);
_if_dbg(_dbg_printf("evts[{}]: ~~~\n{}\n~~~\n", case_number, sink.get()); fflush(NULL));
C4_DONT_OPTIMIZE(sink);
}
C4_IF_EXCEPTIONS_(catch(std::exception const&), else)
{
Expand Down
5 changes: 3 additions & 2 deletions test/test_lib/test_engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,9 @@ void test_new_parser_events_from_yaml(ReferenceYaml const& yaml, std::string con
ParseEngine<EventHandlerYamlStd> parser(&handler);
std::string copy = yaml.parsed;
parser.parse_in_place_ev("(testyaml)", to_substr(copy));
_c4dbgpf("~~~\n{}~~~\n", sink.result);
EXPECT_EQ(sink.result, expected_events);
csubstr result = sink.get();
_c4dbgpf("~~~\n{}~~~\n", sink.get());
EXPECT_EQ(std::string(result.str, result.len), expected_events);
}

void test_new_parser_tree_from_yaml(ReferenceYaml const& yaml)
Expand Down
5 changes: 3 additions & 2 deletions test/test_lib/test_engine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,9 @@ C4_NO_INLINE void test_new_parser_str_from_events(std::string const& expected_ev
handler.reset();
EventProducerFn<EventHandlerYamlStd> event_producer;
event_producer(handler);
_c4dbgpf("~~~\n{}~~~\n", sink.result);
EXPECT_EQ(sink.result, expected_events);
csubstr result = sink.get();
_c4dbgpf("~~~\n{}~~~\n", result);
EXPECT_EQ(std::string(result.str, result.len), expected_events);
}

template<template<class> class EventProducerFn>
Expand Down
5 changes: 3 additions & 2 deletions test/test_suite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ struct TestSequenceLevel
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_NE(evt_str_sink.result, "");
EXPECT_FALSE(evt_str_sink.get().empty());
events_were_generated = true;
}

Expand Down Expand Up @@ -655,7 +655,8 @@ struct TestSequenceData
for(size_t i = 0; i < num; ++i)
{
levels[i].parse_yaml_to_events();
events->compare_emitted_events_to_reference_events(levels[i].evt_str_sink.result,
csubstr result = levels[i].evt_str_sink.get();
events->compare_emitted_events_to_reference_events(std::string(result.str, result.len),
/*ignore_container_style*/false,
/*ignore_scalar_style*/(num>0));
}
Expand Down
11 changes: 5 additions & 6 deletions test/test_suite/test_suite_event_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,16 @@ namespace yml {
// instantiate the template
template class ParseEngine<EventHandlerYamlStd>;


void EventHandlerYamlStd::EventSink::append_escaped(csubstr val)
void append_escaped(evt_string *es, csubstr val)
{
#define _c4flush_use_instead(repl, skip) \
do { \
this->append(val.range(prev, i)); \
this->append(repl); \
es->append(val.range(prev, i)); \
es->append(repl); \
prev = i + skip; \
} \
while(0)
uint8_t const* C4_RESTRICT s = reinterpret_cast<uint8_t const*>(val.str);
uint8_t const* C4_RESTRICT s = reinterpret_cast<uint8_t const*>(es->get().str);
size_t prev = 0;
for(size_t i = 0; i < val.len; ++i)
{
Expand Down Expand Up @@ -73,7 +72,7 @@ void EventHandlerYamlStd::EventSink::append_escaped(csubstr val)
}
}
// flush the rest
this->append(val.sub(prev));
es->append(val.sub(prev));
#undef _c4flush_use_instead
}

Expand Down
165 changes: 135 additions & 30 deletions test/test_suite/test_suite_event_handler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,11 @@
#ifndef _C4_YML_EVENT_HANDLER_STACK_HPP_
#include "c4/yml/event_handler_stack.hpp"
#endif
#ifndef _C4_YML_STD_STRING_HPP_
#include "c4/yml/std/string.hpp"
#endif
#ifndef _C4_YML_DETAIL_PRINT_HPP_
#include "c4/yml/detail/print.hpp"
#endif
#endif

#include <vector>

C4_SUPPRESS_WARNING_GCC_CLANG_PUSH
C4_SUPPRESS_WARNING_GCC_CLANG("-Wold-style-cast")
C4_SUPPRESS_WARNING_GCC("-Wuseless-cast")
Expand All @@ -28,6 +23,127 @@ namespace yml {
/** @addtogroup doc_event_handlers
* @{ */

struct evt_string : private detail::stack<char, /*SSO*/128>
{
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]; }
};


/** The stack state needed specifically by @ref EventHandlerYamlStd */
struct EventHandlerYamlStdState : public ParserState
{
Expand All @@ -53,27 +169,15 @@ struct EventHandlerYamlStd : public EventHandlerStack<EventHandlerYamlStd, Event
// our internal state must inherit from parser state
using state = EventHandlerYamlStdState;

struct EventSink
{
std::string result;
void reset() noexcept { result.clear(); }
void append(csubstr s) noexcept { result.append(s.str, s.len); }
void append(char c) noexcept { result += c; }
void insert(csubstr s, size_t pos) noexcept { result.insert(pos, s.str, s.len); }
void insert(char c, size_t pos) noexcept { result.insert(pos, 1, c); }
csubstr get() const { return csubstr(&result[0], result.size()); }
substr get() { return substr(&result[0], result.size()); }
size_t find_last(csubstr s) const { return result.rfind(s.str, std::string::npos, s.len); }
void append_escaped(csubstr val);
};
using EventSink = evt_string;

/** @} */

public:

/** @cond dev */
EventSink *C4_RESTRICT m_sink;
std::vector<EventSink> m_val_buffers;
evt_string_stack m_val_buffers;
char m_key_tag_buf[256];
char m_val_tag_buf[256];
TagDirective m_tag_directives[RYML_MAX_TAG_DIRECTIVES];
Expand Down Expand Up @@ -102,8 +206,9 @@ struct EventHandlerYamlStd : public EventHandlerStack<EventHandlerYamlStd, Event
{
_stack_reset_root();
m_curr->flags |= RUNK|RTOP;
for(auto &td : m_tag_directives)
for(TagDirective &td : m_tag_directives)
td = {};
m_val_buffers.clear();
m_val_buffers.resize((size_t)m_stack.size());
m_arena.clear();
m_arena.reserve(1024);
Expand Down Expand Up @@ -634,20 +739,20 @@ struct EventHandlerYamlStd : public EventHandlerStack<EventHandlerYamlStd, Event

EventSink& _buf_() noexcept
{
_RYML_CB_ASSERT(m_stack.m_callbacks, (size_t)m_curr->level < m_val_buffers.size());
return m_val_buffers[(size_t)m_curr->level];
_RYML_CB_ASSERT(m_stack.m_callbacks, m_curr->level < m_val_buffers.size());
return m_val_buffers[m_curr->level];
}

EventSink& _buf_(id_type level) noexcept
{
_RYML_CB_ASSERT(m_stack.m_callbacks, (size_t)level < m_val_buffers.size());
return m_val_buffers[(size_t)level];
_RYML_CB_ASSERT(m_stack.m_callbacks, level < m_val_buffers.size());
return m_val_buffers[level];
}

EventSink const& _buf_(id_type level) const noexcept
{
_RYML_CB_ASSERT(m_stack.m_callbacks, (size_t)level < m_val_buffers.size());
return m_val_buffers[(size_t)level];
_RYML_CB_ASSERT(m_stack.m_callbacks, level < m_val_buffers.size());
return m_val_buffers[level];
}

static void _buf_flush_to_(EventSink &C4_RESTRICT src, EventSink &C4_RESTRICT dst) noexcept
Expand All @@ -670,8 +775,8 @@ struct EventHandlerYamlStd : public EventHandlerStack<EventHandlerYamlStd, Event

void _buf_ensure_(id_type size_needed) noexcept
{
if((size_t)size_needed > m_val_buffers.size())
m_val_buffers.resize((size_t)size_needed);
if(size_needed > m_val_buffers.size())
m_val_buffers.resize(size_needed);
}

C4_ALWAYS_INLINE void _send_(csubstr s) noexcept { _buf_().append(s); }
Expand All @@ -683,7 +788,7 @@ struct EventHandlerYamlStd : public EventHandlerStack<EventHandlerYamlStd, Event
_send_key_props_();
_send_(' ');
_send_(scalar_type_code);
_buf_().append_escaped(scalar);
append_escaped(&_buf_(), scalar);
_send_('\n');
}
void _send_val_scalar_(csubstr scalar, char scalar_type_code)
Expand All @@ -692,7 +797,7 @@ struct EventHandlerYamlStd : public EventHandlerStack<EventHandlerYamlStd, Event
_send_val_props_();
_send_(' ');
_send_(scalar_type_code);
_buf_().append_escaped(scalar);
append_escaped(&_buf_(), scalar);
_send_('\n');
}

Expand Down
2 changes: 1 addition & 1 deletion test/test_suite/test_suite_events.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ std::string emit_events_from_source(substr src)
EventHandlerYamlStd handler(&sink);
ParseEngine<EventHandlerYamlStd> parser(&handler);
parser.parse_in_place_ev("(testyaml)", src);
return sink.result;
return std::string(sink.get().str, sink.get().len);
}


Expand Down
4 changes: 3 additions & 1 deletion test/test_yaml_events.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,10 @@ TEST_P(EventsTest, from_parser)
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);
// 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);
EXPECT_EQ(sink.result, exp_copy); // use the diff from std::string which is nice
std::string result_copy(sink.get().str, sink.get().len);
EXPECT_EQ(result_copy, exp_copy);
}

TEST_P(EventsTest, from_tree)
Expand Down
3 changes: 2 additions & 1 deletion tools/yaml_events.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,8 @@ std::string emit_events_direct(csubstr filename, substr filecontents)
EventHandlerYamlStd handler(&sink, create_custom_callbacks());
ParseEngine<EventHandlerYamlStd> parser(&handler);
parser.parse_in_place_ev(filename, filecontents);
return sink.result;
csubstr result = sink.get();
return std::string(result.str, result.len);
}


Expand Down

0 comments on commit 0e9c853

Please sign in to comment.