mirror of
https://github.com/tstack/lnav
synced 2024-11-01 21:40:34 +00:00
[scn] more scnlib conversions
This commit is contained in:
parent
f234b37fe0
commit
be862e0eab
@ -41,6 +41,7 @@
|
||||
|
||||
#include "fmt/format.h"
|
||||
#include "optional.hpp"
|
||||
#include "scn/util/string_view.h"
|
||||
#include "strnatcmp.h"
|
||||
#include "ww898/cp_utf8.hpp"
|
||||
|
||||
@ -128,6 +129,8 @@ struct string_fragment {
|
||||
|
||||
char front() const { return this->sf_string[this->sf_begin]; }
|
||||
|
||||
char back() const { return this->sf_string[this->sf_end - 1]; }
|
||||
|
||||
iterator begin() const { return &this->sf_string[this->sf_begin]; }
|
||||
|
||||
iterator end() const { return &this->sf_string[this->sf_end]; }
|
||||
@ -178,10 +181,7 @@ struct string_fragment {
|
||||
&& strncmp(this->data(), str, this->length()) == 0;
|
||||
}
|
||||
|
||||
bool operator!=(const char* str) const
|
||||
{
|
||||
return !(*this == str);
|
||||
}
|
||||
bool operator!=(const char* str) const { return !(*this == str); }
|
||||
|
||||
bool startswith(const char* prefix) const
|
||||
{
|
||||
@ -448,6 +448,11 @@ struct string_fragment {
|
||||
};
|
||||
}
|
||||
|
||||
scn::string_view to_string_view() const
|
||||
{
|
||||
return scn::string_view{this->begin(), this->end()};
|
||||
}
|
||||
|
||||
const char* sf_string;
|
||||
int sf_begin;
|
||||
int sf_end;
|
||||
@ -480,20 +485,11 @@ public:
|
||||
|
||||
static const intern_string* lookup(const std::string& str) noexcept;
|
||||
|
||||
const char* get() const
|
||||
{
|
||||
return this->is_str.c_str();
|
||||
};
|
||||
const char* get() const { return this->is_str.c_str(); };
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
return this->is_str.size();
|
||||
}
|
||||
size_t size() const { return this->is_str.size(); }
|
||||
|
||||
std::string to_string() const
|
||||
{
|
||||
return this->is_str;
|
||||
}
|
||||
std::string to_string() const { return this->is_str; }
|
||||
|
||||
string_fragment to_string_fragment() const
|
||||
{
|
||||
|
@ -227,33 +227,6 @@ center_str(const std::string& subject, size_t width)
|
||||
return retval;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
size_t
|
||||
strtonum(T& num_out, const char* string, size_t len)
|
||||
{
|
||||
size_t retval = 0;
|
||||
T sign = 1;
|
||||
|
||||
num_out = 0;
|
||||
|
||||
for (; retval < len && isspace(string[retval]); retval++) {
|
||||
;
|
||||
}
|
||||
for (; retval < len && string[retval] == '-'; retval++) {
|
||||
sign *= -1;
|
||||
}
|
||||
for (; retval < len && string[retval] == '+'; retval++) {
|
||||
;
|
||||
}
|
||||
for (; retval < len && isdigit(string[retval]); retval++) {
|
||||
num_out *= 10;
|
||||
num_out += string[retval] - '0';
|
||||
}
|
||||
num_out *= sign;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool
|
||||
is_blank(const std::string& str)
|
||||
{
|
||||
@ -291,11 +264,3 @@ scrub_ws(const char* in)
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
template size_t strtonum<long long>(long long& num_out,
|
||||
const char* string,
|
||||
size_t len);
|
||||
|
||||
template size_t strtonum<long>(long& num_out, const char* string, size_t len);
|
||||
|
||||
template size_t strtonum<int>(int& num_out, const char* string, size_t len);
|
||||
|
@ -211,9 +211,6 @@ std::string repeat(const std::string& input, size_t num);
|
||||
|
||||
std::string center_str(const std::string& subject, size_t width);
|
||||
|
||||
template<typename T>
|
||||
size_t strtonum(T& num_out, const char* data, size_t len);
|
||||
|
||||
inline std::string
|
||||
on_blank(const std::string& str, const std::string& def)
|
||||
{
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "base/itertools.hh"
|
||||
#include "base/time_util.hh"
|
||||
#include "config.h"
|
||||
#include "scn/scn.h"
|
||||
#include "yajlpp/json_ptr.hh"
|
||||
|
||||
const char db_label_source::NULL_STR[] = "<NULL>";
|
||||
@ -48,7 +49,6 @@ db_label_source::text_value_for_line(textview_curses& tc,
|
||||
std::string& label_out,
|
||||
text_sub_source::line_flags_t flags)
|
||||
{
|
||||
|
||||
/*
|
||||
* start_value is the result rowid, each bucket type is a column value
|
||||
* label_out should be the raw text output.
|
||||
@ -103,35 +103,41 @@ db_label_source::text_attrs_for_line(textview_curses& tc,
|
||||
|
||||
int left = 0;
|
||||
for (size_t lpc = 0; lpc < this->dls_headers.size(); lpc++) {
|
||||
const char* row_value = this->dls_rows[row][lpc];
|
||||
size_t row_len = strlen(row_value);
|
||||
auto row_view = scn::string_view{this->dls_rows[row][lpc]};
|
||||
const auto& hm = this->dls_headers[lpc];
|
||||
|
||||
if (this->dls_headers[lpc].hm_graphable) {
|
||||
double num_value;
|
||||
if (hm.hm_graphable) {
|
||||
auto num_scan_res = scn::scan_value<double>(row_view);
|
||||
|
||||
if (sscanf(row_value, "%lf", &num_value) == 1) {
|
||||
if (num_scan_res) {
|
||||
this->dls_chart.chart_attrs_for_value(
|
||||
tc, left, this->dls_headers[lpc].hm_name, num_value, sa);
|
||||
tc, left, hm.hm_name, num_scan_res.value(), sa);
|
||||
}
|
||||
}
|
||||
if (row_len > 2 && row_len < MAX_JSON_WIDTH
|
||||
&& ((row_value[0] == '{' && row_value[row_len - 1] == '}')
|
||||
|| (row_value[0] == '[' && row_value[row_len - 1] == ']')))
|
||||
if (row_view.length() > 2 && row_view.length() < MAX_JSON_WIDTH
|
||||
&& ((row_view.front() == '{' && row_view.back() == '}')
|
||||
|| (row_view.front() == '[' && row_view.back() == ']')))
|
||||
{
|
||||
json_ptr_walk jpw;
|
||||
|
||||
if (jpw.parse(row_value, row_len) == yajl_status_ok
|
||||
if (jpw.parse(row_view.data(), row_view.length()) == yajl_status_ok
|
||||
&& jpw.complete_parse() == yajl_status_ok)
|
||||
{
|
||||
for (const auto& jpw_value : jpw.jpw_values) {
|
||||
double num_value;
|
||||
if (jpw_value.wt_type != yajl_t_number) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (jpw_value.wt_type == yajl_t_number
|
||||
&& sscanf(jpw_value.wt_value.c_str(), "%lf", &num_value)
|
||||
== 1)
|
||||
{
|
||||
auto num_scan_res
|
||||
= scn::scan_value<double>(jpw_value.wt_value);
|
||||
|
||||
if (num_scan_res) {
|
||||
this->dls_chart.chart_attrs_for_value(
|
||||
tc, left, jpw_value.wt_ptr, num_value, sa);
|
||||
tc,
|
||||
left,
|
||||
jpw_value.wt_ptr,
|
||||
num_scan_res.value(),
|
||||
sa);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -163,7 +169,6 @@ db_label_source::push_column(const scoped_value_t& sv)
|
||||
auto& vc = view_colors::singleton();
|
||||
int index = this->dls_rows.back().size();
|
||||
auto& hm = this->dls_headers[index];
|
||||
double num_value = 0.0;
|
||||
|
||||
auto col_sf = sv.match(
|
||||
[](const std::string& str) { return string_fragment::from_str(str); },
|
||||
@ -191,7 +196,8 @@ db_label_source::push_column(const scoped_value_t& sv)
|
||||
struct timeval tv;
|
||||
|
||||
if (!dts.convert_to_timeval(
|
||||
col_sf.data(), col_sf.length(), nullptr, tv)) {
|
||||
col_sf.data(), col_sf.length(), nullptr, tv))
|
||||
{
|
||||
tv.tv_sec = -1;
|
||||
tv.tv_usec = -1;
|
||||
}
|
||||
@ -221,19 +227,22 @@ db_label_source::push_column(const scoped_value_t& sv)
|
||||
}
|
||||
} else if (col_sf.length() > 2
|
||||
&& ((col_sf.startswith("{") && col_sf.endswith("}"))
|
||||
|| (col_sf.startswith("[") && col_sf.startswith("]"))))
|
||||
|| (col_sf.startswith("[") && col_sf.endswith("]"))))
|
||||
{
|
||||
json_ptr_walk jpw;
|
||||
|
||||
if (jpw.parse(col_sf.data(), col_sf.length()) == yajl_status_ok
|
||||
&& jpw.complete_parse() == yajl_status_ok)
|
||||
{
|
||||
for (auto& jpw_value : jpw.jpw_values) {
|
||||
if (jpw_value.wt_type == yajl_t_number
|
||||
&& sscanf(jpw_value.wt_value.c_str(), "%lf", &num_value)
|
||||
== 1)
|
||||
{
|
||||
this->dls_chart.add_value(jpw_value.wt_ptr, num_value);
|
||||
for (const auto& jpw_value : jpw.jpw_values) {
|
||||
if (jpw_value.wt_type != yajl_t_number) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto num_scan_res = scn::scan_value<double>(jpw_value.wt_value);
|
||||
if (num_scan_res) {
|
||||
this->dls_chart.add_value(jpw_value.wt_ptr,
|
||||
num_scan_res.value());
|
||||
this->dls_chart.with_attrs_for_ident(
|
||||
jpw_value.wt_ptr, vc.attrs_for_ident(jpw_value.wt_ptr));
|
||||
}
|
||||
@ -334,16 +343,16 @@ db_overlay_source::list_overlay_count(const listview_curses& lv)
|
||||
lr.lr_end = -1;
|
||||
sa.emplace_back(lr, VC_STYLE.value(text_attrs{A_BOLD}));
|
||||
|
||||
double num_value = 0.0;
|
||||
if (jpw_value.wt_type == yajl_t_number) {
|
||||
auto num_scan_res
|
||||
= scn::scan_value<double>(jpw_value.wt_value);
|
||||
|
||||
if (jpw_value.wt_type == yajl_t_number
|
||||
&& sscanf(jpw_value.wt_value.c_str(), "%lf", &num_value)
|
||||
== 1)
|
||||
{
|
||||
auto attrs = vc.attrs_for_ident(jpw_value.wt_ptr);
|
||||
if (num_scan_res) {
|
||||
auto attrs = vc.attrs_for_ident(jpw_value.wt_ptr);
|
||||
|
||||
chart.add_value(jpw_value.wt_ptr, num_value);
|
||||
chart.with_attrs_for_ident(jpw_value.wt_ptr, attrs);
|
||||
chart.add_value(jpw_value.wt_ptr, num_scan_res.value());
|
||||
chart.with_attrs_for_ident(jpw_value.wt_ptr, attrs);
|
||||
}
|
||||
}
|
||||
|
||||
retval += 1;
|
||||
@ -354,16 +363,18 @@ db_overlay_source::list_overlay_count(const listview_curses& lv)
|
||||
iter != jpw.jpw_values.end();
|
||||
++iter, curr_line++)
|
||||
{
|
||||
double num_value = 0.0;
|
||||
if (iter->wt_type != yajl_t_number) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (iter->wt_type == yajl_t_number
|
||||
&& sscanf(iter->wt_value.c_str(), "%lf", &num_value) == 1)
|
||||
{
|
||||
string_attrs_t& sa = this->dos_lines[curr_line].get_attrs();
|
||||
auto num_scan_res = scn::scan_value<double>(iter->wt_value);
|
||||
|
||||
if (num_scan_res) {
|
||||
auto& sa = this->dos_lines[curr_line].get_attrs();
|
||||
int left = 3;
|
||||
|
||||
chart.chart_attrs_for_value(
|
||||
lv, left, iter->wt_ptr, num_value, sa);
|
||||
lv, left, iter->wt_ptr, num_scan_res.value(), sa);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,12 @@ target_include_directories(
|
||||
.
|
||||
${CMAKE_BINARY_DIR}/src
|
||||
${CMAKE_SOURCE_DIR}/src
|
||||
${CMAKE_SOURCE_DIR}/src/fmtlib
|
||||
)
|
||||
target_link_libraries(
|
||||
logfmt
|
||||
PRIVATE
|
||||
cppfmt
|
||||
cppscnlib
|
||||
)
|
||||
|
||||
add_executable(
|
||||
@ -25,7 +30,6 @@ target_include_directories(
|
||||
.
|
||||
${CMAKE_BINARY_DIR}/src
|
||||
${CMAKE_SOURCE_DIR}/src
|
||||
${CMAKE_SOURCE_DIR}/src/fmtlib
|
||||
../../third-party/doctest-root)
|
||||
target_link_libraries(
|
||||
logfmt.parser.test
|
||||
|
@ -7,6 +7,7 @@ AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/src/ \
|
||||
-I$(top_srcdir)/src/third-party \
|
||||
-I$(top_srcdir)/src/fmtlib \
|
||||
-I$(top_srcdir)/src/third-party/scnlib/include \
|
||||
$(LIBARCHIVE_CFLAGS) \
|
||||
$(READLINE_CFLAGS) \
|
||||
$(SQLITE3_CFLAGS) \
|
||||
@ -32,7 +33,8 @@ logfmt_parser_test_SOURCES = \
|
||||
|
||||
logfmt_parser_test_LDADD = \
|
||||
liblogfmt.a \
|
||||
$(top_builddir)/src/base/libbase.a
|
||||
$(top_builddir)/src/base/libbase.a \
|
||||
$(top_builddir)/src/third-party/scnlib/src/libscnlib.a
|
||||
|
||||
TESTS = \
|
||||
logfmt.parser.test
|
||||
|
@ -31,8 +31,9 @@
|
||||
|
||||
#include "logfmt.parser.hh"
|
||||
|
||||
#include "base/string_util.hh"
|
||||
#include "base/intern_string.hh"
|
||||
#include "config.h"
|
||||
#include "scn/scn.h"
|
||||
|
||||
logfmt::parser::parser(string_fragment sf) : p_next_input(sf) {}
|
||||
|
||||
@ -228,34 +229,38 @@ logfmt::parser::step()
|
||||
if (bvp.is_integer()) {
|
||||
int_value retval;
|
||||
|
||||
strtonum(retval.iv_value,
|
||||
value_pair->first.data(),
|
||||
value_pair->first.length());
|
||||
auto int_scan_res
|
||||
= scn::scan_value<int64_t>(value_pair->first.to_string_view());
|
||||
if (int_scan_res) {
|
||||
retval.iv_value = int_scan_res.value();
|
||||
}
|
||||
retval.iv_str_value = value_pair->first;
|
||||
|
||||
return std::make_pair(key_frag, retval);
|
||||
} else if (bvp.is_float()) {
|
||||
char float_copy[value_pair->first.length() + 1];
|
||||
}
|
||||
if (bvp.is_float()) {
|
||||
float_value retval;
|
||||
|
||||
strncpy(float_copy,
|
||||
value_pair->first.data(),
|
||||
value_pair->first.length());
|
||||
float_copy[value_pair->first.length()] = '\0';
|
||||
retval.fv_value = strtod(float_copy, nullptr);
|
||||
auto float_scan_res
|
||||
= scn::scan_value<double>(value_pair->first.to_string_view());
|
||||
if (float_scan_res) {
|
||||
retval.fv_value = float_scan_res.value();
|
||||
}
|
||||
retval.fv_str_value = value_pair->first;
|
||||
|
||||
return std::make_pair(key_frag, retval);
|
||||
} else if (value_pair->first.iequal(TRUE_FRAG)) {
|
||||
}
|
||||
if (value_pair->first.iequal(TRUE_FRAG)) {
|
||||
return std::make_pair(key_frag,
|
||||
bool_value{true, value_pair->first});
|
||||
} else if (value_pair->first.iequal(FALSE_FRAG)) {
|
||||
}
|
||||
if (value_pair->first.iequal(FALSE_FRAG)) {
|
||||
return std::make_pair(key_frag,
|
||||
bool_value{false, value_pair->first});
|
||||
}
|
||||
return std::make_pair(key_frag, unquoted_value{value_pair->first});
|
||||
} else {
|
||||
this->p_next_input = value_start;
|
||||
return std::make_pair(key_frag, unquoted_value{string_fragment{}});
|
||||
}
|
||||
|
||||
this->p_next_input = value_start;
|
||||
return std::make_pair(key_frag, unquoted_value{string_fragment{}});
|
||||
}
|
||||
|
@ -34,6 +34,7 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "mapbox/variant.hpp"
|
||||
#include "scn/scn.h"
|
||||
#include "sqlite-extension-func.hh"
|
||||
#include "sqlite3.h"
|
||||
#include "vtab_module.hh"
|
||||
@ -112,7 +113,8 @@ json_contains(vtab_types::nullable<const char> nullable_json_in,
|
||||
sqlite3_value* value)
|
||||
{
|
||||
if (nullable_json_in.n_value == nullptr
|
||||
|| nullable_json_in.n_value[0] == '\0') {
|
||||
|| nullable_json_in.n_value[0] == '\0')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -232,12 +234,16 @@ gen_handle_number(void* ctx, const char* numval, size_t numlen)
|
||||
yajl_gen gen = (yajl_gen) sjo->jo_ptr_data;
|
||||
|
||||
if (sjo->jo_ptr.jp_state == json_ptr::match_state_t::DONE) {
|
||||
if (strtonum(sjo->sjo_int, numval, numlen) == numlen) {
|
||||
auto num_sv = scn::string_view{numval, numlen};
|
||||
auto scan_int_res = scn::scan_value<int64_t>(num_sv);
|
||||
|
||||
if (scan_int_res && scan_int_res.empty()) {
|
||||
sjo->sjo_int = scan_int_res.value();
|
||||
sjo->sjo_type = SQLITE_INTEGER;
|
||||
} else {
|
||||
auto numstr = std::string(numval, numlen);
|
||||
auto scan_float_res = scn::scan_value<double>(num_sv);
|
||||
|
||||
sjo->sjo_float = std::stod(numstr);
|
||||
sjo->sjo_float = scan_float_res.value();
|
||||
sjo->sjo_type = SQLITE_FLOAT;
|
||||
}
|
||||
} else {
|
||||
@ -298,7 +304,8 @@ sql_jget(sqlite3_context* context, int argc, sqlite3_value** argv)
|
||||
}
|
||||
case yajl_status_client_canceled:
|
||||
if (jo.jo_ptr.jp_state
|
||||
== json_ptr::match_state_t::ERR_INVALID_ESCAPE) {
|
||||
== json_ptr::match_state_t::ERR_INVALID_ESCAPE)
|
||||
{
|
||||
sqlite3_result_error(
|
||||
context, jo.jo_ptr.error_msg().c_str(), -1);
|
||||
} else {
|
||||
@ -321,7 +328,8 @@ sql_jget(sqlite3_context* context, int argc, sqlite3_value** argv)
|
||||
}
|
||||
case yajl_status_client_canceled:
|
||||
if (jo.jo_ptr.jp_state
|
||||
== json_ptr::match_state_t::ERR_INVALID_ESCAPE) {
|
||||
== json_ptr::match_state_t::ERR_INVALID_ESCAPE)
|
||||
{
|
||||
sqlite3_result_error(
|
||||
context, jo.jo_ptr.error_msg().c_str(), -1);
|
||||
} else {
|
||||
|
@ -74,6 +74,7 @@
|
||||
#include "session_data.hh"
|
||||
#include "shlex.hh"
|
||||
#include "spectro_impls.hh"
|
||||
#include "scn/scn.h"
|
||||
#include "sqlite-extension-func.hh"
|
||||
#include "sysclip.hh"
|
||||
#include "tailer/tailer.looper.hh"
|
||||
@ -666,7 +667,8 @@ com_goto_mark(exec_context& ec,
|
||||
attr_line_t("available types: ")
|
||||
.join(bookmark_type_t::get_all_types()
|
||||
| lnav::itertools::map(
|
||||
&bookmark_type_t::get_name),
|
||||
&bookmark_type_t::get_name)
|
||||
| lnav::itertools::sorted(),
|
||||
", "));
|
||||
return Err(um);
|
||||
}
|
||||
@ -4241,15 +4243,12 @@ com_config(exec_context& ec,
|
||||
changed = true;
|
||||
} else if (ypc.ypc_current_handler->jph_callbacks.yajl_integer)
|
||||
{
|
||||
long long val = 0;
|
||||
|
||||
auto consumed
|
||||
= strtonum(val, value.c_str(), value.length());
|
||||
if (consumed != value.length()) {
|
||||
auto scan_res = scn::scan_value<int64_t>(value);
|
||||
if (!scan_res || !scan_res.empty()) {
|
||||
return ec.make_error("expecting an integer, found: {}",
|
||||
value);
|
||||
}
|
||||
ypc.ypc_callbacks.yajl_integer(&ypc, val);
|
||||
ypc.ypc_callbacks.yajl_integer(&ypc, scan_res.value());
|
||||
changed = true;
|
||||
} else if (ypc.ypc_current_handler->jph_callbacks.yajl_boolean)
|
||||
{
|
||||
|
@ -142,7 +142,8 @@ ensure_dotlnav()
|
||||
|
||||
if (glob(crash_glob.c_str(), GLOB_NOCHECK, nullptr, gl.inout()) == 0) {
|
||||
for (int lpc = 0; lpc < ((int) gl->gl_pathc - MAX_CRASH_LOG_COUNT);
|
||||
lpc++) {
|
||||
lpc++)
|
||||
{
|
||||
log_perror(remove(gl->gl_pathv[lpc]));
|
||||
}
|
||||
}
|
||||
@ -164,7 +165,8 @@ ensure_dotlnav()
|
||||
}
|
||||
|
||||
if (std::chrono::system_clock::from_time_t(st.st_mtime)
|
||||
> old_time) {
|
||||
> old_time)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -225,48 +227,98 @@ install_from_git(const std::string& repo)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ghc::filesystem::is_directory(local_staging_path)) {
|
||||
auto config_path = local_staging_path / "*.json";
|
||||
static_root_mem<glob_t, globfree> gl;
|
||||
bool found_config_file = false, found_format_file = false;
|
||||
if (!ghc::filesystem::is_directory(local_staging_path)) {
|
||||
auto um
|
||||
= lnav::console::user_message::error(
|
||||
attr_line_t("failed to install git repo: ")
|
||||
.append(lnav::roles::file(repo)))
|
||||
.with_reason(
|
||||
attr_line_t("git failed to create the local directory")
|
||||
.append(
|
||||
lnav::roles::file(local_staging_path.string())));
|
||||
lnav::console::print(stderr, um);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (glob(config_path.c_str(), 0, nullptr, gl.inout()) == 0) {
|
||||
for (size_t lpc = 0; lpc < gl->gl_pathc; lpc++) {
|
||||
auto json_file_path = gl->gl_pathv[lpc];
|
||||
auto file_type_result = detect_config_file_type(json_file_path);
|
||||
auto config_path = local_staging_path / "*.{json,lnav,sql}";
|
||||
static_root_mem<glob_t, globfree> gl;
|
||||
int found_config_file = 0;
|
||||
int found_format_file = 0;
|
||||
int found_sql_file = 0;
|
||||
int found_lnav_file = 0;
|
||||
|
||||
if (file_type_result.isErr()) {
|
||||
fprintf(stderr,
|
||||
"error: %s\n",
|
||||
file_type_result.unwrapErr().c_str());
|
||||
return false;
|
||||
}
|
||||
if (file_type_result.unwrap() == config_file_type::CONFIG) {
|
||||
found_config_file = true;
|
||||
} else {
|
||||
found_format_file = true;
|
||||
}
|
||||
if (glob(config_path.c_str(), GLOB_BRACE, nullptr, gl.inout()) == 0) {
|
||||
for (size_t lpc = 0; lpc < gl->gl_pathc; lpc++) {
|
||||
auto file_path = ghc::filesystem::path{gl->gl_pathv[lpc]};
|
||||
|
||||
if (file_path.extension() == ".lnav") {
|
||||
found_lnav_file += 1;
|
||||
continue;
|
||||
}
|
||||
if (file_path.extension() == ".sql") {
|
||||
found_sql_file += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto file_type_result = detect_config_file_type(file_path);
|
||||
|
||||
if (file_type_result.isErr()) {
|
||||
fprintf(stderr,
|
||||
"error: %s\n",
|
||||
file_type_result.unwrapErr().c_str());
|
||||
return false;
|
||||
}
|
||||
if (file_type_result.unwrap() == config_file_type::CONFIG) {
|
||||
found_config_file += 1;
|
||||
} else {
|
||||
found_format_file += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (found_config_file) {
|
||||
rename(local_staging_path.c_str(), local_configs_path.c_str());
|
||||
fprintf(stderr,
|
||||
"info: installed configuration repo -- %s\n",
|
||||
local_configs_path.c_str());
|
||||
} else if (found_format_file) {
|
||||
rename(local_staging_path.c_str(), local_formats_path.c_str());
|
||||
fprintf(stderr,
|
||||
"info: installed format repo -- %s\n",
|
||||
local_formats_path.c_str());
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"error: cannot find a valid lnav configuration or format "
|
||||
"file\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (found_config_file == 0 && found_format_file == 0 && found_sql_file == 0
|
||||
&& found_lnav_file == 0)
|
||||
{
|
||||
auto um = lnav::console::user_message::error(
|
||||
attr_line_t("invalid lnav repo: ")
|
||||
.append(lnav::roles::file(repo)))
|
||||
.with_reason("no .json, .sql, or .lnav files were found");
|
||||
lnav::console::print(stderr, um);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto dest_path = local_formats_path;
|
||||
attr_line_t notes;
|
||||
if (found_format_file > 0) {
|
||||
notes.append("found ")
|
||||
.append(lnav::roles::number(fmt::to_string(found_format_file)))
|
||||
.append(" format file(s)\n");
|
||||
}
|
||||
if (found_config_file > 0) {
|
||||
if (found_format_file == 0) {
|
||||
dest_path = local_configs_path;
|
||||
}
|
||||
notes.append("found ")
|
||||
.append(lnav::roles::number(fmt::to_string(found_config_file)))
|
||||
.append(" configuration file(s)\n");
|
||||
}
|
||||
if (found_sql_file > 0) {
|
||||
notes.append("found ")
|
||||
.append(lnav::roles::number(fmt::to_string(found_sql_file)))
|
||||
.append(" SQL file(s)\n");
|
||||
}
|
||||
if (found_lnav_file > 0) {
|
||||
notes.append("found ")
|
||||
.append(lnav::roles::number(fmt::to_string(found_lnav_file)))
|
||||
.append(" lnav-script file(s)\n");
|
||||
}
|
||||
rename(local_staging_path.c_str(), dest_path.c_str());
|
||||
auto um = lnav::console::user_message::ok(
|
||||
attr_line_t("installed lnav repo at: ")
|
||||
.append(lnav::roles::file(local_configs_path.string())))
|
||||
.with_note(notes);
|
||||
lnav::console::print(stdout, um);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "log_data_table.hh"
|
||||
|
||||
#include "config.h"
|
||||
#include "scn/scn.h"
|
||||
|
||||
log_data_table::log_data_table(logfile_sub_source& lss,
|
||||
log_vtab_manager& lvm,
|
||||
@ -168,29 +169,23 @@ log_data_table::extract(logfile* lf,
|
||||
this->ldt_format_impl->extract(lf, line_number, values);
|
||||
for (const auto& ldt_pair : this->ldt_pairs) {
|
||||
const auto& pvalue = ldt_pair.get_pair_value();
|
||||
auto lr = line_range{
|
||||
pvalue.e_capture.c_begin,
|
||||
pvalue.e_capture.c_end,
|
||||
};
|
||||
|
||||
switch (pvalue.value_token()) {
|
||||
case DT_NUMBER: {
|
||||
char scan_value[line.length() + 1];
|
||||
double d = 0.0;
|
||||
auto num_view = line.to_string_view(lr);
|
||||
auto num_scan_res = scn::scan_value<double>(num_view);
|
||||
auto num = num_scan_res ? num_scan_res.value() : 0.0;
|
||||
|
||||
memcpy(scan_value,
|
||||
line.get_data() + pvalue.e_capture.c_begin,
|
||||
pvalue.e_capture.length());
|
||||
scan_value[pvalue.e_capture.length()] = '\0';
|
||||
if (sscanf(scan_value, "%lf", &d) != 1) {
|
||||
d = 0.0;
|
||||
}
|
||||
values.lvv_values.emplace_back(*meta_iter, d);
|
||||
values.lvv_values.emplace_back(*meta_iter, num);
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
values.lvv_values.emplace_back(
|
||||
*meta_iter,
|
||||
line,
|
||||
line_range{pvalue.e_capture.c_begin,
|
||||
pvalue.e_capture.c_end});
|
||||
values.lvv_values.emplace_back(*meta_iter, line, lr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -131,11 +131,16 @@ logline_value::logline_value(logline_value_meta lvm,
|
||||
case value_kind_t::VALUE_NULL:
|
||||
break;
|
||||
|
||||
case value_kind_t::VALUE_INTEGER:
|
||||
strtonum(this->lv_value.i,
|
||||
sbr.get_data_at(origin.lr_start),
|
||||
origin.length());
|
||||
case value_kind_t::VALUE_INTEGER: {
|
||||
auto scan_res
|
||||
= scn::scan_value<int64_t>(sbr.to_string_view(origin));
|
||||
if (scan_res) {
|
||||
this->lv_value.i = scan_res.value();
|
||||
} else {
|
||||
this->lv_value.i = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case value_kind_t::VALUE_FLOAT: {
|
||||
auto scan_res = scn::scan_value<double>(sbr.to_string_view(origin));
|
||||
@ -941,11 +946,10 @@ external_log_format::scan(logfile& lf,
|
||||
}
|
||||
}
|
||||
|
||||
const char* num_cap_start = pi.get_substr_start(num_cap);
|
||||
const char* num_cap_end = num_cap_start + num_cap->length();
|
||||
double dvalue = strtod(num_cap_start, (char**) &num_cap_end);
|
||||
|
||||
if (num_cap_end == num_cap_start + num_cap->length()) {
|
||||
auto scan_res
|
||||
= scn::scan_value<double>(pi.to_string_view(num_cap));
|
||||
if (scan_res) {
|
||||
auto dvalue = scan_res.value();
|
||||
if (scaling != nullptr) {
|
||||
scaling->scale(dvalue);
|
||||
}
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "base/time_util.hh"
|
||||
#include "config.h"
|
||||
#include "pcrepp/pcrepp.hh"
|
||||
#include "scn/scn.h"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
@ -371,12 +372,16 @@ relative_time::from_str(const char* str, size_t len)
|
||||
return Err(pe_out);
|
||||
}
|
||||
|
||||
const auto numstr = pi.get_substr(pc[0]);
|
||||
auto num_scan_res
|
||||
= scn::scan_value<int64_t>(pi.to_string_view(pc[0]));
|
||||
|
||||
if (sscanf(numstr.c_str(), "%" PRId64, &number) != 1) {
|
||||
pe_out.pe_msg = "Invalid number: " + numstr;
|
||||
if (!num_scan_res) {
|
||||
pe_out.pe_msg
|
||||
= fmt::format(FMT_STRING("Invalid number: {}"),
|
||||
pi.get_substr(pc[0]));
|
||||
return Err(pe_out);
|
||||
}
|
||||
number = num_scan_res.value();
|
||||
number_set = true;
|
||||
break;
|
||||
}
|
||||
@ -469,7 +474,8 @@ relative_time::from_str(const char* str, size_t len)
|
||||
= -retval.rt_field[field].value;
|
||||
}
|
||||
if (last_field_type != RTF__MAX
|
||||
&& field < last_field_type) {
|
||||
&& field < last_field_type)
|
||||
{
|
||||
retval.rt_field[field] = 0;
|
||||
}
|
||||
}
|
||||
@ -531,7 +537,8 @@ relative_time::from_str(const char* str, size_t len)
|
||||
return Err(pe_out);
|
||||
}
|
||||
for (int wday = RTT_SUNDAY; wday < token;
|
||||
wday++) {
|
||||
wday++)
|
||||
{
|
||||
retval.rt_included_days.insert(
|
||||
(token_t) wday);
|
||||
}
|
||||
@ -544,7 +551,8 @@ relative_time::from_str(const char* str, size_t len)
|
||||
return Err(pe_out);
|
||||
}
|
||||
for (int wday = RTT_SATURDAY; wday > token;
|
||||
wday--) {
|
||||
wday--)
|
||||
{
|
||||
retval.rt_included_days.insert(
|
||||
(token_t) wday);
|
||||
}
|
||||
@ -568,7 +576,8 @@ relative_time::from_str(const char* str, size_t len)
|
||||
}
|
||||
|
||||
if (token != RTT_NEXT && token != RTT_PREVIOUS
|
||||
&& token != RTT_WHITE) {
|
||||
&& token != RTT_WHITE)
|
||||
{
|
||||
next_set = false;
|
||||
}
|
||||
|
||||
@ -767,11 +776,13 @@ relative_time::adjust(const exttm& tm) const
|
||||
}
|
||||
if (this->rt_field[RTF_SECONDS].is_set && this->is_absolute(RTF_SECONDS)) {
|
||||
if (this->rt_next
|
||||
&& this->rt_field[RTF_SECONDS].value <= tm.et_tm.tm_sec) {
|
||||
&& this->rt_field[RTF_SECONDS].value <= tm.et_tm.tm_sec)
|
||||
{
|
||||
retval.et_tm.tm_min += 1;
|
||||
}
|
||||
if (this->rt_previous
|
||||
&& this->rt_field[RTF_SECONDS].value >= tm.et_tm.tm_sec) {
|
||||
&& this->rt_field[RTF_SECONDS].value >= tm.et_tm.tm_sec)
|
||||
{
|
||||
retval.et_tm.tm_min -= 1;
|
||||
}
|
||||
retval.et_tm.tm_sec = this->rt_field[RTF_SECONDS].value;
|
||||
@ -780,7 +791,8 @@ relative_time::adjust(const exttm& tm) const
|
||||
}
|
||||
if (this->rt_field[RTF_MINUTES].is_set && this->is_absolute(RTF_MINUTES)) {
|
||||
if (this->rt_next
|
||||
&& this->rt_field[RTF_MINUTES].value <= tm.et_tm.tm_min) {
|
||||
&& this->rt_field[RTF_MINUTES].value <= tm.et_tm.tm_min)
|
||||
{
|
||||
retval.et_tm.tm_hour += 1;
|
||||
}
|
||||
if (this->rt_previous
|
||||
@ -795,11 +807,13 @@ relative_time::adjust(const exttm& tm) const
|
||||
}
|
||||
if (this->rt_field[RTF_HOURS].is_set && this->is_absolute(RTF_HOURS)) {
|
||||
if (this->rt_next
|
||||
&& this->rt_field[RTF_HOURS].value <= tm.et_tm.tm_hour) {
|
||||
&& this->rt_field[RTF_HOURS].value <= tm.et_tm.tm_hour)
|
||||
{
|
||||
retval.et_tm.tm_mday += 1;
|
||||
}
|
||||
if (this->rt_previous
|
||||
&& this->rt_field[RTF_HOURS].value >= tm.et_tm.tm_hour) {
|
||||
&& this->rt_field[RTF_HOURS].value >= tm.et_tm.tm_hour)
|
||||
{
|
||||
retval.et_tm.tm_mday -= 1;
|
||||
}
|
||||
retval.et_tm.tm_hour = this->rt_field[RTF_HOURS].value;
|
||||
@ -812,7 +826,8 @@ relative_time::adjust(const exttm& tm) const
|
||||
retval.et_tm.tm_mon += 1;
|
||||
}
|
||||
if (this->rt_previous
|
||||
&& this->rt_field[RTF_DAYS].value >= tm.et_tm.tm_mday) {
|
||||
&& this->rt_field[RTF_DAYS].value >= tm.et_tm.tm_mday)
|
||||
{
|
||||
retval.et_tm.tm_mon -= 1;
|
||||
}
|
||||
retval.et_tm.tm_mday = this->rt_field[RTF_DAYS].value;
|
||||
@ -821,11 +836,13 @@ relative_time::adjust(const exttm& tm) const
|
||||
}
|
||||
if (this->rt_field[RTF_MONTHS].is_set && this->is_absolute(RTF_MONTHS)) {
|
||||
if (this->rt_next
|
||||
&& this->rt_field[RTF_MONTHS].value <= tm.et_tm.tm_mon) {
|
||||
&& this->rt_field[RTF_MONTHS].value <= tm.et_tm.tm_mon)
|
||||
{
|
||||
retval.et_tm.tm_year += 1;
|
||||
}
|
||||
if (this->rt_previous
|
||||
&& this->rt_field[RTF_MONTHS].value >= tm.et_tm.tm_mon) {
|
||||
&& this->rt_field[RTF_MONTHS].value >= tm.et_tm.tm_mon)
|
||||
{
|
||||
retval.et_tm.tm_year -= 1;
|
||||
}
|
||||
retval.et_tm.tm_mon = this->rt_field[RTF_MONTHS].value;
|
||||
|
@ -1,4 +1,4 @@
|
||||
[1m[31m✘ error[0m: unknown bookmark type: foobar
|
||||
[36m --> [0m[1mcommand-option[0m:2
|
||||
[36m | [0m[37m[40m:[0m[1m[36m[40mnext-mark[0m[37m[40m foobar [0m
|
||||
[36m =[0m [36mhelp[0m: available types: error, warning, file, user, user-expr, search, meta
|
||||
[36m =[0m [36mhelp[0m: available types: error, file, meta, search, user, user-expr, warning
|
||||
|
Loading…
Reference in New Issue
Block a user