[scn] more scnlib conversions

This commit is contained in:
Tim Stack 2022-07-29 21:58:08 -07:00
parent f234b37fe0
commit be862e0eab
14 changed files with 259 additions and 204 deletions

View File

@ -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
{

View File

@ -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);

View File

@ -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)
{

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -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

View File

@ -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{}});
}

View File

@ -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 {

View File

@ -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)
{

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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;

View File

@ -1,4 +1,4 @@
✘ error: unknown bookmark type: foobar
 --> command-option:2
 | :next-mark foobar 
 = help: available types: error, warning, file, user, user-expr, search, meta
 = help: available types: error, file, meta, search, user, user-expr, warning