refactor error API: update tools

This commit is contained in:
Joao Paulo Magalhaes
2025-03-22 20:55:54 +00:00
parent d084cfddbc
commit 471d18c4e0
3 changed files with 95 additions and 71 deletions

View File

@@ -7,6 +7,7 @@
#else #else
#include <c4/yml/std/std.hpp> #include <c4/yml/std/std.hpp>
#include <c4/yml/parse.hpp> #include <c4/yml/parse.hpp>
#include <c4/yml/error.def.hpp>
#include <c4/yml/emit.hpp> #include <c4/yml/emit.hpp>
#include <c4/yml/event_handler_tree.hpp> #include <c4/yml/event_handler_tree.hpp>
#include <c4/yml/parse_engine.def.hpp> #include <c4/yml/parse_engine.def.hpp>

View File

@@ -6,6 +6,7 @@
#include <c4/yml/parse.hpp> #include <c4/yml/parse.hpp>
#include <c4/yml/emit.hpp> #include <c4/yml/emit.hpp>
#include <c4/yml/common.hpp> #include <c4/yml/common.hpp>
#include <c4/yml/error.def.hpp>
#endif #endif
#include <c4/fs/fs.hpp> #include <c4/fs/fs.hpp>
@@ -88,7 +89,13 @@ bool timing_enabled = false;
bool parse_args(int argc, const char *argv[], Args &args) bool parse_args(int argc, const char *argv[], Args &args)
{ {
args = {}; args = {};
for(int i = 1; i < argc; ++i) if(argc < 2)
{
print_usage(argv[0]);
_RYML_ERR_BASIC("missing filename (use - to read from stdin)");
}
args.filename = c4::to_csubstr(argv[argc - 1]);
for(int i = 1; i+1 < argc; ++i)
{ {
c4::csubstr arg = c4::to_csubstr(argv[i]); c4::csubstr arg = c4::to_csubstr(argv[i]);
auto arg0_is = [&](c4::csubstr argshort, c4::csubstr arglong){ auto arg0_is = [&](c4::csubstr argshort, c4::csubstr arglong){
@@ -98,7 +105,7 @@ bool parse_args(int argc, const char *argv[], Args &args)
if(arg0_is(argshort, arglong)) if(arg0_is(argshort, arglong))
{ {
if(i + 1 >= argc) if(i + 1 >= argc)
c4::yml::error("missing argument value"); _RYML_ERR_BASIC("missing argument value: {}", arg);
return true; return true;
} }
return false; return false;
@@ -120,14 +127,14 @@ bool parse_args(int argc, const char *argv[], Args &args)
else if(i+1 < argc) else if(i+1 < argc)
{ {
print_usage(argv[0]); print_usage(argv[0]);
c4::yml::error("unknown argument"); _RYML_ERR_BASIC("unknown argument: {}", arg);
} }
} }
timing_enabled = args.timed_sections; timing_enabled = args.timed_sections;
if(argc < 2) if(argc < 2)
{ {
print_usage(argv[0]); print_usage(argv[0]);
c4::yml::error("missing filename (use - to read from stdin)"); _RYML_ERR_BASIC("missing filename (use - to read from stdin)");
} }
args.filename = c4::to_csubstr(argv[argc - 1]); args.filename = c4::to_csubstr(argv[argc - 1]);
return true; return true;
@@ -147,11 +154,7 @@ void read_file(csubstr filename, std::string *buf)
} }
else else
{ {
if(!fs::path_exists(filename.str)) _RYML_CHECK_BASIC_MSG(fs::path_exists(filename.str), "file not found: {} (cwd={})", filename, fs::cwd<std::string>());
{
std::fprintf(stderr, "cannot find file: %s (cwd=%s)\n", filename.str, fs::cwd<std::string>().c_str()); // NOLINT
yml::error("file not found");
}
fs::file_get_contents<std::string>(filename.str, buf); fs::file_get_contents<std::string>(filename.str, buf);
} }
} }
@@ -192,37 +195,41 @@ void emit_json_docs(yml::Tree const& tree, FILE *output)
emitnode(doc); emitnode(doc);
} }
void report_error(const char* msg, size_t length, yml::Location loc, FILE *f) void dump2stderr(csubstr s)
{ {
if(!loc.name.empty()) if(s.len)
{ {
fwrite(loc.name.str, 1, loc.name.len, f); // NOLINT fwrite(s.str, 1, s.len, stderr); // NOLINT
fputc(':', f); // NOLINT fflush(stderr); // NOLINT
} }
fprintf(f, "%zu:", loc.line); // NOLINT }
if(loc.col)
fprintf(f, "%zu:", loc.col); // NOLINT [[noreturn]] void throwerr(csubstr msg)
if(loc.offset) {
fprintf(f, " (%zuB):", loc.offset); // NOLINT C4_IF_EXCEPTIONS(
fputc(' ', f); // NOLINT throw std::runtime_error({msg.str, msg.len});
fprintf(f, "%.*s\n", static_cast<int>(length), msg); // NOLINT ,
fflush(f); // NOLINT jmp_msg.assign(msg.str, msg.len);
std::longjmp(jmp_env, 1);
);
C4_UNREACHABLE_AFTER_ERR();
} }
yml::Callbacks create_custom_callbacks() yml::Callbacks create_custom_callbacks()
{ {
yml::Callbacks callbacks = {}; return yml::Callbacks{}
callbacks.m_error = [](const char *msg, size_t msg_len, yml::Location location, void *) .set_error_basic([](csubstr msg, yml::ErrorDataBasic const& errdata, void *){
{ yml::err_basic_format(dump2stderr, msg, errdata);
report_error(msg, msg_len, location, stderr); throwerr(msg);
C4_IF_EXCEPTIONS( })
throw std::runtime_error({msg, msg_len}); .set_error_parse([](csubstr msg, yml::ErrorDataParse const& errdata, void *){
, yml::err_parse_format(dump2stderr, msg, errdata);
jmp_msg.assign(msg, msg_len); throwerr(msg);
std::longjmp(jmp_env, 1); })
); .set_error_visit([](csubstr msg, yml::ErrorDataVisit const& errdata, void *){
}; yml::err_visit_format(dump2stderr, msg, errdata);
return callbacks; throwerr(msg);
});
} }
#define TS(name) timed_section C4_XCAT(__, C4_XCAT(name, __LINE__))(#name) #define TS(name) timed_section C4_XCAT(__, C4_XCAT(name, __LINE__))(#name)
@@ -254,14 +261,13 @@ struct timed_section
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void process_file(Args const& args) void process_file(Args const& args, std::string *contents)
{ {
TS(objects); TS(objects);
std::string contents;
yml::Tree tree(yml::get_callbacks()); yml::Tree tree(yml::get_callbacks());
{ {
TS(read_file); TS(read_file);
read_file(args.filename, &contents); read_file(args.filename, contents);
} }
if(args.reserve_size) if(args.reserve_size)
{ {
@@ -270,15 +276,15 @@ void process_file(Args const& args)
if(args.reserve_size) if(args.reserve_size)
{ {
TS(estimate_capacity); TS(estimate_capacity);
cap = yml::estimate_tree_capacity(to_csubstr(contents)); cap = yml::estimate_tree_capacity(to_csubstr(*contents));
} }
if(timing_enabled) if(args.timed_sections)
fprintf(stderr, "reserving capacity=%zu\n", (size_t)cap); // NOLINT fprintf(stderr, "reserving capacity=%zu\n", (size_t)cap); // NOLINT
tree.reserve(cap); tree.reserve(cap);
} }
{ {
TS(parse_yml); TS(parse_yml);
yml::parse_in_place(args.filename, to_substr(contents), &tree); yml::parse_in_place(args.filename, to_substr(*contents), &tree);
} }
if(args.print_tree) if(args.print_tree)
{ {
@@ -298,7 +304,7 @@ void process_file(Args const& args)
std::string output; std::string output;
{ {
TS(emit_to_buffer); TS(emit_to_buffer);
output.resize(contents.size()); // resize, not just reserve output.resize(contents->size()); // resize, not just reserve
if(!args.emit_as_json) if(!args.emit_as_json)
yml::emitrs_yaml(tree, &output); yml::emitrs_yaml(tree, &output);
else else
@@ -323,7 +329,8 @@ void process_file(Args const& args)
else else
{ {
FILE *output = fopen(args.output.str, "wb"); FILE *output = fopen(args.output.str, "wb");
if (!output) c4::yml::error("could not open file"); if (!output)
_RYML_ERR_BASIC("could not open file: {}", args.output.str);
{ {
TS(emit_to_file); TS(emit_to_file);
if(!args.emit_as_json) if(!args.emit_as_json)
@@ -344,12 +351,19 @@ int main(int argc, const char *argv[])
return 0; return 0;
TS(TOTAL); TS(TOTAL);
set_callbacks(create_custom_callbacks()); set_callbacks(create_custom_callbacks());
TS(TOTAL);
std::string yaml;
C4_IF_EXCEPTIONS_(try, if(setjmp(jmp_env) == 0)) C4_IF_EXCEPTIONS_(try, if(setjmp(jmp_env) == 0))
{ {
process_file(args); process_file(args, &yaml);
} }
C4_IF_EXCEPTIONS_(catch(std::exception const&), else) // LCOV_EXCL_LINE C4_IF_EXCEPTIONS_(catch(std::exception const& exc), else) // LCOV_EXCL_LINE
{ {
C4_IF_EXCEPTIONS(
dump2stderr(to_csubstr(exc.what())); // LCOV_EXCL_LINE
,
dump2stderr(to_csubstr(jmp_msg)); // LCOV_EXCL_LINE
);
return 1; // LCOV_EXCL_LINE return 1; // LCOV_EXCL_LINE
} }
return 0; return 0;

View File

@@ -2,7 +2,9 @@
#include <ryml_all.hpp> #include <ryml_all.hpp>
#else #else
#include <c4/yml/std/std.hpp> #include <c4/yml/std/std.hpp>
#include <c4/yml/error.def.hpp>
#include <c4/yml/parse.hpp> #include <c4/yml/parse.hpp>
#include <c4/yml/error.def.hpp>
#include <c4/yml/event_handler_tree.hpp> #include <c4/yml/event_handler_tree.hpp>
#include <c4/yml/parse_engine.def.hpp> #include <c4/yml/parse_engine.def.hpp>
#endif #endif
@@ -309,7 +311,10 @@ csubstr parse_events_ints(csubstr filename, substr filecontents, std::string &pa
if(timing_enabled) fprintf(stderr, "current_size=%zu vs needed_size=%zu. arena_size=%zu\n", evts.size(), sz, arena.size()); 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()) if (!handler.fits_buffers())
{ {
RYML_CHECK(!fail_size); if(fail_size)
{
_RYML_ERR_BASIC("buffers too small");
}
{ {
STOPWATCH("resize"); STOPWATCH("resize");
evts.resize(sz); evts.resize(sz);
@@ -325,7 +330,7 @@ csubstr parse_events_ints(csubstr filename, substr filecontents, std::string &pa
STOPWATCH("redo_parse"); STOPWATCH("redo_parse");
parser.parse_in_place_ev(filename, src); parser.parse_in_place_ev(filename, src);
} }
RYML_CHECK((size_t)handler.m_evt_pos == sz); _RYML_CHECK_BASIC((size_t)handler.m_evt_pos == sz);
} }
evts.resize(sz); evts.resize(sz);
return src; return src;
@@ -472,41 +477,45 @@ std::string load_file(csubstr filename)
} }
else if(!fs::path_exists(filename.str)) else if(!fs::path_exists(filename.str))
{ {
std::fprintf(stderr, "%s: file not found (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()); // LCOV_EXCL_LINE
error("file not found"); err_basic(RYML_LOC_HERE(), "file not found"); // LCOV_EXCL_LINE
} }
return fs::file_get_contents<std::string>(filename.str); return fs::file_get_contents<std::string>(filename.str);
} }
void report_error(const char* msg, size_t length, Location loc, FILE *f) [[noreturn]] C4_NO_INLINE void throwerr(csubstr msg)
{ {
if(!loc.name.empty()) C4_IF_EXCEPTIONS(
throw std::runtime_error({msg.str, msg.len});
,
jmp_msg.assign(msg.str, msg.len);
std::longjmp(jmp_env, 1);
);
C4_UNREACHABLE_AFTER_ERR();
}
void dump2stderr(csubstr s)
{
if(s.len)
{ {
fwrite(loc.name.str, 1, loc.name.len, f); fwrite(s.str, 1, s.len, stderr); // NOLINT
fputc(':', f); fflush(stderr); // NOLINT
} }
fprintf(f, "%zu:", loc.line);
if(loc.col)
fprintf(f, "%zu:", loc.col);
if(loc.offset)
fprintf(f, " (%zuB):", loc.offset);
fputc(' ', f);
fprintf(f, "%.*s\n", static_cast<int>(length), msg);
fflush(f);
} }
Callbacks create_custom_callbacks() Callbacks create_custom_callbacks()
{ {
Callbacks callbacks = {}; return Callbacks{}
callbacks.m_error = [](const char *msg, size_t msg_len, Location location, void *) .set_error_basic([](csubstr msg, yml::ErrorDataBasic const& errdata, void *){
{ yml::err_basic_format(dump2stderr, msg, errdata); // LCOV_EXCL_LINE
report_error(msg, msg_len, location, stderr); throwerr(msg); // LCOV_EXCL_LINE
C4_IF_EXCEPTIONS( })
throw std::runtime_error({msg, msg_len}); .set_error_parse([](csubstr msg, yml::ErrorDataParse const& errdata, void *){
, yml::err_parse_format(dump2stderr, msg, errdata); // LCOV_EXCL_LINE
jmp_msg.assign(msg, msg_len); throwerr(msg); // LCOV_EXCL_LINE
std::longjmp(jmp_env, 1); })
); .set_error_visit([](csubstr msg, yml::ErrorDataVisit const& errdata, void *){
}; yml::err_visit_format(dump2stderr, msg, errdata); // LCOV_EXCL_LINE
return callbacks; throwerr(msg); // LCOV_EXCL_LINE
});
} }