Files
rapidyaml/bm/libyaml.hpp
Joao Paulo Magalhaes 79f3c4534b [chore] update benchmarks
2022-01-16 01:02:38 +00:00

374 lines
10 KiB
C++

#ifndef _LIBYAML_HPP_
#define _LIBYAML_HPP_
#include <yaml.h>
#ifndef RYML_SINGLE_HEADER
#include <c4/yml/std/std.hpp>
#include <c4/yml/yml.hpp>
#include <c4/yml/detail/stack.hpp>
#endif
#include <stdexcept>
#include <string>
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
namespace c4 {
namespace yml {
namespace detail {
class Event;
} // detail
class detail::Event
{
public:
yaml_event_t m_event;
public:
Event() {}
~Event()
{
yaml_event_delete(&m_event);
}
};
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
class LibyamlParser
{
public:
yaml_parser_t m_parser;
csubstr m_input;
Tree * m_tree;
c4::yml::detail::stack<size_t> m_stack;
public:
LibyamlParser() : m_parser(), m_input(), m_tree(), m_stack()
{
memset(&m_parser, 0, sizeof(decltype(m_parser)));
yaml_parser_initialize(&m_parser);
}
~LibyamlParser()
{
yaml_parser_delete(&m_parser);
memset(&m_parser, 0, sizeof(decltype(m_parser)));
}
void parse(Tree *t, const csubstr sp)
{
m_input = sp;
m_tree = t;
m_tree->clear();
m_stack.clear();
yaml_parser_set_input_string(&m_parser, (const unsigned char*)m_input.str, m_input.len);
try
{
_do_parse();
}
catch(std::exception const& exc)
{
std::cout << m_tree->size();
C4_ERROR(exc.what());
}
}
void _do_parse()
{
#if defined(RYML_DBG)
#define _c4_handle_case(_ev) \
case YAML_ ## _ev ## _EVENT: \
printf(#_ev " val=%.*s\n", \
/*(int)prev_scalar.len, prev_scalar.str,*/ \
(int)val.len, val.str);
#else
#define _c4_handle_case(_ev) \
case YAML_ ## _ev ## _EVENT: \
(void)val;
#endif
bool done = false;
//bool doc_had_scalars = false;
csubstr prev_scalar;
while( ! done)
{
detail::Event ev;
if( ! yaml_parser_parse(&m_parser, &ev.m_event))
{
_handle_error(ev);
break;
}
csubstr val = get_scalar_val(ev);
switch(ev.m_event.type)
{
_c4_handle_case(MAPPING_START)
{
/*if(( ! s->stack_top_is_type(DOC) || doc_had_scalars)
&&
( ! m_load_root))
{
C4_ASSERT( ! prev_scalar.empty());
s->begin_map(prev_scalar, s->top_last());
prev_scalar.clear();
}
*/
begin_container(MAP, prev_scalar);
prev_scalar.clear();
break;
}
_c4_handle_case(MAPPING_END)
{
end_container();
break;
}
_c4_handle_case(SEQUENCE_START)
{
begin_container(SEQ, prev_scalar);
prev_scalar.clear();
break;
}
_c4_handle_case(SEQUENCE_END)
{
end_container();
break;
}
_c4_handle_case(SCALAR)
{
size_t parent = m_stack.top();
if(m_tree->is_seq(parent))
{
C4_ASSERT(prev_scalar.empty());
append_val(val);
}
else if(m_tree->is_map(parent))
{
if( ! prev_scalar.empty())
{
append_keyval(prev_scalar, val);
prev_scalar.clear();
}
else
{
prev_scalar = val;
}
}
//doc_had_scalars = true;
break;
}
_c4_handle_case(DOCUMENT_START)
{
auto r = m_tree->root_id();
m_tree->to_doc(r);
//m_stack.push(r);
break;
}
_c4_handle_case(DOCUMENT_END)
{
//m_stack.pop();
break;
}
_c4_handle_case(STREAM_START)
{
//s->begin_stream();
break;
}
_c4_handle_case(STREAM_END)
{
//s->end_stream();
done = true;
break;
}
_c4_handle_case(ALIAS)
{
//C4_NOT_IMPLEMENTED();
break;
}
_c4_handle_case(NO)
{
break;
}
default:
break;
};
}
#undef _c4_handle_case
}
private:
void begin_container(NodeType type, csubstr key)
{
size_t parent, elm;
if( ! m_stack.empty())
{
parent = m_stack.top();
elm = m_tree->append_child(parent);
}
else
{
parent = m_tree->root_id();
//C4_ASSERT(m_tree->is_container(parent));
if(type.is_map())
{
m_tree->to_map(parent);
}
else
{
m_tree->to_seq(parent);
}
elm = parent;
}
m_stack.push(elm);
if(type.is_map())
{
if(key.not_empty())
{
//printf("append map! key=%.*s elm=%zu parent=%zu\n", (int)key.len, key.str, elm, parent);
m_tree->to_map(elm, key);
}
else
{
//printf("append map! elm=%zu parent=%zu\n", elm, parent);
m_tree->to_map(elm);
}
}
else if(type.is_seq())
{
if(key.not_empty())
{
//printf("append seq! key=%.*s elm=%zu parent=%zu\n", (int)key.len, key.str, elm, parent);
m_tree->to_seq(elm, key);
}
else
{
//printf("append seq! elm=%zu parent=%zu\n", elm, parent);
m_tree->to_seq(elm);
}
}
else
{
C4_ERROR("");
}
}
void end_container()
{
if( ! m_stack.empty())
{
m_stack.pop();
}
}
void append_val(csubstr val)
{
size_t elm = m_tree->append_child(m_stack.top());
m_tree->to_val(elm, val);
//printf("append val! %.*s elm=%zu parent=%zu\n", (int)val.len, val.str, elm, m_tree->parent(elm));
}
void append_keyval(csubstr key, csubstr val)
{
size_t elm = m_tree->append_child(m_stack.top());
m_tree->to_keyval(elm, key, val);
//printf("append keyval! %.*s: %.*s elm=%zu parent=%zu\n", (int)key.len, key.str, (int)val.len, val.str, elm, m_tree->parent(elm));
}
csubstr get_scalar_val(detail::Event const &ev) const
{
// the memory in data.scalar is allocated anew, so don't do this
//auto const& scalar = e.m_event.data.scalar;
//csubstr val((const char*)scalar.value, scalar.length);
//return val;
// ... but the event tells us where in the string the value is
auto const& e = ev.m_event;
size_t len = e.end_mark.index - e.start_mark.index;
csubstr val(m_input.str + e.start_mark.index, len);
return val;
}
void _handle_error(detail::Event const& ev)
{
std::cout << "AQUI crl\n" << ev.m_event.start_mark.line << "--" << ev.m_event.end_mark.line << "\n";
Location problem_loc, context_loc;
if(m_parser.problem)
{
auto const& m = m_parser.problem_mark;
problem_loc = Location(m_parser.problem, m.index, m.line+1, m.column+1);
}
if(m_parser.context)
{
auto const& m = m_parser.context_mark;
context_loc = Location(m_parser.context, m.index, m.line+1, m.column+1);
}
switch(m_parser.error)
{
case YAML_MEMORY_ERROR:
error("Memory error: Not enough memory for parsing");
break;
case YAML_READER_ERROR:
if (m_parser.problem_value != -1)
{
char buf[32];
int ret = snprintf(buf, sizeof(buf), "Reader error: #%X", m_parser.problem_value);
C4_CHECK(ret >= 0);
error(buf, static_cast<size_t>(ret), &problem_loc);
}
else
{
error("Reader error", &problem_loc);
}
break;
case YAML_SCANNER_ERROR:
error("Scanner error", &context_loc, &problem_loc);
break;
case YAML_PARSER_ERROR:
error("Parser error", &context_loc, &problem_loc);
break;
default:
/* Couldn't happen. */
error("Internal error");
break;
};
}
static void error(const char* msg, size_t length, Location *loc1 = nullptr, Location *loc2 = nullptr)
{
fprintf(stderr, "%.*s\n", (int)length, msg);
if(loc1 && *loc1)
{
fprintf(stderr, " : %.*s at %zd:%zd (offset %zd)\n", (int)loc1->name.len, loc1->name.str, loc1->line, loc1->col, loc1->offset);
}
if(loc2 && *loc2)
{
fprintf(stderr, " : %.*s at %zd:%zd (offset %zd)\n", (int)loc2->name.len, loc2->name.str, loc2->line, loc2->col, loc2->offset);
}
throw std::runtime_error(std::string(msg, msg+length));
}
template< size_t N >
static void error(char const (&msg)[N], Location *loc1 = nullptr, Location *loc2 = nullptr)
{
error(&msg[0], N-1, loc1, loc2);
}
};
} // namespace yml
} // namespace c4
#endif // _LIBYAML_HPP_