mirror of https://github.com/tstack/lnav.git
[yajlpp] flesh things out a bit more
This commit is contained in:
parent
468358a358
commit
faeaf477ab
|
@ -453,8 +453,7 @@
|
|||
"field": {
|
||||
"title": "/<format_name>/line-format/field",
|
||||
"description": "The name of the field to substitute at this position",
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
"type": "string"
|
||||
},
|
||||
"default-value": {
|
||||
"title": "/<format_name>/line-format/default-value",
|
||||
|
|
|
@ -232,7 +232,7 @@ extract(const std::string& filename, const extract_cb& cb)
|
|||
}
|
||||
|
||||
auto arc_lock = lnav::filesystem::file_lock(tmp_path);
|
||||
auto lock_guard = lnav::filesystem::file_lock::guard(arc_lock);
|
||||
auto lock_guard = lnav::filesystem::file_lock::guard(&arc_lock);
|
||||
auto done_path = tmp_path;
|
||||
|
||||
done_path += ".done";
|
||||
|
|
|
@ -166,5 +166,18 @@ stat_file(const ghc::filesystem::path& path)
|
|||
strerror(errno)));
|
||||
}
|
||||
|
||||
file_lock::file_lock(const ghc::filesystem::path& archive_path)
|
||||
{
|
||||
auto lock_path = archive_path;
|
||||
|
||||
lock_path += ".lck";
|
||||
auto open_res
|
||||
= lnav::filesystem::create_file(lock_path, O_RDWR | O_CLOEXEC, 0600);
|
||||
if (open_res.isErr()) {
|
||||
throw std::runtime_error(open_res.unwrapErr());
|
||||
}
|
||||
this->lh_fd = open_res.unwrap();
|
||||
}
|
||||
|
||||
} // namespace filesystem
|
||||
} // namespace lnav
|
||||
|
|
|
@ -82,33 +82,36 @@ class file_lock {
|
|||
public:
|
||||
class guard {
|
||||
public:
|
||||
explicit guard(file_lock& arc_lock) : g_lock(arc_lock)
|
||||
explicit guard(file_lock* arc_lock) : g_lock(arc_lock)
|
||||
{
|
||||
this->g_lock.lock();
|
||||
};
|
||||
this->g_lock->lock();
|
||||
}
|
||||
|
||||
~guard() { this->g_lock.unlock(); };
|
||||
guard(guard&& other) noexcept
|
||||
: g_lock(std::exchange(other.g_lock, nullptr))
|
||||
{
|
||||
}
|
||||
|
||||
~guard()
|
||||
{
|
||||
if (this->g_lock != nullptr) {
|
||||
this->g_lock->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
guard(const guard&) = delete;
|
||||
guard& operator=(const guard&) = delete;
|
||||
guard& operator=(guard&&) = delete;
|
||||
|
||||
private:
|
||||
file_lock& g_lock;
|
||||
file_lock* g_lock;
|
||||
};
|
||||
|
||||
void lock() const { lockf(this->lh_fd, F_LOCK, 0); }
|
||||
|
||||
void unlock() const { lockf(this->lh_fd, F_ULOCK, 0); }
|
||||
|
||||
explicit file_lock(const ghc::filesystem::path& archive_path)
|
||||
{
|
||||
auto lock_path = archive_path;
|
||||
|
||||
lock_path += ".lck";
|
||||
auto open_res = lnav::filesystem::create_file(
|
||||
lock_path, O_RDWR | O_CLOEXEC, 0600);
|
||||
if (open_res.isErr()) {
|
||||
throw std::runtime_error(open_res.unwrapErr());
|
||||
}
|
||||
this->lh_fd = open_res.unwrap();
|
||||
}
|
||||
explicit file_lock(const ghc::filesystem::path& archive_path);
|
||||
|
||||
auto_fd lh_fd;
|
||||
};
|
||||
|
|
|
@ -79,7 +79,8 @@ sql_dirname(const char* path_in)
|
|||
|
||||
text_end = strlen(path_in) - 1;
|
||||
while (text_end >= 0
|
||||
&& (path_in[text_end] == '/' || path_in[text_end] == '\\')) {
|
||||
&& (path_in[text_end] == '/' || path_in[text_end] == '\\'))
|
||||
{
|
||||
text_end -= 1;
|
||||
}
|
||||
|
||||
|
@ -249,7 +250,8 @@ fs_extension_functions(struct FuncDef** basic_funcs,
|
|||
* TODO: add other functions like normpath, ...
|
||||
*/
|
||||
|
||||
{nullptr}};
|
||||
{nullptr},
|
||||
};
|
||||
|
||||
*basic_funcs = fs_funcs;
|
||||
*agg_funcs = nullptr;
|
||||
|
|
|
@ -1359,7 +1359,7 @@ line_buffer::enable_cache()
|
|||
"%d:cache file path: %s", this->lb_fd.get(), cached_file_path.c_str());
|
||||
|
||||
auto fl = lnav::filesystem::file_lock(cached_file_path);
|
||||
auto guard = lnav::filesystem::file_lock::guard(fl);
|
||||
auto guard = lnav::filesystem::file_lock::guard(&fl);
|
||||
|
||||
if (ghc::filesystem::exists(cached_done_path)) {
|
||||
log_info("%d:using existing cache file");
|
||||
|
|
|
@ -338,11 +338,12 @@ update_installs_from_git()
|
|||
|
||||
if (glob(git_formats.c_str(), GLOB_NOCHECK, nullptr, gl.inout()) == 0) {
|
||||
for (int lpc = 0; lpc < (int) gl->gl_pathc; lpc++) {
|
||||
char* git_dir = dirname(gl->gl_pathv[lpc]);
|
||||
auto git_dir
|
||||
= ghc::filesystem::path(gl->gl_pathv[lpc]).parent_path();
|
||||
|
||||
printf("Updating formats in %s\n", git_dir);
|
||||
auto pull_cmd
|
||||
= fmt::format(FMT_STRING("cd '{}' && git pull"), git_dir);
|
||||
printf("Updating formats in %s\n", git_dir.c_str());
|
||||
auto pull_cmd = fmt::format(FMT_STRING("cd '{}' && git pull"),
|
||||
git_dir.string());
|
||||
int ret = system(pull_cmd.c_str());
|
||||
if (ret == -1) {
|
||||
std::cerr << "Failed to spawn command "
|
||||
|
@ -519,7 +520,7 @@ static const struct json_path_container global_var_handlers = {
|
|||
paths_out.emplace_back(iter.first);
|
||||
}
|
||||
})
|
||||
.FOR_FIELD(_lnav_config, lc_global_vars),
|
||||
.for_field(&_lnav_config::lc_global_vars),
|
||||
};
|
||||
|
||||
static const struct json_path_container style_config_handlers =
|
||||
|
@ -868,7 +869,7 @@ static const struct json_path_container highlighter_handlers = {
|
|||
yajlpp::property_handler("pattern")
|
||||
.with_synopsis("regular expression")
|
||||
.with_description("The regular expression to highlight")
|
||||
.FOR_FIELD(highlighter_config, hc_regex),
|
||||
.for_field(&highlighter_config::hc_regex),
|
||||
|
||||
yajlpp::property_handler("style")
|
||||
.with_description(
|
||||
|
@ -906,7 +907,7 @@ static const struct json_path_container theme_vars_handlers = {
|
|||
paths_out.emplace_back(iter.first);
|
||||
}
|
||||
})
|
||||
.FOR_FIELD(lnav_theme, lt_vars),
|
||||
.for_field(&lnav_theme::lt_vars),
|
||||
};
|
||||
|
||||
static const struct json_path_container theme_def_handlers = {
|
||||
|
|
|
@ -595,7 +595,7 @@ json_array_end(void* ctx)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static struct json_path_container json_log_handlers = {
|
||||
static const struct json_path_container json_log_handlers = {
|
||||
yajlpp::pattern_property_handler("\\w+")
|
||||
.add_cb(read_json_null)
|
||||
.add_cb(read_json_bool)
|
||||
|
@ -671,7 +671,7 @@ rewrite_json_double(yajlpp_parse_context* ypc, double val)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static struct json_path_container json_log_rewrite_handlers = {
|
||||
static const struct json_path_container json_log_rewrite_handlers = {
|
||||
yajlpp::pattern_property_handler("\\w+")
|
||||
.add_cb(rewrite_json_null)
|
||||
.add_cb(rewrite_json_bool)
|
||||
|
|
|
@ -79,10 +79,8 @@ static external_log_format*
|
|||
ensure_format(const yajlpp_provider_context& ypc, loader_userdata* ud)
|
||||
{
|
||||
const intern_string_t name = ypc.get_substr_i(0);
|
||||
std::vector<intern_string_t>* formats = ud->ud_format_names;
|
||||
external_log_format* retval;
|
||||
|
||||
retval = LOG_FORMATS[name].get();
|
||||
auto* formats = ud->ud_format_names;
|
||||
auto* retval = LOG_FORMATS[name].get();
|
||||
if (retval == nullptr) {
|
||||
LOG_FORMATS[name] = std::make_shared<external_log_format>(name);
|
||||
retval = LOG_FORMATS[name].get();
|
||||
|
@ -95,7 +93,8 @@ ensure_format(const yajlpp_provider_context& ypc, loader_userdata* ud)
|
|||
}
|
||||
|
||||
if (!ud->ud_format_path.empty()) {
|
||||
auto i_src_path = intern_string::lookup(ud->ud_format_path.string());
|
||||
const intern_string_t i_src_path
|
||||
= intern_string::lookup(ud->ud_format_path.string());
|
||||
auto srcs_iter = retval->elf_format_sources.find(i_src_path);
|
||||
if (srcs_iter == retval->elf_format_sources.end()) {
|
||||
retval->elf_format_source_order.emplace_back(ud->ud_format_path);
|
||||
|
@ -175,7 +174,7 @@ scaling_factor_provider(const yajlpp_provider_context& ypc,
|
|||
external_log_format::value_def* value_def)
|
||||
{
|
||||
auto scale_name = ypc.get_substr_i(0);
|
||||
scaling_factor& retval = value_def->vd_unit_scaling[scale_name];
|
||||
auto& retval = value_def->vd_unit_scaling[scale_name];
|
||||
|
||||
return &retval;
|
||||
}
|
||||
|
@ -383,7 +382,7 @@ ensure_sample(external_log_format* elf, int index)
|
|||
static external_log_format::sample*
|
||||
sample_provider(const yajlpp_provider_context& ypc, external_log_format* elf)
|
||||
{
|
||||
external_log_format::sample& sample = ensure_sample(elf, ypc.ypc_index);
|
||||
auto& sample = ensure_sample(elf, ypc.ypc_index);
|
||||
|
||||
return &sample;
|
||||
}
|
||||
|
@ -404,7 +403,7 @@ read_json_constant(yajlpp_parse_context* ypc,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static struct json_path_container pattern_handlers = {
|
||||
static const struct json_path_container pattern_handlers = {
|
||||
yajlpp::property_handler("pattern")
|
||||
.with_synopsis("<message-regex>")
|
||||
.with_description(
|
||||
|
@ -455,12 +454,11 @@ static const json_path_handler_base::enum_value_t TRANSFORM_ENUM[] = {
|
|||
json_path_handler_base::ENUM_TERMINATOR,
|
||||
};
|
||||
|
||||
static struct json_path_container line_format_handlers = {
|
||||
static const struct json_path_container line_format_handlers = {
|
||||
yajlpp::property_handler("field")
|
||||
.with_synopsis("<field-name>")
|
||||
.with_description(
|
||||
"The name of the field to substitute at this position")
|
||||
.with_min_length(1)
|
||||
.for_field(&external_log_format::json_format_element::jfe_value),
|
||||
|
||||
yajlpp::property_handler("default-value")
|
||||
|
@ -530,22 +528,22 @@ static const json_path_handler_base::enum_value_t SCALE_OP_ENUM[] = {
|
|||
json_path_handler_base::ENUM_TERMINATOR,
|
||||
};
|
||||
|
||||
static struct json_path_container scaling_factor_handlers = {
|
||||
static const struct json_path_container scaling_factor_handlers = {
|
||||
yajlpp::pattern_property_handler("op")
|
||||
.with_enum_values(SCALE_OP_ENUM)
|
||||
.for_field(&scaling_factor::sf_op),
|
||||
|
||||
yajlpp::pattern_property_handler("value").FOR_FIELD(scaling_factor,
|
||||
sf_value),
|
||||
yajlpp::pattern_property_handler("value").for_field(
|
||||
&scaling_factor::sf_value),
|
||||
};
|
||||
|
||||
static struct json_path_container scale_handlers = {
|
||||
static const struct json_path_container scale_handlers = {
|
||||
yajlpp::pattern_property_handler("(?<scale>[^/]+)")
|
||||
.with_obj_provider(scaling_factor_provider)
|
||||
.with_children(scaling_factor_handlers),
|
||||
};
|
||||
|
||||
static struct json_path_container unit_handlers = {
|
||||
static const struct json_path_container unit_handlers = {
|
||||
yajlpp::property_handler("field")
|
||||
.with_synopsis("<field-name>")
|
||||
.with_description(
|
||||
|
@ -557,7 +555,7 @@ static struct json_path_container unit_handlers = {
|
|||
.with_children(scale_handlers),
|
||||
};
|
||||
|
||||
static struct json_path_container value_def_handlers = {
|
||||
static const struct json_path_container value_def_handlers = {
|
||||
yajlpp::property_handler("kind")
|
||||
.with_synopsis("<data-type>")
|
||||
.with_description("The type of data in the field")
|
||||
|
@ -597,7 +595,7 @@ static struct json_path_container value_def_handlers = {
|
|||
yajlpp::property_handler("action-list#")
|
||||
.with_synopsis("<string>")
|
||||
.with_description("Actions to execute when this field is clicked on")
|
||||
.FOR_FIELD(external_log_format::value_def, vd_action_list),
|
||||
.for_field(&external_log_format::value_def::vd_action_list),
|
||||
|
||||
yajlpp::property_handler("rewriter")
|
||||
.with_synopsis("<command>")
|
||||
|
@ -613,7 +611,7 @@ static struct json_path_container value_def_handlers = {
|
|||
.for_field(&external_log_format::value_def::vd_description),
|
||||
};
|
||||
|
||||
static struct json_path_container highlighter_def_handlers = {
|
||||
static const struct json_path_container highlighter_def_handlers = {
|
||||
yajlpp::property_handler("pattern")
|
||||
.with_synopsis("<regex>")
|
||||
.with_description(
|
||||
|
@ -660,7 +658,7 @@ static const json_path_handler_base::enum_value_t LEVEL_ENUM[] = {
|
|||
json_path_handler_base::ENUM_TERMINATOR,
|
||||
};
|
||||
|
||||
static struct json_path_container sample_handlers = {
|
||||
static const struct json_path_container sample_handlers = {
|
||||
yajlpp::property_handler("description")
|
||||
.with_synopsis("<text>")
|
||||
.with_description("A description of this sample.")
|
||||
|
@ -685,14 +683,14 @@ static const json_path_handler_base::enum_value_t TYPE_ENUM[] = {
|
|||
json_path_handler_base::ENUM_TERMINATOR,
|
||||
};
|
||||
|
||||
static struct json_path_container regex_handlers = {
|
||||
static const struct json_path_container regex_handlers = {
|
||||
yajlpp::pattern_property_handler(R"((?<pattern_name>[^/]+))")
|
||||
.with_description("The set of patterns used to match log messages")
|
||||
.with_obj_provider(pattern_provider)
|
||||
.with_children(pattern_handlers),
|
||||
};
|
||||
|
||||
static struct json_path_container level_handlers = {
|
||||
static const struct json_path_container level_handlers = {
|
||||
yajlpp::pattern_property_handler("(?<level>trace|debug[2345]?|info|stats|"
|
||||
"notice|warning|error|critical|fatal)")
|
||||
.add_cb(read_levels)
|
||||
|
@ -704,7 +702,7 @@ static struct json_path_container level_handlers = {
|
|||
"the number for the corresponding level."),
|
||||
};
|
||||
|
||||
static struct json_path_container value_handlers = {
|
||||
static const struct json_path_container value_handlers = {
|
||||
yajlpp::pattern_property_handler("(?<value_name>[^/]+)")
|
||||
.with_description(
|
||||
"The set of values captured by the log message patterns")
|
||||
|
@ -712,7 +710,7 @@ static struct json_path_container value_handlers = {
|
|||
.with_children(value_def_handlers),
|
||||
};
|
||||
|
||||
static struct json_path_container tag_path_handlers = {
|
||||
static const struct json_path_container tag_path_handlers = {
|
||||
yajlpp::property_handler("glob")
|
||||
.with_synopsis("<glob>")
|
||||
.with_description("The glob to match against file paths")
|
||||
|
@ -720,7 +718,7 @@ static struct json_path_container tag_path_handlers = {
|
|||
.for_field(&format_tag_def::path_restriction::p_glob),
|
||||
};
|
||||
|
||||
static struct json_path_container format_tag_def_handlers = {
|
||||
static const struct json_path_container format_tag_def_handlers = {
|
||||
yajlpp::property_handler("paths#")
|
||||
.with_description("Restrict tagging to the given paths")
|
||||
.for_field(&format_tag_def::ftd_paths)
|
||||
|
@ -742,14 +740,14 @@ static struct json_path_container format_tag_def_handlers = {
|
|||
.for_field(&format_tag_def::ftd_level),
|
||||
};
|
||||
|
||||
static struct json_path_container tag_handlers = {
|
||||
static const struct json_path_container tag_handlers = {
|
||||
yajlpp::pattern_property_handler(R"((?<tag_name>[\w:;\._\-]+))")
|
||||
.with_description("The name of the tag to apply")
|
||||
.with_obj_provider(format_tag_def_provider)
|
||||
.with_children(format_tag_def_handlers),
|
||||
};
|
||||
|
||||
static struct json_path_container highlight_handlers = {
|
||||
static const struct json_path_container highlight_handlers = {
|
||||
yajlpp::pattern_property_handler(R"((?<highlight_name>[^/]+))")
|
||||
.with_description("The definition of a highlight")
|
||||
.with_obj_provider<external_log_format::highlighter_def,
|
||||
|
@ -763,20 +761,20 @@ static struct json_path_container highlight_handlers = {
|
|||
.with_children(highlighter_def_handlers),
|
||||
};
|
||||
|
||||
static struct json_path_container action_def_handlers = {
|
||||
static const struct json_path_container action_def_handlers = {
|
||||
json_path_handler("label", read_action_def),
|
||||
json_path_handler("capture-output", read_action_bool),
|
||||
json_path_handler("cmd#", read_action_cmd),
|
||||
};
|
||||
|
||||
static struct json_path_container action_handlers = {
|
||||
static const struct json_path_container action_handlers = {
|
||||
json_path_handler(
|
||||
lnav::pcre2pp::code::from_const("(?<action_name>\\w+)").to_shared(),
|
||||
read_action_def)
|
||||
.with_children(action_def_handlers),
|
||||
};
|
||||
|
||||
static struct json_path_container search_table_def_handlers = {
|
||||
static const struct json_path_container search_table_def_handlers = {
|
||||
json_path_handler("pattern")
|
||||
.with_synopsis("<regex>")
|
||||
.with_description("The regular expression for this search table.")
|
||||
|
@ -793,7 +791,7 @@ static struct json_path_container search_table_def_handlers = {
|
|||
.for_field(&external_log_format::search_table_def::std_level),
|
||||
};
|
||||
|
||||
static struct json_path_container search_table_handlers = {
|
||||
static const struct json_path_container search_table_handlers = {
|
||||
yajlpp::pattern_property_handler("(?<table_name>\\w+)")
|
||||
.with_description(
|
||||
"The set of search tables to be automatically defined")
|
||||
|
@ -816,7 +814,7 @@ static const json_path_handler_base::enum_value_t MIME_TYPE_ENUM[] = {
|
|||
json_path_handler_base::ENUM_TERMINATOR,
|
||||
};
|
||||
|
||||
struct json_path_container format_handlers = {
|
||||
const struct json_path_container format_handlers = {
|
||||
yajlpp::property_handler("regex")
|
||||
.with_description(
|
||||
"The set of regular expressions used to match log messages")
|
||||
|
@ -978,7 +976,7 @@ read_id(yajlpp_parse_context* ypc, const unsigned char* str, size_t len)
|
|||
return 1;
|
||||
}
|
||||
|
||||
struct json_path_container root_format_handler = json_path_container{
|
||||
const struct json_path_container root_format_handler = json_path_container{
|
||||
json_path_handler("$schema", read_id)
|
||||
.with_synopsis("The URI of the schema for this file")
|
||||
.with_description("Specifies the type of this file"),
|
||||
|
@ -1034,15 +1032,13 @@ write_sample_file()
|
|||
struct script_metadata meta;
|
||||
auto sf = bsf.to_string_fragment();
|
||||
auto_fd script_fd;
|
||||
struct stat st;
|
||||
|
||||
extract_metadata(sf, meta);
|
||||
auto path
|
||||
= fmt::format(FMT_STRING("formats/default/{}.lnav"), meta.sm_name);
|
||||
auto script_path = lnav::paths::dotlnav() / path;
|
||||
if (lnav::filesystem::statp(script_path, &st) == 0
|
||||
&& st.st_size == sf.length())
|
||||
{
|
||||
auto stat_res = lnav::filesystem::stat_file(script_path);
|
||||
if (stat_res.isOk() && stat_res.unwrap().st_size == sf.length()) {
|
||||
// Assume it's the right contents and move on...
|
||||
continue;
|
||||
}
|
||||
|
@ -1167,19 +1163,19 @@ load_from_path(const ghc::filesystem::path& path,
|
|||
log_info("loading formats from path: %s", format_path.c_str());
|
||||
if (glob(format_path.c_str(), 0, nullptr, gl.inout()) == 0) {
|
||||
for (int lpc = 0; lpc < (int) gl->gl_pathc; lpc++) {
|
||||
const char* base = basename(gl->gl_pathv[lpc]);
|
||||
auto filepath = ghc::filesystem::path(gl->gl_pathv[lpc]);
|
||||
|
||||
if (startswith(base, "config.")) {
|
||||
if (startswith(filepath.filename().string(), "config.")) {
|
||||
log_info(" not loading config as format: %s",
|
||||
filepath.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string filename(gl->gl_pathv[lpc]);
|
||||
std::vector<intern_string_t> format_list;
|
||||
|
||||
format_list = load_format_file(filename, errors);
|
||||
auto format_list = load_format_file(filepath, errors);
|
||||
if (format_list.empty()) {
|
||||
log_warning("Empty format file: %s", filename.c_str());
|
||||
log_warning("Empty format file: %s", filepath.c_str());
|
||||
} else {
|
||||
log_info("contents of format file '%s':", filepath.c_str());
|
||||
for (auto iter = format_list.begin(); iter != format_list.end();
|
||||
++iter)
|
||||
{
|
||||
|
@ -1217,8 +1213,7 @@ load_formats(const std::vector<ghc::filesystem::path>& extra_paths,
|
|||
yajl_config(handle, yajl_allow_comments, 1);
|
||||
auto sf = bsf.to_string_fragment();
|
||||
if (ypc_builtin.parse(sf) != yajl_status_ok) {
|
||||
unsigned char* msg = yajl_get_error(
|
||||
handle, 1, (const unsigned char*) sf.data(), sf.length());
|
||||
auto* msg = yajl_get_error(handle, 1, sf.udata(), sf.length());
|
||||
|
||||
errors.emplace_back(
|
||||
lnav::console::user_message::error("invalid json")
|
||||
|
@ -1402,19 +1397,34 @@ extract_metadata(string_fragment contents, struct script_metadata& meta_out)
|
|||
void
|
||||
extract_metadata_from_file(struct script_metadata& meta_inout)
|
||||
{
|
||||
auto stat_res = lnav::filesystem::stat_file(meta_inout.sm_path);
|
||||
if (stat_res.isErr()) {
|
||||
log_warning("unable to open script: %s -- %s",
|
||||
meta_inout.sm_path.c_str(),
|
||||
stat_res.unwrapErr().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
auto st = stat_res.unwrap();
|
||||
if (!S_ISREG(st.st_mode)) {
|
||||
log_warning("script is not a regular file -- %s",
|
||||
meta_inout.sm_path.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
auto open_res = lnav::filesystem::open_file(meta_inout.sm_path, O_RDONLY);
|
||||
if (open_res.isErr()) {
|
||||
log_warning("unable to open script file: %s -- %s",
|
||||
meta_inout.sm_path.c_str(),
|
||||
open_res.unwrapErr().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
auto fd = open_res.unwrap();
|
||||
char buffer[8 * 1024];
|
||||
auto_mem<FILE> fp(fclose);
|
||||
struct stat st;
|
||||
|
||||
if (lnav::filesystem::statp(meta_inout.sm_path, &st) == -1) {
|
||||
log_warning("unable to open script -- %s", meta_inout.sm_path.c_str());
|
||||
} else if (!S_ISREG(st.st_mode)) {
|
||||
log_warning("not a regular file -- %s", meta_inout.sm_path.c_str());
|
||||
} else if ((fp = fopen(meta_inout.sm_path.c_str(), "r")) != nullptr) {
|
||||
size_t len;
|
||||
|
||||
len = fread(buffer, 1, sizeof(buffer), fp.in());
|
||||
extract_metadata(string_fragment::from_bytes(buffer, len), meta_inout);
|
||||
auto rc = read(fd, buffer, sizeof(buffer));
|
||||
if (rc > 0) {
|
||||
extract_metadata(string_fragment::from_bytes(buffer, rc), meta_inout);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ struct available_scripts {
|
|||
void find_format_scripts(const std::vector<ghc::filesystem::path>& extra_paths,
|
||||
available_scripts& scripts);
|
||||
|
||||
extern struct json_path_container format_handlers;
|
||||
extern struct json_path_container root_format_handler;
|
||||
extern const struct json_path_container format_handlers;
|
||||
extern const struct json_path_container root_format_handler;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1890,12 +1890,12 @@ vt_best_index(sqlite3_vtab* tab, sqlite3_index_info* p_info)
|
|||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
static struct json_path_container tags_handler = {
|
||||
static const struct json_path_container tags_handler = {
|
||||
json_path_handler("#")
|
||||
.with_synopsis("tag")
|
||||
.with_description("A tag for the log line")
|
||||
.with_pattern(R"(^#[^\s]+$)")
|
||||
.FOR_FIELD(bookmark_metadata, bm_tags),
|
||||
.for_field(&bookmark_metadata::bm_tags),
|
||||
};
|
||||
|
||||
static int
|
||||
|
|
|
@ -153,8 +153,6 @@ logfile::~logfile() {}
|
|||
bool
|
||||
logfile::exists() const
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (!this->lf_actual_path) {
|
||||
return true;
|
||||
}
|
||||
|
@ -163,13 +161,15 @@ logfile::exists() const
|
|||
return true;
|
||||
}
|
||||
|
||||
if (lnav::filesystem::statp(this->lf_actual_path.value(), &st) == -1) {
|
||||
auto stat_res = lnav::filesystem::stat_file(this->lf_actual_path.value());
|
||||
if (stat_res.isErr()) {
|
||||
log_error("%s: stat failed -- %s",
|
||||
this->lf_actual_path.value().c_str(),
|
||||
strerror(errno));
|
||||
stat_res.unwrapErr().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
auto st = stat_res.unwrap();
|
||||
return this->lf_stat.st_dev == st.st_dev
|
||||
&& this->lf_stat.st_ino == st.st_ino
|
||||
&& this->lf_stat.st_size <= st.st_size;
|
||||
|
|
|
@ -862,7 +862,7 @@ read_commands(yajlpp_parse_context* ypc, const unsigned char* str, size_t len)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static struct json_path_container view_def_handlers = {
|
||||
static const struct json_path_container view_def_handlers = {
|
||||
json_path_handler("top_line", read_top_line),
|
||||
json_path_handler("search", read_current_search),
|
||||
json_path_handler("word_wrap", read_word_wrap),
|
||||
|
@ -870,18 +870,18 @@ static struct json_path_container view_def_handlers = {
|
|||
json_path_handler("commands#", read_commands),
|
||||
};
|
||||
|
||||
static struct json_path_container view_handlers = {
|
||||
static const struct json_path_container view_handlers = {
|
||||
yajlpp::pattern_property_handler("([^/]+)").with_children(
|
||||
view_def_handlers),
|
||||
};
|
||||
|
||||
static struct json_path_container file_state_handlers = {
|
||||
static const struct json_path_container file_state_handlers = {
|
||||
yajlpp::property_handler("visible")
|
||||
.with_description("Indicates whether the file is visible or not")
|
||||
.for_field(&file_state::fs_is_visible),
|
||||
};
|
||||
|
||||
static struct json_path_container file_states_handlers = {
|
||||
static const struct json_path_container file_states_handlers = {
|
||||
yajlpp::pattern_property_handler(R"((?<filename>[^/]+))")
|
||||
.with_description("Map of file names to file state objects")
|
||||
.with_obj_provider<file_state, void>([](const auto& ypc, auto* root) {
|
||||
|
@ -891,7 +891,7 @@ static struct json_path_container file_states_handlers = {
|
|||
.with_children(file_state_handlers),
|
||||
};
|
||||
|
||||
static struct json_path_container view_info_handlers = {
|
||||
static const struct json_path_container view_info_handlers = {
|
||||
yajlpp::property_handler("save-time")
|
||||
.for_field(&session_data_t::sd_save_time),
|
||||
yajlpp::property_handler("time-offset")
|
||||
|
|
|
@ -269,7 +269,7 @@ tailer::looper::complete_path(const network::path& path)
|
|||
static std::vector<std::string>
|
||||
create_ssh_args_from_config(const std::string& dest)
|
||||
{
|
||||
auto& cfg = injector::get<const tailer::config&>();
|
||||
const auto& cfg = injector::get<const tailer::config&>();
|
||||
std::vector<std::string> retval;
|
||||
|
||||
retval.emplace_back(cfg.c_ssh_cmd);
|
||||
|
|
|
@ -383,7 +383,7 @@ json_path_handler_base::gen_schema(yajlpp_gen_context& ygc) const
|
|||
schema.gen("examples");
|
||||
|
||||
yajlpp_array example_array(ygc.ygc_handle);
|
||||
for (auto& ex : this->jph_examples) {
|
||||
for (const auto& ex : this->jph_examples) {
|
||||
example_array.gen(ex);
|
||||
}
|
||||
}
|
||||
|
@ -1107,7 +1107,7 @@ yajlpp_parse_context::reset(const struct json_path_container* handlers)
|
|||
}
|
||||
|
||||
void
|
||||
yajlpp_parse_context::set_static_handler(json_path_handler_base& jph)
|
||||
yajlpp_parse_context::set_static_handler(const json_path_handler_base& jph)
|
||||
{
|
||||
this->ypc_path.clear();
|
||||
this->ypc_path.push_back('/');
|
||||
|
@ -1310,6 +1310,40 @@ yajlpp_parse_context::get_snippet() const
|
|||
.with_line(line_number);
|
||||
}
|
||||
|
||||
void
|
||||
json_path_handler_base::validate_string(yajlpp_parse_context& ypc,
|
||||
string_fragment sf) const
|
||||
{
|
||||
if (this->jph_pattern) {
|
||||
if (!this->jph_pattern->find_in(sf).ignore_error()) {
|
||||
this->report_pattern_error(&ypc, sf.to_string());
|
||||
}
|
||||
}
|
||||
if (sf.empty() && this->jph_min_length > 0) {
|
||||
ypc.report_error(lnav::console::user_message::error(
|
||||
attr_line_t("invalid value for option ")
|
||||
.append_quoted(lnav::roles::symbol(
|
||||
ypc.get_full_path().to_string())))
|
||||
.with_reason("empty values are not allowed")
|
||||
.with_snippet(ypc.get_snippet())
|
||||
.with_help(this->get_help_text(&ypc)));
|
||||
} else if (sf.length() < this->jph_min_length) {
|
||||
ypc.report_error(
|
||||
lnav::console::user_message::error(
|
||||
attr_line_t()
|
||||
.append_quoted(sf)
|
||||
.append(" is not a valid value for option ")
|
||||
.append_quoted(
|
||||
lnav::roles::symbol(ypc.get_full_path().to_string())))
|
||||
.with_reason(attr_line_t("value must be at least ")
|
||||
.append(lnav::roles::number(
|
||||
fmt::to_string(this->jph_min_length)))
|
||||
.append(" characters long"))
|
||||
.with_snippet(ypc.get_snippet())
|
||||
.with_help(this->get_help_text(&ypc)));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
json_path_handler_base::report_pattern_error(yajlpp_parse_context* ypc,
|
||||
const std::string& value_str) const
|
||||
|
@ -1378,8 +1412,6 @@ void
|
|||
json_path_handler_base::report_min_value_error(yajlpp_parse_context* ypc,
|
||||
long long value) const
|
||||
{
|
||||
const auto* jph = ypc->ypc_current_handler;
|
||||
|
||||
ypc->report_error(
|
||||
lnav::console::user_message::error(
|
||||
attr_line_t()
|
||||
|
@ -1389,9 +1421,9 @@ json_path_handler_base::report_min_value_error(yajlpp_parse_context* ypc,
|
|||
lnav::roles::symbol(ypc->get_full_path().to_string())))
|
||||
.with_reason(attr_line_t("value must be greater than or equal to ")
|
||||
.append(lnav::roles::number(
|
||||
fmt::to_string(jph->jph_min_value))))
|
||||
fmt::to_string(this->jph_min_value))))
|
||||
.with_snippet(ypc->get_snippet())
|
||||
.with_help(jph->get_help_text(ypc)));
|
||||
.with_help(this->get_help_text(ypc)));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1465,7 +1497,7 @@ json_path_container::gen_properties(yajlpp_gen_context& ygc) const
|
|||
{
|
||||
yajlpp_map properties(ygc.ygc_handle);
|
||||
|
||||
for (auto& child_handler : this->jpc_children) {
|
||||
for (const auto& child_handler : this->jpc_children) {
|
||||
if (child_handler.jph_is_pattern_property) {
|
||||
continue;
|
||||
}
|
||||
|
@ -1529,5 +1561,5 @@ yajlpp_gen::to_string_fragment()
|
|||
|
||||
yajl_gen_get_buf(this->yg_handle.in(), &buf, &len);
|
||||
|
||||
return string_fragment((const char*) buf, 0, len);
|
||||
return string_fragment::from_bytes(buf, len);
|
||||
}
|
||||
|
|
|
@ -282,10 +282,13 @@ struct json_path_handler_base {
|
|||
std::function<int(yajlpp_parse_context*)> jph_null_cb;
|
||||
std::function<int(yajlpp_parse_context*, int)> jph_bool_cb;
|
||||
std::function<int(yajlpp_parse_context*, long long)> jph_integer_cb;
|
||||
std::function<int(yajlpp_parse_context*, double)> jph_double_cb;
|
||||
std::function<int(
|
||||
yajlpp_parse_context*, const unsigned char* str, size_t len)>
|
||||
jph_str_cb;
|
||||
|
||||
void validate_string(yajlpp_parse_context& ypc, string_fragment sf) const;
|
||||
|
||||
void report_pattern_error(yajlpp_parse_context* ypc,
|
||||
const std::string& value_str) const;
|
||||
void report_min_value_error(yajlpp_parse_context* ypc,
|
||||
|
@ -350,7 +353,7 @@ public:
|
|||
|
||||
void reset(const struct json_path_container* handlers);
|
||||
|
||||
void set_static_handler(struct json_path_handler_base& jph);
|
||||
void set_static_handler(const struct json_path_handler_base& jph);
|
||||
|
||||
template<typename T>
|
||||
yajlpp_parse_context& with_obj(T& obj)
|
||||
|
|
|
@ -41,33 +41,6 @@
|
|||
#include "relative_time.hh"
|
||||
#include "yajlpp.hh"
|
||||
|
||||
#define FOR_FIELD(T, FIELD) for_field<T, decltype(T ::FIELD), &T ::FIELD>()
|
||||
|
||||
inline intern_string_t&
|
||||
assign(intern_string_t& lhs, const string_fragment& rhs)
|
||||
{
|
||||
lhs = intern_string::lookup(rhs.data(), rhs.length());
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
inline std::string&
|
||||
assign(std::string& lhs, const string_fragment& rhs)
|
||||
{
|
||||
lhs.assign(rhs.data(), rhs.length());
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
template<template<typename...> class Container>
|
||||
inline Container<std::string>&
|
||||
assign(Container<std::string>& lhs, const string_fragment& rhs)
|
||||
{
|
||||
lhs.emplace_back(rhs.data(), rhs.length());
|
||||
|
||||
return lhs;
|
||||
}
|
||||
|
||||
struct json_null_t {
|
||||
bool operator==(const json_null_t& other) const { return true; }
|
||||
};
|
||||
|
@ -246,54 +219,6 @@ struct json_path_handler : public json_path_handler_base {
|
|||
return *this;
|
||||
}
|
||||
|
||||
template<typename T, typename MEM_T, MEM_T T::*MEM>
|
||||
static void* get_field_lvalue_cb(void* root,
|
||||
nonstd::optional<std::string> name)
|
||||
{
|
||||
auto obj = (T*) root;
|
||||
auto& mem = obj->*MEM;
|
||||
|
||||
return &mem;
|
||||
}
|
||||
|
||||
template<typename T, typename STR_T, STR_T T::*STR>
|
||||
static int string_field_cb(yajlpp_parse_context* ypc,
|
||||
const unsigned char* str,
|
||||
size_t len)
|
||||
{
|
||||
auto handler = ypc->ypc_current_handler;
|
||||
|
||||
if (ypc->ypc_locations) {
|
||||
(*ypc->ypc_locations)[ypc->get_full_path()]
|
||||
= source_location{ypc->ypc_source, ypc->get_line_number()};
|
||||
}
|
||||
|
||||
assign(ypc->get_lvalue(ypc->get_obj_member<T, STR_T, STR>()),
|
||||
string_fragment(str, 0, len));
|
||||
handler->jph_validator(*ypc, *handler);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T, typename ENUM_T, ENUM_T T::*ENUM>
|
||||
static int enum_field_cb(yajlpp_parse_context* ypc,
|
||||
const unsigned char* str,
|
||||
size_t len)
|
||||
{
|
||||
auto obj = (T*) ypc->ypc_obj_stack.top();
|
||||
auto handler = ypc->ypc_current_handler;
|
||||
auto res = handler->to_enum_value(string_fragment(str, 0, len));
|
||||
|
||||
if (res) {
|
||||
obj->*ENUM = (ENUM_T) res.value();
|
||||
} else {
|
||||
handler->report_enum_error(ypc,
|
||||
std::string((const char*) str, len));
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int null_field_cb(yajlpp_parse_context* ypc)
|
||||
{
|
||||
return ypc->ypc_current_handler->jph_null_cb(ypc);
|
||||
|
@ -316,204 +241,9 @@ struct json_path_handler : public json_path_handler_base {
|
|||
return ypc->ypc_current_handler->jph_integer_cb(ypc, val);
|
||||
}
|
||||
|
||||
template<typename T, typename NUM_T, NUM_T T::*NUM>
|
||||
static int num_field_cb(yajlpp_parse_context* ypc, long long num)
|
||||
static int dbl_field_cb(yajlpp_parse_context* ypc, double val)
|
||||
{
|
||||
auto obj = (T*) ypc->ypc_obj_stack.top();
|
||||
|
||||
obj->*NUM = num;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T, typename NUM_T, NUM_T T::*NUM>
|
||||
static int decimal_field_cb(yajlpp_parse_context* ypc, double num)
|
||||
{
|
||||
auto obj = (T*) ypc->ypc_obj_stack.top();
|
||||
|
||||
obj->*NUM = num;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename T, typename STR_T, STR_T T::*STR>
|
||||
static void string_field_validator(yajlpp_parse_context& ypc,
|
||||
const json_path_handler_base& jph)
|
||||
{
|
||||
auto& field_ptr = ypc.get_rvalue(ypc.get_obj_member<T, STR_T, STR>());
|
||||
|
||||
if (jph.jph_pattern) {
|
||||
auto sf = to_string_fragment(field_ptr);
|
||||
|
||||
if (!jph.jph_pattern->find_in(sf).ignore_error()) {
|
||||
jph.report_pattern_error(&ypc, sf.to_string());
|
||||
}
|
||||
}
|
||||
if (field_ptr.empty() && jph.jph_min_length > 0) {
|
||||
ypc.report_error(
|
||||
lnav::console::user_message::error(
|
||||
attr_line_t("invalid value for option ")
|
||||
.template append_quoted(lnav::roles::symbol(
|
||||
ypc.get_full_path().to_string())))
|
||||
.with_reason("empty values are not allowed")
|
||||
.with_snippet(ypc.get_snippet())
|
||||
.with_help(jph.get_help_text(&ypc)));
|
||||
} else if (field_ptr.size() < jph.jph_min_length) {
|
||||
ypc.report_error(
|
||||
lnav::console::user_message::error(
|
||||
attr_line_t()
|
||||
.template append_quoted(field_ptr)
|
||||
.append(" is not a valid value for option ")
|
||||
.append_quoted(lnav::roles::symbol(
|
||||
ypc.get_full_path().to_string())))
|
||||
.with_reason(attr_line_t("value must be at least ")
|
||||
.append(lnav::roles::number(
|
||||
fmt::to_string(jph.jph_min_length)))
|
||||
.append(" characters long"))
|
||||
.with_snippet(ypc.get_snippet())
|
||||
.with_help(jph.get_help_text(&ypc)));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, typename NUM_T, NUM_T T::*NUM>
|
||||
static void number_field_validator(yajlpp_parse_context& ypc,
|
||||
const json_path_handler_base& jph)
|
||||
{
|
||||
auto& field_ptr = ypc.get_rvalue(ypc.get_obj_member<T, NUM_T, NUM>());
|
||||
|
||||
if (field_ptr < jph.jph_min_value) {
|
||||
jph.report_min_value_error(&ypc, field_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, typename R, R T::*FIELD>
|
||||
static yajl_gen_status field_gen(yajlpp_gen_context& ygc,
|
||||
const json_path_handler_base& jph,
|
||||
yajl_gen handle)
|
||||
{
|
||||
auto def_obj = (T*) (ygc.ygc_default_stack.empty()
|
||||
? nullptr
|
||||
: ygc.ygc_default_stack.top());
|
||||
auto obj = (T*) ygc.ygc_obj_stack.top();
|
||||
|
||||
if (def_obj != nullptr && def_obj->*FIELD == obj->*FIELD) {
|
||||
return yajl_gen_status_ok;
|
||||
}
|
||||
|
||||
if (ygc.ygc_depth) {
|
||||
yajl_gen_string(handle, jph.jph_property);
|
||||
}
|
||||
|
||||
yajlpp_generator gen(handle);
|
||||
|
||||
return gen(obj->*FIELD);
|
||||
}
|
||||
|
||||
template<typename T, typename R, R T::*FIELD>
|
||||
static yajl_gen_status map_field_gen(yajlpp_gen_context& ygc,
|
||||
const json_path_handler_base& jph,
|
||||
yajl_gen handle)
|
||||
{
|
||||
const auto def_container = (T*) (ygc.ygc_default_stack.empty()
|
||||
? nullptr
|
||||
: ygc.ygc_default_stack.top());
|
||||
auto container = (T*) ygc.ygc_obj_stack.top();
|
||||
auto& obj = container->*FIELD;
|
||||
yajl_gen_status rc;
|
||||
|
||||
for (const auto& pair : obj) {
|
||||
if (def_container != nullptr) {
|
||||
auto& def_obj = def_container->*FIELD;
|
||||
auto iter = def_obj.find(pair.first);
|
||||
|
||||
if (iter != def_obj.end() && iter->second == pair.second) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ((rc = yajl_gen_string(handle, pair.first))
|
||||
!= yajl_gen_status_ok)
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
if ((rc = yajl_gen_string(handle, pair.second))
|
||||
!= yajl_gen_status_ok)
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
return yajl_gen_status_ok;
|
||||
}
|
||||
|
||||
template<typename T, typename STR_T, std::string T::*STR>
|
||||
json_path_handler& for_field()
|
||||
{
|
||||
this->add_cb(string_field_cb<T, STR_T, STR>);
|
||||
this->jph_gen_callback = field_gen<T, STR_T, STR>;
|
||||
this->jph_validator = string_field_validator<T, STR_T, STR>;
|
||||
this->jph_field_getter = get_field_lvalue_cb<T, STR_T, STR>;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T,
|
||||
typename STR_T,
|
||||
std::map<std::string, std::string> T::*STR>
|
||||
json_path_handler& for_field()
|
||||
{
|
||||
this->add_cb(string_field_cb<T, STR_T, STR>);
|
||||
this->jph_gen_callback = map_field_gen<T, STR_T, STR>;
|
||||
this->jph_validator = string_field_validator<T, STR_T, STR>;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T,
|
||||
typename STR_T,
|
||||
std::map<std::string, std::vector<std::string>> T::*STR>
|
||||
json_path_handler& for_field()
|
||||
{
|
||||
this->add_cb(string_field_cb<T, STR_T, STR>);
|
||||
this->jph_validator = string_field_validator<T, STR_T, STR>;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T, typename STR_T, std::vector<std::string> T::*STR>
|
||||
json_path_handler& for_field()
|
||||
{
|
||||
this->add_cb(string_field_cb<T, STR_T, STR>);
|
||||
this->jph_gen_callback = field_gen<T, STR_T, STR>;
|
||||
this->jph_validator = string_field_validator<T, STR_T, STR>;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T, typename STR_T, intern_string_t T::*STR>
|
||||
json_path_handler& for_field()
|
||||
{
|
||||
this->add_cb(string_field_cb<T, intern_string_t, STR>);
|
||||
this->jph_gen_callback = field_gen<T, intern_string_t, STR>;
|
||||
this->jph_validator = string_field_validator<T, intern_string_t, STR>;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T, typename BOOL_T, bool T::*BOOL>
|
||||
json_path_handler& for_field()
|
||||
{
|
||||
this->add_cb(bool_field_cb);
|
||||
this->jph_bool_cb = [&](yajlpp_parse_context* ypc, int val) {
|
||||
auto obj = (T*) ypc->ypc_obj_stack.top();
|
||||
|
||||
obj->*BOOL = static_cast<bool>(val);
|
||||
|
||||
return 1;
|
||||
};
|
||||
this->jph_gen_callback = field_gen<T, bool, BOOL>;
|
||||
|
||||
return *this;
|
||||
return ypc->ypc_current_handler->jph_double_cb(ypc, val);
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
|
@ -572,22 +302,37 @@ struct json_path_handler : public json_path_handler_base {
|
|||
};
|
||||
|
||||
template<typename T, typename... Args>
|
||||
struct LastIsNumber {
|
||||
static constexpr bool value = LastIsNumber<Args...>::value;
|
||||
struct LastIsInteger {
|
||||
static constexpr bool value = LastIsInteger<Args...>::value;
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct LastIsNumber<U T::*> {
|
||||
struct LastIsInteger<U T::*> {
|
||||
static constexpr bool value
|
||||
= std::is_integral<U>::value && !std::is_same<U, bool>::value;
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct LastIsNumber<nonstd::optional<U> T::*> {
|
||||
struct LastIsInteger<nonstd::optional<U> T::*> {
|
||||
static constexpr bool value
|
||||
= std::is_integral<U>::value && !std::is_same<U, bool>::value;
|
||||
};
|
||||
|
||||
template<typename T, typename... Args>
|
||||
struct LastIsFloat {
|
||||
static constexpr bool value = LastIsFloat<Args...>::value;
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct LastIsFloat<U T::*> {
|
||||
static constexpr bool value = std::is_same<U, double>::value;
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct LastIsFloat<nonstd::optional<U> T::*> {
|
||||
static constexpr bool value = std::is_same<U, double>::value;
|
||||
};
|
||||
|
||||
template<typename T, typename... Args>
|
||||
struct LastIsVector {
|
||||
using value_type = typename LastIsVector<Args...>::value_type;
|
||||
|
@ -675,12 +420,7 @@ struct json_path_handler : public json_path_handler_base {
|
|||
auto value_str = std::string((const char*) str, len);
|
||||
auto jph = ypc->ypc_current_handler;
|
||||
|
||||
if (jph->jph_pattern) {
|
||||
if (!jph->jph_pattern->find_in(value_str).ignore_error()) {
|
||||
jph->report_pattern_error(ypc, value_str);
|
||||
}
|
||||
}
|
||||
|
||||
jph->validate_string(*ypc, value_str);
|
||||
json_path_handler::get_field(obj, args...)
|
||||
.emplace_back(std::move(value_str));
|
||||
|
||||
|
@ -937,12 +677,7 @@ struct json_path_handler : public json_path_handler_base {
|
|||
auto value_str = std::string((const char*) str, len);
|
||||
auto jph = ypc->ypc_current_handler;
|
||||
|
||||
if (jph->jph_pattern) {
|
||||
if (!jph->jph_pattern->find_in(value_str).ignore_error()) {
|
||||
jph->report_pattern_error(ypc, value_str);
|
||||
}
|
||||
}
|
||||
|
||||
jph->validate_string(*ypc, value_str);
|
||||
json_path_handler::get_field(obj, args...) = std::move(value_str);
|
||||
|
||||
return 1;
|
||||
|
@ -1055,12 +790,7 @@ struct json_path_handler : public json_path_handler_base {
|
|||
auto value_str = std::string((const char*) str, len);
|
||||
auto jph = ypc->ypc_current_handler;
|
||||
|
||||
if (jph->jph_pattern) {
|
||||
if (!jph->jph_pattern->find_in(value_str).ignore_error()) {
|
||||
jph->report_pattern_error(ypc, value_str);
|
||||
}
|
||||
}
|
||||
|
||||
jph->validate_string(*ypc, value_str);
|
||||
json_path_handler::get_field(obj, args...) = std::move(value_str);
|
||||
|
||||
return 1;
|
||||
|
@ -1114,12 +844,7 @@ struct json_path_handler : public json_path_handler_base {
|
|||
auto value_str = std::string((const char*) str, len);
|
||||
auto jph = ypc->ypc_current_handler;
|
||||
|
||||
if (jph->jph_pattern) {
|
||||
if (!jph->jph_pattern->find_in(value_str).ignore_error()) {
|
||||
jph->report_pattern_error(ypc, value_str);
|
||||
}
|
||||
}
|
||||
|
||||
jph->validate_string(*ypc, value_str);
|
||||
auto& field = json_path_handler::get_field(obj, args...);
|
||||
|
||||
field.pp_path = ypc->get_full_path();
|
||||
|
@ -1168,12 +893,7 @@ struct json_path_handler : public json_path_handler_base {
|
|||
auto value_str = std::string((const char*) str, len);
|
||||
auto jph = ypc->ypc_current_handler;
|
||||
|
||||
if (jph->jph_pattern) {
|
||||
if (!jph->jph_pattern->find_in(value_str).ignore_error()) {
|
||||
jph->report_pattern_error(ypc, value_str);
|
||||
}
|
||||
}
|
||||
|
||||
jph->validate_string(*ypc, value_str);
|
||||
json_path_handler::get_field(obj, args...)
|
||||
= intern_string::lookup(value_str);
|
||||
|
||||
|
@ -1220,12 +940,7 @@ struct json_path_handler : public json_path_handler_base {
|
|||
auto value_str = std::string((const char*) str, len);
|
||||
auto jph = ypc->ypc_current_handler;
|
||||
|
||||
if (jph->jph_pattern) {
|
||||
if (!jph->jph_pattern->find_in(value_str).ignore_error()) {
|
||||
jph->report_pattern_error(ypc, value_str);
|
||||
}
|
||||
}
|
||||
|
||||
jph->validate_string(*ypc, value_str);
|
||||
auto& field = json_path_handler::get_field(obj, args...);
|
||||
field.pp_path = ypc->get_full_path();
|
||||
field.pp_location.sl_source = ypc->ypc_source;
|
||||
|
@ -1297,7 +1012,7 @@ struct json_path_handler : public json_path_handler_base {
|
|||
}
|
||||
|
||||
template<typename... Args,
|
||||
std::enable_if_t<LastIsNumber<Args...>::value, bool> = true>
|
||||
std::enable_if_t<LastIsInteger<Args...>::value, bool> = true>
|
||||
json_path_handler& for_field(Args... args)
|
||||
{
|
||||
this->add_cb(int_field_cb);
|
||||
|
@ -1350,6 +1065,59 @@ struct json_path_handler : public json_path_handler_base {
|
|||
return *this;
|
||||
}
|
||||
|
||||
template<typename... Args,
|
||||
std::enable_if_t<LastIsFloat<Args...>::value, bool> = true>
|
||||
json_path_handler& for_field(Args... args)
|
||||
{
|
||||
this->add_cb(dbl_field_cb);
|
||||
this->jph_double_cb = [args...](yajlpp_parse_context* ypc, double val) {
|
||||
auto jph = ypc->ypc_current_handler;
|
||||
auto* obj = ypc->ypc_obj_stack.top();
|
||||
|
||||
if (val < jph->jph_min_value) {
|
||||
jph->report_min_value_error(ypc, val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
json_path_handler::get_field(obj, args...) = val;
|
||||
|
||||
return 1;
|
||||
};
|
||||
this->jph_gen_callback = [args...](yajlpp_gen_context& ygc,
|
||||
const json_path_handler_base& jph,
|
||||
yajl_gen handle) {
|
||||
const auto& field = json_path_handler::get_field(
|
||||
ygc.ygc_obj_stack.top(), args...);
|
||||
|
||||
if (!ygc.ygc_default_stack.empty()) {
|
||||
const auto& field_def = json_path_handler::get_field(
|
||||
ygc.ygc_default_stack.top(), args...);
|
||||
|
||||
if (field == field_def) {
|
||||
return yajl_gen_status_ok;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_field_set(field)) {
|
||||
return yajl_gen_status_ok;
|
||||
}
|
||||
|
||||
if (ygc.ygc_depth) {
|
||||
yajl_gen_string(handle, jph.jph_property);
|
||||
}
|
||||
|
||||
yajlpp_generator gen(handle);
|
||||
|
||||
return gen(field);
|
||||
};
|
||||
this->jph_field_getter
|
||||
= [args...](void* root, nonstd::optional<std::string> name) {
|
||||
return (void*) &json_path_handler::get_field(root, args...);
|
||||
};
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<
|
||||
typename... Args,
|
||||
std::enable_if_t<LastIs<std::chrono::seconds, Args...>::value, bool>
|
||||
|
@ -1465,34 +1233,6 @@ struct json_path_handler : public json_path_handler_base {
|
|||
};
|
||||
|
||||
return *this;
|
||||
};
|
||||
|
||||
template<typename T, typename NUM_T, NUM_T T::*NUM>
|
||||
json_path_handler& for_field(
|
||||
typename std::enable_if<std::is_integral<NUM_T>::value
|
||||
&& !std::is_same<NUM_T, bool>::value>::type*
|
||||
dummy
|
||||
= 0)
|
||||
{
|
||||
this->add_cb(num_field_cb<T, NUM_T, NUM>);
|
||||
this->jph_validator = number_field_validator<T, NUM_T, NUM>;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T, typename NUM_T, double T::*NUM>
|
||||
json_path_handler& for_field()
|
||||
{
|
||||
this->add_cb(decimal_field_cb<T, NUM_T, NUM>);
|
||||
this->jph_validator = number_field_validator<T, NUM_T, NUM>;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T, typename ENUM_T, ENUM_T T::*ENUM>
|
||||
json_path_handler& for_field(
|
||||
typename std::enable_if<std::is_enum<ENUM_T>::value>::type* dummy = 0)
|
||||
{
|
||||
this->add_cb(enum_field_cb<T, ENUM_T, ENUM>);
|
||||
return *this;
|
||||
}
|
||||
|
||||
json_path_handler& with_children(const json_path_container& container);
|
||||
|
@ -1617,7 +1357,7 @@ struct typed_json_path_container : public json_path_container {
|
|||
return gen.to_string_fragment().to_string();
|
||||
}
|
||||
|
||||
json_string to_json_string(T& obj) const
|
||||
json_string to_json_string(const T& obj) const
|
||||
{
|
||||
yajlpp_gen gen;
|
||||
yajlpp_gen_context ygc(gen, *this);
|
||||
|
|
|
@ -226,6 +226,7 @@ dist_noinst_DATA = \
|
|||
expected/test_tailer.sh_12f539e535df04364316699f9edeac461aa9f9de.err \
|
||||
expected/test_tailer.sh_12f539e535df04364316699f9edeac461aa9f9de.out \
|
||||
ansi-colors.0.in \
|
||||
bad-config/formats/invalid-json-format/format.json \
|
||||
bad-config/formats/invalid-properties/format.json \
|
||||
bad-config/formats/invalid-regex/format.json \
|
||||
bad-config/formats/invalid-sample/format.json \
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"$schema": "https://lnav.org/schemas/format-v1.schema.json",
|
||||
"bad_json_log": {
|
||||
"json": true,
|
||||
"line-format": [
|
||||
{
|
||||
"field": ""
|
||||
},
|
||||
{
|
||||
"field": "__timestamp__",
|
||||
"timestamp-format": ""
|
||||
}
|
||||
],
|
||||
"value": {
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,3 +1,11 @@
|
|||
[1m[31m✘ error[0m: invalid value for option “[1m/bad_json_log/line-format#/timestamp-format[0m”
|
||||
[1m[31mreason[0m: empty values are not allowed
|
||||
[36m --> [0m[1m{test_dir}/bad-config/formats/invalid-json-format/format.json[0m:11
|
||||
[36m | [0m[37m[40m "timestamp-format": "" [0m
|
||||
[36m =[0m [36mhelp[0m: [1mProperty Synopsis[0m
|
||||
[1m/bad_json_log/line-format#/timestamp-format[0m [4m<string>[0m
|
||||
[1mDescription[0m
|
||||
The strftime(3) format for this field
|
||||
[1m[31m✘ error[0m: “invalid(abc” is not a valid regular expression
|
||||
[1m[31mreason[0m: missing closing parenthesis
|
||||
[36m --> [0m[1m/invalid_props_log/tags/badtag3/pattern[0m
|
||||
|
@ -78,6 +86,9 @@
|
|||
[1m/$schema[0m [4mThe URI of the schema for this file[0m
|
||||
[1mDescription[0m
|
||||
Specifies the type of this file
|
||||
[1m[31m✘ error[0m: invalid line format element “[1m/bad_json_log/line-format/0/field[0m”
|
||||
[1m[31mreason[0m: “” is not a defined value
|
||||
[36m --> [0m[1m{test_dir}/bad-config/formats/invalid-json-format/format.json[0m:7
|
||||
[1m[31m✘ error[0m: invalid pattern: “[1mincomplete-match[0m”
|
||||
[1m[31mreason[0m: pattern does not match entire message
|
||||
[36m --> [0m[1m{test_dir}/bad-config/formats/invalid-regex/format.json[0m:20
|
||||
|
|
Loading…
Reference in New Issue