mirror of
https://github.com/biojppm/rapidyaml.git
synced 2026-01-18 21:41:18 +01:00
Update tools
This commit is contained in:
@@ -6,10 +6,19 @@ c4_add_executable(ryml-parse-emit
|
||||
|
||||
c4_add_executable(ryml-yaml-events
|
||||
SOURCES yaml_events.cpp
|
||||
../test/test_suite/test_suite_events.hpp
|
||||
../test/test_suite/test_suite_events_emitter.cpp
|
||||
../test/test_suite/test_suite_event_handler.hpp
|
||||
../test/test_suite/test_suite_event_handler.cpp
|
||||
INC_DIRS ../test
|
||||
../src_extra/c4/yml/extra/event_handler_ints.hpp
|
||||
../src_extra/c4/yml/extra/event_handler_ints.cpp
|
||||
../src_extra/c4/yml/extra/event_handler_testsuite.hpp
|
||||
../src_extra/c4/yml/extra/event_handler_testsuite.cpp
|
||||
../src_extra/c4/yml/extra/ints_utils.hpp
|
||||
../src_extra/c4/yml/extra/ints_utils.cpp
|
||||
../src_extra/c4/yml/extra/ints_to_testsuite.hpp
|
||||
../src_extra/c4/yml/extra/ints_to_testsuite.cpp
|
||||
../src_extra/c4/yml/extra/scalar.hpp
|
||||
../src_extra/c4/yml/extra/scalar.cpp
|
||||
../src_extra/c4/yml/extra/string.hpp
|
||||
../test/testsuite/testsuite_events.hpp
|
||||
../test/testsuite/testsuite_events_emitter.cpp
|
||||
INC_DIRS ../test ../src_extra
|
||||
LIBS ryml c4fs
|
||||
FOLDER tools)
|
||||
|
||||
@@ -4,7 +4,8 @@ from os.path import abspath, dirname
|
||||
import sys
|
||||
import subprocess
|
||||
import argparse
|
||||
|
||||
from typing import List
|
||||
from enum import Enum
|
||||
|
||||
projdir = abspath(dirname(dirname(__file__)))
|
||||
sys.path.insert(0, f"{projdir}/ext/c4core/cmake")
|
||||
@@ -12,6 +13,31 @@ import amalgamate_utils as am
|
||||
sys.path.insert(0, f"{projdir}/ext/c4core/tools")
|
||||
import amalgamate as am_c4core
|
||||
|
||||
|
||||
class Event(Enum):
|
||||
tree = "tree"
|
||||
testsuite = "testsuite"
|
||||
ints = "ints"
|
||||
ints_utils = "ints_utils"
|
||||
all = "all"
|
||||
none = "none"
|
||||
def __str__(self):
|
||||
return self.value
|
||||
|
||||
|
||||
event_doc = {
|
||||
Event.tree: """(the default) enable the normal ryml event handler
|
||||
to create the tree, and additionally the Tree, Node, parser and
|
||||
emitter utilities; if this is not enabled, none of these
|
||||
components will be included in the amalgamated file""",
|
||||
Event.testsuite: "enable the (extra) YAML test suite event handler",
|
||||
Event.ints: "enable the (extra) integer-based event handler",
|
||||
Event.ints_utils: "enable the (extra) integer-based event handler utils",
|
||||
Event.all: "enable all event handlers",
|
||||
Event.none: "disable all event handlers",
|
||||
}
|
||||
|
||||
|
||||
ryml_defmacro = "RYML_SINGLE_HDR_DEFINE_NOW"
|
||||
c4core_defmacro = "C4CORE_SINGLE_HDR_DEFINE_NOW"
|
||||
exports_def_code = f""" // shared library: export when defining
|
||||
@@ -42,7 +68,8 @@ c4core_def_code = f""" // propagate defines to c4core
|
||||
def amalgamate_ryml(filename: str,
|
||||
with_c4core: bool,
|
||||
with_fastfloat: bool,
|
||||
with_stl: bool):
|
||||
with_stl: bool,
|
||||
events: List[Event]):
|
||||
c4core_amalgamated = ""
|
||||
if with_c4core:
|
||||
c4core_amalgamated = "src/c4/c4core_all.hpp"
|
||||
@@ -66,11 +93,11 @@ INSTRUCTIONS:
|
||||
`_RYML_SINGLE_HEADER_AMALGAMATED_HPP_`, ie like this:
|
||||
```
|
||||
#ifndef _RYML_SINGLE_HEADER_AMALGAMATED_HPP_
|
||||
#include <ryml_all.hpp>
|
||||
#include <header_file_name.hpp>
|
||||
#endif
|
||||
```
|
||||
|
||||
- In one (and only one) of your project source files, #define
|
||||
- In one -- and only one -- of your project source files, #define
|
||||
{ryml_defmacro} and then include this header. This will enable
|
||||
the function and class definitions in the header file.
|
||||
|
||||
@@ -79,6 +106,13 @@ INSTRUCTIONS:
|
||||
symbol export/import.
|
||||
|
||||
"""
|
||||
def has_evt(*which):
|
||||
if Event.all in events:
|
||||
return True
|
||||
for e in which:
|
||||
if e in events:
|
||||
return True
|
||||
return False
|
||||
srcfiles = [
|
||||
am.cmttext(ryml_preamble),
|
||||
am.cmtfile("LICENSE.txt"),
|
||||
@@ -91,40 +125,49 @@ INSTRUCTIONS:
|
||||
"src/c4/yml/common.hpp",
|
||||
"src/c4/yml/node_type.hpp",
|
||||
"src/c4/yml/tag.hpp",
|
||||
"src/c4/yml/tree.hpp",
|
||||
"src/c4/yml/node.hpp",
|
||||
"src/c4/yml/writer.hpp",
|
||||
"src/c4/yml/detail/parser_dbg.hpp",
|
||||
am.injcode("#define C4_YML_EMIT_DEF_HPP_"),
|
||||
"src/c4/yml/emit.hpp",
|
||||
"src/c4/yml/emit.def.hpp",
|
||||
am.onlyif(has_evt(Event.tree), "src/c4/yml/tree.hpp"),
|
||||
am.onlyif(has_evt(Event.tree), "src/c4/yml/node.hpp"),
|
||||
am.onlyif(has_evt(Event.tree), "src/c4/yml/writer.hpp"),
|
||||
"src/c4/yml/detail/dbgprint.hpp",
|
||||
am.onlyif(has_evt(Event.tree), am.injcode("#define C4_YML_EMIT_DEF_HPP_")),
|
||||
am.onlyif(has_evt(Event.tree), "src/c4/yml/emit.hpp"),
|
||||
am.onlyif(has_evt(Event.tree), "src/c4/yml/emit.def.hpp"),
|
||||
"src/c4/yml/detail/stack.hpp",
|
||||
"src/c4/yml/filter_processor.hpp",
|
||||
"src/c4/yml/parser_state.hpp",
|
||||
"src/c4/yml/event_handler_stack.hpp",
|
||||
"src/c4/yml/event_handler_tree.hpp",
|
||||
am.onlyif(has_evt(Event.tree), "src/c4/yml/event_handler_tree.hpp"),
|
||||
am.onlyif(has_evt(Event.ints), "src_extra/c4/yml/extra/event_handler_ints.hpp"),
|
||||
am.onlyif(has_evt(Event.ints_utils), "src_extra/c4/yml/extra/event_handler_ints_utils.hpp"),
|
||||
am.onlyif(has_evt(Event.testsuite), "src_extra/c4/yml/extra/string.hpp"),
|
||||
am.onlyif(has_evt(Event.testsuite), "src_extra/c4/yml/extra/event_handler_testsuite.hpp"),
|
||||
am.onlyif(has_evt(Event.ints_utils, Event.testsuite), "src_extra/c4/yml/extra/scalar.hpp"),
|
||||
"src/c4/yml/parse_engine.hpp",
|
||||
"src/c4/yml/preprocess.hpp",
|
||||
"src/c4/yml/reference_resolver.hpp",
|
||||
"src/c4/yml/parse.hpp",
|
||||
am.onlyif(with_stl, "src/c4/yml/std/map.hpp"),
|
||||
am.onlyif(with_stl, "src/c4/yml/std/string.hpp"),
|
||||
am.onlyif(with_stl, "src/c4/yml/std/vector.hpp"),
|
||||
am.onlyif(with_stl, "src/c4/yml/std/std.hpp"),
|
||||
am.onlyif(has_evt(Event.tree), "src/c4/yml/reference_resolver.hpp"),
|
||||
am.onlyif(has_evt(Event.tree), "src/c4/yml/parse.hpp"),
|
||||
am.onlyif(with_stl and has_evt(Event.tree), "src/c4/yml/std/map.hpp"),
|
||||
am.onlyif(with_stl and has_evt(Event.tree), "src/c4/yml/std/string.hpp"),
|
||||
am.onlyif(with_stl and has_evt(Event.tree), "src/c4/yml/std/vector.hpp"),
|
||||
am.onlyif(with_stl and has_evt(Event.tree), "src/c4/yml/std/std.hpp"),
|
||||
"src/c4/yml/version.cpp",
|
||||
"src/c4/yml/common.cpp",
|
||||
"src/c4/yml/node_type.cpp",
|
||||
"src/c4/yml/tag.cpp",
|
||||
"src/c4/yml/tree.cpp",
|
||||
"src/c4/yml/parse_engine.def.hpp",
|
||||
"src/c4/yml/reference_resolver.cpp",
|
||||
"src/c4/yml/parse.cpp",
|
||||
"src/c4/yml/node.cpp",
|
||||
am.onlyif(has_evt(Event.tree), "src/c4/yml/tree.cpp"),
|
||||
am.onlyif(has_evt(Event.ints), "src_extra/c4/yml/extra/event_handler_ints.cpp"),
|
||||
am.onlyif(has_evt(Event.ints_utils, Event.testsuite), "src_extra/c4/yml/extra/scalar.cpp"),
|
||||
am.onlyif(has_evt(Event.ints_utils), "src_extra/c4/yml/extra/event_handler_ints_utils.cpp"),
|
||||
am.onlyif(has_evt(Event.testsuite), "src_extra/c4/yml/extra/event_handler_testsuite.cpp"),
|
||||
am.onlyif(has_evt(Event.tree), "src/c4/yml/reference_resolver.cpp"),
|
||||
am.onlyif(has_evt(Event.tree), "src/c4/yml/parse.cpp"),
|
||||
am.onlyif(has_evt(Event.tree), "src/c4/yml/node.cpp"),
|
||||
"src/c4/yml/preprocess.cpp",
|
||||
"src/c4/yml/detail/checks.hpp",
|
||||
"src/c4/yml/detail/print.hpp",
|
||||
"src/c4/yml/yml.hpp",
|
||||
"src/ryml.hpp",
|
||||
am.onlyif(has_evt(Event.tree), "src/c4/yml/detail/checks.hpp"),
|
||||
am.onlyif(has_evt(Event.tree), "src/c4/yml/detail/print.hpp"),
|
||||
am.onlyif(has_evt(Event.tree), "src/c4/yml/yml.hpp"),
|
||||
am.onlyif(has_evt(Event.tree), "src/ryml.hpp"),
|
||||
]
|
||||
result = am.catfiles(srcfiles,
|
||||
projdir,
|
||||
@@ -143,14 +186,25 @@ INSTRUCTIONS:
|
||||
|
||||
|
||||
def mkparser():
|
||||
return am.mkparser(c4core=(True, "amalgamate c4core together with ryml"),
|
||||
fastfloat=(True, "enable fastfloat library"),
|
||||
stl=(True, "enable stl interop"))
|
||||
p = am.mkparser(
|
||||
c4core=(True, "amalgamate c4core together with ryml"),
|
||||
fastfloat=(True, "enable fastfloat library"),
|
||||
stl=(True, "enable stl interop")
|
||||
)
|
||||
default = [str(Event.tree)]
|
||||
evtdoc = '. '.join([f"'{e}': {event_doc[e]}" for e in Event])
|
||||
defaultdoc = ','.join([str(e) for e in default])
|
||||
p.add_argument('-e', '--events', type=str, default=default, choices=[str(e) for e in Event], nargs="+",
|
||||
help=f"""Specify which event handlers to include. Possible
|
||||
values are: {evtdoc}. The default is {defaultdoc}.""")
|
||||
return p
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
args = mkparser().parse_args()
|
||||
args.events = [Event(e) for e in args.events] # is there a better way to do this?
|
||||
amalgamate_ryml(filename=args.output,
|
||||
with_c4core=args.c4core,
|
||||
with_fastfloat=args.fastfloat,
|
||||
with_stl=args.stl)
|
||||
with_stl=args.stl,
|
||||
events=args.events)
|
||||
|
||||
@@ -6,10 +6,17 @@
|
||||
#include <c4/yml/event_handler_tree.hpp>
|
||||
#include <c4/yml/parse_engine.def.hpp>
|
||||
#endif
|
||||
#include <test_suite/test_suite_events.hpp>
|
||||
#include <test_suite/test_suite_event_handler.hpp>
|
||||
#include <c4/yml/extra/string.hpp>
|
||||
#include <c4/yml/extra/scalar.hpp>
|
||||
#include <c4/yml/extra/event_handler_ints.hpp>
|
||||
#include <c4/yml/extra/event_handler_testsuite.hpp>
|
||||
#include <c4/yml/extra/ints_utils.hpp>
|
||||
#include <c4/yml/extra/ints_to_testsuite.hpp>
|
||||
#include <testsuite/testsuite_events.hpp>
|
||||
#include <c4/fs/fs.hpp>
|
||||
#include <cstdio>
|
||||
#include <chrono>
|
||||
|
||||
|
||||
#ifdef C4_EXCEPTIONS
|
||||
#include <stdexcept>
|
||||
@@ -19,80 +26,225 @@ std::jmp_buf jmp_env = {};
|
||||
c4::csubstr jmp_msg = {};
|
||||
#endif
|
||||
|
||||
C4_SUPPRESS_WARNING_GCC("-Wold-style-cast")
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const char usage[] = R"(usage:
|
||||
|
||||
ryml-yaml-events [-s|-t] [-] # read from stdin (default)
|
||||
ryml-yaml-events [-s|-t] <file> # read from file
|
||||
|
||||
The option can be one of the following:
|
||||
|
||||
-s emit events from source: parse the YAML source,
|
||||
and directly emit events during the parse (ie, no
|
||||
ryml tree is created). This is the default behavior
|
||||
when the option is omitted.
|
||||
|
||||
-t events from tree: parse the YAML source, creating a
|
||||
ryml tree. Once the tree is completely created, emit
|
||||
the events from the created tree.
|
||||
|
||||
When the option is omitted, -s is assumed.
|
||||
|
||||
|
||||
EXAMPLES:
|
||||
|
||||
$ ryml-yaml-events # emit events direct from stdin
|
||||
$ ryml-yaml-events - # emit events direct from stdin
|
||||
$ ryml-yaml-events -s - # emit events direct from stdin
|
||||
|
||||
$ ryml-yaml-events -t # parse stdin to tree, emit events from created tree
|
||||
$ ryml-yaml-events -t - # parse stdin to tree, emit events from created tree
|
||||
|
||||
$ ryml-yaml-events <file> # emit events direct from file
|
||||
$ ryml-yaml-events - <file> # emit events direct from file
|
||||
$ ryml-yaml-events -s <file> # emit events direct from file
|
||||
|
||||
$ ryml-yaml-events -t <file> # parse file to tree, emit events from created tree
|
||||
|
||||
)";
|
||||
|
||||
using namespace c4;
|
||||
using namespace c4::yml;
|
||||
|
||||
enum class evts_type
|
||||
{
|
||||
testsuite_src,
|
||||
testsuite_ints,
|
||||
testsuite_tree,
|
||||
ryml_ints,
|
||||
};
|
||||
|
||||
struct Args
|
||||
{
|
||||
csubstr filename = "-";
|
||||
bool events_from_tree = false;
|
||||
static bool parse(Args *args, int argc, const char *argv[]);
|
||||
evts_type evts = evts_type::testsuite_src;
|
||||
int ints_size = -1; // estimate by default
|
||||
bool ints_size_force = false; // do not force the estimated size
|
||||
static bool parse(Args *args, int argc, const char *argv[], int *errcode);
|
||||
};
|
||||
|
||||
const char usage[] = R"(usage:
|
||||
|
||||
ryml-yaml-events <command> <options> [-] # read from stdin (default)
|
||||
ryml-yaml-events <command> <options> <file> # read from file
|
||||
|
||||
The command must be one of the following:
|
||||
|
||||
testsuite_src,ts_src,tss
|
||||
emit test suite events directly from source: parse the YAML
|
||||
source, and directly emit events during the parse (ie, no
|
||||
ryml tree is created). This is the default behavior when the
|
||||
option is omitted.
|
||||
|
||||
testsuite_tree,ts_tree,tst
|
||||
emit test suite events from tree: parse the YAML source,
|
||||
creating a ryml tree. Once the tree is completely created,
|
||||
emit the test suite events by iterating over the nodes of the
|
||||
created tree.
|
||||
|
||||
testsuite_ints,ts_ints,tsi
|
||||
emit test suite events from the ryml int events handler:
|
||||
parse the YAML source to a container of ryml int events. Once
|
||||
this is completed, emit the corresponding test suite events.
|
||||
|
||||
ryml_ints,ri
|
||||
emit ryml int events: parse the YAML source to a container of
|
||||
ryml int events. Once this is completed, print those same int
|
||||
events.
|
||||
|
||||
The following options influence the behavior of the program:
|
||||
|
||||
--timings,--timing,-t
|
||||
print task timings and size information (to stderr)
|
||||
|
||||
The following options influence the behavior of testsuite_ints and ryml_ints:
|
||||
|
||||
--ints-size <int-number>,-is <int-number>
|
||||
when using int events, set the int event buffer size from this
|
||||
value. use a negative value to force a conservative estimation
|
||||
from a first run over the YAML source, and then multiply the
|
||||
estimation by the symmetrical of that value. For example, -2
|
||||
will result in 2*estimation. Default is -1.
|
||||
|
||||
--ints-size-force,-isf
|
||||
when using int events, force the initial int event buffer size
|
||||
to prevail: if this size is not large enough to accomodate the
|
||||
actual number of events required from the YAML source, exit
|
||||
with a nonzero error code. This is in contrast to the default
|
||||
behavior, which consists of expanding the buffer as needed,
|
||||
which requires two parses and two string copies of the
|
||||
original source buffer.
|
||||
|
||||
EXAMPLES:
|
||||
|
||||
$ ryml-yaml-events ts_src # parse stdin to test suite events, then print the events
|
||||
$ ryml-yaml-events ts_src - # parse stdin to test suite events, then print the events
|
||||
$ ryml-yaml-events ts_src <file> # parse file to test suite events, then print the events
|
||||
|
||||
$ ryml-yaml-events ts_tree # parse stdin to ryml tree, emit test suite events from created tree
|
||||
$ ryml-yaml-events ts_tree - # parse stdin to ryml tree, emit test suite events from created tree
|
||||
$ ryml-yaml-events ts_tree <file> # parse file to ryml tree, emit test suite events from created tree
|
||||
|
||||
$ ryml-yaml-events ts_ints # parse stdin to ryml int events, emit test suite events from ryml int events
|
||||
$ ryml-yaml-events ts_ints - # parse stdin to ryml int events, emit test suite events from ryml int events
|
||||
$ ryml-yaml-events ts_ints <file> # parse file to ryml int events, emit test suite events from ryml int events
|
||||
|
||||
$ ryml-yaml-events ryml_ints # parse stdin to ryml int events, emit ryml int events
|
||||
$ ryml-yaml-events ryml_ints - # parse stdin to ryml int events, emit ryml int events
|
||||
$ ryml-yaml-events ryml_ints <file> # parse file to ryml int events, emit ryml int events
|
||||
|
||||
)";
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
using IntEvents = std::vector<extra::ievt::DataType>;
|
||||
|
||||
std::string load_file(csubstr filename);
|
||||
std::string emit_events_from_tree(csubstr filename, substr filecontents);
|
||||
std::string emit_events_direct(csubstr filename, substr filecontents);
|
||||
extra::string emit_testsuite_events(csubstr filename, substr filecontents);
|
||||
std::string emit_testsuite_events_from_tree(csubstr filename, substr filecontents);
|
||||
std::string emit_testsuite_events_from_ints(csubstr filename, substr filecontents, IntEvents &evts, bool fail_size);
|
||||
void emit_ints_events(csubstr filename, substr filecontents, IntEvents &evts, bool fail_size);
|
||||
int estimate_ints_size(csubstr filecontents, int size);
|
||||
Callbacks create_custom_callbacks();
|
||||
|
||||
|
||||
bool timing_enabled = false;
|
||||
double src_size = 0;
|
||||
namespace stdc = std::chrono;
|
||||
struct stopwatch
|
||||
{
|
||||
using clock_type = stdc::steady_clock;
|
||||
const char *name;
|
||||
clock_type::time_point start;
|
||||
stopwatch(const char *name_)
|
||||
{
|
||||
if(!timing_enabled) return;
|
||||
name = name_;
|
||||
stack.emplace_back(this);
|
||||
start = clock_type::now();
|
||||
}
|
||||
~stopwatch()
|
||||
{
|
||||
if(!timing_enabled) return;
|
||||
stdc::duration<double, std::milli> delta = clock_type::now() - start;
|
||||
for(stopwatch const* sw : stack)
|
||||
fprintf(stderr, "%s:", sw->name);
|
||||
fprintf(stderr, " %.6fms (%.3fMB/s)\n", delta.count(), src_size / delta.count() * 1.e-3);
|
||||
stack.resize(stack.size()-1);
|
||||
}
|
||||
static std::vector<stopwatch*> stack;
|
||||
|
||||
};
|
||||
std::vector<stopwatch*> stopwatch::stack;
|
||||
#define STOPWATCH(name) stopwatch C4_XCAT(timer, __LINE__){name}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
Args args = {};
|
||||
if(!Args::parse(&args, argc, argv))
|
||||
return 1;
|
||||
{
|
||||
int errcode = 0;
|
||||
if(!Args::parse(&args, argc, argv, &errcode))
|
||||
return errcode;
|
||||
}
|
||||
set_callbacks(create_custom_callbacks());
|
||||
C4_IF_EXCEPTIONS_(try, if(setjmp(jmp_env) == 0))
|
||||
{
|
||||
std::string src = load_file(args.filename);
|
||||
const std::string events = args.events_from_tree ?
|
||||
emit_events_from_tree(args.filename, to_substr(src))
|
||||
:
|
||||
emit_events_direct(args.filename, to_substr(src));
|
||||
std::fwrite(events.data(), 1, events.size(), stdout);
|
||||
std::string src;
|
||||
{
|
||||
STOPWATCH("load_file");
|
||||
src = load_file(args.filename);
|
||||
src_size = (double)src.size();
|
||||
if(timing_enabled) fprintf(stderr, "src_size=%zuB\n", src.size());
|
||||
}
|
||||
STOPWATCH("process");
|
||||
switch(args.evts)
|
||||
{
|
||||
case evts_type::testsuite_src:
|
||||
{
|
||||
extra::string evts;
|
||||
{
|
||||
STOPWATCH("testsuite_src");
|
||||
evts = emit_testsuite_events(args.filename, to_substr(src));
|
||||
}
|
||||
{
|
||||
STOPWATCH("print");
|
||||
std::fwrite(evts.data(), 1, evts.size(), stdout);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case evts_type::testsuite_tree:
|
||||
{
|
||||
std::string evts;
|
||||
{
|
||||
STOPWATCH("testsuite_tree");
|
||||
evts = emit_testsuite_events_from_tree(args.filename, to_substr(src));
|
||||
}
|
||||
{
|
||||
STOPWATCH("print");
|
||||
std::fwrite(evts.data(), 1, evts.size(), stdout);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case evts_type::testsuite_ints:
|
||||
{
|
||||
substr ssrc = to_substr(src);
|
||||
int estimated_size = estimate_ints_size(ssrc, args.ints_size);
|
||||
IntEvents int_evts((size_t)estimated_size);
|
||||
std::string ts_evts;
|
||||
{
|
||||
STOPWATCH("testsuite_ints");
|
||||
ts_evts = emit_testsuite_events_from_ints(args.filename, to_substr(src), int_evts, args.ints_size_force);
|
||||
}
|
||||
{
|
||||
STOPWATCH("print");
|
||||
std::fwrite(ts_evts.data(), 1, ts_evts.size(), stdout);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case evts_type::ryml_ints:
|
||||
{
|
||||
substr ssrc = to_substr(src);
|
||||
int estimated_size = estimate_ints_size(ssrc, args.ints_size);
|
||||
IntEvents int_evts((size_t)estimated_size);
|
||||
{
|
||||
STOPWATCH("ryml_ints");
|
||||
emit_ints_events(args.filename, to_substr(src), int_evts, args.ints_size_force);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
C4_IF_EXCEPTIONS_(catch(std::exception const&), else)
|
||||
{
|
||||
@@ -104,49 +256,206 @@ int main(int argc, const char *argv[])
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
std::string emit_events_from_tree(csubstr filename, substr filecontents)
|
||||
std::string emit_testsuite_events_from_tree(csubstr filename, substr filecontents)
|
||||
{
|
||||
Tree tree(create_custom_callbacks());
|
||||
tree.reserve(estimate_tree_capacity(filecontents));
|
||||
parse_in_place(filename, filecontents, &tree);
|
||||
return emit_events_from_tree<std::string>(tree);
|
||||
{
|
||||
STOPWATCH("tree_reserve");
|
||||
tree.reserve(estimate_tree_capacity(filecontents));
|
||||
}
|
||||
{
|
||||
STOPWATCH("parse");
|
||||
parse_in_place(filename, filecontents, &tree);
|
||||
}
|
||||
{
|
||||
STOPWATCH("emit_events");
|
||||
std::string result = emit_events_from_tree<std::string>(tree);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
std::string emit_events_direct(csubstr filename, substr filecontents)
|
||||
extra::string emit_testsuite_events(csubstr filename, substr filecontents)
|
||||
{
|
||||
EventHandlerYamlStd::EventSink sink = {};
|
||||
EventHandlerYamlStd handler(&sink, create_custom_callbacks());
|
||||
ParseEngine<EventHandlerYamlStd> parser(&handler);
|
||||
parser.parse_in_place_ev(filename, filecontents);
|
||||
csubstr result = sink;
|
||||
return std::string(result.str, result.len);
|
||||
extra::EventHandlerTestSuite::EventSink sink = {};
|
||||
extra::EventHandlerTestSuite handler(&sink, create_custom_callbacks());
|
||||
ParseEngine<extra::EventHandlerTestSuite> parser(&handler);
|
||||
{
|
||||
STOPWATCH("parse");
|
||||
parser.parse_in_place_ev(filename, filecontents);
|
||||
}
|
||||
return sink;
|
||||
}
|
||||
|
||||
csubstr parse_events_ints(csubstr filename, substr filecontents, std::string &parsed, std::string &arena, IntEvents &evts, bool fail_size)
|
||||
{
|
||||
using I = extra::ievt::DataType;
|
||||
using Handler = extra::EventHandlerInts;
|
||||
Handler handler(create_custom_callbacks());
|
||||
ParseEngine<Handler> parser(&handler);
|
||||
substr src = filecontents;
|
||||
if(!fail_size)
|
||||
{
|
||||
STOPWATCH("copy_src");
|
||||
parsed.assign(filecontents.str, filecontents.len);
|
||||
src = to_substr(parsed);
|
||||
}
|
||||
arena.resize(src.len);
|
||||
handler.reset(src, to_substr(arena), evts.data(), (I)evts.size());
|
||||
{
|
||||
STOPWATCH("parse");
|
||||
parser.parse_in_place_ev(filename, src);
|
||||
}
|
||||
size_t sz = (size_t)handler.required_size_events();
|
||||
if(timing_enabled) fprintf(stderr, "current_size=%zu vs needed_size=%zu. arena_size=%zu\n", evts.size(), sz, arena.size());
|
||||
if (!handler.fits_buffers())
|
||||
{
|
||||
RYML_CHECK(!fail_size);
|
||||
{
|
||||
STOPWATCH("resize");
|
||||
evts.resize(sz);
|
||||
arena.resize(handler.required_size_arena());
|
||||
}
|
||||
{
|
||||
STOPWATCH("redo_copy_src");
|
||||
parsed.assign(filecontents.str, filecontents.len);
|
||||
src = to_substr(parsed);
|
||||
}
|
||||
handler.reset(src, to_substr(arena), evts.data(), (I)evts.size());
|
||||
{
|
||||
STOPWATCH("redo_parse");
|
||||
parser.parse_in_place_ev(filename, src);
|
||||
}
|
||||
RYML_CHECK((size_t)handler.m_evt_pos == sz);
|
||||
}
|
||||
evts.resize(sz);
|
||||
return src;
|
||||
}
|
||||
|
||||
std::string emit_testsuite_events_from_ints(csubstr filename, substr filecontents, IntEvents &evts, bool fail_size)
|
||||
{
|
||||
using I = extra::ievt::DataType;
|
||||
std::string buf;
|
||||
std::string arena;
|
||||
csubstr parsed;
|
||||
{
|
||||
STOPWATCH("events");
|
||||
parsed = parse_events_ints(filename, filecontents, buf, arena, evts, fail_size);
|
||||
}
|
||||
std::string result;
|
||||
{
|
||||
STOPWATCH("emit");
|
||||
extra::events_ints_to_testsuite(parsed, to_substr(arena), evts.data(), (I)evts.size(), &result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void emit_ints_events(csubstr filename, substr filecontents, IntEvents &evts, bool fail_size)
|
||||
{
|
||||
using I = extra::ievt::DataType;
|
||||
std::string buf;
|
||||
std::string arena;
|
||||
csubstr parsed;
|
||||
{
|
||||
STOPWATCH("events");
|
||||
parsed = parse_events_ints(filename, filecontents, buf, arena, evts, fail_size);
|
||||
}
|
||||
{
|
||||
STOPWATCH("emit");
|
||||
extra::events_ints_print(parsed, to_substr(arena), evts.data(), (I)evts.size());
|
||||
}
|
||||
}
|
||||
|
||||
int estimate_ints_size(csubstr filecontents, int size)
|
||||
{
|
||||
if(size < 0)
|
||||
{
|
||||
STOPWATCH("estimate_size");
|
||||
int est = extra::estimate_events_ints_size(filecontents);
|
||||
if(timing_enabled) fprintf(stderr, "estimated_size=%d*%d=%d\n", -size, est, -size * est);
|
||||
size = -size * est;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool Args::parse(Args *args, int argc, const char *argv[])
|
||||
// return true if the program should continue (eg -h should exit)
|
||||
bool Args::parse(Args *args, int argc, const char *argv[], int *errcode)
|
||||
{
|
||||
if(argc > 3)
|
||||
{
|
||||
*errcode = 0;
|
||||
auto argerr = [&](const char *msg){
|
||||
std::printf(usage);
|
||||
std::printf("ERROR: %s\n", msg);
|
||||
*errcode = 1;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
// set defaults
|
||||
*args = {};
|
||||
if(argc == 3)
|
||||
// parse the command argument
|
||||
if(argc < 2)
|
||||
return argerr("must provide a command"); // LCOV_EXCL_LINE
|
||||
bool has_cmd = false;
|
||||
{
|
||||
args->events_from_tree = (to_csubstr(argv[1]) == "-t");
|
||||
args->filename = to_csubstr(argv[2]);
|
||||
csubstr s = to_csubstr(argv[1]);
|
||||
if(s == "testsuite_src" || s == "ts_src" || s == "tss")
|
||||
{
|
||||
args->evts = evts_type::testsuite_src;
|
||||
has_cmd = true;
|
||||
}
|
||||
else if(s == "testsuite_tree" || s == "ts_tree" || s == "tst")
|
||||
{
|
||||
args->evts = evts_type::testsuite_tree;
|
||||
has_cmd = true;
|
||||
}
|
||||
else if(s == "testsuite_ints" || s == "ts_ints" || s == "tsi")
|
||||
{
|
||||
args->evts = evts_type::testsuite_ints;
|
||||
has_cmd = true;
|
||||
}
|
||||
else if(s == "ryml_ints" || s == "ri")
|
||||
{
|
||||
args->evts = evts_type::ryml_ints;
|
||||
has_cmd = true;
|
||||
}
|
||||
else if(s == "--help" || s == "-h")
|
||||
{
|
||||
std::printf(usage);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if(argc == 2)
|
||||
if(!has_cmd)
|
||||
return argerr("unknown command");
|
||||
// parse other args
|
||||
int i = 2; // cmd is mandatory at i=1, so start after that at i=2
|
||||
for(; i < argc; ++i)
|
||||
{
|
||||
csubstr a = to_csubstr(argv[1]);
|
||||
if(a == "-t")
|
||||
args->events_from_tree = true;
|
||||
else if(a == "-s")
|
||||
args->events_from_tree = false;
|
||||
csubstr arg = to_csubstr(argv[i]);
|
||||
if(arg == "--help" || arg == "-h")
|
||||
{
|
||||
std::printf(usage);
|
||||
return false;
|
||||
}
|
||||
else if(arg == "--timings" || arg == "--timing" || arg == "-t")
|
||||
{
|
||||
timing_enabled = true;
|
||||
}
|
||||
else if(arg == "--ints-size-force" || arg == "-isf")
|
||||
{
|
||||
args->ints_size_force = true;
|
||||
}
|
||||
else if(arg == "--ints-size" || arg == "-is")
|
||||
{
|
||||
if(i + 1 >= argc)
|
||||
return argerr("ints-size value not given"); // LCOV_EXCL_LINE
|
||||
else if(!atoi(to_csubstr(argv[i+1]), &args->ints_size))
|
||||
return argerr("ints-size value fails to parse"); // LCOV_EXCL_LINE
|
||||
++i; // shift 1
|
||||
}
|
||||
else
|
||||
args->filename = a;
|
||||
{
|
||||
args->filename = arg;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -154,19 +463,16 @@ bool Args::parse(Args *args, int argc, const char *argv[])
|
||||
std::string load_file(csubstr filename)
|
||||
{
|
||||
if(filename == "-") // read from stdin
|
||||
{
|
||||
{ // LCOV_EXCL_START
|
||||
std::string buf;
|
||||
buf.reserve(128);
|
||||
for(int c = std::getchar(); c != EOF; c = std::getchar())
|
||||
{
|
||||
buf.push_back(static_cast<char>(c));
|
||||
if(buf.size() == buf.capacity())
|
||||
buf.reserve(2u * (buf.capacity() >= 128u ? buf.capacity() : 128u));
|
||||
}
|
||||
return buf;
|
||||
return buf; // LCOV_EXCL_STOP
|
||||
}
|
||||
if(!fs::path_exists(filename.str))
|
||||
else if(!fs::path_exists(filename.str))
|
||||
{
|
||||
std::fprintf(stderr, "cannot find file: %s (cwd=%s)\n", filename.str, fs::cwd<std::string>().c_str());
|
||||
std::fprintf(stderr, "%s: file not found (cwd=%s)\n", filename.str, fs::cwd<std::string>().c_str());
|
||||
error("file not found");
|
||||
}
|
||||
return fs::file_get_contents<std::string>(filename.str);
|
||||
@@ -204,4 +510,3 @@ Callbacks create_custom_callbacks()
|
||||
};
|
||||
return callbacks;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user