[clang-format] init

This commit is contained in:
Timothy Stack 2022-03-16 15:38:08 -07:00
parent d0ba84d9be
commit 66ef5fdae1
330 changed files with 114036 additions and 105710 deletions

View File

@ -1,12 +1,12 @@
---
Language: Cpp
# BasedOnStyle: Chromium
AccessModifierOffset: -2
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveMacros: false
AlignConsecutiveAssignments: false
AlignConsecutiveBitFields: false
AlignConsecutiveDeclarations: false
AlignConsecutiveMacros: Consecutive
AlignConsecutiveAssignments: None
AlignConsecutiveBitFields: None
AlignConsecutiveDeclarations: None
AlignEscapedNewlines: DontAlign
AlignOperands: DontAlign
AlignTrailingComments: false
@ -20,38 +20,38 @@ AllowShortFunctionsOnASingleLine: Inline
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
# AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: TopLevelDefinitions
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
AfterCaseLabel: false
AfterClass: true
AfterClass: false
AfterControlStatement: MultiLine
AfterEnum: true
AfterEnum: false
AfterFunction: true
AfterNamespace: true
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: true
AfterUnion: true
AfterStruct: false
AfterUnion: false
AfterExternBlock: true
BeforeCatch: false
BeforeElse: false
BeforeLambdaBody: true
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeBinaryOperators: All
BreakBeforeBraces: Custom
# BreakBeforeInheritanceComma: true
BreakInheritanceList: BeforeComma
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: true
BreakConstructorInitializers: BeforeComma
# BreakConstructorInitializersBeforeComma: true
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: true
BreakStringLiterals: true
ColumnLimit: 80
@ -88,7 +88,7 @@ IndentCaseBlocks: false
IndentGotoLabels: true
IndentPPDirectives: AfterHash
IndentExternBlock: NoIndent
IndentWidth: 2
IndentWidth: 4
IndentWrappedFunctionNames: false
InsertTrailingCommas: Wrapped
JavaScriptQuotes: Double
@ -99,11 +99,11 @@ MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Never
ObjCBlockIndentWidth: 2
ObjCBlockIndentWidth: 4
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakAssignment: 4
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
@ -143,13 +143,13 @@ RawStringFormats:
CanonicalDelimiter: ''
BasedOnStyle: google
ReflowComments: true
SortIncludes: true
SortIncludes: CaseInsensitive
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterCStyleCast: true
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatementsExceptForEachMacros
@ -157,7 +157,7 @@ SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: false
SpacesInAngles: Never
SpacesInConditionalStatement: false
SpacesInContainerLiterals: false
SpacesInCStyleCastParentheses: false

View File

@ -35,7 +35,7 @@ set(lnav_LIBS
)
add_subdirectory(src)
add_subdirectory(test)
# add_subdirectory(test)
# ---- Install rules ----

View File

@ -35,6 +35,7 @@ class LnavConan(ConanFile):
"pcre:with_jit": True,
"sqlite3:enable_json1": True,
"sqlite3:enable_soundex": True,
"readline:with_library": "curses",
}
def generate(self):

View File

@ -19,6 +19,8 @@ add_subdirectory(pcrepp)
add_subdirectory(remote)
add_subdirectory(tailer)
add_subdirectory(formats/logfmt)
add_subdirectory(yajl)
add_subdirectory(yajlpp)
add_executable(bin2c bin2c.hh tools/bin2c.c)
target_link_libraries(bin2c ZLIB::ZLIB)
@ -81,7 +83,9 @@ set(GEN_SRCS "")
add_custom_command(OUTPUT time_fmts.cc COMMAND ptimec ${TIME_FORMATS} >
time_fmts.cc)
list(APPEND GEN_SRCS time_fmts.cc)
add_library(lnavdt STATIC config.h.in ptimec.hh ptimec_rt.cc time_fmts.cc)
target_include_directories(lnavdt PUBLIC . ${CMAKE_CURRENT_BINARY_DIR})
function(bin2c)
cmake_parse_arguments(BIN2C_ "" "VARNAME" "" ${ARGN})
@ -220,6 +224,19 @@ add_library(
fmtlib/fmt/printf.h
fmtlib/fmt/ranges.h
fmtlib/fmt/time.h)
target_include_directories(cppfmt PUBLIC fmtlib)
add_library(lnavfileio STATIC
grep_proc.hh
line_buffer.hh
shared_buffer.hh
grep_proc.cc
line_buffer.cc
shared_buffer.cc
)
target_include_directories(lnavfileio PRIVATE . ${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries(lnavfileio cppfmt pcrepp base BZip2::BZip2 ZLIB::ZLIB)
add_library(
diag STATIC
@ -251,7 +268,6 @@ add_library(
fs-extension-functions.cc
fstat_vtab.cc
fts_fuzzy_match.cc
grep_proc.cc
help_text.cc
help_text_formatter.cc
highlighter.cc
@ -259,9 +275,6 @@ add_library(
hotkeys.cc
input_dispatcher.cc
json-extension-functions.cc
yajlpp/json_op.cc
yajlpp/json_ptr.cc
line_buffer.cc
listview_curses.cc
lnav_commands.cc
lnav_config.cc
@ -282,7 +295,6 @@ add_library(
data_parser.cc
papertrail_proc.cc
pcap_manager.cc
ptimec_rt.cc
pretty_printer.cc
pugixml/pugixml.cpp
readline_callbacks.cc
@ -293,7 +305,6 @@ add_library(
relative_time.cc
session_data.cc
sequence_matcher.cc
shared_buffer.cc
shlex.cc
sqlite-extension-func.cc
statusview_curses.cc
@ -324,22 +335,6 @@ add_library(
xml_util.cc
xpath_vtab.cc
xterm_mouse.cc
yajlpp/yajlpp.cc
yajl/yajl.c
yajl/yajl_alloc.c
yajl/yajl_alloc.h
yajl/yajl_buf.c
yajl/yajl_buf.h
yajl/yajl_bytestack.h
yajl/yajl_encode.c
yajl/yajl_encode.h
yajl/yajl_gen.c
yajl/yajl_lex.c
yajl/yajl_lex.h
yajl/yajl_parser.c
yajl/yajl_parser.h
yajl/yajl_tree.c
yajl/yajl_version.c
spookyhash/SpookyV2.cpp
third-party/sqlite/ext/series.c
third-party/sqlite/ext/dbdump.c
@ -393,7 +388,6 @@ add_library(
plain_text_source.hh
pretty_printer.hh
preview_status_source.hh
ptimec.hh
pugixml/pugiconfig.hpp
pugixml/pugixml.hpp
readline_callbacks.hh
@ -436,18 +430,12 @@ add_library(
vis_line.hh
vtab_module.hh
vtab_module_json.hh
yajlpp/yajlpp.hh
yajlpp/yajlpp_def.hh
xml_util.hh
xpath_vtab.hh
mapbox/recursive_wrapper.hpp
mapbox/variant.hpp
mapbox/variant_io.hpp
mapbox/variant_visitor.hpp
yajl/api/yajl_common.h
yajl/api/yajl_gen.h
yajl/api/yajl_parse.h
yajl/api/yajl_tree.h
ghc/filesystem.hpp
ghc/fs_fwd.hpp
ghc/fs_impl.hpp
@ -465,11 +453,14 @@ target_include_directories(diag PUBLIC . fmtlib ${CMAKE_CURRENT_BINARY_DIR}
target_link_libraries(
diag
base
lnavdt
lnavfileio
pcrepp
tailerservice
tailerpp
tailercommon
logfmt
yajlpp
${lnav_LIBS})
target_compile_definitions(diag PRIVATE SQLITE_OMIT_LOAD_EXTENSION)
@ -479,13 +470,6 @@ if(HAVE_LIBUTIL)
target_link_libraries(diag util)
endif ()
add_executable(test_yajlpp yajlpp/test_yajlpp.cc)
target_link_libraries(test_yajlpp diag ${lnav_LIBS})
add_test(NAME test_yajlpp COMMAND test_yajlpp)
add_executable(drive_json_op yajlpp/drive_json_op.cc)
target_link_libraries(drive_json_op diag ${lnav_LIBS})
add_executable(lnav ${lnav_SRCS})
target_link_libraries(lnav diag)

View File

@ -21,46 +21,52 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "all_logs_vtab.hh"
#include "config.h"
#include "string_attr_type.hh"
static auto intern_lifetime = intern_string::get_table_lifetime();
all_logs_vtab::all_logs_vtab()
: log_vtab_impl(intern_string::lookup("all_logs")),
alv_value_meta(intern_string::lookup("log_format"),
value_kind_t::VALUE_TEXT,
0),
alv_msg_meta(intern_string::lookup("log_msg_format"),
value_kind_t::VALUE_TEXT,
1),
alv_schema_meta(intern_string::lookup("log_msg_schema"),
value_kind_t::VALUE_TEXT,
2) {
alv_value_meta(
intern_string::lookup("log_format"), value_kind_t::VALUE_TEXT, 0),
alv_msg_meta(
intern_string::lookup("log_msg_format"), value_kind_t::VALUE_TEXT, 1),
alv_schema_meta(
intern_string::lookup("log_msg_schema"), value_kind_t::VALUE_TEXT, 2)
{
this->alv_value_meta.lvm_identifier = true;
this->alv_msg_meta.lvm_identifier = true;
this->alv_schema_meta.lvm_identifier = true;
}
void all_logs_vtab::get_columns(std::vector<vtab_column> &cols) const
void
all_logs_vtab::get_columns(std::vector<vtab_column>& cols) const
{
cols.emplace_back(vtab_column(this->alv_value_meta.lvm_name.get())
.with_comment("The name of the log file format"));
cols.emplace_back(vtab_column(this->alv_msg_meta.lvm_name.get())
.with_comment("The message format with variables replaced by hash marks"));
cols.emplace_back(this->alv_schema_meta.lvm_name.get(), SQLITE3_TEXT, "", true,
cols.emplace_back(
vtab_column(this->alv_msg_meta.lvm_name.get())
.with_comment(
"The message format with variables replaced by hash marks"));
cols.emplace_back(this->alv_schema_meta.lvm_name.get(),
SQLITE3_TEXT,
"",
true,
"The ID for the message schema");
}
void all_logs_vtab::extract(std::shared_ptr<logfile> lf, uint64_t line_number,
void
all_logs_vtab::extract(std::shared_ptr<logfile> lf,
uint64_t line_number,
shared_buffer_ref& line,
std::vector<logline_value>& values)
{
@ -98,7 +104,8 @@ void all_logs_vtab::extract(std::shared_ptr<logfile> lf, uint64_t line_number,
values.emplace_back(this->alv_schema_meta, schema_ref);
}
bool all_logs_vtab::is_valid(log_cursor &lc, logfile_sub_source &lss)
bool
all_logs_vtab::is_valid(log_cursor& lc, logfile_sub_source& lss)
{
auto cl = lss.at(lc.lc_curr_line);
auto lf = lss.find(cl);
@ -111,7 +118,8 @@ bool all_logs_vtab::is_valid(log_cursor &lc, logfile_sub_source &lss)
return true;
}
bool all_logs_vtab::next(log_cursor &lc, logfile_sub_source &lss)
bool
all_logs_vtab::next(log_cursor& lc, logfile_sub_source& lss)
{
lc.lc_curr_line = lc.lc_curr_line + vis_line_t(1);
lc.lc_sub_index = 0;

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@ -32,15 +32,14 @@
#include <array>
#include "log_vtab_impl.hh"
#include "data_parser.hh"
#include "log_vtab_impl.hh"
/**
* A virtual table that provides access to all log messages from all formats.
*/
class all_logs_vtab : public log_vtab_impl {
public:
all_logs_vtab();
void get_columns(std::vector<vtab_column>& cols) const override;

View File

@ -21,33 +21,35 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @file ansi_scrubber.cc
*/
#include "config.h"
#include <algorithm>
#include "base/opt_util.hh"
#include "view_curses.hh"
#include "pcrepp/pcrepp.hh"
#include "ansi_scrubber.hh"
#include "base/opt_util.hh"
#include "config.h"
#include "pcrepp/pcrepp.hh"
#include "view_curses.hh"
using namespace std;
static pcrepp &ansi_regex()
static pcrepp&
ansi_regex()
{
static pcrepp retval("\x1b\\[([\\d=;\\?]*)([a-zA-Z])");
return retval;
}
void scrub_ansi_string(std::string &str, string_attrs_t &sa)
void
scrub_ansi_string(std::string& str, string_attrs_t& sa)
{
pcre_context_static<60> context;
pcrepp& regex = ansi_regex();
@ -67,7 +69,8 @@ void scrub_ansi_string(std::string &str, string_attrs_t &sa)
switch (pi.get_substr_start(&caps[2])[0]) {
case 'm':
for (lpc = caps[1].c_begin;
lpc != string::npos && lpc < (size_t) caps[1].c_end;) {
lpc != string::npos && lpc < (size_t) caps[1].c_end;)
{
int ansi_code = 0;
if (sscanf(&(str[lpc]), "%d", &ansi_code) == 1) {
@ -110,9 +113,10 @@ void scrub_ansi_string(std::string &str, string_attrs_t &sa)
case 'C': {
unsigned int spaces = 0;
if (sscanf(&(str[caps[1].c_begin]), "%u", &spaces) == 1 &&
spaces > 0) {
str.insert((unsigned long) caps[0].c_end, spaces, ' ');
if (sscanf(&(str[caps[1].c_begin]), "%u", &spaces) == 1
&& spaces > 0) {
str.insert(
(std::string::size_type) caps[0].c_end, spaces, ' ');
}
break;
}
@ -120,11 +124,13 @@ void scrub_ansi_string(std::string &str, string_attrs_t &sa)
case 'H': {
unsigned int row = 0, spaces = 0;
if (sscanf(&(str[caps[1].c_begin]), "%u;%u", &row, &spaces) == 2 &&
spaces > 1) {
if (sscanf(&(str[caps[1].c_begin]), "%u;%u", &row, &spaces) == 2
&& spaces > 1) {
int ispaces = spaces - 1;
if (ispaces > caps[0].c_begin) {
str.insert((unsigned long) caps[0].c_end, ispaces - caps[0].c_begin, ' ');
str.insert((unsigned long) caps[0].c_end,
ispaces - caps[0].c_begin,
' ');
}
}
break;
@ -142,8 +148,7 @@ void scrub_ansi_string(std::string &str, string_attrs_t &sa)
break;
}
}
str.erase(str.begin() + caps[0].c_begin,
str.begin() + caps[0].c_end);
str.erase(str.begin() + caps[0].c_begin, str.begin() + caps[0].c_end);
if (has_attrs) {
for (auto rit = sa.rbegin(); rit != sa.rend(); rit++) {
@ -172,7 +177,8 @@ void scrub_ansi_string(std::string &str, string_attrs_t &sa)
}
}
void add_ansi_vars(std::map<std::string, std::string> &vars)
void
add_ansi_vars(std::map<std::string, std::string>& vars)
{
vars["ansi_csi"] = ANSI_CSI;
vars["ansi_norm"] = ANSI_NORM;

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*

View File

@ -21,36 +21,35 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @file archive_manager.cc
*/
#include "config.h"
#include <unistd.h>
#include "config.h"
#if HAVE_ARCHIVE_H
# include "archive.h"
# include "archive_entry.h"
#endif
#include "archive_manager.cfg.hh"
#include "archive_manager.hh"
#include "auto_fd.hh"
#include "auto_mem.hh"
#include "fmt/format.h"
#include "base/fs_util.hh"
#include "base/humanize.hh"
#include "base/injector.hh"
#include "base/lnav_log.hh"
#include "base/humanize.hh"
#include "base/paths.hh"
#include "fmt/format.h"
#include "lnav_util.hh"
#include "archive_manager.hh"
#include "archive_manager.cfg.hh"
namespace fs = ghc::filesystem;
namespace archive_manager {
@ -59,12 +58,13 @@ class archive_lock {
public:
class guard {
public:
explicit guard(archive_lock& arc_lock) : g_lock(arc_lock) {
explicit guard(archive_lock& arc_lock) : g_lock(arc_lock)
{
this->g_lock.lock();
};
~guard() {
~guard()
{
this->g_lock.unlock();
};
@ -72,19 +72,23 @@ public:
archive_lock& g_lock;
};
void lock() const {
void lock() const
{
lockf(this->lh_fd, F_LOCK, 0);
};
void unlock() const {
void unlock() const
{
lockf(this->lh_fd, F_ULOCK, 0);
};
explicit archive_lock(const fs::path& archive_path) {
explicit archive_lock(const fs::path& archive_path)
{
auto lock_path = archive_path;
lock_path += ".lck";
this->lh_fd = lnav::filesystem::openp(lock_path, O_CREAT | O_RDWR, 0600);
this->lh_fd
= lnav::filesystem::openp(lock_path, O_CREAT | O_RDWR, 0600);
log_perror(fcntl(this->lh_fd, F_SETFD, FD_CLOEXEC));
};
@ -96,7 +100,8 @@ public:
* Enables a subset of the supported archive formats to speed up detection,
* since some formats, like xar are unlikely to be used.
*/
static void enable_desired_archive_formats(archive *arc)
static void
enable_desired_archive_formats(archive* arc)
{
archive_read_support_format_7zip(arc);
archive_read_support_format_cpio(arc);
@ -107,7 +112,8 @@ static void enable_desired_archive_formats(archive *arc)
}
#endif
bool is_archive(const fs::path& filename)
bool
is_archive(const fs::path& filename)
{
#if HAVE_ARCHIVE_H
auto_mem<archive> arc(archive_read_free);
@ -145,8 +151,8 @@ bool is_archive(const fs::path& filename)
return false;
}
}
log_info("detected archive: %s -- %s",
filename.c_str(), format_name);
log_info(
"detected archive: %s -- %s", filename.c_str(), format_name);
return true;
} else {
log_info("archive read header failed: %s -- %s",
@ -163,8 +169,8 @@ bool is_archive(const fs::path& filename)
return false;
}
static
fs::path archive_cache_path()
static fs::path
archive_cache_path()
{
return lnav::paths::workdir() / "archives";
}
@ -213,7 +219,9 @@ copy_data(const std::string& filename,
if (tmp_space.available < cfg.amc_min_free_space) {
return Err(fmt::format(
FMT_STRING("available space on disk ({}) is below the minimum-free threshold ({}). Unable to unpack '{}' to '{}'"),
FMT_STRING("available space on disk ({}) is below the "
"minimum-free threshold ({}). Unable to unpack "
"'{}' to '{}'"),
humanize::file_size(tmp_space.available),
humanize::file_size(cfg.amc_min_free_space),
entry_path.filename().string(),
@ -244,12 +252,11 @@ copy_data(const std::string& filename,
}
}
static walk_result_t extract(const std::string &filename, const extract_cb &cb)
static walk_result_t
extract(const std::string& filename, const extract_cb& cb)
{
static int FLAGS = ARCHIVE_EXTRACT_TIME
| ARCHIVE_EXTRACT_PERM
| ARCHIVE_EXTRACT_ACL
| ARCHIVE_EXTRACT_FFLAGS;
static int FLAGS = ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM
| ARCHIVE_EXTRACT_ACL | ARCHIVE_EXTRACT_FFLAGS;
auto tmp_path = filename_to_tmp_path(filename);
auto arc_lock = archive_lock(tmp_path);
@ -267,9 +274,9 @@ static walk_result_t extract(const std::string &filename, const extract_cb &cb)
}
}
if (file_count > 0) {
fs::last_write_time(
done_path, std::chrono::system_clock::now());
log_info("%s: archive has already been extracted!", done_path.c_str());
fs::last_write_time(done_path, std::chrono::system_clock::now());
log_info("%s: archive has already been extracted!",
done_path.c_str());
return Ok();
} else {
log_warning("%s: archive cache has been damaged, re-extracting",
@ -289,15 +296,14 @@ static walk_result_t extract(const std::string &filename, const extract_cb &cb)
ext = archive_write_disk_new();
archive_write_disk_set_options(ext, FLAGS);
archive_write_disk_set_standard_lookup(ext);
if (archive_read_open_filename(arc, filename.c_str(), 10240) != ARCHIVE_OK) {
if (archive_read_open_filename(arc, filename.c_str(), 10240) != ARCHIVE_OK)
{
return Err(fmt::format("unable to open archive: {} -- {}",
filename,
archive_error_string(arc)));
}
log_info("extracting %s to %s",
filename.c_str(),
tmp_path.c_str());
log_info("extracting %s to %s", filename.c_str(), tmp_path.c_str());
while (true) {
struct archive_entry* entry;
auto r = archive_read_next_header(arc, &entry);
@ -321,9 +327,9 @@ static walk_result_t extract(const std::string &filename, const extract_cb &cb)
desired_pathname = fs::path(filename).filename();
}
auto entry_path = tmp_path / desired_pathname;
auto prog = cb(entry_path,
archive_entry_size_is_set(entry) ?
archive_entry_size(entry) : -1);
auto prog = cb(
entry_path,
archive_entry_size_is_set(entry) ? archive_entry_size(entry) : -1);
archive_entry_copy_pathname(wentry, entry_path.c_str());
auto entry_mode = archive_entry_mode(wentry);
@ -334,9 +340,8 @@ static walk_result_t extract(const std::string &filename, const extract_cb &cb)
return Err(fmt::format("unable to write entry: {} -- {}",
entry_path.string(),
archive_error_string(ext)));
}
else if (!archive_entry_size_is_set(entry) ||
archive_entry_size(entry) > 0) {
} else if (!archive_entry_size_is_set(entry)
|| archive_entry_size(entry) > 0) {
TRY(copy_data(filename, arc, entry, ext, entry_path, prog));
}
r = archive_write_finish_entry(ext);
@ -355,12 +360,12 @@ static walk_result_t extract(const std::string &filename, const extract_cb &cb)
}
#endif
walk_result_t walk_archive_files(
walk_result_t
walk_archive_files(
const std::string& filename,
const extract_cb& cb,
const std::function<void(
const fs::path&,
const fs::directory_entry &)>& callback)
const std::function<void(const fs::path&, const fs::directory_entry&)>&
callback)
{
#if HAVE_ARCHIVE_H
auto tmp_path = filename_to_tmp_path(filename);
@ -385,7 +390,8 @@ walk_result_t walk_archive_files(
#endif
}
void cleanup_cache()
void
cleanup_cache()
{
(void) std::async(std::launch::async, []() {
auto now = std::chrono::system_clock::now();
@ -421,4 +427,4 @@ void cleanup_cache()
});
}
}
} // namespace archive_manager

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
@ -41,6 +41,6 @@ struct config {
std::chrono::seconds amc_cache_ttl{std::chrono::hours(48)};
};
}
} // namespace archive_manager
#endif

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
@ -33,8 +33,8 @@
#define lnav_archive_manager_hh
#include <atomic>
#include <string>
#include <functional>
#include <string>
#include <utility>
#include "base/result.h"
@ -43,18 +43,18 @@
namespace archive_manager {
struct extract_progress {
extract_progress(ghc::filesystem::path path,
ssize_t total) : ep_path(std::move(path)),
ep_total_size(total)
{}
extract_progress(ghc::filesystem::path path, ssize_t total)
: ep_path(std::move(path)), ep_total_size(total)
{
}
const ghc::filesystem::path ep_path;
const ssize_t ep_total_size;
std::atomic<size_t> ep_out_size{0};
};
using extract_cb = std::function<extract_progress *(
const ghc::filesystem::path &, ssize_t)>;
using extract_cb
= std::function<extract_progress*(const ghc::filesystem::path&, ssize_t)>;
bool is_archive(const ghc::filesystem::path& filename);
@ -65,12 +65,11 @@ using walk_result_t = Result<void, std::string>;
walk_result_t walk_archive_files(
const std::string& filename,
const extract_cb& cb,
const std::function<void(
const ghc::filesystem::path &,
const std::function<void(const ghc::filesystem::path&,
const ghc::filesystem::directory_entry&)>&);
void cleanup_cache();
}
} // namespace archive_manager
#endif

View File

@ -21,22 +21,23 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <algorithm>
#include "auto_mem.hh"
#include "ansi_scrubber.hh"
#include "view_curses.hh"
#include "attr_line.hh"
attr_line_t &attr_line_t::with_ansi_string(const char *str, ...)
#include "ansi_scrubber.hh"
#include "auto_mem.hh"
#include "config.h"
#include "view_curses.hh"
attr_line_t&
attr_line_t::with_ansi_string(const char* str, ...)
{
auto_mem<char> formatted_str;
va_list args;
@ -53,7 +54,8 @@ attr_line_t &attr_line_t::with_ansi_string(const char *str, ...)
return *this;
}
attr_line_t &attr_line_t::with_ansi_string(const std::string &str)
attr_line_t&
attr_line_t::with_ansi_string(const std::string& str)
{
this->al_string = str;
scrub_ansi_string(this->al_string, this->al_attrs);
@ -61,7 +63,10 @@ attr_line_t &attr_line_t::with_ansi_string(const std::string &str)
return *this;
}
attr_line_t &attr_line_t::insert(size_t index, const attr_line_t &al, text_wrap_settings *tws)
attr_line_t&
attr_line_t::insert(size_t index,
const attr_line_t& al,
text_wrap_settings* tws)
{
if (index < this->al_string.length()) {
shift_string_attrs(this->al_attrs, index, al.al_string.length());
@ -92,7 +97,8 @@ attr_line_t &attr_line_t::insert(size_t index, const attr_line_t &al, text_wrap_
ssize_t line_len = index - line_start;
ssize_t usable_width = tws->tws_width - tws->tws_indent;
ssize_t avail = std::max((ssize_t) 0, (ssize_t) tws->tws_width - line_len);
ssize_t avail
= std::max((ssize_t) 0, (ssize_t) tws->tws_width - line_len);
if (avail == 0) {
avail = INT_MAX;
@ -102,16 +108,16 @@ attr_line_t &attr_line_t::insert(size_t index, const attr_line_t &al, text_wrap_
ssize_t lpc;
// Find the end of a word or a breakpoint.
for (lpc = start_pos;
lpc < (int)this->al_string.length() &&
(isalnum(this->al_string[lpc]) ||
this->al_string[lpc] == ',' ||
this->al_string[lpc] == '_' ||
this->al_string[lpc] == '.' ||
this->al_string[lpc] == ';');
lpc++) {
if (this->al_string[lpc] == '-' ||
this->al_string[lpc] == '.') {
for (lpc = start_pos; lpc < (int) this->al_string.length()
&& (isalnum(this->al_string[lpc])
|| this->al_string[lpc] == ','
|| this->al_string[lpc] == '_'
|| this->al_string[lpc] == '.'
|| this->al_string[lpc] == ';');
lpc++)
{
if (this->al_string[lpc] == '-' || this->al_string[lpc] == '.')
{
lpc += 1;
break;
}
@ -133,8 +139,8 @@ attr_line_t &attr_line_t::insert(size_t index, const attr_line_t &al, text_wrap_
lpc += 1 + tws->tws_indent;
break;
}
if (isalnum(this->al_string[lpc]) ||
this->al_string[lpc] == '_') {
if (isalnum(this->al_string[lpc])
|| this->al_string[lpc] == '_') {
break;
}
avail -= 1;
@ -147,10 +153,10 @@ attr_line_t &attr_line_t::insert(size_t index, const attr_line_t &al, text_wrap_
start_pos += 1 + tws->tws_indent;
avail = usable_width;
for (lpc = start_pos;
lpc < (int)this->al_string.length() &&
this->al_string[lpc] == ' ';
lpc++) {
for (lpc = start_pos; lpc < (int) this->al_string.length()
&& this->al_string[lpc] == ' ';
lpc++)
{
}
if (lpc != start_pos) {
@ -164,7 +170,8 @@ attr_line_t &attr_line_t::insert(size_t index, const attr_line_t &al, text_wrap_
return *this;
}
attr_line_t attr_line_t::subline(size_t start, size_t len) const
attr_line_t
attr_line_t::subline(size_t start, size_t len) const
{
if (len == std::string::npos) {
len = this->al_string.length() - start;
@ -179,9 +186,10 @@ attr_line_t attr_line_t::subline(size_t start, size_t len) const
continue;
}
retval.al_attrs.emplace_back(lr.intersection(sa.sa_range)
.shift(lr.lr_start, -lr.lr_start),
sa.sa_type, sa.sa_value);
retval.al_attrs.emplace_back(
lr.intersection(sa.sa_range).shift(lr.lr_start, -lr.lr_start),
sa.sa_type,
sa.sa_value);
line_range& last_lr = retval.al_attrs.back().sa_range;
@ -191,7 +199,8 @@ attr_line_t attr_line_t::subline(size_t start, size_t len) const
return retval;
}
void attr_line_t::split_lines(std::vector<attr_line_t> &lines) const
void
attr_line_t::split_lines(std::vector<attr_line_t>& lines) const
{
size_t pos = 0, next_line;
@ -202,7 +211,8 @@ void attr_line_t::split_lines(std::vector<attr_line_t> &lines) const
lines.emplace_back(this->subline(pos));
}
attr_line_t &attr_line_t::right_justify(unsigned long width)
attr_line_t&
attr_line_t::right_justify(unsigned long width)
{
long padding = width - this->length();
if (padding > 0) {
@ -220,7 +230,8 @@ attr_line_t &attr_line_t::right_justify(unsigned long width)
return *this;
}
size_t attr_line_t::nearest_text(size_t x) const
size_t
attr_line_t::nearest_text(size_t x) const
{
if (x > 0 && x >= (size_t) this->length()) {
if (this->empty()) {
@ -237,18 +248,18 @@ size_t attr_line_t::nearest_text(size_t x) const
return x;
}
void attr_line_t::apply_hide()
void
attr_line_t::apply_hide()
{
auto& sa = this->al_attrs;
for (auto& sattr : sa) {
if (sattr.sa_type == &SA_HIDDEN &&
sattr.sa_range.length() > 3) {
if (sattr.sa_type == &SA_HIDDEN && sattr.sa_range.length() > 3) {
struct line_range& lr = sattr.sa_range;
std::for_each(sa.begin(), sa.end(), [&](string_attr& attr) {
if (attr.sa_type == &view_curses::VC_STYLE &&
lr.contains(attr.sa_range)) {
if (attr.sa_type == &view_curses::VC_STYLE
&& lr.contains(attr.sa_range)) {
attr.sa_type = &SA_REMOVED;
}
});
@ -258,7 +269,6 @@ void attr_line_t::apply_hide()
sattr.sa_type = &view_curses::VC_ROLE;
sattr.sa_value.sav_int = view_colors::VCR_HIDDEN;
lr.lr_end = lr.lr_start + 3;
}
}
}

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
@ -32,14 +32,14 @@
#ifndef attr_line_hh
#define attr_line_hh
#include <limits.h>
#include <string>
#include <vector>
#include <limits.h>
#include "base/intern_string.hh"
#include "base/lnav_log.hh"
#include "base/string_util.hh"
#include "base/intern_string.hh"
#include "string_attr_type.hh"
/**
@ -49,9 +49,11 @@ struct line_range {
int lr_start;
int lr_end;
explicit line_range(int start = -1, int end = -1) : lr_start(start), lr_end(end) { };
explicit line_range(int start = -1, int end = -1)
: lr_start(start), lr_end(end){};
bool is_valid() const {
bool is_valid() const
{
return this->lr_start != -1;
}
@ -60,19 +62,23 @@ struct line_range {
return this->lr_end == -1 ? INT_MAX : this->lr_end - this->lr_start;
};
bool contains(int pos) const {
bool contains(int pos) const
{
return this->lr_start <= pos && pos < this->lr_end;
};
bool contains(const struct line_range &other) const {
bool contains(const struct line_range& other) const
{
return this->contains(other.lr_start) && other.lr_end <= this->lr_end;
};
bool intersects(const struct line_range &other) const {
bool intersects(const struct line_range& other) const
{
return this->contains(other.lr_start) || this->contains(other.lr_end);
};
line_range intersection(const struct line_range &other) const {
line_range intersection(const struct line_range& other) const
{
int actual_end;
if (this->lr_end == -1) {
@ -85,7 +91,8 @@ struct line_range {
return line_range{std::max(this->lr_start, other.lr_start), actual_end};
};
line_range &shift(int32_t start, int32_t amount) {
line_range& shift(int32_t start, int32_t amount)
{
if (this->lr_start >= start) {
this->lr_start = std::max(0, this->lr_start + amount);
}
@ -99,7 +106,8 @@ struct line_range {
return *this;
};
void ltrim(const char *str) {
void ltrim(const char* str)
{
while (this->lr_start < this->lr_end && isspace(str[this->lr_start])) {
this->lr_start += 1;
}
@ -107,27 +115,37 @@ struct line_range {
bool operator<(const struct line_range& rhs) const
{
if (this->lr_start < rhs.lr_start) { return true; }
else if (this->lr_start > rhs.lr_start) { return false; }
if (this->lr_start < rhs.lr_start) {
return true;
} else if (this->lr_start > rhs.lr_start) {
return false;
}
if (this->lr_end == rhs.lr_end) { return false; }
if (this->lr_end == rhs.lr_end) {
return false;
}
if (this->lr_end < rhs.lr_end) { return true; }
if (this->lr_end < rhs.lr_end) {
return true;
}
return false;
};
bool operator==(const struct line_range &rhs) const {
bool operator==(const struct line_range& rhs) const
{
return (this->lr_start == rhs.lr_start && this->lr_end == rhs.lr_end);
};
const char *substr(const std::string &str) const {
const char* substr(const std::string& str) const
{
if (this->lr_start == -1) {
return str.c_str();
}
return &(str.c_str()[this->lr_start]);
}
size_t sublen(const std::string &str) const {
size_t sublen(const std::string& str) const
{
if (this->lr_start == -1) {
return str.length();
}
@ -148,34 +166,47 @@ typedef union {
struct string_attr {
string_attr(const struct line_range& lr, string_attr_type_t type, void* val)
: sa_range(lr), sa_type(type) {
: sa_range(lr), sa_type(type)
{
require(lr.is_valid());
require(type);
this->sa_value.sav_ptr = val;
};
string_attr(const struct line_range &lr, string_attr_type_t type, std::string val)
: sa_range(lr), sa_type(type), sa_str_value(std::move(val)) {
string_attr(const struct line_range& lr,
string_attr_type_t type,
std::string val)
: sa_range(lr), sa_type(type), sa_str_value(std::move(val))
{
require(lr.is_valid());
require(type);
};
string_attr(const struct line_range &lr, string_attr_type_t type, intern_string_t val)
: sa_range(lr), sa_type(type) {
string_attr(const struct line_range& lr,
string_attr_type_t type,
intern_string_t val)
: sa_range(lr), sa_type(type)
{
require(lr.is_valid());
require(type);
this->sa_value.sav_ptr = val.unwrap();
};
string_attr(const struct line_range &lr, string_attr_type_t type, int64_t val = 0)
: sa_range(lr), sa_type(type) {
string_attr(const struct line_range& lr,
string_attr_type_t type,
int64_t val = 0)
: sa_range(lr), sa_type(type)
{
require(lr.is_valid());
require(type);
this->sa_value.sav_int = val;
};
string_attr(const struct line_range &lr, string_attr_type_t type, string_attr_value_t val)
: sa_range(lr), sa_type(type), sa_value(val) {
string_attr(const struct line_range& lr,
string_attr_type_t type,
string_attr_value_t val)
: sa_range(lr), sa_type(type), sa_value(val)
{
require(lr.is_valid());
require(type);
};
@ -187,7 +218,8 @@ struct string_attr {
return this->sa_range < rhs.sa_range;
};
intern_string_t to_string() const {
intern_string_t to_string() const
{
return intern_string_t((const intern_string*) this->sa_value.sav_ptr);
};
@ -201,7 +233,9 @@ struct string_attr {
typedef std::vector<string_attr> string_attrs_t;
inline string_attrs_t::const_iterator
find_string_attr(const string_attrs_t &sa, string_attr_type_t type, int start = 0)
find_string_attr(const string_attrs_t& sa,
string_attr_type_t type,
int start = 0)
{
string_attrs_t::const_iterator iter;
@ -215,7 +249,9 @@ find_string_attr(const string_attrs_t &sa, string_attr_type_t type, int start =
}
inline nonstd::optional<const string_attr*>
get_string_attr(const string_attrs_t &sa, string_attr_type_t type, int start = 0)
get_string_attr(const string_attrs_t& sa,
string_attr_type_t type,
int start = 0)
{
auto iter = find_string_attr(sa, type, start);
@ -228,7 +264,9 @@ get_string_attr(const string_attrs_t &sa, string_attr_type_t type, int start = 0
template<typename T>
inline string_attrs_t::const_iterator
find_string_attr_containing(const string_attrs_t &sa, string_attr_type_t type, T x)
find_string_attr_containing(const string_attrs_t& sa,
string_attr_type_t type,
T x)
{
string_attrs_t::const_iterator iter;
@ -318,7 +356,8 @@ find_string_attr_range(const string_attrs_t &sa, string_attr_type_t type)
return line_range();
}
inline void remove_string_attr(string_attrs_t &sa, const struct line_range &lr)
inline void
remove_string_attr(string_attrs_t& sa, const struct line_range& lr)
{
string_attrs_t::iterator iter;
@ -327,7 +366,8 @@ inline void remove_string_attr(string_attrs_t &sa, const struct line_range &lr)
}
}
inline void remove_string_attr(string_attrs_t &sa, string_attr_type_t type)
inline void
remove_string_attr(string_attrs_t& sa, string_attr_type_t type)
{
for (auto iter = sa.begin(); iter != sa.end();) {
if (iter->sa_type == type) {
@ -338,7 +378,8 @@ inline void remove_string_attr(string_attrs_t &sa, string_attr_type_t type)
}
}
inline void shift_string_attrs(string_attrs_t &sa, int32_t start, int32_t amount)
inline void
shift_string_attrs(string_attrs_t& sa, int32_t start, int32_t amount)
{
for (auto& iter : sa) {
iter.sa_range.shift(start, amount);
@ -348,12 +389,14 @@ inline void shift_string_attrs(string_attrs_t &sa, int32_t start, int32_t amount
struct text_wrap_settings {
text_wrap_settings() : tws_indent(2), tws_width(80){};
text_wrap_settings &with_indent(int indent) {
text_wrap_settings& with_indent(int indent)
{
this->tws_indent = indent;
return *this;
};
text_wrap_settings &with_width(int width) {
text_wrap_settings& with_width(int width)
{
this->tws_width = width;
return *this;
};
@ -367,35 +410,52 @@ struct text_wrap_settings {
*/
class attr_line_t {
public:
attr_line_t() {
attr_line_t()
{
this->al_attrs.reserve(RESERVE_SIZE);
};
attr_line_t(std::string str) : al_string(std::move(str)) {
attr_line_t(std::string str) : al_string(std::move(str))
{
this->al_attrs.reserve(RESERVE_SIZE);
};
attr_line_t(const char *str) : al_string(str) {
attr_line_t(const char* str) : al_string(str)
{
this->al_attrs.reserve(RESERVE_SIZE);
};
static inline attr_line_t from_ansi_str(const char *str) {
static inline attr_line_t from_ansi_str(const char* str)
{
attr_line_t retval;
return retval.with_ansi_string("%s", str);
};
/** @return The string itself. */
std::string &get_string() { return this->al_string; };
std::string& get_string()
{
return this->al_string;
};
const std::string &get_string() const { return this->al_string; };
const std::string& get_string() const
{
return this->al_string;
};
/** @return The attributes for the string. */
string_attrs_t &get_attrs() { return this->al_attrs; };
string_attrs_t& get_attrs()
{
return this->al_attrs;
};
const string_attrs_t &get_attrs() const { return this->al_attrs; };
const string_attrs_t& get_attrs() const
{
return this->al_attrs;
};
attr_line_t &with_string(const std::string &str) {
attr_line_t& with_string(const std::string& str)
{
this->al_string = str;
return *this;
}
@ -404,15 +464,17 @@ public:
attr_line_t& with_ansi_string(const std::string& str);
attr_line_t &with_attr(const string_attr &sa) {
attr_line_t& with_attr(const string_attr& sa)
{
this->al_attrs.push_back(sa);
return *this;
};
attr_line_t &ensure_space() {
if (!this->al_string.empty() &&
this->al_string.back() != ' ' &&
this->al_string.back() != '[') {
attr_line_t& ensure_space()
{
if (!this->al_string.empty() && this->al_string.back() != ' '
&& this->al_string.back() != '[')
{
this->append(1, ' ');
}
@ -420,9 +482,8 @@ public:
};
template<typename S, typename T = void*>
attr_line_t &append(S str,
string_attr_type_t type = nullptr,
T val = T()) {
attr_line_t& append(S str, string_attr_type_t type = nullptr, T val = T())
{
size_t start_len = this->al_string.length();
this->al_string.append(str);
@ -434,24 +495,31 @@ public:
return *this;
};
attr_line_t &append(const char *str, size_t len) {
attr_line_t& append(const char* str, size_t len)
{
this->al_string.append(str, len);
return *this;
};
attr_line_t &insert(size_t index, const attr_line_t &al, text_wrap_settings *tws = nullptr);
attr_line_t& insert(size_t index,
const attr_line_t& al,
text_wrap_settings* tws = nullptr);
attr_line_t &append(const attr_line_t &al, text_wrap_settings *tws = nullptr) {
attr_line_t& append(const attr_line_t& al,
text_wrap_settings* tws = nullptr)
{
return this->insert(this->al_string.length(), al, tws);
};
attr_line_t &append(size_t len, char c) {
attr_line_t& append(size_t len, char c)
{
this->al_string.append(len, c);
return *this;
};
attr_line_t &insert(size_t index, size_t len, char c) {
attr_line_t& insert(size_t index, size_t len, char c)
{
this->al_string.insert(index, len, c);
shift_string_attrs(this->al_attrs, index, len);
@ -459,7 +527,8 @@ public:
return *this;
}
attr_line_t &insert(size_t index, const char *str) {
attr_line_t& insert(size_t index, const char* str)
{
this->al_string.insert(index, str);
shift_string_attrs(this->al_attrs, index, strlen(str));
@ -467,7 +536,8 @@ public:
return *this;
}
attr_line_t &erase(size_t pos, size_t len = std::string::npos) {
attr_line_t& erase(size_t pos, size_t len = std::string::npos)
{
this->al_string.erase(pos, len);
shift_string_attrs(this->al_attrs, pos, -((int32_t) len));
@ -475,7 +545,8 @@ public:
return *this;
};
attr_line_t &erase_utf8_chars(size_t start) {
attr_line_t& erase_utf8_chars(size_t start)
{
auto byte_index = utf8_char_to_byte_index(this->al_string, start);
this->erase(byte_index);
@ -484,7 +555,8 @@ public:
attr_line_t& right_justify(unsigned long width);
ssize_t length() const {
ssize_t length() const
{
size_t retval = this->al_string.length();
for (const auto& al_attr : this->al_attrs) {
@ -497,14 +569,16 @@ public:
return retval;
};
std::string get_substring(const line_range &lr) const {
std::string get_substring(const line_range& lr) const
{
if (!lr.is_valid()) {
return "";
}
return this->al_string.substr(lr.lr_start, lr.length());
};
string_attrs_t::const_iterator find_attr(size_t near) const {
string_attrs_t::const_iterator find_attr(size_t near) const
{
near = std::min(near, this->al_string.length() - 1);
while (near > 0 && isspace(this->al_string[near])) {
@ -514,7 +588,8 @@ public:
return find_string_attr(this->al_attrs, near);
};
bool empty() const {
bool empty() const
{
return this->length() == 0;
};

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
@ -32,14 +32,14 @@
#ifndef auto_fd_hh
#define auto_fd_hh
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/select.h>
#include <exception>
#include <new>
#include <string>
#include <exception>
#include <errno.h>
#include <fcntl.h>
#include <sys/select.h>
#include <unistd.h>
#include "base/lnav_log.hh"
#include "base/result.h"
@ -51,7 +51,6 @@
*/
class auto_fd {
public:
/**
* Wrapper for the posix pipe(2) function that stores the file descriptor
* results in an auto_fd array.
@ -80,7 +79,8 @@ public:
* @param fd The file descriptor to duplicate.
* @return A new auto_fd that contains the duplicated file descriptor.
*/
static auto_fd dup_of(int fd) {
static auto_fd dup_of(int fd)
{
if (fd == -1) {
return auto_fd{};
}
@ -99,8 +99,7 @@ public:
*
* @param fd The file descriptor to be managed.
*/
explicit auto_fd(int fd = -1)
: af_fd(fd)
explicit auto_fd(int fd = -1) : af_fd(fd)
{
require(fd >= -1);
};
@ -112,9 +111,7 @@ public:
*
* @param af The source of the file descriptor.
*/
auto_fd(auto_fd && af) noexcept
: af_fd(af.release()) {
};
auto_fd(auto_fd&& af) noexcept : af_fd(af.release()){};
/**
* Const copy constructor. The file descriptor from the source will be
@ -122,8 +119,7 @@ public:
*
* @param af The source of the file descriptor.
*/
auto_fd(const auto_fd &af)
: af_fd(-1)
auto_fd(const auto_fd& af) : af_fd(-1)
{
if (af.af_fd != -1 && (this->af_fd = dup(af.af_fd)) == -1) {
throw std::bad_alloc();
@ -139,7 +135,10 @@ public:
};
/** @return The file descriptor as a plain integer. */
operator int() const { return this->af_fd; };
operator int() const
{
return this->af_fd;
};
/**
* Replace the current descriptor with the given one. The current
@ -162,7 +161,8 @@ public:
* @param af The old manager of the file descriptor.
* @return *this
*/
auto_fd &operator=(auto_fd && af) noexcept {
auto_fd& operator=(auto_fd&& af) noexcept
{
this->reset(af.release());
return *this;
};
@ -218,7 +218,8 @@ public:
}
};
void close_on_exec() const {
void close_on_exec() const
{
if (this->af_fd == -1) {
return;
}
@ -231,7 +232,8 @@ private:
class auto_pipe {
public:
static Result<auto_pipe, std::string> for_child_fd(int child_fd) {
static Result<auto_pipe, std::string> for_child_fd(int child_fd)
{
auto_pipe retval(child_fd);
if (retval.open() == -1) {
@ -255,24 +257,29 @@ public:
}
};
int open() {
int open()
{
return auto_fd::pipe(this->ap_fd);
};
void close() {
void close()
{
this->ap_fd[0].reset();
this->ap_fd[1].reset();
};
auto_fd &read_end() {
auto_fd& read_end()
{
return this->ap_fd[0];
};
auto_fd &write_end() {
auto_fd& write_end()
{
return this->ap_fd[1];
};
void after_fork(pid_t child_pid) {
void after_fork(pid_t child_pid)
{
int new_fd;
switch (child_pid) {
@ -286,8 +293,7 @@ public:
this->read_end() = ::open("/dev/null", O_RDONLY);
}
new_fd = this->read_end().get();
}
else {
} else {
this->read_end().reset();
if (this->write_end().get() == -1) {
this->write_end() = ::open("/dev/null", O_WRONLY);
@ -304,8 +310,7 @@ public:
default:
if (this->ap_child_flags == O_RDONLY) {
this->read_end().reset();
}
else {
} else {
this->write_end().reset();
}
break;

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
@ -32,11 +32,11 @@
#ifndef lnav_auto_mem_hh
#define lnav_auto_mem_hh
#include <exception>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <exception>
#include "base/result.h"
@ -52,8 +52,7 @@ template<class T, free_func_t default_free = free>
class auto_mem {
public:
explicit auto_mem(T* ptr = nullptr)
: am_ptr(ptr), am_free_func(default_free) {
};
: am_ptr(ptr), am_free_func(default_free){};
auto_mem(const auto_mem& am) = delete;
@ -62,15 +61,17 @@ public:
: am_ptr(nullptr), am_free_func((free_func_t) free_func){};
auto_mem(auto_mem&& other) noexcept
: am_ptr(other.release()),
am_free_func(other.am_free_func) {
};
: am_ptr(other.release()), am_free_func(other.am_free_func){};
~auto_mem() {
~auto_mem()
{
this->reset();
};
operator T *() const { return this->am_ptr; };
operator T*() const
{
return this->am_ptr;
};
auto_mem& operator=(T* ptr)
{
@ -124,53 +125,75 @@ private:
template<typename T, void (*free_func)(T*)>
class static_root_mem {
public:
static_root_mem() {
static_root_mem()
{
memset(&this->srm_value, 0, sizeof(T));
};
~static_root_mem() { free_func(&this->srm_value); };
~static_root_mem()
{
free_func(&this->srm_value);
};
const T *operator->() const { return &this->srm_value; };
const T* operator->() const
{
return &this->srm_value;
};
const T &in() const { return this->srm_value; };
const T& in() const
{
return this->srm_value;
};
T *inout() {
T* inout()
{
free_func(&this->srm_value);
memset(&this->srm_value, 0, sizeof(T));
return &this->srm_value;
};
private:
static_root_mem &operator =(T &) { return *this; };
static_root_mem& operator=(T&)
{
return *this;
};
static_root_mem &operator =(static_root_mem &) { return *this; };
static_root_mem& operator=(static_root_mem&)
{
return *this;
};
T srm_value;
};
class auto_buffer {
public:
static auto_buffer alloc(size_t size) {
static auto_buffer alloc(size_t size)
{
return auto_buffer{(char*) malloc(size), size};
}
auto_buffer(auto_buffer&& other) noexcept
: ab_buffer(other.ab_buffer), ab_size(other.ab_size) {
: ab_buffer(other.ab_buffer), ab_size(other.ab_size)
{
other.ab_buffer = nullptr;
other.ab_size = 0;
}
~auto_buffer() {
~auto_buffer()
{
free(this->ab_buffer);
this->ab_buffer = nullptr;
this->ab_size = 0;
}
char *in() {
char* in()
{
return this->ab_buffer;
}
std::pair<char *, size_t> release() {
std::pair<char*, size_t> release()
{
auto retval = std::make_pair(this->ab_buffer, this->ab_size);
this->ab_buffer = nullptr;
@ -178,11 +201,13 @@ public:
return retval;
}
size_t size() const {
size_t size() const
{
return this->ab_size;
}
void expand_by(size_t amount) {
void expand_by(size_t amount)
{
if (amount == 0) {
return;
}
@ -197,13 +222,14 @@ public:
this->ab_size = new_size;
}
auto_buffer& shrink_to(size_t new_size) {
auto_buffer& shrink_to(size_t new_size)
{
this->ab_size = new_size;
return *this;
}
private:
auto_buffer(char *buffer, size_t size) : ab_buffer(buffer), ab_size(size) {
}
auto_buffer(char* buffer, size_t size) : ab_buffer(buffer), ab_size(size) {}
char* ab_buffer;
size_t ab_size;

View File

@ -21,23 +21,24 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "auto_pid.hh"
#include <unistd.h>
#include "lnav_log.hh"
#include "config.h"
#include "fmt/format.h"
#include "auto_pid.hh"
#include "lnav_log.hh"
namespace lnav {
namespace pid {
Result<auto_pid<process_state::RUNNING>, std::string> from_fork()
Result<auto_pid<process_state::running>, std::string>
from_fork()
{
auto pid = ::fork();
@ -49,7 +50,7 @@ Result<auto_pid<process_state::RUNNING>, std::string> from_fork()
log_debug("started child: %d", pid);
}
return Ok(auto_pid<process_state::RUNNING>(pid));
}
}
return Ok(auto_pid<process_state::running>(pid));
}
} // namespace pid
} // namespace lnav

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
@ -32,50 +32,58 @@
#ifndef auto_pid_hh
#define auto_pid_hh
#include <errno.h>
#include <signal.h>
#include <cerrno>
#include <csignal>
#include <sys/types.h>
#include <sys/wait.h>
#include "base/result.h"
#include "base/lnav_log.hh"
#include "base/result.h"
#include "mapbox/variant.hpp"
enum class process_state {
RUNNING,
FINISHED,
running,
finished,
};
template<process_state ProcState>
class auto_pid {
public:
explicit auto_pid(pid_t child, int status = 0) : ap_child(child),
ap_status(status)
{};
explicit auto_pid(pid_t child, int status = 0)
: ap_child(child), ap_status(status)
{
}
auto_pid(const auto_pid& other) = delete;
auto_pid(auto_pid&& other) noexcept
: ap_child(std::move(other).release()),
ap_status(other.ap_status)
{};
: ap_child(std::move(other).release()), ap_status(other.ap_status)
{
}
~auto_pid() noexcept
{ this->reset(); };
{
this->reset();
}
auto_pid& operator=(auto_pid&& other) noexcept
{
this->reset(std::move(other).release());
this->ap_status = other.ap_status;
return *this;
};
}
auto_pid& operator=(const auto_pid& other) = delete;
pid_t in() const
{ return this->ap_child; }
{
return this->ap_child;
}
bool in_child() const
{
static_assert(ProcState == process_state::RUNNING,
static_assert(ProcState == process_state::running,
"this method is only available in the RUNNING state");
return this->ap_child == 0;
};
@ -87,31 +95,31 @@ public:
int status() const
{
static_assert(ProcState == process_state::FINISHED,
static_assert(ProcState == process_state::finished,
"wait_for_child() must be called first");
return this->ap_status;
};
bool was_normal_exit() const
{
static_assert(ProcState == process_state::FINISHED,
static_assert(ProcState == process_state::finished,
"wait_for_child() must be called first");
return WIFEXITED(this->ap_status);
}
int exit_status() const
{
static_assert(ProcState == process_state::FINISHED,
static_assert(ProcState == process_state::finished,
"wait_for_child() must be called first");
return WEXITSTATUS(this->ap_status);
}
using poll_result = mapbox::util::variant<
auto_pid<process_state::RUNNING>,
auto_pid<process_state::FINISHED>
>;
using poll_result
= mapbox::util::variant<auto_pid<process_state::running>,
auto_pid<process_state::finished>>;
poll_result poll() && {
poll_result poll() &&
{
if (this->ap_child != -1) {
auto rc = waitpid(this->ap_child, &this->ap_status, WNOHANG);
@ -120,20 +128,21 @@ public:
}
}
return auto_pid<process_state::FINISHED>(
return auto_pid<process_state::finished>(
std::exchange(this->ap_child, -1), this->ap_status);
}
auto_pid<process_state::FINISHED> wait_for_child(int options = 0) &&
auto_pid<process_state::finished> wait_for_child(int options = 0) &&
{
if (this->ap_child != -1) {
while ((waitpid(this->ap_child,
&this->ap_status,
options)) < 0 && (errno == EINTR)) { ;
while ((waitpid(this->ap_child, &this->ap_status, options)) < 0
&& (errno == EINTR))
{
;
}
}
return auto_pid<process_state::FINISHED>(
return auto_pid<process_state::finished>(
std::exchange(this->ap_child, -1), this->ap_status);
}
@ -141,7 +150,7 @@ public:
{
if (this->ap_child != child) {
this->ap_status = 0;
if (ProcState == process_state::RUNNING && this->ap_child != -1) {
if (ProcState == process_state::running && this->ap_child != -1) {
log_debug("sending SIGTERM to child: %d", this->ap_child);
kill(this->ap_child, SIGTERM);
}
@ -156,8 +165,8 @@ private:
namespace lnav {
namespace pid {
Result<auto_pid<process_state::RUNNING>, std::string> from_fork();
}
}
Result<auto_pid<process_state::running>, std::string> from_fork();
} // namespace pid
} // namespace lnav
#endif

View File

@ -21,20 +21,21 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @file date_time_scanner.cc
*/
#include "config.h"
#include "date_time_scanner.hh"
#include "config.h"
#include "ptimec.hh"
size_t date_time_scanner::ftime(char *dst, size_t len, const exttm &tm) const
size_t
date_time_scanner::ftime(char* dst, size_t len, const exttm& tm) const
{
off_t off = 0;
@ -43,7 +44,8 @@ size_t date_time_scanner::ftime(char *dst, size_t len, const exttm &tm) const
return (size_t) off;
}
bool next_format(const char * const fmt[], int &index, int &locked_index)
bool
next_format(const char* const fmt[], int& index, int& locked_index)
{
bool retval = true;
@ -52,18 +54,17 @@ bool next_format(const char * const fmt[], int &index, int &locked_index)
if (fmt[index] == nullptr) {
retval = false;
}
}
else if (index == locked_index) {
} else if (index == locked_index) {
retval = false;
}
else {
} else {
index = locked_index;
}
return retval;
}
const char *date_time_scanner::scan(const char *time_dest,
const char*
date_time_scanner::scan(const char* time_dest,
size_t time_len,
const char* const time_fmt[],
struct exttm* tm_out,
@ -78,14 +79,10 @@ const char *date_time_scanner::scan(const char *time_dest,
time_fmt = PTIMEC_FORMAT_STR;
}
while (next_format(time_fmt,
curr_time_fmt,
this->dts_fmt_lock)) {
while (next_format(time_fmt, curr_time_fmt, this->dts_fmt_lock)) {
*tm_out = this->dts_base_tm;
tm_out->et_flags = 0;
if (time_len > 1 &&
time_dest[0] == '+' &&
isdigit(time_dest[1])) {
if (time_len > 1 && time_dest[0] == '+' && isdigit(time_dest[1])) {
char time_cp[time_len + 1];
int gmt_int, off;
@ -105,7 +102,8 @@ const char *date_time_scanner::scan(const char *time_dest,
}
tv_out.tv_sec = gmt;
tv_out.tv_usec = 0;
tm_out->et_flags = ETF_DAY_SET|ETF_MONTH_SET|ETF_YEAR_SET|ETF_MACHINE_ORIENTED|ETF_EPOCH_TIME;
tm_out->et_flags = ETF_DAY_SET | ETF_MONTH_SET | ETF_YEAR_SET
| ETF_MACHINE_ORIENTED | ETF_EPOCH_TIME;
this->dts_fmt_lock = curr_time_fmt;
this->dts_fmt_len = off;
@ -113,8 +111,7 @@ const char *date_time_scanner::scan(const char *time_dest,
found = true;
break;
}
}
else if (time_fmt == PTIMEC_FORMAT_STR) {
} else if (time_fmt == PTIMEC_FORMAT_STR) {
ptime_func func = PTIMEC_FORMATS[curr_time_fmt].pf_func;
off_t off = 0;
@ -129,8 +126,10 @@ const char *date_time_scanner::scan(const char *time_dest,
if (tm_out->et_tm.tm_year < 70) {
tm_out->et_tm.tm_year = 80;
}
if (convert_local &&
(this->dts_local_time || tm_out->et_flags & ETF_EPOCH_TIME)) {
if (convert_local
&& (this->dts_local_time
|| tm_out->et_flags & ETF_EPOCH_TIME))
{
time_t gmt = tm2sec(&tm_out->et_tm);
this->to_localtime(gmt, *tm_out);
@ -145,8 +144,7 @@ const char *date_time_scanner::scan(const char *time_dest,
found = true;
break;
}
}
else {
} else {
off_t off = 0;
#ifdef HAVE_STRUCT_TM_TM_ZONE
@ -154,14 +152,19 @@ const char *date_time_scanner::scan(const char *time_dest,
tm_out->et_tm.tm_zone = nullptr;
}
#endif
if (ptime_fmt(time_fmt[curr_time_fmt], tm_out, time_dest, off, time_len) &&
(time_dest[off] == '.' || time_dest[off] == ',' || off == (off_t)time_len)) {
if (ptime_fmt(
time_fmt[curr_time_fmt], tm_out, time_dest, off, time_len)
&& (time_dest[off] == '.' || time_dest[off] == ','
|| off == (off_t) time_len))
{
retval = &time_dest[off];
if (tm_out->et_tm.tm_year < 70) {
tm_out->et_tm.tm_year = 80;
}
if (convert_local &&
(this->dts_local_time || tm_out->et_flags & ETF_EPOCH_TIME)) {
if (convert_local
&& (this->dts_local_time
|| tm_out->et_flags & ETF_EPOCH_TIME))
{
time_t gmt = tm2sec(&tm_out->et_tm);
this->to_localtime(gmt, *tm_out);
@ -197,8 +200,7 @@ const char *date_time_scanner::scan(const char *time_dest,
tv_out.tv_usec = tm_out->et_nsec / 1000;
this->dts_fmt_len += 7;
retval += 7;
}
else if (ptime_L(tm_out, time_dest, off, time_len)) {
} else if (ptime_L(tm_out, time_dest, off, time_len)) {
tv_out.tv_usec = tm_out->et_nsec / 1000;
this->dts_fmt_len += 4;
retval += 4;
@ -209,15 +211,16 @@ const char *date_time_scanner::scan(const char *time_dest,
return retval;
}
void date_time_scanner::to_localtime(time_t t, exttm &tm_out)
void
date_time_scanner::to_localtime(time_t t, exttm& tm_out)
{
if (t < (24 * 60 * 60)) {
// Don't convert and risk going past the epoch.
return;
}
if (t < this->dts_local_offset_valid ||
t >= this->dts_local_offset_expiry) {
if (t < this->dts_local_offset_valid || t >= this->dts_local_offset_expiry)
{
time_t new_gmt;
localtime_r(&t, &tm_out.et_tm);
@ -230,10 +233,9 @@ void date_time_scanner::to_localtime(time_t t, exttm &tm_out)
this->dts_local_offset_cache = t - new_gmt;
this->dts_local_offset_valid = t;
this->dts_local_offset_expiry = t + (EXPIRE_TIME - 1);
this->dts_local_offset_expiry -=
this->dts_local_offset_expiry % EXPIRE_TIME;
}
else {
this->dts_local_offset_expiry
-= this->dts_local_offset_expiry % EXPIRE_TIME;
} else {
time_t adjust_gmt = t - this->dts_local_offset_cache;
gmtime_r(&adjust_gmt, &tm_out.et_tm);
}

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
@ -32,11 +32,11 @@
#ifndef lnav_date_time_scanner_hh
#define lnav_date_time_scanner_hh
#include <time.h>
#include <sys/types.h>
#include <string>
#include <sys/types.h>
#include <time.h>
#include "time_util.hh"
/**
@ -47,11 +47,13 @@
* an exttm struct to a string using the ftime() method.
*/
struct date_time_scanner {
date_time_scanner() {
date_time_scanner()
{
this->clear();
};
void clear() {
void clear()
{
this->dts_base_time = 0;
memset(&this->dts_base_tm, 0, sizeof(this->dts_base_tm));
this->dts_fmt_lock = -1;
@ -61,12 +63,14 @@ struct date_time_scanner {
/**
* Unlock this scanner so that the format is rediscovered.
*/
void unlock() {
void unlock()
{
this->dts_fmt_lock = -1;
this->dts_fmt_len = -1;
}
void set_base_time(time_t base_time) {
void set_base_time(time_t base_time)
{
this->dts_base_time = base_time;
localtime_r(&base_time, &this->dts_base_tm.et_tm);
};
@ -104,7 +108,8 @@ struct date_time_scanner {
bool convert_to_timeval(const char* time_src,
ssize_t time_len,
const char* const time_fmt[],
struct timeval &tv_out) {
struct timeval& tv_out)
{
struct exttm tm;
if (time_len == -1) {
@ -116,12 +121,13 @@ struct date_time_scanner {
return false;
};
bool convert_to_timeval(const std::string &time_src,
struct timeval &tv_out) {
bool convert_to_timeval(const std::string& time_src, struct timeval& tv_out)
{
struct exttm tm;
if (this->scan(time_src.c_str(), time_src.size(),
nullptr, &tm, tv_out) != nullptr) {
if (this->scan(time_src.c_str(), time_src.size(), nullptr, &tm, tv_out)
!= nullptr)
{
return true;
}
return false;

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@ -36,12 +36,13 @@ namespace lnav {
namespace enums {
template<typename E>
constexpr auto to_underlying(E e) noexcept
constexpr auto
to_underlying(E e) noexcept
{
return static_cast<std::underlying_type_t<E>>(e);
}
}
}
} // namespace enums
} // namespace lnav
#endif

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@ -43,24 +43,27 @@ public:
file_off_t fr_offset{0};
file_ssize_t fr_size{0};
void clear() {
void clear()
{
this->fr_offset = 0;
this->fr_size = 0;
}
ssize_t next_offset() const {
ssize_t next_offset() const
{
return this->fr_offset + this->fr_size;
}
bool empty() const {
bool empty() const
{
return fr_size == 0;
}
};
struct source_location {
source_location()
: sl_source(intern_string::lookup("unknown")),
sl_line_number(-1) {
: sl_source(intern_string::lookup("unknown")), sl_line_number(-1)
{
}
source_location(intern_string_t source, int line)

View File

@ -21,16 +21,16 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "fmt/format.h"
#include "fs_util.hh"
#include "config.h"
#include "fmt/format.h"
#include "opt_util.hh"
namespace lnav {
@ -46,13 +46,15 @@ open_temp_file(const ghc::filesystem::path &pattern)
strcpy(pattern_copy, pattern_str.c_str());
if ((fd = mkstemp(pattern_copy)) == -1) {
return Err(fmt::format("unable to create temporary file: {} -- {}",
pattern.string(), strerror(errno)));
pattern.string(),
strerror(errno)));
}
return Ok(std::make_pair(ghc::filesystem::path(pattern_copy), fd));
}
Result<std::string, std::string> read_file(const ghc::filesystem::path &path)
Result<std::string, std::string>
read_file(const ghc::filesystem::path& path)
{
try {
ghc::filesystem::ifstream file_stream(path);
@ -70,7 +72,8 @@ Result<std::string, std::string> read_file(const ghc::filesystem::path &path)
}
}
std::string build_path(const std::vector<ghc::filesystem::path> &paths)
std::string
build_path(const std::vector<ghc::filesystem::path>& paths)
{
std::string retval;
@ -90,5 +93,5 @@ std::string build_path(const std::vector<ghc::filesystem::path> &paths)
return retval;
}
}
}
} // namespace filesystem
} // namespace lnav

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@ -33,32 +33,38 @@
#include <string>
#include <vector>
#include "result.h"
#include "ghc/filesystem.hpp"
#include "result.h"
namespace lnav {
namespace filesystem {
inline int statp(const ghc::filesystem::path &path, struct stat *buf) {
inline int
statp(const ghc::filesystem::path& path, struct stat* buf)
{
return stat(path.c_str(), buf);
}
inline int openp(const ghc::filesystem::path &path, int flags) {
inline int
openp(const ghc::filesystem::path& path, int flags)
{
return open(path.c_str(), flags);
}
inline int openp(const ghc::filesystem::path &path, int flags, mode_t mode) {
inline int
openp(const ghc::filesystem::path& path, int flags, mode_t mode)
{
return open(path.c_str(), flags, mode);
}
Result<std::pair<ghc::filesystem::path, int>, std::string>
open_temp_file(const ghc::filesystem::path &pattern);
Result<std::pair<ghc::filesystem::path, int>, std::string> open_temp_file(
const ghc::filesystem::path& pattern);
Result<std::string, std::string> read_file(const ghc::filesystem::path& path);
std::string build_path(const std::vector<ghc::filesystem::path>& paths);
}
}
} // namespace filesystem
} // namespace lnav
#endif

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@ -33,12 +33,11 @@
#include <utility>
template<typename F, typename FrontArg>
decltype(auto) bind_mem(F&& f, FrontArg&& frontArg)
decltype(auto)
bind_mem(F&& f, FrontArg&& frontArg)
{
return [f = std::forward<F>(f),
frontArg = std::forward<FrontArg>(frontArg)]
(auto&&...backArgs)
{
frontArg = std::forward<FrontArg>(frontArg)](auto&&... backArgs) {
return (frontArg->*f)(std::forward<decltype(backArgs)>(backArgs)...);
};
}
@ -46,13 +45,23 @@ decltype(auto) bind_mem(F&& f, FrontArg&& frontArg)
struct noop_func {
struct anything {
template<class T>
operator T(){ return {}; }
operator T()
{
return {};
}
// optional reference support. Somewhat evil.
template<class T>
operator T&()const{ static T t{}; return t; }
operator T&() const
{
static T t{};
return t;
}
};
template<class... Args>
anything operator()(Args&&...)const{return {};}
anything operator()(Args&&...) const
{
return {};
}
};
#endif

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@ -44,7 +44,9 @@ namespace futures {
* @return The new future.
*/
template<class T>
std::future<std::decay_t<T>> make_ready_future( T&& t ) {
std::future<std::decay_t<T>>
make_ready_future(T&& t)
{
std::promise<std::decay_t<T>> pr;
auto r = pr.get_future();
pr.set_value(std::forward<T>(t));
@ -66,7 +68,8 @@ public:
explicit future_queue(std::function<void(T&)> processor)
: fq_processor(processor){};
~future_queue() {
~future_queue()
{
this->pop_to();
}
@ -77,7 +80,8 @@ public:
*
* @param f The future to add to the queue.
*/
void push_back(std::future<T>&& f) {
void push_back(std::future<T>&& f)
{
this->fq_deque.emplace_back(std::move(f));
this->pop_to(MAX_QUEUE_SIZE);
}
@ -88,7 +92,8 @@ public:
*
* @param size The new desired size of the queue.
*/
void pop_to(size_t size = 0) {
void pop_to(size_t size = 0)
{
while (this->fq_deque.size() > size) {
auto v = this->fq_deque.front().get();
this->fq_processor(v);
@ -100,7 +105,7 @@ public:
std::deque<std::future<T>> fq_deque;
};
}
}
} // namespace futures
} // namespace lnav
#endif

View File

@ -21,27 +21,34 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <cmath>
#include <vector>
#include "fmt/format.h"
#include "humanize.hh"
#include "config.h"
#include "fmt/format.h"
namespace humanize {
std::string file_size(file_ssize_t value)
std::string
file_size(file_ssize_t value)
{
static const double LN1024 = log(1024.0);
static const std::vector<const char*> UNITS = {
" ", "K", "M", "G", "T", "P", "E",
" ",
"K",
"M",
"G",
"T",
"P",
"E",
};
if (value < 0) {
@ -52,8 +59,8 @@ std::string file_size(file_ssize_t value)
return "0.0 B";
}
auto exp = floor(std::min(log(value) / LN1024,
(double) (UNITS.size() - 1)));
auto exp
= floor(std::min(log(value) / LN1024, (double) (UNITS.size() - 1)));
auto divisor = pow(1024, exp);
return fmt::format(FMT_STRING("{:.1f}{}B"),
@ -61,7 +68,8 @@ std::string file_size(file_ssize_t value)
UNITS[exp]);
}
const std::string& sparkline(double value, nonstd::optional<double> upper_opt)
const std::string&
sparkline(double value, nonstd::optional<double> upper_opt)
{
static const std::string ZERO = " ";
static const std::string BARS[] = {
@ -91,4 +99,4 @@ const std::string& sparkline(double value, nonstd::optional<double> upper_opt)
return BARS[index];
}
}
} // namespace humanize

View File

@ -21,21 +21,21 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <iostream>
#include "doctest/doctest.h"
#include "base/humanize.hh"
TEST_CASE("humanize::file_size") {
#include "config.h"
#include "doctest/doctest.h"
TEST_CASE("humanize::file_size")
{
CHECK(humanize::file_size(0) == "0.0 B");
CHECK(humanize::file_size(1) == "1.0 B");
CHECK(humanize::file_size(1024) == "1.0KB");

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@ -48,6 +48,6 @@ std::string file_size(file_ssize_t value);
const std::string& sparkline(double value, nonstd::optional<double> upper);
}
} // namespace humanize
#endif

View File

@ -21,22 +21,23 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "humanize.network.hh"
#include "config.h"
#include "pcrepp/pcrepp.hh"
namespace humanize {
namespace network {
namespace path {
nonstd::optional<::network::path> from_str(const char *str)
nonstd::optional<::network::path>
from_str(const char* str)
{
static const pcrepp REMOTE_PATTERN(
"(?:(?<username>[\\w\\._\\-]+)@)?"
@ -65,6 +66,6 @@ nonstd::optional<::network::path> from_str(const char *str)
};
}
}
}
}
} // namespace path
} // namespace network
} // namespace humanize

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@ -32,15 +32,16 @@
#include <string>
#include "optional.hpp"
#include "network.tcp.hh"
#include "fmt/format.h"
#include "network.tcp.hh"
#include "optional.hpp"
namespace fmt {
template<>
struct formatter<network::locality> {
constexpr auto parse(format_parse_context& ctx) {
constexpr auto parse(format_parse_context& ctx)
{
auto it = ctx.begin(), end = ctx.end();
// Check if reached the end of the range:
@ -52,11 +53,11 @@ struct formatter<network::locality> {
}
template<typename FormatContext>
auto format(const network::locality& l, FormatContext& ctx) {
auto format(const network::locality& l, FormatContext& ctx)
{
bool is_ipv6 = l.l_hostname.find(':') != std::string::npos;
return format_to(
ctx.out(),
return format_to(ctx.out(),
"{}{}{}{}{}",
l.l_username.value_or(std::string()),
l.l_username ? "@" : "",
@ -68,7 +69,8 @@ struct formatter<network::locality> {
template<>
struct formatter<network::path> {
constexpr auto parse(format_parse_context& ctx) {
constexpr auto parse(format_parse_context& ctx)
{
auto it = ctx.begin(), end = ctx.end();
// Check if reached the end of the range:
@ -80,16 +82,14 @@ struct formatter<network::path> {
}
template<typename FormatContext>
auto format(const network::path& p, FormatContext& ctx) {
auto format(const network::path& p, FormatContext& ctx)
{
return format_to(
ctx.out(),
"{}:{}",
p.p_locality,
p.p_path == "." ? "" : p.p_path);
ctx.out(), "{}:{}", p.p_locality, p.p_path == "." ? "" : p.p_path);
}
};
}
} // namespace fmt
namespace humanize {
namespace network {
@ -97,14 +97,14 @@ namespace path {
nonstd::optional<::network::path> from_str(const char* str);
inline nonstd::optional<::network::path> from_str(const std::string &str)
inline nonstd::optional<::network::path>
from_str(const std::string& str)
{
return from_str(str.c_str());
}
}
}
}
} // namespace path
} // namespace network
} // namespace humanize
#endif

View File

@ -21,21 +21,20 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <iostream>
#include "base/humanize.network.hh"
#include "config.h"
#include "doctest/doctest.h"
#include "base/humanize.network.hh"
TEST_CASE("humanize::network::path") {
TEST_CASE("humanize::network::path")
{
{
auto rp_opt = humanize::network::path::from_str("foobar");
CHECK(!rp_opt);
@ -70,8 +69,8 @@ TEST_CASE("humanize::network::path") {
CHECK(!rp.p_locality.l_service.has_value());
CHECK(rp.p_path == "/var/log");
CHECK(fmt::format("{}", rp.p_locality) ==
"dean@[fe80::184f:c67:baf1:fe02%en0]");
CHECK(fmt::format("{}", rp.p_locality)
== "dean@[fe80::184f:c67:baf1:fe02%en0]");
}
{
@ -85,13 +84,13 @@ TEST_CASE("humanize::network::path") {
CHECK(!rp.p_locality.l_service.has_value());
CHECK(rp.p_path == "/var/log");
CHECK(fmt::format("{}", rp.p_locality) ==
"[fe80::184f:c67:baf1:fe02%en0]");
CHECK(fmt::format("{}", rp.p_locality)
== "[fe80::184f:c67:baf1:fe02%en0]");
}
{
auto rp_opt = humanize::network::path::from_str(
"host1.example.com:/var/log");
auto rp_opt
= humanize::network::path::from_str("host1.example.com:/var/log");
CHECK(rp_opt.has_value());
auto rp = *rp_opt;

View File

@ -21,34 +21,36 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <chrono>
#include "humanize.time.hh"
#include "config.h"
#include "fmt/format.h"
#include "time_util.hh"
#include "humanize.time.hh"
namespace humanize {
namespace time {
using namespace std::chrono_literals;
point point::from_tv(const timeval &tv)
point
point::from_tv(const timeval& tv)
{
return point(tv);
}
std::string point::as_time_ago() const
std::string
point::as_time_ago() const
{
struct timeval current_time = this->p_recent_point
.value_or(current_timeval());
struct timeval current_time
= this->p_recent_point.value_or(current_timeval());
const char* fmt;
char buffer[64];
int amount;
@ -57,7 +59,8 @@ std::string point::as_time_ago() const
current_time.tv_sec = convert_log_time_to_local(current_time.tv_sec);
}
auto delta = std::chrono::seconds(current_time.tv_sec - this->p_past_point.tv_sec);
auto delta
= std::chrono::seconds(current_time.tv_sec - this->p_past_point.tv_sec);
if (delta < 0s) {
return "in the future";
} else if (delta < 1min) {
@ -66,7 +69,8 @@ std::string point::as_time_ago() const
return "one minute ago";
} else if (delta < 1h) {
fmt = "%d minutes ago";
amount = std::chrono::duration_cast<std::chrono::minutes>(delta).count();
amount
= std::chrono::duration_cast<std::chrono::minutes>(delta).count();
} else if (delta < 2h) {
return "one hour ago";
} else if (delta < 24h) {
@ -89,7 +93,8 @@ std::string point::as_time_ago() const
return std::string(buffer);
}
std::string point::as_precise_time_ago() const
std::string
point::as_precise_time_ago() const
{
struct timeval now, diff;
@ -121,12 +126,14 @@ std::string point::as_precise_time_ago() const
}
}
duration duration::from_tv(const struct timeval &tv)
duration
duration::from_tv(const struct timeval& tv)
{
return duration{tv};
}
std::string duration::to_string() const
std::string
duration::to_string() const
{
/* 24h22m33s111 */
@ -144,8 +151,8 @@ std::string duration::to_string() const
auto* curr_interval = intervals;
auto usecs = std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::seconds(this->d_timeval.tv_sec)) +
std::chrono::microseconds(this->d_timeval.tv_usec);
std::chrono::seconds(this->d_timeval.tv_sec))
+ std::chrono::microseconds(this->d_timeval.tv_usec);
auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(usecs);
std::string retval;
bool neg = false;
@ -157,8 +164,8 @@ std::string duration::to_string() const
uint64_t remaining;
if (millis >= 10min) {
remaining = std::chrono::duration_cast<std::chrono::seconds>(millis)
.count();
remaining
= std::chrono::duration_cast<std::chrono::seconds>(millis).count();
curr_interval += 1;
} else {
remaining = millis.count();
@ -171,8 +178,7 @@ std::string duration::to_string() const
if (curr_interval->length) {
amount = remaining % curr_interval->length;
remaining = remaining / curr_interval->length;
}
else {
} else {
amount = remaining;
remaining = 0;
}
@ -181,7 +187,10 @@ std::string duration::to_string() const
break;
}
snprintf(segment, sizeof(segment), curr_interval->format, amount,
snprintf(segment,
sizeof(segment),
curr_interval->format,
amount,
curr_interval->symbol);
retval.insert(0, segment);
}
@ -193,5 +202,5 @@ std::string duration::to_string() const
return retval;
}
}
}
} // namespace time
} // namespace humanize

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@ -30,10 +30,10 @@
#ifndef lnav_humanize_time_hh
#define lnav_humanize_time_hh
#include <sys/time.h>
#include <string>
#include <sys/time.h>
#include "optional.hpp"
namespace humanize {
@ -60,9 +60,10 @@ public:
std::string as_precise_time_ago() const;
private:
explicit point(const struct timeval &tv) : p_past_point{tv.tv_sec,
tv.tv_usec}
{}
explicit point(const struct timeval& tv)
: p_past_point{tv.tv_sec, tv.tv_usec}
{
}
struct timeval p_past_point;
nonstd::optional<struct timeval> p_recent_point;
@ -74,13 +75,14 @@ public:
static duration from_tv(const struct timeval& tv);
std::string to_string() const;
private:
explicit duration(const struct timeval& tv) : d_timeval(tv) {}
struct timeval d_timeval;
};
}
}
} // namespace time
} // namespace humanize
#endif

View File

@ -21,18 +21,17 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <chrono>
#include <iostream>
#include "doctest/doctest.h"
#include "config.h"
#include "doctest/doctest.h"
#include "humanize.time.hh"
TEST_CASE("time ago")
@ -42,87 +41,82 @@ TEST_CASE("time ago")
time_t t1 = 1610000000;
auto t1_chrono = std::chrono::seconds(t1);
auto p1 = humanize::time::point::from_tv({t1, 0})
.with_recent_point({(time_t) t1 + 5, 0});
auto p1 = humanize::time::point::from_tv({t1, 0}).with_recent_point(
{(time_t) t1 + 5, 0});
CHECK(p1.as_time_ago() == "just now");
CHECK(p1.as_precise_time_ago() == " 5 seconds ago");
auto p2 = humanize::time::point::from_tv({t1, 0})
.with_recent_point({(time_t) t1 + 65, 0});
auto p2 = humanize::time::point::from_tv({t1, 0}).with_recent_point(
{(time_t) t1 + 65, 0});
CHECK(p2.as_time_ago() == "one minute ago");
CHECK(p2.as_precise_time_ago() == " 1 minute and 5 seconds ago");
auto p3 = humanize::time::point::from_tv({t1, 0})
.with_recent_point({(time_t) t1 + (3 * 60 + 5), 0});
auto p3 = humanize::time::point::from_tv({t1, 0}).with_recent_point(
{(time_t) t1 + (3 * 60 + 5), 0});
CHECK(p3.as_time_ago() == "3 minutes ago");
CHECK(p3.as_precise_time_ago() == " 3 minutes and 5 seconds ago");
auto p4 = humanize::time::point::from_tv({t1, 0})
.with_recent_point({(time_t) (t1_chrono + 65min).count(), 0});
auto p4 = humanize::time::point::from_tv({t1, 0}).with_recent_point(
{(time_t) (t1_chrono + 65min).count(), 0});
CHECK(p4.as_time_ago() == "one hour ago");
CHECK(p4.as_precise_time_ago() == "one hour ago");
auto p5 = humanize::time::point::from_tv({t1, 0})
.with_recent_point({(time_t) (t1_chrono + 3h).count(), 0});
auto p5 = humanize::time::point::from_tv({t1, 0}).with_recent_point(
{(time_t) (t1_chrono + 3h).count(), 0});
CHECK(p5.as_time_ago() == "3 hours ago");
CHECK(p5.as_precise_time_ago() == "3 hours ago");
auto p6 = humanize::time::point::from_tv({t1, 0})
.with_recent_point({(time_t) (t1_chrono + 25h).count(), 0});
auto p6 = humanize::time::point::from_tv({t1, 0}).with_recent_point(
{(time_t) (t1_chrono + 25h).count(), 0});
CHECK(p6.as_time_ago() == "one day ago");
CHECK(p6.as_precise_time_ago() == "one day ago");
auto p7 = humanize::time::point::from_tv({t1, 0})
.with_recent_point({(time_t) (t1_chrono + 50h).count(), 0});
auto p7 = humanize::time::point::from_tv({t1, 0}).with_recent_point(
{(time_t) (t1_chrono + 50h).count(), 0});
CHECK(p7.as_time_ago() == "2 days ago");
CHECK(p7.as_precise_time_ago() == "2 days ago");
auto p8 = humanize::time::point::from_tv({t1, 0})
.with_recent_point({(time_t) (t1_chrono + 370 * 24h).count(), 0});
auto p8 = humanize::time::point::from_tv({t1, 0}).with_recent_point(
{(time_t) (t1_chrono + 370 * 24h).count(), 0});
CHECK(p8.as_time_ago() == "over a year ago");
CHECK(p8.as_precise_time_ago() == "over a year ago");
auto p9 = humanize::time::point::from_tv({t1, 0})
.with_recent_point({(time_t) (t1_chrono + 800 * 24h).count(), 0});
auto p9 = humanize::time::point::from_tv({t1, 0}).with_recent_point(
{(time_t) (t1_chrono + 800 * 24h).count(), 0});
CHECK(p9.as_time_ago() == "over 2 years ago");
CHECK(p9.as_precise_time_ago() == "over 2 years ago");
CHECK(humanize::time::point::from_tv({1610000000, 0})
.with_recent_point({(time_t) 1612000000, 0})
.as_time_ago() == "23 days ago");
.as_time_ago()
== "23 days ago");
}
TEST_CASE("duration to_string") {
TEST_CASE("duration to_string")
{
std::string val;
val = humanize::time::duration::from_tv({25 * 60 * 60, 123000})
.to_string();
val = humanize::time::duration::from_tv({25 * 60 * 60, 123000}).to_string();
CHECK(val == "1d1h0m0s");
val = humanize::time::duration::from_tv({10, 123000})
.to_string();
val = humanize::time::duration::from_tv({10, 123000}).to_string();
CHECK(val == "10s123");
val = humanize::time::duration::from_tv({10, 0})
.to_string();
val = humanize::time::duration::from_tv({10, 0}).to_string();
CHECK(val == "10s000");
val = humanize::time::duration::from_tv({0, 100000})
.to_string();
val = humanize::time::duration::from_tv({0, 100000}).to_string();
CHECK(val == "100");
val = humanize::time::duration::from_tv({0, 0})
.to_string();
val = humanize::time::duration::from_tv({0, 0}).to_string();
CHECK(val == "");
val = humanize::time::duration::from_tv({0, -10000})
.to_string();
val = humanize::time::duration::from_tv({0, -10000}).to_string();
CHECK(val == "-010");
val = humanize::time::duration::from_tv({-10, 0})
.to_string();
val = humanize::time::duration::from_tv({-10, 0}).to_string();
CHECK(val == "-10s000");
}

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
@ -39,33 +39,34 @@ namespace injector {
namespace details {
template<typename I, typename R, typename... Args>
std::function<std::shared_ptr<I>()> create_factory(R (*)(Args...)) {
return []() {
return std::make_shared<I>(::injector::get<Args>()...);
};
std::function<std::shared_ptr<I>()>
create_factory(R (*)(Args...))
{
return []() { return std::make_shared<I>(::injector::get<Args>()...); };
}
template<typename I,
std::enable_if_t<has_injectable<I>::value, bool> = true>
std::function<std::shared_ptr<I>()> create_factory() {
template<typename I, std::enable_if_t<has_injectable<I>::value, bool> = true>
std::function<std::shared_ptr<I>()>
create_factory()
{
typename I::injectable* i = nullptr;
return create_factory<I>(i);
}
template<typename I,
std::enable_if_t<!has_injectable<I>::value, bool> = true>
std::function<std::shared_ptr<I>()> create_factory() noexcept {
return []() {
return std::make_shared<I>();
};
template<typename I, std::enable_if_t<!has_injectable<I>::value, bool> = true>
std::function<std::shared_ptr<I>()>
create_factory() noexcept
{
return []() { return std::make_shared<I>(); };
}
}
} // namespace details
template<typename T, typename... Annotations>
struct bind : singleton_storage<T, Annotations...> {
static bool to_singleton() noexcept {
static bool to_singleton() noexcept
{
static T storage;
singleton_storage<T, Annotations...>::ss_data = &storage;
@ -73,20 +74,24 @@ struct bind : singleton_storage<T, Annotations...> {
}
template<typename... Args>
static bool to_instance(T* (*f)(Args...)) noexcept {
singleton_storage<T, Annotations...>::ss_data = f(::injector::get<Args>()...);
static bool to_instance(T* (*f)(Args...)) noexcept
{
singleton_storage<T, Annotations...>::ss_data
= f(::injector::get<Args>()...);
return true;
}
static bool to_instance(T* data) noexcept {
static bool to_instance(T* data) noexcept
{
singleton_storage<T, Annotations...>::ss_data = data;
return true;
}
template<typename I>
static bool to() noexcept {
singleton_storage<T, Annotations...>::ss_factory =
details::create_factory<I>();
static bool to() noexcept
{
singleton_storage<T, Annotations...>::ss_factory
= details::create_factory<I>();
return true;
}
};
@ -96,15 +101,17 @@ struct bind_multiple : multiple_storage<T> {
bind_multiple() noexcept = default;
template<typename I>
bind_multiple& add() noexcept {
multiple_storage<T>::get_factories()[typeid(I).name()] =
details::create_factory<I>();
bind_multiple& add() noexcept
{
multiple_storage<T>::get_factories()[typeid(I).name()]
= details::create_factory<I>();
return *this;
}
template<typename I, typename... Annotations>
bind_multiple& add_singleton() noexcept {
bind_multiple& add_singleton() noexcept
{
auto factory = details::create_factory<I>();
auto single = factory();
@ -112,14 +119,13 @@ struct bind_multiple : multiple_storage<T> {
bind<T, Annotations...>::to_instance(single.get());
}
bind<I, Annotations...>::to_instance(single.get());
multiple_storage<T>::get_factories()[typeid(I).name()] = [single]() {
return single;
};
multiple_storage<T>::get_factories()[typeid(I).name()]
= [single]() { return single; };
return *this;
}
};
}
} // namespace injector
#endif

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
@ -32,12 +32,12 @@
#ifndef lnav_injector_hh
#define lnav_injector_hh
#include <assert.h>
#include <map>
#include <memory>
#include <vector>
#include <type_traits>
#include <vector>
#include <assert.h>
#include "base/lnav_log.hh"
@ -50,26 +50,30 @@ template<class ...>
using void_t = void;
template<class, class = void>
struct has_injectable : std::false_type {};
struct has_injectable : std::false_type {
};
template<class T>
struct has_injectable<T, void_t<typename T::injectable>> : std::true_type
{};
struct has_injectable<T, void_t<typename T::injectable>> : std::true_type {
};
template<typename T, typename... Annotations>
struct singleton_storage {
static T *get() {
static T* get()
{
static int _[] = {0, (force_linking(Annotations{}), 0)...};
(void) _;
assert(ss_data != nullptr);
return ss_data;
}
static std::shared_ptr<T> create() {
static std::shared_ptr<T> create()
{
static int _[] = {0, (force_linking(Annotations{}), 0)...};
(void) _;
return ss_factory();
}
protected:
static T* ss_data;
static std::function<std::shared_ptr<T>()> ss_factory;
@ -79,7 +83,8 @@ template<typename T, typename...Annotations>
T* singleton_storage<T, Annotations...>::ss_data = nullptr;
template<typename T, typename... Annotations>
std::function<std::shared_ptr<T>()> singleton_storage<T, Annotations...>::ss_factory;
std::function<std::shared_ptr<T>()>
singleton_storage<T, Annotations...>::ss_factory;
template<typename T>
struct Impl {
@ -88,7 +93,8 @@ struct Impl {
template<typename T>
struct multiple_storage {
static std::vector<std::shared_ptr<T>> create() {
static std::vector<std::shared_ptr<T>> create()
{
std::vector<std::shared_ptr<T>> retval;
for (const auto& pair : get_factories()) {
@ -96,28 +102,35 @@ struct multiple_storage {
}
return retval;
}
protected:
using factory_map_t = std::map<std::string, std::function<std::shared_ptr<T>()>>;
static factory_map_t& get_factories() {
protected:
using factory_map_t
= std::map<std::string, std::function<std::shared_ptr<T>()>>;
static factory_map_t& get_factories()
{
static factory_map_t retval;
return retval;
}
};
template<typename T, typename...Annotations,
template<typename T,
typename... Annotations,
std::enable_if_t<std::is_reference<T>::value, bool> = true>
T get()
T
get()
{
using plain_t = std::remove_const_t<std::remove_reference_t<T>>;
return *singleton_storage<plain_t, Annotations...>::get();
}
template<typename T, typename...Annotations,
template<typename T,
typename... Annotations,
std::enable_if_t<std::is_pointer<T>::value, bool> = true>
T get()
T
get()
{
using plain_t = std::remove_const_t<std::remove_pointer_t<T>>;
@ -125,31 +138,38 @@ T get()
}
template<class T>
struct is_shared_ptr : std::false_type {};
struct is_shared_ptr : std::false_type {
};
template<class T>
struct is_shared_ptr<std::shared_ptr<T>> : std::true_type {};
struct is_shared_ptr<std::shared_ptr<T>> : std::true_type {
};
template<class T>
struct is_vector : std::false_type {};
struct is_vector : std::false_type {
};
template<class T>
struct is_vector<std::vector<T>> : std::true_type {};
template<typename T, typename...Annotations,
std::enable_if_t<is_shared_ptr<T>::value, bool> = true>
T get()
{
return singleton_storage<typename T::element_type, Annotations...>::create();
}
struct is_vector<std::vector<T>> : std::true_type {
};
template<typename T,
std::enable_if_t<is_vector<T>::value, bool> = true>
T get()
typename... Annotations,
std::enable_if_t<is_shared_ptr<T>::value, bool> = true>
T
get()
{
return singleton_storage<typename T::element_type,
Annotations...>::create();
}
template<typename T, std::enable_if_t<is_vector<T>::value, bool> = true>
T
get()
{
return multiple_storage<typename T::value_type::element_type>::create();
}
}
} // namespace injector
#endif

View File

@ -21,26 +21,27 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @file intern_string.cc
*/
#include "config.h"
#include <string.h>
#include <mutex>
#include "intern_string.hh"
#include <string.h>
#include "config.h"
const static int TABLE_SIZE = 4095;
struct intern_string::intern_table {
~intern_table() {
~intern_table()
{
for (auto is : this->it_table) {
auto curr = is;
@ -56,7 +57,8 @@ struct intern_string::intern_table {
intern_string* it_table[TABLE_SIZE];
};
intern_table_lifetime intern_string::get_table_lifetime()
intern_table_lifetime
intern_string::get_table_lifetime()
{
static intern_table_lifetime retval = std::make_shared<intern_table>();
@ -76,7 +78,8 @@ hash_str(const char *str, size_t len)
return retval;
}
const intern_string *intern_string::lookup(const char *str, ssize_t len) noexcept
const intern_string*
intern_string::lookup(const char* str, ssize_t len) noexcept
{
unsigned long h;
intern_string* curr;
@ -94,7 +97,8 @@ const intern_string *intern_string::lookup(const char *str, ssize_t len) noexcep
curr = tab->it_table[h];
while (curr != nullptr) {
if (curr->is_str.size() == len && strncmp(curr->is_str.c_str(), str, len) == 0) {
if (curr->is_str.size() == len
&& strncmp(curr->is_str.c_str(), str, len) == 0) {
return curr;
}
curr = curr->is_next;
@ -106,20 +110,22 @@ const intern_string *intern_string::lookup(const char *str, ssize_t len) noexcep
return curr;
}
}
const intern_string *intern_string::lookup(const string_fragment &sf) noexcept
const intern_string*
intern_string::lookup(const string_fragment& sf) noexcept
{
return lookup(sf.data(), sf.length());
}
const intern_string *intern_string::lookup(const std::string &str) noexcept
const intern_string*
intern_string::lookup(const std::string& str) noexcept
{
return lookup(str.c_str(), str.size());
}
bool intern_string::startswith(const char *prefix) const
bool
intern_string::startswith(const char* prefix) const
{
const char* curr = this->is_str.data();
@ -131,7 +137,8 @@ bool intern_string::startswith(const char *prefix) const
return *prefix == '\0';
}
void string_fragment::trim(const char *tokens)
void
string_fragment::trim(const char* tokens)
{
while (this->sf_begin < this->sf_end) {
bool found = false;
@ -165,7 +172,8 @@ void string_fragment::trim(const char *tokens)
}
}
nonstd::optional<string_fragment> string_fragment::consume_n(int amount) const
nonstd::optional<string_fragment>
string_fragment::consume_n(int amount) const
{
if (amount > this->length()) {
return nonstd::nullopt;

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
@ -32,72 +32,81 @@
#ifndef intern_string_hh
#define intern_string_hh
#include <string>
#include <string.h>
#include <sys/types.h>
#include <string>
#include "fmt/format.h"
#include "optional.hpp"
#include "strnatcmp.h"
#include "fmt/format.h"
struct string_fragment {
using iterator = const char*;
explicit string_fragment(const char* str = "", int begin = 0, int end = -1)
: sf_string(str), sf_begin(begin), sf_end(end == -1 ? strlen(str) : end) {
};
: sf_string(str), sf_begin(begin),
sf_end(end == -1 ? strlen(str) : end){};
explicit string_fragment(const unsigned char *str, int begin = 0, int end = -1)
: sf_string((const char *) str),
sf_begin(begin),
sf_end(end == -1 ? strlen((const char *) str) : end) {
};
explicit string_fragment(const unsigned char* str,
int begin = 0,
int end = -1)
: sf_string((const char*) str), sf_begin(begin),
sf_end(end == -1 ? strlen((const char*) str) : end){};
string_fragment(const std::string& str)
: sf_string(str.c_str()), sf_begin(0), sf_end(str.length()) {
: sf_string(str.c_str()), sf_begin(0), sf_end(str.length())
{
}
bool is_valid() const {
bool is_valid() const
{
return this->sf_begin != -1;
};
int length() const {
int length() const
{
return this->sf_end - this->sf_begin;
};
const char *data() const {
const char* data() const
{
return &this->sf_string[this->sf_begin];
}
iterator begin() const {
iterator begin() const
{
return &this->sf_string[this->sf_begin];
}
iterator end() const {
iterator end() const
{
return &this->sf_string[this->sf_end];
}
bool empty() const {
bool empty() const
{
return !this->is_valid() || length() == 0;
};
char operator[](int index) const {
char operator[](int index) const
{
return this->sf_string[sf_begin + index];
};
bool operator==(const std::string &str) const {
bool operator==(const std::string& str) const
{
if (this->length() != (int) str.length()) {
return false;
}
return memcmp(&this->sf_string[this->sf_begin],
str.c_str(),
str.length()) == 0;
return memcmp(
&this->sf_string[this->sf_begin], str.c_str(), str.length())
== 0;
};
bool operator==(const string_fragment &sf) const {
bool operator==(const string_fragment& sf) const
{
if (this->length() != sf.length()) {
return false;
}
@ -105,27 +114,32 @@ struct string_fragment {
return memcmp(this->data(), sf.data(), sf.length()) == 0;
};
bool iequal(const string_fragment &sf) const {
bool iequal(const string_fragment& sf) const
{
if (this->length() != sf.length()) {
return false;
}
return strnatcasecmp(this->length(), this->data(),
sf.length(), sf.data()) == 0;
return strnatcasecmp(
this->length(), this->data(), sf.length(), sf.data())
== 0;
};
bool operator==(const char *str) const {
bool operator==(const char* str) const
{
size_t len = strlen(str);
return len == (size_t) this->length() &&
strncmp(this->data(), str, this->length()) == 0;
return len == (size_t) this->length()
&& strncmp(this->data(), str, this->length()) == 0;
};
bool operator!=(const char *str) const {
bool operator!=(const char* str) const
{
return !(*this == str);
}
bool startswith(const char *prefix) const {
bool startswith(const char* prefix) const
{
auto iter = this->begin();
while (*prefix != '\0' && *prefix == *iter && iter < this->end()) {
@ -136,15 +150,14 @@ struct string_fragment {
return *prefix == '\0';
}
string_fragment substr(int begin) const {
string_fragment substr(int begin) const
{
return string_fragment{
this->sf_string,
this->sf_begin + begin,
this->sf_end
};
this->sf_string, this->sf_begin + begin, this->sf_end};
}
nonstd::optional<size_t> find(char ch) const {
nonstd::optional<size_t> find(char ch) const
{
for (int lpc = this->sf_begin; lpc < this->sf_end; lpc++) {
if (this->sf_string[lpc] == ch) {
return lpc;
@ -155,7 +168,8 @@ struct string_fragment {
}
template<typename P>
nonstd::optional<string_fragment> consume(P predicate) const {
nonstd::optional<string_fragment> consume(P predicate) const
{
int consumed = 0;
while (consumed < this->length()) {
if (!predicate(this->data()[consumed])) {
@ -179,7 +193,8 @@ struct string_fragment {
nonstd::optional<string_fragment> consume_n(int amount) const;
template<typename P>
string_fragment skip(P predicate) const {
string_fragment skip(P predicate) const
{
int offset = 0;
while (offset < this->length() && predicate(this->data()[offset])) {
offset += 1;
@ -192,10 +207,12 @@ struct string_fragment {
};
}
using split_result = nonstd::optional<std::pair<string_fragment, string_fragment>>;
using split_result
= nonstd::optional<std::pair<string_fragment, string_fragment>>;
template<typename P>
split_result split_while(P& predicate) const {
split_result split_while(P& predicate) const
{
int consumed = 0;
while (consumed < this->length()) {
if (!predicate(this->data()[consumed])) {
@ -219,14 +236,14 @@ struct string_fragment {
this->sf_string,
this->sf_begin + consumed,
this->sf_end,
}
);
});
}
struct tag1 {
const char t_value;
bool operator()(char ch) const {
bool operator()(char ch) const
{
return this->t_value == ch;
}
};
@ -234,7 +251,8 @@ struct string_fragment {
struct quoted_string_body {
bool qs_in_escape{false};
bool operator()(char ch) {
bool operator()(char ch)
{
if (this->qs_in_escape) {
this->qs_in_escape = false;
return true;
@ -249,23 +267,27 @@ struct string_fragment {
}
};
const char *to_string(char *buf) const {
const char* to_string(char* buf) const
{
memcpy(buf, this->data(), this->length());
buf[this->length()] = '\0';
return buf;
};
std::string to_string() const {
std::string to_string() const
{
return {this->data(), (size_t) this->length()};
}
void clear() {
void clear()
{
this->sf_begin = 0;
this->sf_end = 0;
};
void invalidate() {
void invalidate()
{
this->sf_begin = -1;
this->sf_end = -1;
};
@ -277,17 +299,20 @@ struct string_fragment {
int sf_end;
};
inline bool operator<(const char *left, const string_fragment &right) {
inline bool
operator<(const char* left, const string_fragment& right)
{
int rc = strncmp(left, right.data(), right.length());
return rc < 0;
}
inline bool operator<(const string_fragment &left, const char *right) {
inline bool
operator<(const string_fragment& left, const char* right)
{
return strncmp(left.data(), right, left.length()) < 0;
}
class intern_string {
public:
static const intern_string* lookup(const char* str, ssize_t len) noexcept;
@ -295,19 +320,23 @@ public:
static const intern_string* lookup(const std::string& str) noexcept;
const char *get() const {
const char* get() const
{
return this->is_str.c_str();
};
size_t size() const {
size_t size() const
{
return this->is_str.size();
}
std::string to_string() const {
std::string to_string() const
{
return this->is_str;
}
string_fragment to_string_fragment() const {
string_fragment to_string_fragment() const
{
return string_fragment{this->is_str};
}
@ -315,11 +344,13 @@ public:
struct intern_table;
static std::shared_ptr<intern_table> get_table_lifetime();
private:
friend intern_table;
intern_string(const char* str, ssize_t len)
: is_next(nullptr), is_str(str, (size_t) len) {
: is_next(nullptr), is_str(str, (size_t) len)
{
}
intern_string* is_next;
@ -332,81 +363,96 @@ class intern_string_t {
public:
using iterator = const char*;
intern_string_t(const intern_string *is = nullptr) : ist_interned_string(is) {
intern_string_t(const intern_string* is = nullptr) : ist_interned_string(is)
{
}
const intern_string *unwrap() const {
const intern_string* unwrap() const
{
return this->ist_interned_string;
}
void clear() {
void clear()
{
this->ist_interned_string = nullptr;
};
bool empty() const {
bool empty() const
{
return this->ist_interned_string == nullptr;
}
const char *get() const {
const char* get() const
{
if (this->empty()) {
return "";
}
return this->ist_interned_string->get();
}
iterator begin() const {
iterator begin() const
{
return this->get();
}
iterator end() const {
iterator end() const
{
return this->get() + this->size();
}
size_t size() const {
size_t size() const
{
if (this->ist_interned_string == nullptr) {
return 0;
}
return this->ist_interned_string->size();
}
size_t hash() const {
size_t hash() const
{
auto ptr = (uintptr_t) this->ist_interned_string;
return ptr;
}
std::string to_string() const {
std::string to_string() const
{
if (this->ist_interned_string == nullptr) {
return "";
}
return this->ist_interned_string->to_string();
}
string_fragment to_string_fragment() const {
string_fragment to_string_fragment() const
{
if (this->ist_interned_string == nullptr) {
return string_fragment{"", 0, 0};
}
return this->ist_interned_string->to_string_fragment();
}
bool operator<(const intern_string_t &rhs) const {
bool operator<(const intern_string_t& rhs) const
{
return strcmp(this->get(), rhs.get()) < 0;
}
bool operator==(const intern_string_t &rhs) const {
bool operator==(const intern_string_t& rhs) const
{
return this->ist_interned_string == rhs.ist_interned_string;
}
bool operator!=(const intern_string_t &rhs) const {
bool operator!=(const intern_string_t& rhs) const
{
return !(*this == rhs);
}
bool operator==(const char *rhs) const {
bool operator==(const char* rhs) const
{
return strcmp(this->get(), rhs) == 0;
}
bool operator!=(const char *rhs) const {
bool operator!=(const char* rhs) const
{
return strcmp(this->get(), rhs) != 0;
}
@ -436,55 +482,74 @@ struct formatter<intern_string_t> : formatter<string_view> {
string_view{is.get(), (size_t) is.size()}, ctx);
}
};
}
} // namespace fmt
namespace std {
template<>
struct hash<const intern_string_t> {
std::size_t operator()(const intern_string_t &ist) const {
std::size_t operator()(const intern_string_t& ist) const
{
return ist.hash();
}
};
}
} // namespace std
inline bool operator<(const char *left, const intern_string_t &right) {
inline bool
operator<(const char* left, const intern_string_t& right)
{
int rc = strncmp(left, right.get(), right.size());
return rc < 0;
}
inline bool operator<(const intern_string_t &left, const char *right) {
inline bool
operator<(const intern_string_t& left, const char* right)
{
return strncmp(left.get(), right, left.size()) < 0;
}
inline bool operator==(const intern_string_t &left, const string_fragment &sf) {
return ((int) left.size() == sf.length()) &&
(memcmp(left.get(), sf.data(), left.size()) == 0);
inline bool
operator==(const intern_string_t& left, const string_fragment& sf)
{
return ((int) left.size() == sf.length())
&& (memcmp(left.get(), sf.data(), left.size()) == 0);
}
inline bool operator==(const string_fragment &left, const intern_string_t &right) {
return (left.length() == (int) right.size()) &&
(memcmp(left.data(), right.get(), left.length()) == 0);
inline bool
operator==(const string_fragment& left, const intern_string_t& right)
{
return (left.length() == (int) right.size())
&& (memcmp(left.data(), right.get(), left.length()) == 0);
}
namespace std {
inline string to_string(const string_fragment &s) {
inline string
to_string(const string_fragment& s)
{
return {s.data(), (size_t) s.length()};
}
inline string to_string(const intern_string_t &s) {
inline string
to_string(const intern_string_t& s)
{
return s.to_string();
}
}
} // namespace std
inline string_fragment to_string_fragment(const string_fragment &s) {
inline string_fragment
to_string_fragment(const string_fragment& s)
{
return s;
}
inline string_fragment to_string_fragment(const intern_string_t &s) {
inline string_fragment
to_string_fragment(const intern_string_t& s)
{
return string_fragment(s.get(), 0, s.size());
}
inline string_fragment to_string_fragment(const std::string &s) {
inline string_fragment
to_string_fragment(const std::string& s)
{
return string_fragment(s.c_str(), 0, s.length());
}

View File

@ -21,21 +21,20 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <cctype>
#include <iostream>
#include "doctest/doctest.h"
#include "intern_string.hh"
#include "config.h"
#include "doctest/doctest.h"
TEST_CASE("consume")
{
auto is_eq = string_fragment::tag1{'='};

View File

@ -25,10 +25,10 @@
* SUCH DAMAGE.
*/
#include "config.h"
#include "is_utf8.hh"
#include "config.h"
/*
Check if the given unsigned char * is a valid utf-8 sequence.
@ -56,240 +56,236 @@
-----------------------------------------------------------------------------
Returns the first erroneous byte position, and give in
`faulty_bytes` the number of actually existing bytes taking part in this error.
`faulty_bytes` the number of actually existing bytes taking part in this
error.
*/
ssize_t is_utf8(unsigned char *str, size_t len, const char **message, int *faulty_bytes)
ssize_t
is_utf8(unsigned char* str, size_t len, const char** message, int* faulty_bytes)
{
size_t i = 0;
*message = nullptr;
*faulty_bytes = 0;
while (i < len)
{
while (i < len) {
if (str[i] == '\n') {
*message = nullptr;
return i;
}
if (str[i] <= 0x7F) /* 00..7F */
{
if (str[i] <= 0x7F) /* 00..7F */ {
i += 1;
}
else if (str[i] >= 0xC2 && str[i] <= 0xDF) /* C2..DF 80..BF */
{
if (i + 1 < len) /* Expect a 2nd byte */
{
if (str[i + 1] < 0x80 || str[i + 1] > 0xBF)
{
*message = "After a first byte between C2 and DF, expecting a 2nd byte between 80 and BF";
} else if (str[i] >= 0xC2 && str[i] <= 0xDF) /* C2..DF 80..BF */ {
if (i + 1 < len) /* Expect a 2nd byte */ {
if (str[i + 1] < 0x80 || str[i + 1] > 0xBF) {
*message
= "After a first byte between C2 and DF, expecting a "
"2nd byte between 80 and BF";
*faulty_bytes = 2;
return i;
}
}
else
{
*message = "After a first byte between C2 and DF, expecting a 2nd byte.";
} else {
*message
= "After a first byte between C2 and DF, expecting a 2nd "
"byte.";
*faulty_bytes = 1;
return i;
}
i += 2;
}
else if (str[i] == 0xE0) /* E0 A0..BF 80..BF */
{
if (i + 2 < len) /* Expect a 2nd and 3rd byte */
{
if (str[i + 1] < 0xA0 || str[i + 1] > 0xBF)
{
*message = "After a first byte of E0, expecting a 2nd byte between A0 and BF.";
} else if (str[i] == 0xE0) /* E0 A0..BF 80..BF */ {
if (i + 2 < len) /* Expect a 2nd and 3rd byte */ {
if (str[i + 1] < 0xA0 || str[i + 1] > 0xBF) {
*message
= "After a first byte of E0, expecting a 2nd byte "
"between A0 and BF.";
*faulty_bytes = 2;
return i;
}
if (str[i + 2] < 0x80 || str[i + 2] > 0xBF)
{
*message = "After a first byte of E0, expecting a 3nd byte between 80 and BF.";
if (str[i + 2] < 0x80 || str[i + 2] > 0xBF) {
*message
= "After a first byte of E0, expecting a 3nd byte "
"between 80 and BF.";
*faulty_bytes = 3;
return i;
}
}
else
{
*message = "After a first byte of E0, expecting two following bytes.";
} else {
*message
= "After a first byte of E0, expecting two following "
"bytes.";
*faulty_bytes = 1;
return i;
}
i += 3;
}
else if (str[i] >= 0xE1 && str[i] <= 0xEC) /* E1..EC 80..BF 80..BF */
} else if (str[i] >= 0xE1 && str[i] <= 0xEC) /* E1..EC 80..BF 80..BF */
{
if (i + 2 < len) /* Expect a 2nd and 3rd byte */
{
if (str[i + 1] < 0x80 || str[i + 1] > 0xBF)
{
*message = "After a first byte between E1 and EC, expecting the 2nd byte between 80 and BF.";
if (i + 2 < len) /* Expect a 2nd and 3rd byte */ {
if (str[i + 1] < 0x80 || str[i + 1] > 0xBF) {
*message
= "After a first byte between E1 and EC, expecting the "
"2nd byte between 80 and BF.";
*faulty_bytes = 2;
return i;
}
if (str[i + 2] < 0x80 || str[i + 2] > 0xBF)
{
*message = "After a first byte between E1 and EC, expecting the 3rd byte between 80 and BF.";
if (str[i + 2] < 0x80 || str[i + 2] > 0xBF) {
*message
= "After a first byte between E1 and EC, expecting the "
"3rd byte between 80 and BF.";
*faulty_bytes = 3;
return i;
}
}
else
{
*message = "After a first byte between E1 and EC, expecting two following bytes.";
} else {
*message
= "After a first byte between E1 and EC, expecting two "
"following bytes.";
*faulty_bytes = 1;
return i;
}
i += 3;
}
else if (str[i] == 0xED) /* ED 80..9F 80..BF */
{
if (i + 2 < len) /* Expect a 2nd and 3rd byte */
{
if (str[i + 1] < 0x80 || str[i + 1] > 0x9F)
{
*message = "After a first byte of ED, expecting 2nd byte between 80 and 9F.";
} else if (str[i] == 0xED) /* ED 80..9F 80..BF */ {
if (i + 2 < len) /* Expect a 2nd and 3rd byte */ {
if (str[i + 1] < 0x80 || str[i + 1] > 0x9F) {
*message
= "After a first byte of ED, expecting 2nd byte "
"between 80 and 9F.";
*faulty_bytes = 2;
return i;
}
if (str[i + 2] < 0x80 || str[i + 2] > 0xBF)
{
*message = "After a first byte of ED, expecting 3rd byte between 80 and BF.";
if (str[i + 2] < 0x80 || str[i + 2] > 0xBF) {
*message
= "After a first byte of ED, expecting 3rd byte "
"between 80 and BF.";
*faulty_bytes = 3;
return i;
}
}
else
{
*message = "After a first byte of ED, expecting two following bytes.";
} else {
*message
= "After a first byte of ED, expecting two following "
"bytes.";
*faulty_bytes = 1;
return i;
}
i += 3;
}
else if (str[i] >= 0xEE && str[i] <= 0xEF) /* EE..EF 80..BF 80..BF */
} else if (str[i] >= 0xEE && str[i] <= 0xEF) /* EE..EF 80..BF 80..BF */
{
if (i + 2 < len) /* Expect a 2nd and 3rd byte */
{
if (str[i + 1] < 0x80 || str[i + 1] > 0xBF)
{
*message = "After a first byte between EE and EF, expecting 2nd byte between 80 and BF.";
if (i + 2 < len) /* Expect a 2nd and 3rd byte */ {
if (str[i + 1] < 0x80 || str[i + 1] > 0xBF) {
*message
= "After a first byte between EE and EF, expecting 2nd "
"byte between 80 and BF.";
*faulty_bytes = 2;
return i;
}
if (str[i + 2] < 0x80 || str[i + 2] > 0xBF)
{
*message = "After a first byte between EE and EF, expecting 3rd byte between 80 and BF.";
if (str[i + 2] < 0x80 || str[i + 2] > 0xBF) {
*message
= "After a first byte between EE and EF, expecting 3rd "
"byte between 80 and BF.";
*faulty_bytes = 3;
return i;
}
}
else
{
*message = "After a first byte between EE and EF, two following bytes.";
} else {
*message
= "After a first byte between EE and EF, two following "
"bytes.";
*faulty_bytes = 1;
return i;
}
i += 3;
}
else if (str[i] == 0xF0) /* F0 90..BF 80..BF 80..BF */
{
if (i + 3 < len) /* Expect a 2nd, 3rd 3th byte */
{
if (str[i + 1] < 0x90 || str[i + 1] > 0xBF)
{
*message = "After a first byte of F0, expecting 2nd byte between 90 and BF.";
} else if (str[i] == 0xF0) /* F0 90..BF 80..BF 80..BF */ {
if (i + 3 < len) /* Expect a 2nd, 3rd 3th byte */ {
if (str[i + 1] < 0x90 || str[i + 1] > 0xBF) {
*message
= "After a first byte of F0, expecting 2nd byte "
"between 90 and BF.";
*faulty_bytes = 2;
return i;
}
if (str[i + 2] < 0x80 || str[i + 2] > 0xBF)
{
*message = "After a first byte of F0, expecting 3rd byte between 80 and BF.";
if (str[i + 2] < 0x80 || str[i + 2] > 0xBF) {
*message
= "After a first byte of F0, expecting 3rd byte "
"between 80 and BF.";
*faulty_bytes = 3;
return i;
}
if (str[i + 3] < 0x80 || str[i + 3] > 0xBF)
{
*message = "After a first byte of F0, expecting 4th byte between 80 and BF.";
if (str[i + 3] < 0x80 || str[i + 3] > 0xBF) {
*message
= "After a first byte of F0, expecting 4th byte "
"between 80 and BF.";
*faulty_bytes = 4;
return i;
}
}
else
{
*message = "After a first byte of F0, expecting three following bytes.";
} else {
*message
= "After a first byte of F0, expecting three following "
"bytes.";
*faulty_bytes = 1;
return i;
}
i += 4;
}
else if (str[i] >= 0xF1 && str[i] <= 0xF3) /* F1..F3 80..BF 80..BF 80..BF */
{
if (i + 3 < len) /* Expect a 2nd, 3rd 3th byte */
{
if (str[i + 1] < 0x80 || str[i + 1] > 0xBF)
{
*message = "After a first byte of F1, F2, or F3, expecting a 2nd byte between 80 and BF.";
} else if (str[i] >= 0xF1
&& str[i] <= 0xF3) /* F1..F3 80..BF 80..BF 80..BF */ {
if (i + 3 < len) /* Expect a 2nd, 3rd 3th byte */ {
if (str[i + 1] < 0x80 || str[i + 1] > 0xBF) {
*message
= "After a first byte of F1, F2, or F3, expecting a "
"2nd byte between 80 and BF.";
*faulty_bytes = 2;
return i;
}
if (str[i + 2] < 0x80 || str[i + 2] > 0xBF)
{
*message = "After a first byte of F1, F2, or F3, expecting a 3rd byte between 80 and BF.";
if (str[i + 2] < 0x80 || str[i + 2] > 0xBF) {
*message
= "After a first byte of F1, F2, or F3, expecting a "
"3rd byte between 80 and BF.";
*faulty_bytes = 3;
return i;
}
if (str[i + 3] < 0x80 || str[i + 3] > 0xBF)
{
*message = "After a first byte of F1, F2, or F3, expecting a 4th byte between 80 and BF.";
if (str[i + 3] < 0x80 || str[i + 3] > 0xBF) {
*message
= "After a first byte of F1, F2, or F3, expecting a "
"4th byte between 80 and BF.";
*faulty_bytes = 4;
return i;
}
}
else
{
*message = "After a first byte of F1, F2, or F3, expecting three following bytes.";
} else {
*message
= "After a first byte of F1, F2, or F3, expecting three "
"following bytes.";
*faulty_bytes = 1;
return i;
}
i += 4;
}
else if (str[i] == 0xF4) /* F4 80..8F 80..BF 80..BF */
{
if (i + 3 < len) /* Expect a 2nd, 3rd 3th byte */
{
if (str[i + 1] < 0x80 || str[i + 1] > 0x8F)
{
*message = "After a first byte of F4, expecting 2nd byte between 80 and 8F.";
} else if (str[i] == 0xF4) /* F4 80..8F 80..BF 80..BF */ {
if (i + 3 < len) /* Expect a 2nd, 3rd 3th byte */ {
if (str[i + 1] < 0x80 || str[i + 1] > 0x8F) {
*message
= "After a first byte of F4, expecting 2nd byte "
"between 80 and 8F.";
*faulty_bytes = 2;
return i;
}
if (str[i + 2] < 0x80 || str[i + 2] > 0xBF)
{
*message = "After a first byte of F4, expecting 3rd byte between 80 and BF.";
if (str[i + 2] < 0x80 || str[i + 2] > 0xBF) {
*message
= "After a first byte of F4, expecting 3rd byte "
"between 80 and BF.";
*faulty_bytes = 3;
return i;
}
if (str[i + 3] < 0x80 || str[i + 3] > 0xBF)
{
*message = "After a first byte of F4, expecting 4th byte between 80 and BF.";
if (str[i + 3] < 0x80 || str[i + 3] > 0xBF) {
*message
= "After a first byte of F4, expecting 4th byte "
"between 80 and BF.";
*faulty_bytes = 4;
return i;
}
}
else
{
*message = "After a first byte of F4, expecting three following bytes.";
} else {
*message
= "After a first byte of F4, expecting three following "
"bytes.";
*faulty_bytes = 1;
return i;
}
i += 4;
}
else
{
*message = "Expecting bytes in the following ranges: 00..7F C2..F4.";
} else {
*message
= "Expecting bytes in the following ranges: 00..7F C2..F4.";
*faulty_bytes = 1;
return i;
}

View File

@ -28,9 +28,12 @@
#ifndef _IS_UTF8_H
#define _IS_UTF8_H
#include <sys/types.h>
#include <stdlib.h>
#include <sys/types.h>
ssize_t is_utf8(unsigned char *str, size_t len, const char **message, int *faulty_bytes);
ssize_t is_utf8(unsigned char* str,
size_t len,
const char** message,
int* faulty_bytes);
#endif /* _IS_UTF8_H */

View File

@ -21,30 +21,32 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @file isc.cc
*/
#include "config.h"
#include <algorithm>
#include "isc.hh"
#include "config.h"
namespace isc {
void service_base::start()
void
service_base::start()
{
log_debug("starting service thread for: %s", this->s_name.c_str());
this->s_thread = std::thread(&service_base::run, this);
this->s_started = true;
}
void *service_base::run()
void*
service_base::run()
{
log_info("BEGIN isc thread: %s", this->s_name.c_str());
while (this->s_looping) {
@ -66,7 +68,8 @@ void *service_base::run()
return nullptr;
}
void service_base::stop()
void
service_base::stop()
{
if (this->s_started) {
log_debug("stopping service thread: %s", this->s_name.c_str());
@ -82,7 +85,8 @@ void service_base::stop()
}
supervisor::supervisor(service_list servs, service_base* parent)
: s_service_list(std::move(servs)), s_parent(parent) {
: s_service_list(std::move(servs)), s_parent(parent)
{
for (auto& serv : this->s_service_list) {
serv->start();
}
@ -93,7 +97,8 @@ supervisor::~supervisor()
this->stop_children();
}
void supervisor::stop_children()
void
supervisor::stop_children()
{
for (auto& serv : this->s_service_list) {
serv->stop();
@ -101,11 +106,12 @@ void supervisor::stop_children()
this->cleanup_children();
}
void supervisor::cleanup_children()
void
supervisor::cleanup_children()
{
this->s_service_list.erase(
std::remove_if(
this->s_service_list.begin(), this->s_service_list.end(),
std::remove_if(this->s_service_list.begin(),
this->s_service_list.end(),
[this](auto& child) {
if (child->is_looping()) {
return false;
@ -120,10 +126,11 @@ void supervisor::cleanup_children()
this->s_service_list.end());
}
void supervisor::add_child_service(std::shared_ptr<service_base> new_service)
void
supervisor::add_child_service(std::shared_ptr<service_base> new_service)
{
this->s_service_list.emplace_back(new_service);
new_service->start();
}
}
} // namespace isc

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
@ -30,16 +30,16 @@
*/
#include <atomic>
#include <deque>
#include <chrono>
#include <condition_variable>
#include <deque>
#include <mutex>
#include <thread>
#include <condition_variable>
#include <utility>
#include "injector.hh"
#include "time_util.hh"
#include "safe/safe.h"
#include "time_util.hh"
#ifndef lnav_isc_hh
# define lnav_isc_hh
@ -50,7 +50,9 @@ struct msg {
std::function<void()> m_callback;
};
inline msg empty_msg() {
inline msg
empty_msg()
{
return {[]() {}};
}
@ -58,20 +60,23 @@ class msg_port {
public:
msg_port() = default;
void send(msg&& m) {
safe::WriteAccess<safe_message_list, std::unique_lock> writable_msgs(this->mp_messages);
void send(msg&& m)
{
safe::WriteAccess<safe_message_list, std::unique_lock> writable_msgs(
this->mp_messages);
writable_msgs->emplace_back(m);
this->sp_cond.notify_all();
}
template<class Rep, class Period>
void process_for(const std::chrono::duration<Rep, Period>& rel_time) {
void process_for(const std::chrono::duration<Rep, Period>& rel_time)
{
std::deque<msg> tmp_msgs;
{
safe::WriteAccess<safe_message_list, std::unique_lock> writable_msgs(
this->mp_messages);
safe::WriteAccess<safe_message_list, std::unique_lock>
writable_msgs(this->mp_messages);
if (writable_msgs->empty()) {
this->sp_cond.template wait_for(writable_msgs.lock, rel_time);
@ -86,6 +91,7 @@ public:
tmp_msgs.pop_front();
}
}
private:
using message_list = std::deque<msg>;
using safe_message_list = safe::Safe<message_list>;
@ -103,7 +109,8 @@ struct supervisor {
~supervisor();
bool empty() const {
bool empty() const
{
return this->s_service_list.empty();
}
@ -112,6 +119,7 @@ struct supervisor {
void stop_children();
void cleanup_children();
protected:
service_list s_service_list;
service_base* s_parent;
@ -120,20 +128,24 @@ protected:
class service_base : public std::enable_shared_from_this<service_base> {
public:
explicit service_base(std::string name)
: s_name(std::move(name)), s_children({}, this) {
: s_name(std::move(name)), s_children({}, this)
{
}
virtual ~service_base() = default;
bool is_looping() const {
bool is_looping() const
{
return this->s_looping;
}
msg_port& get_port() {
msg_port& get_port()
{
return this->s_port;
}
friend supervisor;
private:
void start();
@ -144,7 +156,9 @@ protected:
virtual void loop_body(){};
virtual void child_finished(std::shared_ptr<service_base> child){};
virtual void stopped(){};
virtual std::chrono::milliseconds compute_timeout(mstime_t current_time) const {
virtual std::chrono::milliseconds compute_timeout(
mstime_t current_time) const
{
using namespace std::literals::chrono_literals;
return 1s;
@ -162,36 +176,37 @@ template<typename T>
class service : public service_base {
public:
explicit service(std::string sub_name = "")
: service_base(std::string(__PRETTY_FUNCTION__) + " " + sub_name) {
: service_base(std::string(__PRETTY_FUNCTION__) + " " + sub_name)
{
}
template<typename F>
void send(F msg) {
this->s_port.send({
[lifetime = this->shared_from_this(), this, msg]() {
void send(F msg)
{
this->s_port.send({[lifetime = this->shared_from_this(), this, msg]() {
msg(*(static_cast<T*>(this)));
}
});
}});
}
template<typename F, class Rep, class Period>
void send_and_wait(F msg,
const std::chrono::duration<Rep, Period>& rel_time) {
const std::chrono::duration<Rep, Period>& rel_time)
{
msg_port reply_port;
this->s_port.send({
[lifetime = this->shared_from_this(), this, &reply_port, msg]() {
this->s_port.send(
{[lifetime = this->shared_from_this(), this, &reply_port, msg]() {
msg(*(static_cast<T*>(this)));
reply_port.send(empty_msg());
}
});
}});
reply_port.template process_for(rel_time);
}
};
template<typename T, typename Service, typename... Annotations>
struct to {
void send(std::function<void(T&)> cb) {
void send(std::function<void(T&)> cb)
{
auto& service = injector::get<T&, Service>();
service.send(cb);
@ -199,19 +214,21 @@ struct to {
template<class Rep, class Period>
void send_and_wait(std::function<void(T)> cb,
const std::chrono::duration<Rep, Period>& rel_time) {
const std::chrono::duration<Rep, Period>& rel_time)
{
auto& service = injector::get<T&, Service>();
service.send_and_wait(cb, rel_time);
}
void send_and_wait(std::function<void(T)> cb) {
void send_and_wait(std::function<void(T)> cb)
{
using namespace std::literals::chrono_literals;
this->send_and_wait(cb, 48h);
}
};
}
} // namespace isc
#endif

View File

@ -21,30 +21,32 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @file lnav.gzip.cc
*/
#include "config.h"
#include "lnav.gzip.hh"
#include <zlib.h>
#include "config.h"
#include "fmt/format.h"
#include "lnav.gzip.hh"
namespace lnav {
namespace gzip {
bool is_gzipped(const char *buffer, size_t len)
bool
is_gzipped(const char* buffer, size_t len)
{
return len > 2 && buffer[0] == '\037' && buffer[1] == '\213';
}
Result<auto_buffer, std::string> compress(const void* input, size_t len)
Result<auto_buffer, std::string>
compress(const void* input, size_t len)
{
auto retval = auto_buffer::alloc(len + 4096);
@ -57,9 +59,11 @@ Result<auto_buffer, std::string> compress(const void* input, size_t len)
zs.avail_out = (uInt) retval.size();
zs.next_out = (Bytef*) retval.in();
auto rc = deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 | 16, 8, Z_DEFAULT_STRATEGY);
auto rc = deflateInit2(
&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 | 16, 8, Z_DEFAULT_STRATEGY);
if (rc != Z_OK) {
return Err(fmt::format("unable to initialize compressor -- {}", zError(rc)));
return Err(
fmt::format("unable to initialize compressor -- {}", zError(rc)));
}
rc = deflate(&zs, Z_FINISH);
if (rc != Z_STREAM_END) {
@ -67,14 +71,14 @@ Result<auto_buffer, std::string> compress(const void* input, size_t len)
}
rc = deflateEnd(&zs);
if (rc != Z_OK) {
return Err(fmt::format("unable to finalize compression -- {}", zError(rc)));
return Err(
fmt::format("unable to finalize compression -- {}", zError(rc)));
}
return Ok(std::move(retval.shrink_to(zs.total_out)));
}
Result<auto_buffer, std::string> uncompress(const std::string& src,
const void *buffer,
size_t size)
Result<auto_buffer, std::string>
uncompress(const std::string& src, const void* buffer, size_t size)
{
auto uncomp = auto_buffer::alloc(size * 2);
z_stream strm;
@ -88,7 +92,8 @@ Result<auto_buffer, std::string> uncompress(const std::string& src,
if ((err = inflateInit2(&strm, (16 + MAX_WBITS))) != Z_OK) {
return Err(fmt::format("invalid gzip data: {} -- {}",
src, strm.msg ? strm.msg : zError(err)));
src,
strm.msg ? strm.msg : zError(err)));
}
bool done = false;
@ -108,17 +113,19 @@ Result<auto_buffer, std::string> uncompress(const std::string& src,
} else if (err != Z_OK) {
inflateEnd(&strm);
return Err(fmt::format("unable to uncompress: {} -- {}",
src, strm.msg ? strm.msg : zError(err)));
src,
strm.msg ? strm.msg : zError(err)));
}
}
if (inflateEnd(&strm) != Z_OK) {
return Err(fmt::format("unable to uncompress: {} -- {}",
src, strm.msg ? strm.msg : zError(err)));
src,
strm.msg ? strm.msg : zError(err)));
}
return Ok(std::move(uncomp.shrink_to(strm.total_out)));
}
}
}
} // namespace gzip
} // namespace lnav

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
@ -48,7 +48,7 @@ Result<auto_buffer, std::string> uncompress(const std::string& src,
const void* buffer,
size_t size);
}
}
} // namespace gzip
} // namespace lnav
#endif

View File

@ -21,35 +21,35 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <zlib.h>
#include <iostream>
#include "doctest/doctest.h"
#include <zlib.h>
#include "base/lnav.gzip.hh"
#include "config.h"
#include "doctest/doctest.h"
TEST_CASE("lnav::gzip::uncompress") {
TEST_CASE("lnav::gzip::uncompress")
{
{
auto u_res = lnav::gzip::uncompress("empty", nullptr, 0);
CHECK(u_res.isErr());
CHECK(u_res.unwrapErr() ==
"unable to uncompress: empty -- buffer error");
CHECK(u_res.unwrapErr()
== "unable to uncompress: empty -- buffer error");
}
{
auto u_res = lnav::gzip::uncompress("garbage", "abc", 3);
CHECK(u_res.isErr());
CHECK(u_res.unwrapErr() ==
"unable to uncompress: garbage -- incorrect header check");
CHECK(u_res.unwrapErr()
== "unable to uncompress: garbage -- incorrect header check");
}
}

View File

@ -21,28 +21,28 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @file lnav_log.cc
*/
#include "config.h"
#include <time.h>
#include <assert.h>
#include <ctype.h>
#include <fcntl.h>
#include <stdio.h>
#include <assert.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <termios.h>
#include <sys/resource.h>
#include <termios.h>
#include <time.h>
#include <unistd.h>
#include "config.h"
#ifdef HAVE_EXECINFO_H
# include <execinfo.h>
@ -51,16 +51,16 @@
# include "backward-cpp/backward.hpp"
#endif
#include <sys/types.h>
#include <sys/time.h>
#include <sys/utsname.h>
#include <sys/wait.h>
#include <sys/param.h>
#include <algorithm>
#include <mutex>
#include <thread>
#include <vector>
#include <algorithm>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <sys/wait.h>
#ifdef HAVE_PCRE_H
# include <pcre.h>
@ -71,39 +71,41 @@
#endif
#if defined HAVE_NCURSESW_CURSES_H
# include <ncursesw/termcap.h>
# include <ncursesw/curses.h>
# include <ncursesw/termcap.h>
#elif defined HAVE_NCURSESW_H
# include <termcap.h>
# include <ncursesw.h>
# include <termcap.h>
#elif defined HAVE_NCURSES_CURSES_H
# include <ncurses/termcap.h>
# include <ncurses/curses.h>
# include <ncurses/termcap.h>
#elif defined HAVE_NCURSES_H
# include <termcap.h>
# include <ncurses.h>
#elif defined HAVE_CURSES_H
# include <termcap.h>
#elif defined HAVE_CURSES_H
# include <curses.h>
# include <termcap.h>
#else
# error "SysV or X/Open-compatible Curses header file required"
#endif
#include "opt_util.hh"
#include "lnav_log.hh"
#include "enum_util.hh"
#include "auto_mem.hh"
#include "enum_util.hh"
#include "lnav_log.hh"
#include "opt_util.hh"
static const size_t BUFFER_SIZE = 256 * 1024;
static const size_t MAX_LOG_LINE_SIZE = 2048;
static const char *CRASH_MSG =
"\n"
static const char* CRASH_MSG
= "\n"
"\n"
"==== GURU MEDITATION ====\n"
"Unfortunately, lnav has crashed, sorry for the inconvenience.\n"
"\n"
"You can help improve lnav by sending the following file to " PACKAGE_BUGREPORT " :\n"
"You can help improve lnav by sending the following file "
"to " PACKAGE_BUGREPORT
" :\n"
" %s\n"
"=========================\n";
@ -115,7 +117,8 @@ nonstd::optional<const struct termios *> lnav_log_orig_termios;
// Otherwise, any attempts to log will fail.
static std::mutex* lnav_log_mutex = new std::mutex();
static std::vector<log_state_dumper*>& DUMPER_LIST()
static std::vector<log_state_dumper*>&
DUMPER_LIST()
{
static std::vector<log_state_dumper*> retval;
@ -141,12 +144,7 @@ static struct {
off_t lr_frag_start;
off_t lr_frag_end;
char lr_data[BUFFER_SIZE];
} log_ring = {
0,
BUFFER_SIZE,
0,
{}
};
} log_ring = {0, BUFFER_SIZE, 0, {}};
static const char* LEVEL_NAMES[] = {
"T",
@ -156,7 +154,8 @@ static const char *LEVEL_NAMES[] = {
"E",
};
static char *log_alloc()
static char*
log_alloc()
{
off_t data_end = log_ring.lr_length + MAX_LOG_LINE_SIZE;
@ -185,7 +184,8 @@ static char *log_alloc()
return &log_ring.lr_data[log_ring.lr_length];
}
void log_argv(int argc, char *argv[])
void
log_argv(int argc, char* argv[])
{
const char* log_path = getenv("LNAV_LOG_PATH");
@ -199,12 +199,14 @@ void log_argv(int argc, char *argv[])
}
}
void log_set_thread_prefix(std::string prefix)
void
log_set_thread_prefix(std::string prefix)
{
// thread_log_prefix = std::move(prefix);
}
void log_host_info()
void
log_host_info()
{
char cwd[MAXPATHLEN];
const char* jittarget;
@ -242,8 +244,7 @@ void log_host_info()
log_info(" egid=%d", getegid());
if (getcwd(cwd, sizeof(cwd)) == nullptr) {
log_info(" ERROR: getcwd failed");
}
else {
} else {
log_info(" cwd=%s", cwd);
}
log_info("Executable:");
@ -253,13 +254,25 @@ void log_host_info()
log_rusage(lnav_log_level_t::INFO, ru);
}
void log_rusage_raw(enum lnav_log_level_t level, const char *src_file, int line_number, const struct rusage &ru)
void
log_rusage_raw(enum lnav_log_level_t level,
const char* src_file,
int line_number,
const struct rusage& ru)
{
log_msg(level, src_file, line_number, "rusage:");
log_msg(level, src_file, line_number, " utime=%d.%06d",
ru.ru_utime.tv_sec, ru.ru_utime.tv_usec);
log_msg(level, src_file, line_number, " stime=%d.%06d",
ru.ru_stime.tv_sec, ru.ru_stime.tv_usec);
log_msg(level,
src_file,
line_number,
" utime=%d.%06d",
ru.ru_utime.tv_sec,
ru.ru_utime.tv_usec);
log_msg(level,
src_file,
line_number,
" stime=%d.%06d",
ru.ru_stime.tv_sec,
ru.ru_stime.tv_usec);
log_msg(level, src_file, line_number, " maxrss=%ld", ru.ru_maxrss);
log_msg(level, src_file, line_number, " ixrss=%ld", ru.ru_ixrss);
log_msg(level, src_file, line_number, " idrss=%ld", ru.ru_idrss);
@ -276,8 +289,12 @@ void log_rusage_raw(enum lnav_log_level_t level, const char *src_file, int line_
log_msg(level, src_file, line_number, " nivcsw=%ld", ru.ru_nivcsw);
}
void log_msg(lnav_log_level_t level, const char *src_file, int line_number,
const char *fmt, ...)
void
log_msg(lnav_log_level_t level,
const char* src_file,
int line_number,
const char* fmt,
...)
{
struct timeval curr_time;
struct tm localtm;
@ -309,8 +326,8 @@ void log_msg(lnav_log_level_t level, const char *src_file, int line_number,
gettimeofday(&curr_time, nullptr);
localtime_r(&curr_time.tv_sec, &localtm);
auto line = log_alloc();
prefix_size = snprintf(
line, MAX_LOG_LINE_SIZE,
prefix_size = snprintf(line,
MAX_LOG_LINE_SIZE,
"%4d-%02d-%02dT%02d:%02d:%02d.%03d %s t%u %s:%d ",
localtm.tm_year + 1900,
localtm.tm_mon + 1,
@ -331,8 +348,8 @@ void log_msg(lnav_log_level_t level, const char *src_file, int line_number,
thread_log_prefix.c_str());
}
#endif
rc = vsnprintf(&line[prefix_size], MAX_LOG_LINE_SIZE - prefix_size,
fmt, args);
rc = vsnprintf(
&line[prefix_size], MAX_LOG_LINE_SIZE - prefix_size, fmt, args);
if (rc >= (ssize_t) (MAX_LOG_LINE_SIZE - prefix_size)) {
rc = MAX_LOG_LINE_SIZE - prefix_size - 1;
}
@ -345,7 +362,8 @@ void log_msg(lnav_log_level_t level, const char *src_file, int line_number,
va_end(args);
}
void log_msg_extra(const char *fmt, ...)
void
log_msg_extra(const char* fmt, ...)
{
std::lock_guard<std::mutex> mg(*lnav_log_mutex);
va_list args;
@ -361,7 +379,8 @@ void log_msg_extra(const char *fmt, ...)
va_end(args);
}
void log_msg_extra_complete()
void
log_msg_extra_complete()
{
std::lock_guard<std::mutex> mg(*lnav_log_mutex);
auto line = log_alloc();
@ -375,7 +394,8 @@ void log_msg_extra_complete()
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-result"
static void sigabrt(int sig, siginfo_t *info, void *ctx)
static void
sigabrt(int sig, siginfo_t* info, void* ctx)
{
char crash_path[1024], latest_crash_path[1024];
int fd;
@ -398,7 +418,8 @@ static void sigabrt(int sig, siginfo_t *info, void *ctx)
#endif
curr_time = time(nullptr);
localtime_r(&curr_time, &localtm);
snprintf(crash_path, sizeof(crash_path),
snprintf(crash_path,
sizeof(crash_path),
"%s/crash-%4d-%02d-%02d-%02d-%02d-%02d.%d.log",
lnav_log_crash_dir,
localtm.tm_year + 1900,
@ -408,11 +429,14 @@ static void sigabrt(int sig, siginfo_t *info, void *ctx)
localtm.tm_min,
localtm.tm_sec,
getpid());
snprintf(latest_crash_path, sizeof(latest_crash_path),
"%s/latest-crash.log", lnav_log_crash_dir);
snprintf(latest_crash_path,
sizeof(latest_crash_path),
"%s/latest-crash.log",
lnav_log_crash_dir);
if ((fd = open(crash_path, O_CREAT | O_TRUNC | O_RDWR, 0600)) != -1) {
if (log_ring.lr_frag_start < (off_t) BUFFER_SIZE) {
(void)write(fd, &log_ring.lr_data[log_ring.lr_frag_start],
(void) write(fd,
&log_ring.lr_data[log_ring.lr_frag_start],
log_ring.lr_frag_end - log_ring.lr_frag_start);
}
(void) write(fd, log_ring.lr_data, log_ring.lr_length);
@ -425,15 +449,19 @@ static void sigabrt(int sig, siginfo_t *info, void *ctx)
void* error_addr = nullptr;
# ifdef REG_RIP // x86_64
error_addr = reinterpret_cast<void *>(uctx->uc_mcontext.gregs[REG_RIP]);
error_addr
= reinterpret_cast<void*>(uctx->uc_mcontext.gregs[REG_RIP]);
# elif defined(REG_EIP) // x86_32
error_addr = reinterpret_cast<void *>(uctx->uc_mcontext.gregs[REG_EIP]);
error_addr
= reinterpret_cast<void*>(uctx->uc_mcontext.gregs[REG_EIP]);
# endif
backward::StackTrace st;
if (error_addr) {
st.load_from(error_addr, 32, reinterpret_cast<void *>(uctx),
st.load_from(error_addr,
32,
reinterpret_cast<void*>(uctx),
info->si_addr);
} else {
st.load_here(32, reinterpret_cast<void*>(uctx), info->si_addr);
@ -445,7 +473,8 @@ static void sigabrt(int sig, siginfo_t *info, void *ctx)
auto trace = tr.resolve(st[lpc]);
char buf[1024];
snprintf(buf, sizeof(buf),
snprintf(buf,
sizeof(buf),
"Frame %lu:%s:%s (%s:%d)\n",
lpc,
trace.object_filename.c_str(),
@ -467,7 +496,8 @@ static void sigabrt(int sig, siginfo_t *info, void *ctx)
}
if (log_ring.lr_frag_start < (off_t) BUFFER_SIZE) {
write(fd, &log_ring.lr_data[log_ring.lr_frag_start],
write(fd,
&log_ring.lr_data[log_ring.lr_frag_start],
log_ring.lr_frag_end - log_ring.lr_frag_start);
}
write(fd, log_ring.lr_data, log_ring.lr_length);
@ -530,7 +560,6 @@ static void sigabrt(int sig, siginfo_t *info, void *ctx)
int status;
while (wait(&status) < 0) {
}
break;
}
@ -543,7 +572,8 @@ static void sigabrt(int sig, siginfo_t *info, void *ctx)
}
#pragma GCC diagnostic pop
void log_install_handlers()
void
log_install_handlers()
{
const size_t stack_size = 8 * 1024 * 1024;
const int sigs[] = {
@ -575,13 +605,15 @@ void log_install_handlers()
}
}
void log_abort()
void
log_abort()
{
raise(SIGABRT);
_exit(1);
}
void log_pipe_err(int fd)
void
log_pipe_err(int fd)
{
std::thread reader([fd]() {
char buffer[1024];
@ -596,8 +628,7 @@ void log_pipe_err(int fd)
done = true;
break;
default:
while (buffer[rc - 1] == '\n' ||
buffer[rc - 1] == '\r') {
while (buffer[rc - 1] == '\n' || buffer[rc - 1] == '\r') {
rc -= 1;
}

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
@ -32,10 +32,11 @@
#ifndef lnav_log_hh
#define lnav_log_hh
#include <string>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <string>
#ifndef lnav_dead2
# define lnav_dead2 __attribute__((noreturn))
@ -55,9 +56,15 @@ enum class lnav_log_level_t : uint32_t {
void log_argv(int argc, char* argv[]);
void log_host_info();
void log_rusage_raw(enum lnav_log_level_t level, const char *src_file, int line_number, const struct rusage &ru);
void log_msg(enum lnav_log_level_t level, const char *src_file, int line_number,
const char *fmt, ...);
void log_rusage_raw(enum lnav_log_level_t level,
const char* src_file,
int line_number,
const struct rusage& ru);
void log_msg(enum lnav_log_level_t level,
const char* src_file,
int line_number,
const char* fmt,
...);
void log_msg_extra(const char* fmt, ...);
void log_msg_extra_complete();
void log_install_handlers();
@ -98,40 +105,43 @@ extern enum lnav_log_level_t lnav_log_level;
if (lnav_log_level <= level) { \
log_msg(level, __FILE__, __LINE__, fmt); \
} \
} \
while (false)
} while (false)
#define log_rusage(level, ru) \
log_rusage_raw(level, __FILE__, __LINE__, ru);
#define log_rusage(level, ru) log_rusage_raw(level, __FILE__, __LINE__, ru);
#define log_error(fmt...) \
log_msg_wrapper(lnav_log_level_t::ERROR, fmt);
#define log_error(fmt...) log_msg_wrapper(lnav_log_level_t::ERROR, fmt);
#define log_warning(fmt...) \
log_msg_wrapper(lnav_log_level_t::WARNING, fmt);
#define log_warning(fmt...) log_msg_wrapper(lnav_log_level_t::WARNING, fmt);
#define log_info(fmt...) \
log_msg_wrapper(lnav_log_level_t::INFO, fmt);
#define log_info(fmt...) log_msg_wrapper(lnav_log_level_t::INFO, fmt);
#define log_debug(fmt...) \
log_msg_wrapper(lnav_log_level_t::DEBUG, fmt);
#define log_debug(fmt...) log_msg_wrapper(lnav_log_level_t::DEBUG, fmt);
#define log_trace(fmt...) \
log_msg_wrapper(lnav_log_level_t::TRACE, fmt);
#define log_trace(fmt...) log_msg_wrapper(lnav_log_level_t::TRACE, fmt);
#define require(e) \
((void) ((e) ? 0 : lnav_require (#e, __FILE__, __LINE__)))
#define require(e) ((void) ((e) ? 0 : lnav_require(#e, __FILE__, __LINE__)))
#define lnav_require(e, file, line) \
(log_msg(lnav_log_level_t::ERROR, file, line, "failed precondition `%s'", e), log_abort(), 1)
(log_msg( \
lnav_log_level_t::ERROR, file, line, "failed precondition `%s'", e), \
log_abort(), \
1)
#define ensure(e) \
((void) ((e) ? 0 : lnav_ensure (#e, __FILE__, __LINE__)))
#define ensure(e) ((void) ((e) ? 0 : lnav_ensure(#e, __FILE__, __LINE__)))
#define lnav_ensure(e, file, line) \
(log_msg(lnav_log_level_t::ERROR, file, line, "failed postcondition `%s'", e), log_abort(), 1)
(log_msg( \
lnav_log_level_t::ERROR, file, line, "failed postcondition `%s'", e), \
log_abort(), \
1)
#define log_perror(e) \
((void) ((e != -1) ? 0 : lnav_log_perror(#e, __FILE__, __LINE__)))
#define lnav_log_perror(e, file, line) \
(log_msg(lnav_log_level_t::ERROR, file, line, "syscall failed `%s' -- %s", e, strerror(errno)), 1)
(log_msg(lnav_log_level_t::ERROR, \
file, \
line, \
"syscall failed `%s' -- %s", \
e, \
strerror(errno)), \
1)
#endif

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@ -41,17 +41,20 @@
* @param step The granularity.
*/
template<typename Size, typename Step>
inline int rounddown(Size size, Step step)
inline int
rounddown(Size size, Step step)
{
return size - (size % step);
}
inline int rounddown_offset(size_t size, int step, int offset)
inline int
rounddown_offset(size_t size, int step, int offset)
{
return size - ((size - offset) % step);
}
inline size_t roundup_size(size_t size, int step)
inline size_t
roundup_size(size_t size, int step)
{
size_t retval = size + step;

View File

@ -21,27 +21,26 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include "fmt/format.h"
#include "network.tcp.hh"
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#include "config.h"
#include "fmt/format.h"
namespace network {
namespace tcp {
Result<auto_fd, std::string> connect(const char *hostname,
const char *servname)
Result<auto_fd, std::string>
connect(const char* hostname, const char* servname)
{
struct addrinfo hints, *ai;
@ -52,7 +51,9 @@ Result<auto_fd, std::string> connect(const char *hostname,
if (rc != 0) {
return Err(fmt::format("unable to resolve {}:{} -- {}",
hostname, servname, gai_strerror(rc)));
hostname,
servname,
gai_strerror(rc)));
}
auto retval = auto_fd(socket(ai->ai_family, ai->ai_socktype, 0));
@ -60,11 +61,13 @@ Result<auto_fd, std::string> connect(const char *hostname,
rc = ::connect(retval, ai->ai_addr, ai->ai_addrlen);
if (rc != 0) {
return Err(fmt::format("unable to connect to {}:{} -- {}",
hostname, servname, strerror(rc)));
hostname,
servname,
strerror(rc)));
}
return Ok(retval);
}
}
}
} // namespace tcp
} // namespace network

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@ -40,11 +40,11 @@ namespace network {
struct locality {
locality(nonstd::optional<std::string> username,
std::string hostname,
nonstd::optional<std::string> service) :
l_username(std::move(username)),
l_hostname(std::move(hostname)),
nonstd::optional<std::string> service)
: l_username(std::move(username)), l_hostname(std::move(hostname)),
l_service(std::move(service))
{}
{
}
nonstd::optional<std::string> l_username;
std::string l_hostname;
@ -55,11 +55,13 @@ struct path {
locality p_locality;
std::string p_path;
path(locality l, std::string path) : p_locality(std::move(l)),
p_path(std::move(path))
{}
path(locality l, std::string path)
: p_locality(std::move(l)), p_path(std::move(path))
{
}
path home() const {
path home() const
{
return {
this->p_locality,
".",
@ -73,6 +75,6 @@ Result<auto_fd, std::string> connect(const char *hostname,
const char* servname);
}
}
} // namespace network
#endif

View File

@ -21,18 +21,16 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <iostream>
#include "config.h"
#include "doctest/doctest.h"
#include "network.tcp.hh"
TEST_CASE("bad hostname")

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@ -52,21 +52,32 @@ namespace detail {
}
template<class T>
struct is_optional : std::false_type {};
struct is_optional : std::false_type {
};
template<class T>
struct is_optional<nonstd::optional<T>> : std::true_type {};
}
struct is_optional<nonstd::optional<T>> : std::true_type {
};
} // namespace detail
template <class T, class F, std::enable_if_t<detail::is_optional<std::decay_t<T>>::value, int> = 0>
auto operator|(T&& t, F f) -> decltype(detail::void_or_nullopt<decltype(f(std::forward<T>(t).operator*()))>()) {
template<class T,
class F,
std::enable_if_t<detail::is_optional<std::decay_t<T>>::value, int> = 0>
auto
operator|(T&& t, F f)
-> decltype(detail::void_or_nullopt<decltype(f(std::forward<T>(t).
operator*()))>())
{
using return_type = decltype(f(std::forward<T>(t).operator*()));
if (t) return f(std::forward<T>(t).operator*());
else return detail::void_or_nullopt<return_type>();
if (t)
return f(std::forward<T>(t).operator*());
else
return detail::void_or_nullopt<return_type>();
}
template<class T>
optional_constexpr nonstd::optional< typename std::decay<T>::type > make_optional_from_nullable( T && v )
optional_constexpr nonstd::optional<typename std::decay<T>::type>
make_optional_from_nullable(T&& v)
{
if (v != nullptr) {
return nonstd::optional<typename std::decay<T>::type>(
@ -76,7 +87,8 @@ optional_constexpr nonstd::optional< typename std::decay<T>::type > make_optiona
}
template<template<typename, typename...> class C, typename T>
nonstd::optional<T> cget(const C<T> &container, size_t index)
nonstd::optional<T>
cget(const C<T>& container, size_t index)
{
if (index < container.size()) {
return container[index];
@ -85,7 +97,9 @@ nonstd::optional<T> cget(const C<T> &container, size_t index)
return nonstd::nullopt;
}
inline nonstd::optional<const char *> getenv_opt(const char *name) {
inline nonstd::optional<const char*>
getenv_opt(const char* name)
{
return make_optional_from_nullable(getenv(name));
}

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@ -30,18 +30,20 @@
#include "config.h"
#ifdef __CYGWIN__
#include <sstream>
# include <iostream>
# include <sstream>
#endif
#include "paths.hh"
#include "fmt/format.h"
#include "paths.hh"
namespace lnav {
namespace paths {
#ifdef __CYGWIN__
char* windows_to_unix_file_path(char* input) {
char*
windows_to_unix_file_path(char* input)
{
if (input == nullptr) {
return nullptr;
}
@ -49,13 +51,17 @@ char* windows_to_unix_file_path(char* input) {
file_path.assign(input);
// Replace the slashes
std::replace(file_path.begin(), file_path.end(), WINDOWS_FILE_PATH_SEPARATOR, UNIX_FILE_PATH_SEPARATOR);
std::replace(file_path.begin(),
file_path.end(),
WINDOWS_FILE_PATH_SEPARATOR,
UNIX_FILE_PATH_SEPARATOR);
// Convert the drive letter to lowercase
std::transform(file_path.begin(), file_path.begin() + 1, file_path.begin(),
[](unsigned char character) {
return std::tolower(character);
});
std::transform(
file_path.begin(),
file_path.begin() + 1,
file_path.begin(),
[](unsigned char character) { return std::tolower(character); });
// Remove the colon
const auto drive_letter = file_path.substr(0, 1);
@ -70,7 +76,8 @@ char* windows_to_unix_file_path(char* input) {
}
#endif
ghc::filesystem::path dotlnav()
ghc::filesystem::path
dotlnav()
{
#ifdef __CYGWIN__
auto home_env = windows_to_unix_file_path(getenv("APPDATA"));
@ -110,7 +117,8 @@ ghc::filesystem::path dotlnav()
return ghc::filesystem::current_path();
}
ghc::filesystem::path workdir()
ghc::filesystem::path
workdir()
{
auto subdir_name = fmt::format("lnav-user-{}-work", getuid());
auto tmp_path = ghc::filesystem::temp_directory_path();
@ -118,5 +126,5 @@ ghc::filesystem::path workdir()
return tmp_path / ghc::filesystem::path(subdir_name);
}
}
}
} // namespace paths
} // namespace lnav

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@ -52,7 +52,7 @@ ghc::filesystem::path dotlnav();
ghc::filesystem::path workdir();
}
}
} // namespace paths
} // namespace lnav
#endif

View File

@ -21,30 +21,31 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <iterator>
#include <regex>
#include <sstream>
#include "lnav_log.hh"
#include "is_utf8.hh"
#include "string_util.hh"
void scrub_to_utf8(char *buffer, size_t length)
#include "config.h"
#include "is_utf8.hh"
#include "lnav_log.hh"
void
scrub_to_utf8(char* buffer, size_t length)
{
const char* msg;
int faulty_bytes;
while (true) {
ssize_t utf8_end = is_utf8(
(unsigned char *) buffer, length, &msg, &faulty_bytes);
ssize_t utf8_end
= is_utf8((unsigned char*) buffer, length, &msg, &faulty_bytes);
if (msg == nullptr) {
break;
@ -55,7 +56,8 @@ void scrub_to_utf8(char *buffer, size_t length)
}
}
size_t unquote(char *dst, const char *str, size_t len)
size_t
unquote(char* dst, const char* str, size_t len)
{
if (str[0] == 'r' || str[0] == 'u') {
str += 1;
@ -70,8 +72,7 @@ size_t unquote(char *dst, const char *str, size_t len)
dst[index] = str[lpc];
if (str[lpc] == quote_char) {
lpc += 1;
}
else if (str[lpc] == '\\' && (lpc + 1) < len) {
} else if (str[lpc] == '\\' && (lpc + 1) < len) {
switch (str[lpc + 1]) {
case 'n':
dst[index] = '\n';
@ -94,7 +95,8 @@ size_t unquote(char *dst, const char *str, size_t len)
return index;
}
size_t unquote_w3c(char *dst, const char *str, size_t len)
size_t
unquote_w3c(char* dst, const char* str, size_t len)
{
size_t index = 0;
@ -111,7 +113,8 @@ size_t unquote_w3c(char *dst, const char *str, size_t len)
return index;
}
void truncate_to(std::string &str, size_t max_char_len)
void
truncate_to(std::string& str, size_t max_char_len)
{
static const std::string ELLIPSIS = "\u22ef";
@ -139,23 +142,25 @@ void truncate_to(std::string &str, size_t max_char_len)
auto chars_to_remove = (str_char_len - max_char_len) + 1;
auto midpoint = str_char_len / 2;
auto chars_to_keep_at_front = midpoint - (chars_to_remove / 2);
auto bytes_to_keep_at_front =
utf8_char_to_byte_index(str, chars_to_keep_at_front);
auto remove_up_to_bytes =
utf8_char_to_byte_index(str, chars_to_keep_at_front + chars_to_remove);
auto bytes_to_keep_at_front
= utf8_char_to_byte_index(str, chars_to_keep_at_front);
auto remove_up_to_bytes = utf8_char_to_byte_index(
str, chars_to_keep_at_front + chars_to_remove);
auto bytes_to_remove = remove_up_to_bytes - bytes_to_keep_at_front;
str.erase(bytes_to_keep_at_front, bytes_to_remove);
str.insert(bytes_to_keep_at_front, ELLIPSIS);
}
bool is_url(const char *fn)
bool
is_url(const char* fn)
{
static const auto url_re = std::regex("^(file|https?|ftps?|scp|sftp):.*");
return std::regex_match(fn, url_re);
}
size_t abbreviate_str(char *str, size_t len, size_t max_len)
size_t
abbreviate_str(char* str, size_t len, size_t max_len)
{
size_t last_start = 1;
@ -184,7 +189,8 @@ size_t abbreviate_str(char *str, size_t len, size_t max_len)
return len;
}
void split_ws(const std::string &str, std::vector<std::string> &toks_out)
void
split_ws(const std::string& str, std::vector<std::string>& toks_out)
{
std::stringstream ss(str);
std::string buf;
@ -194,14 +200,16 @@ void split_ws(const std::string &str, std::vector<std::string> &toks_out)
}
}
std::string repeat(const std::string& input, size_t num)
std::string
repeat(const std::string& input, size_t num)
{
std::ostringstream os;
std::fill_n(std::ostream_iterator<std::string>(os), num, input);
return os.str();
}
std::string center_str(const std::string &subject, size_t width)
std::string
center_str(const std::string& subject, size_t width)
{
std::string retval = subject;
@ -219,18 +227,23 @@ std::string center_str(const std::string &subject, size_t width)
}
template<typename T>
size_t strtonum(T &num_out, const char *string, size_t len)
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 && isspace(string[retval]); retval++) {
;
}
for (; retval < len && string[retval] == '-'; retval++) {
sign *= -1;
}
for (; retval < len && string[retval] == '+'; retval++);
for (; retval < len && string[retval] == '+'; retval++) {
;
}
for (; retval < len && isdigit(string[retval]); retval++) {
num_out *= 10;
num_out += string[retval] - '0';
@ -240,11 +253,10 @@ size_t strtonum(T &num_out, const char *string, size_t len)
return retval;
}
template
size_t strtonum<long long>(long long &num_out, const char *string, size_t len);
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<long>(long& num_out, const char* string, size_t len);
template
size_t strtonum<int>(int &num_out, const char *string, size_t len);
template size_t strtonum<int>(int& num_out, const char* string, size_t len);

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@ -30,15 +30,18 @@
#ifndef lnav_string_util_hh
#define lnav_string_util_hh
#include <string.h>
#include <string>
#include <vector>
#include <string.h>
#include "ww898/cp_utf8.hpp"
void scrub_to_utf8(char* buffer, size_t length);
inline bool is_line_ending(char ch) {
inline bool
is_line_ending(char ch)
{
return ch == '\r' || ch == '\n';
}
@ -46,22 +49,26 @@ size_t unquote(char *dst, const char *str, size_t len);
size_t unquote_w3c(char* dst, const char* str, size_t len);
inline bool startswith(const char *str, const char *prefix)
inline bool
startswith(const char* str, const char* prefix)
{
return strncmp(str, prefix, strlen(prefix)) == 0;
}
inline bool startswith(const std::string &str, const char *prefix)
inline bool
startswith(const std::string& str, const char* prefix)
{
return startswith(str.c_str(), prefix);
}
inline bool startswith(const std::string &str, const std::string& prefix)
inline bool
startswith(const std::string& str, const std::string& prefix)
{
return startswith(str.c_str(), prefix.c_str());
}
inline bool endswith(const char *str, const char *suffix)
inline bool
endswith(const char* str, const char* suffix)
{
size_t len = strlen(str), suffix_len = strlen(suffix);
@ -73,7 +80,8 @@ inline bool endswith(const char *str, const char *suffix)
}
template<int N>
inline bool endswith(const std::string& str, const char (&suffix) [N])
inline bool
endswith(const std::string& str, const char (&suffix)[N])
{
if (N - 1 > str.length()) {
return false;
@ -84,17 +92,21 @@ inline bool endswith(const std::string& str, const char (&suffix) [N])
void truncate_to(std::string& str, size_t max_char_len);
inline std::string trim(const std::string &str)
inline std::string
trim(const std::string& str)
{
std::string::size_type start, end;
for (start = 0; start < str.size() && isspace(str[start]); start++);
for (end = str.size(); end > 0 && isspace(str[end - 1]); end--);
for (start = 0; start < str.size() && isspace(str[start]); start++)
;
for (end = str.size(); end > 0 && isspace(str[end - 1]); end--)
;
return str.substr(start, end - start);
}
inline std::string tolower(const char *str)
inline std::string
tolower(const char* str)
{
std::string retval;
@ -105,12 +117,14 @@ inline std::string tolower(const char *str)
return retval;
}
inline std::string tolower(const std::string &str)
inline std::string
tolower(const std::string& str)
{
return tolower(str.c_str());
}
inline std::string toupper(const char *str)
inline std::string
toupper(const char* str)
{
std::string retval;
@ -121,17 +135,20 @@ inline std::string toupper(const char *str)
return retval;
}
inline std::string toupper(const std::string &str)
inline std::string
toupper(const std::string& str)
{
return toupper(str.c_str());
}
inline ssize_t utf8_char_to_byte_index(const std::string &str, ssize_t ch_index)
inline ssize_t
utf8_char_to_byte_index(const std::string& str, ssize_t ch_index)
{
ssize_t retval = 0;
while (ch_index > 0) {
auto ch_len = ww898::utf::utf8::char_size([&str, retval]() {
auto ch_len
= ww898::utf::utf8::char_size([&str, retval]() {
return std::make_pair(str[retval], str.length() - retval - 1);
}).unwrapOr(1);
@ -142,7 +159,8 @@ inline ssize_t utf8_char_to_byte_index(const std::string &str, ssize_t ch_index)
return retval;
}
inline Result<size_t, const char *> utf8_string_length(const char *str, ssize_t len = -1)
inline Result<size_t, const char*>
utf8_string_length(const char* str, ssize_t len = -1)
{
size_t retval = 0;
@ -151,7 +169,8 @@ inline Result<size_t, const char *> utf8_string_length(const char *str, ssize_t
}
for (ssize_t byte_index = 0; byte_index < len;) {
auto ch_size = TRY(ww898::utf::utf8::char_size([str, len, byte_index]() {
auto ch_size
= TRY(ww898::utf::utf8::char_size([str, len, byte_index]() {
return std::make_pair(str[byte_index], len - byte_index);
}));
byte_index += ch_size;
@ -161,7 +180,8 @@ inline Result<size_t, const char *> utf8_string_length(const char *str, ssize_t
return Ok(retval);
}
inline Result<size_t, const char *> utf8_string_length(const std::string& str)
inline Result<size_t, const char*>
utf8_string_length(const std::string& str)
{
return utf8_string_length(str.c_str(), str.length());
}

View File

@ -21,20 +21,19 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <iostream>
#include "doctest/doctest.h"
#include "base/string_util.hh"
#include "base/strnatcmp.h"
#include "base/string_util.hh"
#include "config.h"
#include "doctest/doctest.h"
TEST_CASE("endswith")
{
@ -74,7 +73,8 @@ TEST_CASE ("truncate_to")
CHECK(str == "01\u22efyz");
}
TEST_CASE("strnatcmp") {
TEST_CASE("strnatcmp")
{
{
constexpr const char* n1 = "010";
constexpr const char* n2 = "020";

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

View File

@ -21,27 +21,29 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @file time_util.cc
*/
#include "config.h"
#include <chrono>
#include "time_util.hh"
#include "config.h"
static time_t BAD_DATE = -1;
time_t tm2sec(const struct tm *t)
time_t
tm2sec(const struct tm* t)
{
int year;
time_t days, secs;
const int dayoffset[12] =
{ 306, 337, 0, 31, 61, 92, 122, 153, 184, 214, 245, 275 };
const int dayoffset[12]
= {306, 337, 0, 31, 61, 92, 122, 153, 184, 214, 245, 275};
year = t->tm_year;
@ -66,7 +68,8 @@ time_t tm2sec(const struct tm *t)
if (secs < 0) {
return BAD_DATE;
} /* must have overflowed */
else {
else
{
#ifdef HAVE_STRUCT_TM_TM_ZONE
if (t->tm_zone) {
secs -= t->tm_gmtoff;
@ -86,19 +89,16 @@ static const int EPOCH_YEAR = 1970;
#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
static const int year_lengths[2] = {
365,
366
};
static const int year_lengths[2] = {365, 366};
const unsigned short int mon_yday[2][13] = {
/* Normal years. */
{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
/* Leap years. */
{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
};
{0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}};
void secs2wday(const struct timeval &tv, struct tm *res)
void
secs2wday(const struct timeval& tv, struct tm* res)
{
long days, rem;
time_t lcltime;
@ -118,7 +118,8 @@ void secs2wday(const struct timeval &tv, struct tm *res)
res->tm_wday += DAYSPERWEEK;
}
struct tm *secs2tm(lnav::time64_t tim, struct tm *res)
struct tm*
secs2tm(lnav::time64_t tim, struct tm* res)
{
long days, rem;
lnav::time64_t lcltime;
@ -131,8 +132,7 @@ struct tm *secs2tm(lnav::time64_t tim, struct tm *res)
days = ((long) lcltime) / SECSPERDAY;
rem = ((long) lcltime) % SECSPERDAY;
while (rem < 0)
{
while (rem < 0) {
rem += SECSPERDAY;
--days;
}
@ -149,21 +149,16 @@ struct tm *secs2tm(lnav::time64_t tim, struct tm *res)
/* compute year & day of year */
y = EPOCH_YEAR;
if (days >= 0)
{
for (;;)
{
if (days >= 0) {
for (;;) {
yleap = isleap(y);
if (days < year_lengths[yleap])
break;
y++;
days -= year_lengths[yleap];
}
}
else
{
do
{
} else {
do {
--y;
yleap = isleap(y);
days += year_lengths[yleap];
@ -184,14 +179,15 @@ struct tm *secs2tm(lnav::time64_t tim, struct tm *res)
return (res);
}
struct timeval exttm::to_timeval() const
struct timeval
exttm::to_timeval() const
{
struct timeval retval;
retval.tv_sec = tm2sec(&this->et_tm);
retval.tv_usec =
std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::nanoseconds(this->et_nsec)).count();
retval.tv_usec = std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::nanoseconds(this->et_nsec))
.count();
return retval;
}

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@ -30,11 +30,13 @@
#ifndef lnav_time_util_hh
#define lnav_time_util_hh
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <inttypes.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include "config.h"
namespace lnav {
@ -52,8 +54,9 @@ struct tm *secs2tm(lnav::time64_t tim, struct tm *res);
time_t tm2sec(const struct tm* t);
void secs2wday(const struct timeval& tv, struct tm* res);
inline
time_t convert_log_time_to_local(time_t value) {
inline time_t
convert_log_time_to_local(time_t value)
{
struct tm tm;
localtime_r(&value, &tm);
@ -88,37 +91,41 @@ struct exttm {
unsigned int et_flags;
long et_gmtoff;
bool operator==(const exttm &other) const {
bool operator==(const exttm& other) const
{
return memcmp(this, &other, sizeof(exttm)) == 0;
};
struct timeval to_timeval() const;
};
inline
bool operator<(const struct timeval &left, time_t right) {
inline bool
operator<(const struct timeval& left, time_t right)
{
return left.tv_sec < right;
}
inline
bool operator<(time_t left, const struct timeval &right) {
inline bool
operator<(time_t left, const struct timeval& right)
{
return left < right.tv_sec;
}
inline
bool operator<(const struct timeval &left, const struct timeval &right) {
return left.tv_sec < right.tv_sec ||
((left.tv_sec == right.tv_sec) && (left.tv_usec < right.tv_usec));
inline bool
operator<(const struct timeval& left, const struct timeval& right)
{
return left.tv_sec < right.tv_sec
|| ((left.tv_sec == right.tv_sec) && (left.tv_usec < right.tv_usec));
}
inline
bool operator!=(const struct timeval &left, const struct timeval &right) {
return left.tv_sec != right.tv_sec ||
left.tv_usec != right.tv_usec;
inline bool
operator!=(const struct timeval& left, const struct timeval& right)
{
return left.tv_sec != right.tv_sec || left.tv_usec != right.tv_usec;
}
inline
struct timeval operator-(const struct timeval& lhs, const struct timeval& rhs)
inline struct timeval
operator-(const struct timeval& lhs, const struct timeval& rhs)
{
struct timeval diff;
@ -128,7 +135,9 @@ struct timeval operator-(const struct timeval& lhs, const struct timeval& rhs)
typedef int64_t mstime_t;
inline mstime_t getmstime() {
inline mstime_t
getmstime()
{
struct timeval tv;
gettimeofday(&tv, nullptr);
@ -136,7 +145,9 @@ inline mstime_t getmstime() {
return tv.tv_sec * 1000ULL + tv.tv_usec / 1000ULL;
}
inline struct timeval current_timeval() {
inline struct timeval
current_timeval()
{
struct timeval retval;
gettimeofday(&retval, nullptr);
@ -144,7 +155,9 @@ inline struct timeval current_timeval() {
return retval;
}
inline struct timespec current_timespec() {
inline struct timespec
current_timespec()
{
struct timespec retval;
clock_gettime(CLOCK_REALTIME, &retval);
@ -152,12 +165,14 @@ inline struct timespec current_timespec() {
return retval;
}
inline time_t day_num(time_t ti)
inline time_t
day_num(time_t ti)
{
return ti / (24 * 60 * 60);
}
inline time_t hour_num(time_t ti)
inline time_t
hour_num(time_t ti)
{
return ti / (60 * 60);
}

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
@ -33,6 +33,7 @@
#define lnav_big_array_hh
#include <sys/mman.h>
#include <unistd.h>
#include "base/math_util.hh"
@ -40,11 +41,13 @@ template<typename T>
struct big_array {
static const size_t DEFAULT_INCREMENT = 100 * 1000;
big_array() : ba_ptr(nullptr), ba_size(0), ba_capacity(0) {
big_array()
: ba_ptr(nullptr), ba_size(0), ba_capacity(0){
};
bool reserve(size_t size) {
bool reserve(size_t size)
{
if (size < this->ba_capacity) {
return false;
}
@ -55,9 +58,9 @@ struct big_array {
}
this->ba_capacity = size + DEFAULT_INCREMENT;
void *result = mmap(nullptr,
roundup_size(this->ba_capacity * sizeof(T),
getpagesize()),
void* result
= mmap(nullptr,
roundup_size(this->ba_capacity * sizeof(T), getpagesize()),
PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE,
-1,
@ -70,48 +73,58 @@ struct big_array {
return true;
};
void clear() {
void clear()
{
this->ba_size = 0;
};
size_t size() const {
size_t size() const
{
return this->ba_size;
};
void shrink_to(size_t new_size) {
void shrink_to(size_t new_size)
{
require(new_size <= this->ba_size);
this->ba_size = new_size;
}
bool empty() const {
bool empty() const
{
return this->ba_size == 0;
};
void push_back(const T &val) {
void push_back(const T& val)
{
this->ba_ptr[this->ba_size] = val;
this->ba_size += 1;
};
T &operator[](size_t index) {
T& operator[](size_t index)
{
return this->ba_ptr[index];
};
const T &operator[](size_t index) const {
const T& operator[](size_t index) const
{
return this->ba_ptr[index];
};
T &back() {
T& back()
{
return this->ba_ptr[this->ba_size - 1];
}
typedef T* iterator;
iterator begin() {
iterator begin()
{
return this->ba_ptr;
};
iterator end() {
iterator end()
{
return this->ba_ptr + this->ba_size;
};

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
@ -32,21 +32,24 @@
#ifndef lnav_bin2c_hh
#define lnav_bin2c_hh
#include <zlib.h>
#include <memory>
#include <assert.h>
#include <sys/types.h>
#include <memory>
#include <zlib.h>
#include "base/intern_string.hh"
struct bin_src_file {
bin_src_file(const char *name, const unsigned char *data,
size_t compressed_size, size_t size)
bin_src_file(const char* name,
const unsigned char* data,
size_t compressed_size,
size_t size)
: bsf_name(name), bsf_data(new unsigned char[size + 1]), bsf_size(size)
{
uLongf zsize = size;
auto rc = uncompress(this->bsf_data.get(), &zsize, data, compressed_size);
auto rc
= uncompress(this->bsf_data.get(), &zsize, data, compressed_size);
assert(rc == Z_OK);
assert(zsize == size);
this->bsf_data[size] = '\0';

View File

@ -21,18 +21,18 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @file bookmarks.cc
*/
#include "config.h"
#include "bookmarks.hh"
#include "config.h"
using namespace std;
set<string> bookmark_metadata::KNOWN_TAGS;

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
@ -32,11 +32,11 @@
#ifndef bookmarks_hh
#define bookmarks_hh
#include <algorithm>
#include <map>
#include <set>
#include <string>
#include <vector>
#include <algorithm>
#include "base/lnav_log.hh"
@ -47,18 +47,18 @@ struct bookmark_metadata {
std::string bm_comment;
std::vector<std::string> bm_tags;
void add_tag(const std::string &tag) {
if (std::find(this->bm_tags.begin(),
this->bm_tags.end(),
tag) == this->bm_tags.end()) {
void add_tag(const std::string& tag)
{
if (std::find(this->bm_tags.begin(), this->bm_tags.end(), tag)
== this->bm_tags.end())
{
this->bm_tags.push_back(tag);
}
};
bool remove_tag(const std::string &tag) {
auto iter = std::find(this->bm_tags.begin(),
this->bm_tags.end(),
tag);
bool remove_tag(const std::string& tag)
{
auto iter = std::find(this->bm_tags.begin(), this->bm_tags.end(), tag);
bool retval = false;
if (iter != this->bm_tags.end()) {
@ -68,13 +68,14 @@ struct bookmark_metadata {
return retval;
};
bool empty() const {
return this->bm_name.empty() &&
this->bm_comment.empty() &&
this->bm_tags.empty();
bool empty() const
{
return this->bm_name.empty() && this->bm_comment.empty()
&& this->bm_tags.empty();
};
void clear() {
void clear()
{
this->bm_comment.clear();
this->bm_tags.clear();
};
@ -118,15 +119,15 @@ public:
if (lb == this->end() || *lb != vl) {
this->insert(lb, vl);
retval = this->end();
}
else {
} else {
retval = lb;
}
return retval;
};
std::pair<iterator, iterator> equal_range(LineType start, LineType stop) {
std::pair<iterator, iterator> equal_range(LineType start, LineType stop)
{
auto lb = std::lower_bound(this->begin(), this->end(), start);
if (stop == LineType(-1)) {
@ -165,15 +166,18 @@ class bookmark_type_t {
public:
typedef std::vector<bookmark_type_t*>::iterator type_iterator;
static type_iterator type_begin() {
static type_iterator type_begin()
{
return get_all_types().begin();
};
static type_iterator type_end() {
static type_iterator type_end()
{
return get_all_types().end();
};
static bookmark_type_t *find_type(const std::string &name) {
static bookmark_type_t* find_type(const std::string& name)
{
auto iter = find_if(type_begin(), type_end(), mark_eq(name));
bookmark_type_t* retval = nullptr;
@ -183,17 +187,20 @@ public:
return retval;
};
static std::vector<bookmark_type_t *> &get_all_types() {
static std::vector<bookmark_type_t*>& get_all_types()
{
static std::vector<bookmark_type_t*> all_types;
return all_types;
};
explicit bookmark_type_t(std::string name) : bt_name(std::move(name)) {
explicit bookmark_type_t(std::string name) : bt_name(std::move(name))
{
get_all_types().push_back(this);
};
const std::string &get_name() const {
const std::string& get_name() const
{
return this->bt_name;
};
@ -201,7 +208,8 @@ private:
struct mark_eq {
explicit mark_eq(const std::string& name) : me_name(name){};
bool operator()(bookmark_type_t *bt) {
bool operator()(bookmark_type_t* bt)
{
return bt->bt_name == this->me_name;
};
@ -212,7 +220,8 @@ private:
};
template<typename LineType>
LineType bookmark_vector<LineType>::next(LineType start) const
LineType
bookmark_vector<LineType>::next(LineType start) const
{
LineType retval(-1);
@ -229,7 +238,8 @@ LineType bookmark_vector<LineType>::next(LineType start) const
}
template<typename LineType>
LineType bookmark_vector<LineType>::prev(LineType start) const
LineType
bookmark_vector<LineType>::prev(LineType start) const
{
LineType retval(-1);
@ -251,7 +261,7 @@ LineType bookmark_vector<LineType>::prev(LineType start) const
*/
template<typename LineType>
struct bookmarks {
typedef std::map<bookmark_type_t *, bookmark_vector<LineType> > type;
typedef std::map<const bookmark_type_t*, bookmark_vector<LineType> > type;
};
#endif

View File

@ -21,16 +21,15 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "bottom_status_source.hh"
#include "config.h"
bottom_status_source::bottom_status_source()
{
@ -59,22 +58,22 @@ bottom_status_source::bottom_status_source()
this->bss_line_error.set_share(1);
}
void bottom_status_source::update_line_number(listview_curses *lc)
void
bottom_status_source::update_line_number(listview_curses* lc)
{
status_field& sf = this->bss_fields[BSF_LINE_NUMBER];
if (lc->get_inner_height() == 0) {
sf.set_value(" L0");
}
else {
} else {
sf.set_value(" L%'d", (int) lc->get_top());
}
if (lc->get_inner_height() > 0) {
std::vector<attr_line_t> rows(1);
lc->get_data_source()->
listview_value_for_rows(*lc, lc->get_top(), rows);
lc->get_data_source()->listview_value_for_rows(
*lc, lc->get_top(), rows);
auto& sa = rows[0].get_attrs();
auto iter = find_string_attr(sa, &SA_ERROR);
if (iter != sa.end()) {
@ -87,7 +86,8 @@ void bottom_status_source::update_line_number(listview_curses *lc)
}
}
void bottom_status_source::update_search_term(textview_curses &tc)
void
bottom_status_source::update_search_term(textview_curses& tc)
{
auto& sf = this->bss_fields[BSF_SEARCH_TERM];
auto search_term = tc.get_current_search();
@ -102,7 +102,8 @@ void bottom_status_source::update_search_term(textview_curses &tc)
this->update_loading(0, 0);
}
void bottom_status_source::update_percent(listview_curses *lc)
void
bottom_status_source::update_percent(listview_curses* lc)
{
status_field& sf = this->bss_fields[BSF_PERCENT];
vis_line_t top = lc->get_top();
@ -118,14 +119,14 @@ void bottom_status_source::update_percent(listview_curses *lc)
percent = (double) (bottom + 1);
percent /= (double) lc->get_inner_height();
percent *= 100.0;
}
else {
} else {
percent = 0.0;
}
sf.set_value("%3d%% ", (int) percent);
}
void bottom_status_source::update_marks(listview_curses *lc)
void
bottom_status_source::update_marks(listview_curses* lc)
{
auto* tc = static_cast<textview_curses*>(lc);
vis_bookmarks& bm = tc->get_bookmarks();
@ -139,22 +140,22 @@ void bottom_status_source::update_marks(listview_curses *lc)
lb = std::lower_bound(bv.begin(), bv.end(), tc->get_top());
if (lb != bv.end() && *lb == tc->get_top()) {
sf.set_value(
" Hit %'d of %'d for ",
std::distance(bv.begin(), lb) + 1, tc->get_match_count());
sf.set_value(" Hit %'d of %'d for ",
std::distance(bv.begin(), lb) + 1,
tc->get_match_count());
} else {
sf.set_value(" %'d hits for ", tc->get_match_count());
}
} else {
sf.clear();
}
}
else {
} else {
sf.clear();
}
}
void bottom_status_source::update_hits(textview_curses *tc)
void
bottom_status_source::update_hits(textview_curses* tc)
{
status_field& sf = this->bss_fields[BSF_HITS];
view_colors::role_t new_role;
@ -163,13 +164,11 @@ void bottom_status_source::update_hits(textview_curses *tc)
this->bss_hit_spinner += 1;
if (this->bss_hit_spinner % 2) {
new_role = view_colors::VCR_ACTIVE_STATUS;
}
else{
} else {
new_role = view_colors::VCR_ACTIVE_STATUS2;
}
sf.set_cylon(true);
}
else {
} else {
new_role = view_colors::VCR_STATUS;
sf.set_cylon(false);
}
@ -178,7 +177,8 @@ void bottom_status_source::update_hits(textview_curses *tc)
this->update_marks(tc);
}
void bottom_status_source::update_loading(file_off_t off, file_size_t total)
void
bottom_status_source::update_loading(file_off_t off, file_size_t total)
{
auto& sf = this->bss_fields[BSF_LOADING];
@ -192,8 +192,7 @@ void bottom_status_source::update_loading(file_off_t off, file_size_t total)
} else {
sf.clear();
}
}
else {
} else {
int pct = (int) (((double) off / (double) total) * 100.0);
if (this->bss_load_percent != pct) {
@ -206,34 +205,32 @@ void bottom_status_source::update_loading(file_off_t off, file_size_t total)
}
}
size_t bottom_status_source::statusview_fields()
size_t
bottom_status_source::statusview_fields()
{
size_t retval;
if (this->bss_prompt.empty() &&
this->bss_error.empty() &&
this->bss_line_error.empty()) {
if (this->bss_prompt.empty() && this->bss_error.empty()
&& this->bss_line_error.empty())
{
retval = BSF__MAX;
}
else{
} else {
retval = 1;
}
return retval;
}
status_field &bottom_status_source::statusview_value_for_field(int field)
status_field&
bottom_status_source::statusview_value_for_field(int field)
{
if (!this->bss_error.empty()) {
return this->bss_error;
}
else if (!this->bss_prompt.empty()) {
} else if (!this->bss_prompt.empty()) {
return this->bss_prompt;
}
else if (!this->bss_line_error.empty()) {
} else if (!this->bss_line_error.empty()) {
return this->bss_line_error;
}
else {
} else {
return this->get_field((field_t) field);
}
}

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@ -33,12 +33,12 @@
#include <string>
#include "grep_proc.hh"
#include "textview_curses.hh"
#include "statusview_curses.hh"
#include "textview_curses.hh"
class bottom_status_source
: public status_data_source,
public grep_proc_control {
: public status_data_source
, public grep_proc_control {
public:
typedef enum {
BSF_LINE_NUMBER,
@ -53,7 +53,10 @@ public:
bottom_status_source();
status_field &get_field(field_t id) { return this->bss_fields[id]; };
status_field& get_field(field_t id)
{
return this->bss_fields[id];
};
void set_prompt(const std::string& prompt)
{

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
@ -32,10 +32,13 @@
#ifndef lnav_bound_tags_hh
#define lnav_bound_tags_hh
struct last_relative_time_tag {};
struct last_relative_time_tag {
};
struct sqlite_db_tag {};
struct sqlite_db_tag {
};
struct sql_cmd_map_tag {};
struct sql_cmd_map_tag {
};
#endif

View File

@ -21,21 +21,21 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef byte_array_hh
#define byte_array_hh
#include <ostream>
#include <string>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <string>
#include <ostream>
#include "base/lnav_log.hh"
template<size_t COUNT, typename T = unsigned char>
@ -87,9 +87,13 @@ struct byte_array {
return std::string(buffer);
}
const unsigned char *in() const { return this->ba_data; };
const unsigned char* in() const
{
return this->ba_data;
};
T *out(int offset = 0) {
T* out(int offset = 0)
{
T* ptr = (T*) this->ba_data;
return &ptr[offset];
@ -99,7 +103,8 @@ struct byte_array {
};
template<size_t COUNT, typename T = unsigned char>
std::ostream& operator<<(std::ostream& os, const byte_array<COUNT, T>& ba)
std::ostream&
operator<<(std::ostream& os, const byte_array<COUNT, T>& ba)
{
os << ba.to_string();
return os;

View File

@ -21,29 +21,28 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @file logfile_sub_source.hh
*/
#include "config.h"
#include <string.h>
#include <sqlite3.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sqlite3.h>
#include <string.h>
#include <sys/socket.h>
#include "log_level.hh"
#include "base/strnatcmp.h"
#include "config.h"
#include "log_level.hh"
#define MAX_ADDR_LEN 128
static int try_inet_pton(int p_len, const char *p, char *n)
static int
try_inet_pton(int p_len, const char* p, char* n)
{
static int ADDR_FAMILIES[] = {AF_INET, AF_INET6};
@ -62,13 +61,14 @@ static int try_inet_pton(int p_len, const char *p, char *n)
return retval;
}
static int convert_v6_to_v4(int family, char *n)
static int
convert_v6_to_v4(int family, char* n)
{
struct in6_addr* ia = (struct in6_addr*) n;
if (family == AF_INET6 &&
(IN6_IS_ADDR_V4COMPAT(ia) ||
IN6_IS_ADDR_V4MAPPED(ia))) {
if (family == AF_INET6
&& (IN6_IS_ADDR_V4COMPAT(ia) || IN6_IS_ADDR_V4MAPPED(ia)))
{
family = AF_INET;
memmove(n, n + 12, sizeof(struct in_addr));
}
@ -76,13 +76,10 @@ static int convert_v6_to_v4(int family, char *n)
return family;
}
static
int ipaddress(void *ptr,
int a_len, const void *a_in,
int b_len, const void *b_in)
static int
ipaddress(void* ptr, int a_len, const void* a_in, int b_len, const void* b_in)
{
char a_addr[sizeof(struct in6_addr)],
b_addr[sizeof(struct in6_addr)];
char a_addr[sizeof(struct in6_addr)], b_addr[sizeof(struct in6_addr)];
const char *a_str = (const char*) a_in, *b_str = (const char*) b_in;
int a_family, b_family, retval;
@ -100,26 +97,21 @@ int ipaddress(void *ptr,
if (a_family == AF_MAX && b_family == AF_MAX) {
return strnatcasecmp(a_len, a_str, b_len, b_str);
}
else if (a_family == AF_MAX && b_family != AF_MAX) {
} else if (a_family == AF_MAX && b_family != AF_MAX) {
retval = -1;
}
else if (a_family != AF_MAX && b_family == AF_MAX) {
} else if (a_family != AF_MAX && b_family == AF_MAX) {
retval = 1;
}
else {
} else {
a_family = convert_v6_to_v4(a_family, a_addr);
b_family = convert_v6_to_v4(b_family, b_addr);
if (a_family == b_family) {
retval = memcmp(a_addr, b_addr,
a_family == AF_INET ?
sizeof(struct in_addr) :
sizeof(struct in6_addr));
}
else if (a_family == AF_INET) {
retval = memcmp(a_addr,
b_addr,
a_family == AF_INET ? sizeof(struct in_addr)
: sizeof(struct in6_addr));
} else if (a_family == AF_INET) {
retval = -1;
}
else {
} else {
retval = 1;
}
}
@ -127,40 +119,37 @@ int ipaddress(void *ptr,
return retval;
}
static
int sql_strnatcmp(void *ptr,
int a_len, const void *a_in,
int b_len, const void *b_in)
static int
sql_strnatcmp(
void* ptr, int a_len, const void* a_in, int b_len, const void* b_in)
{
return strnatcmp(a_len, (char*) a_in, b_len, (char*) b_in);
}
static
int sql_strnatcasecmp(void *ptr,
int a_len, const void *a_in,
int b_len, const void *b_in)
static int
sql_strnatcasecmp(
void* ptr, int a_len, const void* a_in, int b_len, const void* b_in)
{
return strnatcasecmp(a_len, (char*) a_in, b_len, (char*) b_in);
}
static
int sql_loglevelcmp(void *ptr,
int a_len, const void *a_in,
int b_len, const void *b_in)
static int
sql_loglevelcmp(
void* ptr, int a_len, const void* a_in, int b_len, const void* b_in)
{
return levelcmp((const char *)a_in, a_len,
(const char *)b_in, b_len);
return levelcmp((const char*) a_in, a_len, (const char*) b_in, b_len);
}
int register_collation_functions(sqlite3 *db)
int
register_collation_functions(sqlite3* db)
{
sqlite3_create_collation(db, "ipaddress", SQLITE_UTF8, nullptr, ipaddress);
sqlite3_create_collation(db, "naturalcase", SQLITE_UTF8, nullptr,
sql_strnatcmp);
sqlite3_create_collation(db, "naturalnocase", SQLITE_UTF8, nullptr,
sql_strnatcasecmp);
sqlite3_create_collation(db, "loglevel", SQLITE_UTF8, nullptr,
sql_loglevelcmp);
sqlite3_create_collation(
db, "naturalcase", SQLITE_UTF8, nullptr, sql_strnatcmp);
sqlite3_create_collation(
db, "naturalnocase", SQLITE_UTF8, nullptr, sql_strnatcasecmp);
sqlite3_create_collation(
db, "loglevel", SQLITE_UTF8, nullptr, sql_loglevelcmp);
return 0;
}

View File

@ -21,48 +21,51 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @file column_namer.cc
*/
#include "config.h"
#include <algorithm>
#include "base/string_util.hh"
#include "sql_util.hh"
#include "base/lnav_log.hh"
#include "column_namer.hh"
bool column_namer::existing_name(const std::string &in_name) const
#include "base/lnav_log.hh"
#include "base/string_util.hh"
#include "config.h"
#include "sql_util.hh"
bool
column_namer::existing_name(const std::string& in_name) const
{
if (std::binary_search(
std::begin(sql_keywords), std::end(sql_keywords), toupper(in_name)))
{
if (std::binary_search(std::begin(sql_keywords),
std::end(sql_keywords),
toupper(in_name))) {
return true;
}
if (std::find(this->cn_builtin_names.begin(),
this->cn_builtin_names.end(),
in_name) != this->cn_builtin_names.end()) {
in_name)
!= this->cn_builtin_names.end())
{
return true;
}
if (std::find(this->cn_names.begin(),
this->cn_names.end(),
in_name) != this->cn_names.end()) {
if (std::find(this->cn_names.begin(), this->cn_names.end(), in_name)
!= this->cn_names.end())
{
return true;
}
return false;
}
std::string column_namer::add_column(const std::string &in_name)
std::string
column_namer::add_column(const std::string& in_name)
{
std::string base_name = in_name, retval;
size_t buf_size;

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
@ -33,8 +33,8 @@
#define lnav_column_namer_hh
#include <string>
#include <vector>
#include <unordered_map>
#include <vector>
class column_namer {
public:

View File

@ -21,32 +21,31 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <vector>
#include "base/fs_util.hh"
#include "base/string_util.hh"
#include "base/injector.hh"
#include "yajlpp/json_ptr.hh"
#include "lnav.hh"
#include "log_format_loader.hh"
#include "shlex.hh"
#include "lnav_util.hh"
#include "sql_util.hh"
#include "lnav_config.hh"
#include "service_tags.hh"
#include "bound_tags.hh"
#include "command_executor.hh"
#include "base/fs_util.hh"
#include "base/injector.hh"
#include "base/string_util.hh"
#include "bound_tags.hh"
#include "config.h"
#include "db_sub_source.hh"
#include "lnav.hh"
#include "lnav_config.hh"
#include "lnav_util.hh"
#include "log_format_loader.hh"
#include "papertrail_proc.hh"
#include "service_tags.hh"
#include "shlex.hh"
#include "sql_util.hh"
#include "yajlpp/json_ptr.hh"
using namespace std;
@ -59,7 +58,8 @@ SELECT count(*) AS total, min(log_line) AS log_line, log_msg_format
ORDER BY total DESC
)";
int sql_progress(const struct log_cursor &lc)
int
sql_progress(const struct log_cursor& lc)
{
static sig_atomic_t sql_counter = 0;
@ -89,7 +89,8 @@ int sql_progress(const struct log_cursor &lc)
return 0;
}
void sql_progress_finished()
void
sql_progress_finished()
{
if (lnav_data.ld_window == nullptr) {
return;
@ -102,9 +103,14 @@ void sql_progress_finished()
lnav_data.ld_views[LNV_DB].redo_search();
}
Result<string, string> execute_from_file(exec_context &ec, const ghc::filesystem::path &path, int line_number, char mode, const string &cmdline);
Result<string, string> execute_from_file(exec_context& ec,
const ghc::filesystem::path& path,
int line_number,
char mode,
const string& cmdline);
Result<string, string> execute_command(exec_context &ec, const string &cmdline)
Result<string, string>
execute_command(exec_context& ec, const string& cmdline)
{
vector<string> args;
@ -117,8 +123,7 @@ Result<string, string> execute_command(exec_context &ec, const string &cmdline)
if ((iter = lnav_commands.find(args[0])) == lnav_commands.end()) {
return ec.make_error("unknown command - {}", args[0]);
}
else {
} else {
return iter->second->c_func(ec, cmdline, args);
}
}
@ -126,7 +131,8 @@ Result<string, string> execute_command(exec_context &ec, const string &cmdline)
return ec.make_error("no command to execute");
}
Result<string, string> execute_sql(exec_context &ec, const string &sql, string &alt_msg)
Result<string, string>
execute_sql(exec_context& ec, const string& sql, string& alt_msg)
{
db_label_source& dls = lnav_data.ld_db_row_source;
auto_mem<sqlite3_stmt> stmt(sqlite3_finalize);
@ -143,8 +149,8 @@ Result<string, string> execute_sql(exec_context &ec, const string &sql, string &
vector<string> args;
split_ws(stmt_str, args);
auto sql_cmd_map = injector::get<
readline_context::command_map_t *, sql_cmd_map_tag>();
auto sql_cmd_map = injector::get<readline_context::command_map_t*,
sql_cmd_map_tag>();
auto cmd_iter = sql_cmd_map->find(args[0]);
if (cmd_iter != sql_cmd_map->end()) {
@ -159,33 +165,29 @@ Result<string, string> execute_sql(exec_context &ec, const string &sql, string &
ec.ec_accumulator->clear();
pair<string, int> source = ec.ec_source.top();
sql_progress_guard progress_guard(sql_progress,
sql_progress_finished,
source.first,
source.second);
sql_progress_guard progress_guard(
sql_progress, sql_progress_finished, source.first, source.second);
gettimeofday(&start_tv, nullptr);
retcode = sqlite3_prepare_v2(lnav_data.ld_db.in(),
stmt_str.c_str(),
-1,
stmt.out(),
nullptr);
retcode = sqlite3_prepare_v2(
lnav_data.ld_db.in(), stmt_str.c_str(), -1, stmt.out(), nullptr);
if (retcode != SQLITE_OK) {
const char* errmsg = sqlite3_errmsg(lnav_data.ld_db);
alt_msg = "";
return ec.make_error("{}", errmsg);
}
else if (stmt == nullptr) {
} else if (stmt == nullptr) {
alt_msg = "";
return ec.make_error("No statement given");
}
#ifdef HAVE_SQLITE3_STMT_READONLY
else if (ec.is_read_only() && !sqlite3_stmt_readonly(stmt.in())) {
else if (ec.is_read_only() && !sqlite3_stmt_readonly(stmt.in()))
{
return ec.make_error(
"modifying statements are not allowed in this context: {}", sql);
}
#endif
else {
else
{
bool done = false;
int param_count;
@ -202,8 +204,7 @@ Result<string, string> execute_sql(exec_context &ec, const string &sql, string &
ov_iter->second.c_str(),
ov_iter->second.length(),
SQLITE_TRANSIENT);
}
else if (name[0] == '$') {
} else if (name[0] == '$') {
const auto& lvars = ec.ec_local_vars.top();
const auto& gvars = ec.ec_global_vars;
map<string, string>::const_iterator local_var, global_var;
@ -216,45 +217,48 @@ Result<string, string> execute_sql(exec_context &ec, const string &sql, string &
getmaxyx(lnav_data.ld_window, lines, cols);
if (strcmp(name, "$LINES") == 0) {
snprintf(buf, sizeof(buf), "%d", lines);
sqlite3_bind_text(stmt.in(), lpc + 1,
buf, -1,
SQLITE_TRANSIENT);
sqlite3_bind_text(
stmt.in(), lpc + 1, buf, -1, SQLITE_TRANSIENT);
} else if (strcmp(name, "$COLS") == 0) {
snprintf(buf, sizeof(buf), "%d", cols);
sqlite3_bind_text(stmt.in(), lpc + 1,
buf, -1,
SQLITE_TRANSIENT);
sqlite3_bind_text(
stmt.in(), lpc + 1, buf, -1, SQLITE_TRANSIENT);
}
}
if ((local_var = lvars.find(&name[1])) != lvars.end()) {
sqlite3_bind_text(stmt.in(), lpc + 1,
local_var->second.c_str(), -1,
sqlite3_bind_text(stmt.in(),
lpc + 1,
local_var->second.c_str(),
-1,
SQLITE_TRANSIENT);
}
else if ((global_var = gvars.find(&name[1])) != gvars.end()) {
sqlite3_bind_text(stmt.in(), lpc + 1,
global_var->second.c_str(), -1,
} else if ((global_var = gvars.find(&name[1])) != gvars.end()) {
sqlite3_bind_text(stmt.in(),
lpc + 1,
global_var->second.c_str(),
-1,
SQLITE_TRANSIENT);
} else if ((env_value = getenv(&name[1])) != nullptr) {
sqlite3_bind_text(
stmt.in(), lpc + 1, env_value, -1, SQLITE_STATIC);
}
else if ((env_value = getenv(&name[1])) != nullptr) {
sqlite3_bind_text(stmt.in(), lpc + 1, env_value, -1, SQLITE_STATIC);
}
}
else if (name[0] == ':' && ec.ec_line_values != nullptr) {
} else if (name[0] == ':' && ec.ec_line_values != nullptr) {
for (auto& lv : *ec.ec_line_values) {
if (lv.lv_meta.lvm_name != &name[1]) {
continue;
}
switch (lv.lv_meta.lvm_kind) {
case value_kind_t::VALUE_BOOLEAN:
sqlite3_bind_int64(stmt.in(), lpc + 1, lv.lv_value.i);
sqlite3_bind_int64(
stmt.in(), lpc + 1, lv.lv_value.i);
break;
case value_kind_t::VALUE_FLOAT:
sqlite3_bind_double(stmt.in(), lpc + 1, lv.lv_value.d);
sqlite3_bind_double(
stmt.in(), lpc + 1, lv.lv_value.d);
break;
case value_kind_t::VALUE_INTEGER:
sqlite3_bind_int64(stmt.in(), lpc + 1, lv.lv_value.i);
sqlite3_bind_int64(
stmt.in(), lpc + 1, lv.lv_value.i);
break;
case value_kind_t::VALUE_NULL:
sqlite3_bind_null(stmt.in(), lpc + 1);
@ -268,8 +272,7 @@ Result<string, string> execute_sql(exec_context &ec, const string &sql, string &
break;
}
}
}
else {
} else {
sqlite3_bind_null(stmt.in(), lpc + 1);
log_warning("Could not bind variable: %s", name);
}
@ -304,8 +307,8 @@ Result<string, string> execute_sql(exec_context &ec, const string &sql, string &
}
}
if (!dls.dls_rows.empty() && !ec.ec_local_vars.empty() &&
!ec.ec_dry_run) {
if (!dls.dls_rows.empty() && !ec.ec_local_vars.empty()
&& !ec.ec_dry_run) {
auto& vars = ec.ec_local_vars.top();
for (unsigned int lpc = 0; lpc < dls.dls_headers.size(); lpc++) {
@ -342,8 +345,7 @@ Result<string, string> execute_sql(exec_context &ec, const string &sql, string &
if (!ec.ec_accumulator->empty()) {
retval = ec.ec_accumulator->get_string();
}
else if (!dls.dls_rows.empty()) {
} else if (!dls.dls_rows.empty()) {
if (lnav_data.ld_flags & LNF_HEADLESS) {
if (ec.ec_local_vars.size() == 1) {
ensure_view(&lnav_data.ld_views[LNV_DB]);
@ -351,14 +353,14 @@ Result<string, string> execute_sql(exec_context &ec, const string &sql, string &
retval = "";
alt_msg = "";
}
else if (dls.dls_rows.size() == 1) {
} else if (dls.dls_rows.size() == 1) {
auto& row = dls.dls_rows[0];
if (dls.dls_headers.size() == 1) {
retval = row[0];
} else {
for (unsigned int lpc = 0; lpc < dls.dls_headers.size(); lpc++) {
for (unsigned int lpc = 0; lpc < dls.dls_headers.size();
lpc++) {
if (lpc > 0) {
retval.append("; ");
}
@ -367,29 +369,31 @@ Result<string, string> execute_sql(exec_context &ec, const string &sql, string &
retval.append(row[lpc]);
}
}
}
else {
} else {
int row_count = dls.dls_rows.size();
char row_count_buf[128];
struct timeval diff_tv;
timersub(&end_tv, &start_tv, &diff_tv);
snprintf(row_count_buf, sizeof(row_count_buf),
ANSI_BOLD("%'d") " row%s matched in "
ANSI_BOLD("%ld.%03ld") " seconds",
snprintf(row_count_buf,
sizeof(row_count_buf),
ANSI_BOLD("%'d") " row%s matched in " ANSI_BOLD(
"%ld.%03ld") " seconds",
row_count,
row_count == 1 ? "" : "s",
diff_tv.tv_sec,
std::max((long) diff_tv.tv_usec / 1000, 1L));
retval = row_count_buf;
alt_msg = HELP_MSG_2(
y, Y,
y,
Y,
"to move forward/backward through query results "
"in the log view");
}
}
#ifdef HAVE_SQLITE3_STMT_READONLY
else if (sqlite3_stmt_readonly(stmt.in())) {
else if (sqlite3_stmt_readonly(stmt.in()))
{
retval = "info: No rows matched";
alt_msg = "";
@ -405,7 +409,10 @@ Result<string, string> execute_sql(exec_context &ec, const string &sql, string &
return Ok(retval);
}
static Result<string, string> execute_file_contents(exec_context &ec, const ghc::filesystem::path &path, bool multiline)
static Result<string, string>
execute_file_contents(exec_context& ec,
const ghc::filesystem::path& path,
bool multiline)
{
static ghc::filesystem::path stdin_path("-");
static ghc::filesystem::path dev_stdin_path("/dev/stdin");
@ -418,8 +425,7 @@ static Result<string, string> execute_file_contents(exec_context &ec, const ghc:
return ec.make_error("stdin has already been consumed");
}
file = stdin;
}
else if ((file = fopen(path.c_str(), "r")) == nullptr) {
} else if ((file = fopen(path.c_str(), "r")) == nullptr) {
return ec.make_error("unable to open file");
}
@ -448,7 +454,8 @@ static Result<string, string> execute_file_contents(exec_context &ec, const ghc:
case ';':
case '|':
if (mode) {
retval = TRY(execute_from_file(ec, path, starting_line_number, mode, trim(cmdline)));
retval = TRY(execute_from_file(
ec, path, starting_line_number, mode, trim(cmdline)));
}
starting_line_number = line_number;
@ -458,17 +465,17 @@ static Result<string, string> execute_file_contents(exec_context &ec, const ghc:
default:
if (multiline) {
cmdline += line;
}
else {
retval = TRY(execute_from_file(ec, path, line_number, ':', line.in()));
} else {
retval = TRY(execute_from_file(
ec, path, line_number, ':', line.in()));
}
break;
}
}
if (mode) {
retval = TRY(execute_from_file(ec, path, starting_line_number, mode, trim(cmdline)));
retval = TRY(execute_from_file(
ec, path, starting_line_number, mode, trim(cmdline)));
}
if (file == stdin) {
@ -483,7 +490,8 @@ static Result<string, string> execute_file_contents(exec_context &ec, const ghc:
return Ok(retval);
}
Result<string, string> execute_file(exec_context &ec, const string &path_and_args, bool multiline)
Result<string, string>
execute_file(exec_context& ec, const string& path_and_args, bool multiline)
{
available_scripts scripts;
vector<string> split_args;
@ -508,8 +516,8 @@ Result<string, string> execute_file(exec_context &ec, const string &path_and_arg
add_ansi_vars(vars);
snprintf(env_arg_name, sizeof(env_arg_name), "%d",
(int) split_args.size() - 1);
snprintf(
env_arg_name, sizeof(env_arg_name), "%d", (int) split_args.size() - 1);
vars["#"] = env_arg_name;
for (size_t lpc = 0; lpc < split_args.size(); lpc++) {
@ -561,21 +569,26 @@ Result<string, string> execute_file(exec_context &ec, const string &path_and_arg
if (!paths_to_exec.empty()) {
for (auto& path_iter : paths_to_exec) {
retval = TRY(
execute_file_contents(ec, path_iter.sm_path, multiline));
retval
= TRY(execute_file_contents(ec, path_iter.sm_path, multiline));
}
}
ec.ec_local_vars.pop();
if (paths_to_exec.empty()) {
return ec.make_error("unknown script -- {} -- {}",
script_name, open_error);
return ec.make_error(
"unknown script -- {} -- {}", script_name, open_error);
}
return Ok(retval);
}
Result<string, string> execute_from_file(exec_context &ec, const ghc::filesystem::path &path, int line_number, char mode, const string &cmdline)
Result<string, string>
execute_from_file(exec_context& ec,
const ghc::filesystem::path& path,
int line_number,
char mode,
const string& cmdline)
{
string retval, alt_msg;
auto _sg = ec.enter_source(path.string(), line_number);
@ -585,9 +598,8 @@ Result<string, string> execute_from_file(exec_context &ec, const ghc::filesystem
retval = TRY(execute_command(ec, cmdline));
break;
case '/':
lnav_data.ld_view_stack.top() | [cmdline] (auto tc) {
tc->execute_search(cmdline.substr(1));
};
lnav_data.ld_view_stack.top() |
[cmdline](auto tc) { tc->execute_search(cmdline.substr(1)); };
break;
case ';':
setup_logline_table(ec);
@ -609,15 +621,16 @@ Result<string, string> execute_from_file(exec_context &ec, const ghc::filesystem
return Ok(retval);
}
Result<string, string> execute_any(exec_context &ec, const string &cmdline_with_mode)
Result<string, string>
execute_any(exec_context& ec, const string& cmdline_with_mode)
{
string retval, alt_msg, cmdline = cmdline_with_mode.substr(1);
auto _cleanup = finally([&ec] {
if (ec.is_read_write() &&
// only rebuild in a script or non-interactive mode so we don't
// block the UI.
(lnav_data.ld_flags & LNF_HEADLESS ||
ec.ec_path_stack.size() > 1)) {
(lnav_data.ld_flags & LNF_HEADLESS || ec.ec_path_stack.size() > 1))
{
rescan_files();
rebuild_indexes_repeatedly();
}
@ -628,9 +641,8 @@ Result<string, string> execute_any(exec_context &ec, const string &cmdline_with_
retval = TRY(execute_command(ec, cmdline));
break;
case '/':
lnav_data.ld_view_stack.top() | [cmdline] (auto tc) {
tc->execute_search(cmdline.substr(1));
};
lnav_data.ld_view_stack.top() |
[cmdline](auto tc) { tc->execute_search(cmdline.substr(1)); };
break;
case ';':
setup_logline_table(ec);
@ -648,7 +660,9 @@ Result<string, string> execute_any(exec_context &ec, const string &cmdline_with_
return Ok(retval);
}
void execute_init_commands(exec_context &ec, vector<pair<Result<string, string>, string> > &msgs)
void
execute_init_commands(exec_context& ec,
vector<pair<Result<string, string>, string> >& msgs)
{
if (lnav_data.ld_cmd_init_done) {
return;
@ -669,13 +683,13 @@ void execute_init_commands(exec_context &ec, vector<pair<Result<string, string>,
msgs.emplace_back(execute_command(ec, cmd.substr(1)), alt_msg);
break;
case '/':
lnav_data.ld_view_stack.top() | [cmd] (auto tc) {
tc->execute_search(cmd.substr(1));
};
lnav_data.ld_view_stack.top() |
[cmd](auto tc) { tc->execute_search(cmd.substr(1)); };
break;
case ';':
setup_logline_table(ec);
msgs.emplace_back(execute_sql(ec, cmd.substr(1), alt_msg), alt_msg);
msgs.emplace_back(execute_sql(ec, cmd.substr(1), alt_msg),
alt_msg);
break;
case '|':
msgs.emplace_back(execute_file(ec, cmd.substr(1)), alt_msg);
@ -691,16 +705,13 @@ void execute_init_commands(exec_context &ec, vector<pair<Result<string, string>,
if (!lnav_data.ld_pt_search.empty()) {
#ifdef HAVE_LIBCURL
auto pt = make_shared<papertrail_proc>(
lnav_data.ld_pt_search.substr(3),
auto pt = make_shared<papertrail_proc>(lnav_data.ld_pt_search.substr(3),
lnav_data.ld_pt_min_time,
lnav_data.ld_pt_max_time);
lnav_data.ld_active_files.fc_file_names[lnav_data.ld_pt_search]
.with_fd(pt->copy_fd());
isc::to<curl_looper&, services::curl_streamer_t>()
.send([pt](auto& clooper) {
clooper.add_request(pt);
});
lnav_data.ld_active_files.fc_file_names[lnav_data.ld_pt_search].with_fd(
pt->copy_fd());
isc::to<curl_looper&, services::curl_streamer_t>().send(
[pt](auto& clooper) { clooper.add_request(pt); });
#endif
}
@ -711,7 +722,8 @@ void execute_init_commands(exec_context &ec, vector<pair<Result<string, string>,
lnav_data.ld_cmd_init_done = true;
}
int sql_callback(exec_context &ec, sqlite3_stmt *stmt)
int
sql_callback(exec_context& ec, sqlite3_stmt* stmt)
{
auto& dls = lnav_data.ld_db_row_source;
@ -735,8 +747,8 @@ int sql_callback(exec_context &ec, sqlite3_stmt *stmt)
string colname = sqlite3_column_name(stmt, lpc);
bool graphable;
graphable = ((type == SQLITE_INTEGER || type == SQLITE_FLOAT) &&
!binary_search(lnav_data.ld_db_key_names.begin(),
graphable = ((type == SQLITE_INTEGER || type == SQLITE_FLOAT)
&& !binary_search(lnav_data.ld_db_key_names.begin(),
lnav_data.ld_db_key_names.end(),
colname));
@ -752,8 +764,10 @@ int sql_callback(exec_context &ec, sqlite3_stmt *stmt)
db_label_source::header_meta& hm = dls.dls_headers[lpc];
dls.push_column(value);
if ((hm.hm_column_type == SQLITE_TEXT ||
hm.hm_column_type == SQLITE_NULL) && hm.hm_sub_type == 0) {
if ((hm.hm_column_type == SQLITE_TEXT
|| hm.hm_column_type == SQLITE_NULL)
&& hm.hm_sub_type == 0)
{
sqlite3_value* raw_value = sqlite3_column_value(stmt, lpc);
switch (sqlite3_value_type(raw_value)) {
@ -768,7 +782,8 @@ int sql_callback(exec_context &ec, sqlite3_stmt *stmt)
return retval;
}
future<string> pipe_callback(exec_context &ec, const string &cmdline, auto_fd &fd)
future<string>
pipe_callback(exec_context& ec, const string& cmdline, auto_fd& fd)
{
auto out = ec.get_output();
@ -791,8 +806,10 @@ future<string> pipe_callback(exec_context &ec, const string &cmdline, auto_fd &f
});
} else {
auto pp = make_shared<piper_proc>(
fd, false, lnav::filesystem::open_temp_file(ghc::filesystem::temp_directory_path() /
"lnav.out.XXXXXX")
fd,
false,
lnav::filesystem::open_temp_file(
ghc::filesystem::temp_directory_path() / "lnav.out.XXXXXX")
.map([](auto pair) {
ghc::filesystem::remove(pair.first);
@ -805,7 +822,8 @@ future<string> pipe_callback(exec_context &ec, const string &cmdline, auto_fd &f
lnav_data.ld_pipers.push_back(pp);
snprintf(desc,
sizeof(desc), "[%d] Output of %s",
sizeof(desc),
"[%d] Output of %s",
exec_count++,
cmdline.c_str());
lnav_data.ld_active_files.fc_file_names[desc]
@ -822,7 +840,8 @@ future<string> pipe_callback(exec_context &ec, const string &cmdline, auto_fd &f
}
}
void add_global_vars(exec_context &ec)
void
add_global_vars(exec_context& ec)
{
for (const auto& iter : lnav_config.lc_global_vars) {
shlex subber(iter.second);
@ -838,7 +857,8 @@ void add_global_vars(exec_context &ec)
}
}
std::string exec_context::get_error_prefix()
std::string
exec_context::get_error_prefix()
{
if (this->ec_source.size() <= 1) {
return "error: ";
@ -849,7 +869,8 @@ std::string exec_context::get_error_prefix()
return fmt::format("{}:{}: error: ", source.first, source.second);
}
void exec_context::set_output(const string &name, FILE *file, int (*closer)(FILE *))
void
exec_context::set_output(const string& name, FILE* file, int (*closer)(FILE*))
{
log_info("redirecting command output to: %s", name.c_str());
this->ec_output_stack.back().second | [](auto out) {
@ -857,10 +878,12 @@ void exec_context::set_output(const string &name, FILE *file, int (*closer)(FILE
out.second(out.first);
}
};
this->ec_output_stack.back() = std::make_pair(name, std::make_pair(file, closer));
this->ec_output_stack.back()
= std::make_pair(name, std::make_pair(file, closer));
}
void exec_context::clear_output()
void
exec_context::clear_output()
{
log_info("redirecting command output to screen");
this->ec_output_stack.back().second | [](auto out) {
@ -876,8 +899,8 @@ exec_context::exec_context(std::vector<logline_value> *line_values,
pipe_callback_t pipe_callback)
: ec_line_values(line_values),
ec_accumulator(std::make_unique<attr_line_t>()),
ec_sql_callback(sql_callback),
ec_pipe_callback(pipe_callback) {
ec_sql_callback(sql_callback), ec_pipe_callback(pipe_callback)
{
this->ec_local_vars.push(std::map<std::string, std::string>());
this->ec_path_stack.emplace_back(".");
this->ec_source.emplace("command", 1);
@ -887,7 +910,8 @@ exec_context::exec_context(std::vector<logline_value> *line_values,
exec_context::output_guard::output_guard(exec_context& context,
std::string name,
const nonstd::optional<output_t>& file)
: sg_context(context) {
: sg_context(context)
{
if (file) {
log_info("redirecting command output to: %s", name.c_str());
}

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@ -30,16 +30,19 @@
#ifndef LNAV_COMMAND_EXECUTOR_H
#define LNAV_COMMAND_EXECUTOR_H
#include <sqlite3.h>
#include <future>
#include <stack>
#include <string>
#include "fmt/format.h"
#include "optional.hpp"
#include <sqlite3.h>
#include "auto_fd.hh"
#include "bookmarks.hh"
#include "fmt/format.h"
#include "ghc/filesystem.hpp"
#include "optional.hpp"
#include "shlex.resolver.hh"
#include "vis_line.hh"
struct exec_context;
class attr_line_t;
@ -48,8 +51,9 @@ class logline_value;
typedef int (*sql_callback_t)(exec_context& ec, sqlite3_stmt* stmt);
int sql_callback(exec_context& ec, sqlite3_stmt* stmt);
typedef std::future<std::string> (*pipe_callback_t)(
exec_context &ec, const std::string &cmdline, auto_fd &fd);
typedef std::future<std::string> (*pipe_callback_t)(exec_context& ec,
const std::string& cmdline,
auto_fd& fd);
struct exec_context {
enum class perm_t {
@ -63,15 +67,18 @@ struct exec_context {
sql_callback_t sql_callback = ::sql_callback,
pipe_callback_t pipe_callback = nullptr);
bool is_read_write() const {
bool is_read_write() const
{
return this->ec_perms == perm_t::READ_WRITE;
}
bool is_read_only() const {
bool is_read_only() const
{
return this->ec_perms == perm_t::READ_ONLY;
}
exec_context& with_perms(perm_t perms) {
exec_context& with_perms(perm_t perms)
{
this->ec_perms = perms;
return *this;
}
@ -79,16 +86,19 @@ struct exec_context {
std::string get_error_prefix();
template<typename... Args>
Result<std::string, std::string> make_error(
fmt::string_view format_str, const Args& ...args) {
return Err(this->get_error_prefix() +
fmt::vformat(format_str, fmt::make_format_args(args...)));
Result<std::string, std::string> make_error(fmt::string_view format_str,
const Args&... args)
{
return Err(this->get_error_prefix()
+ fmt::vformat(format_str, fmt::make_format_args(args...)));
}
nonstd::optional<FILE *> get_output() {
nonstd::optional<FILE*> get_output()
{
for (auto iter = this->ec_output_stack.rbegin();
iter != this->ec_output_stack.rend();
++iter) {
++iter)
{
if (iter->second && (*iter->second).first) {
return (*iter->second).first;
}
@ -102,11 +112,10 @@ struct exec_context {
void clear_output();
struct source_guard {
source_guard(exec_context &context) : sg_context(context) {
source_guard(exec_context& context) : sg_context(context) {}
}
~source_guard() {
~source_guard()
{
this->sg_context.ec_source.pop();
}
@ -116,19 +125,22 @@ struct exec_context {
struct output_guard {
explicit output_guard(exec_context& context,
std::string name = "default",
const nonstd::optional<output_t>& file = nonstd::nullopt);
const nonstd::optional<output_t>& file
= nonstd::nullopt);
~output_guard();
exec_context& sg_context;
};
source_guard enter_source(const std::string& path, int line_number) {
source_guard enter_source(const std::string& path, int line_number)
{
this->ec_source.emplace(path, line_number);
return {*this};
}
scoped_resolver create_resolver() {
scoped_resolver create_resolver()
{
return {
&this->ec_local_vars.top(),
&this->ec_global_vars,
@ -146,7 +158,8 @@ struct exec_context {
std::vector<ghc::filesystem::path> ec_path_stack;
std::stack<std::pair<std::string, int>> ec_source;
std::vector<std::pair<std::string, nonstd::optional<output_t>>> ec_output_stack;
std::vector<std::pair<std::string, nonstd::optional<output_t>>>
ec_output_stack;
std::unique_ptr<attr_line_t> ec_accumulator;
@ -154,15 +167,25 @@ struct exec_context {
pipe_callback_t ec_pipe_callback;
};
Result<std::string, std::string> execute_command(exec_context &ec, const std::string &cmdline);
Result<std::string, std::string> execute_command(exec_context& ec,
const std::string& cmdline);
Result<std::string, std::string> execute_sql(exec_context &ec, const std::string &sql, std::string &alt_msg);
Result<std::string, std::string> execute_file(exec_context &ec, const std::string &path_and_args, bool multiline = true);
Result<std::string, std::string> execute_any(exec_context &ec, const std::string &cmdline);
void execute_init_commands(exec_context &ec, std::vector<std::pair<Result<std::string, std::string>, std::string> > &msgs);
Result<std::string, std::string> execute_sql(exec_context& ec,
const std::string& sql,
std::string& alt_msg);
Result<std::string, std::string> execute_file(exec_context& ec,
const std::string& path_and_args,
bool multiline = true);
Result<std::string, std::string> execute_any(exec_context& ec,
const std::string& cmdline);
void execute_init_commands(
exec_context& ec,
std::vector<std::pair<Result<std::string, std::string>, std::string>>&
msgs);
std::future<std::string> pipe_callback(
exec_context &ec, const std::string &cmdline, auto_fd &fd);
std::future<std::string> pipe_callback(exec_context& ec,
const std::string& cmdline,
auto_fd& fd);
int sql_progress(const struct log_cursor& lc);
void sql_progress_finished();

View File

@ -21,18 +21,18 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @file curl_looper.cc
*/
#include "config.h"
#include <algorithm>
#include "config.h"
#if defined(HAVE_LIBCURL)
# include <curl/multi.h>
@ -41,25 +41,26 @@
using namespace std;
struct curl_request_eq {
explicit curl_request_eq(const std::string &name) : cre_name(name) {
};
explicit curl_request_eq(const std::string& name) : cre_name(name){};
bool operator()(const std::shared_ptr<curl_request>& cr) const {
bool operator()(const std::shared_ptr<curl_request>& cr) const
{
return this->cre_name == cr->get_name();
};
bool operator()(const pair<mstime_t, std::shared_ptr<curl_request>> &pair) const {
bool operator()(
const pair<mstime_t, std::shared_ptr<curl_request>>& pair) const
{
return this->cre_name == pair.second->get_name();
};
const std::string& cre_name;
};
int curl_request::debug_cb(CURL *handle,
curl_infotype type,
char *data,
size_t size,
void *userp) {
int
curl_request::debug_cb(
CURL* handle, curl_infotype type, char* data, size_t size, void* userp)
{
curl_request* cr = (curl_request*) userp;
bool write_to_log;
@ -71,8 +72,7 @@ int curl_request::debug_cb(CURL *handle,
case CURLINFO_HEADER_OUT:
if (lnav_log_level == lnav_log_level_t::TRACE) {
write_to_log = true;
}
else {
} else {
write_to_log = false;
}
break;
@ -91,7 +91,8 @@ int curl_request::debug_cb(CURL *handle,
return 0;
}
void curl_looper::loop_body()
void
curl_looper::loop_body()
{
mstime_t current_time = getmstime();
@ -104,7 +105,8 @@ void curl_looper::loop_body()
this->requeue_requests(current_time + 5);
}
void curl_looper::perform_io()
void
curl_looper::perform_io()
{
if (this->cl_handle_to_request.empty()) {
return;
@ -114,43 +116,41 @@ void curl_looper::perform_io()
auto timeout = this->compute_timeout(current_time);
int running_handles;
curl_multi_wait(this->cl_curl_multi,
nullptr,
0,
timeout.count(),
nullptr);
curl_multi_wait(this->cl_curl_multi, nullptr, 0, timeout.count(), nullptr);
curl_multi_perform(this->cl_curl_multi, &running_handles);
}
void curl_looper::requeue_requests(mstime_t up_to_time)
void
curl_looper::requeue_requests(mstime_t up_to_time)
{
while (!this->cl_poll_queue.empty()
&& this->cl_poll_queue.front().first <= up_to_time)
{
while (!this->cl_poll_queue.empty() &&
this->cl_poll_queue.front().first <= up_to_time) {
auto cr = this->cl_poll_queue.front().second;
log_debug("%s:polling request is ready again -- %p",
cr->get_name().c_str(), cr.get());
cr->get_name().c_str(),
cr.get());
this->cl_handle_to_request[cr->get_handle()] = cr;
curl_multi_add_handle(this->cl_curl_multi, cr->get_handle());
this->cl_poll_queue.erase(this->cl_poll_queue.begin());
}
}
void curl_looper::check_for_new_requests() {
void
curl_looper::check_for_new_requests()
{
while (!this->cl_new_requests.empty()) {
auto cr = this->cl_new_requests.back();
log_info("%s:new curl request %p",
cr->get_name().c_str(),
cr.get());
log_info("%s:new curl request %p", cr->get_name().c_str(), cr.get());
this->cl_handle_to_request[cr->get_handle()] = cr;
curl_multi_add_handle(this->cl_curl_multi, cr->get_handle());
this->cl_new_requests.pop_back();
}
while (!this->cl_close_requests.empty()) {
const std::string& name = this->cl_close_requests.back();
auto all_iter = find_if(
this->cl_all_requests.begin(),
auto all_iter = find_if(this->cl_all_requests.begin(),
this->cl_all_requests.end(),
curl_request_eq(name));
@ -158,13 +158,12 @@ void curl_looper::check_for_new_requests() {
if (all_iter != this->cl_all_requests.end()) {
auto cr = *all_iter;
log_info("%s:closing request -- %p",
cr->get_name().c_str(), cr.get());
log_info(
"%s:closing request -- %p", cr->get_name().c_str(), cr.get());
(*all_iter)->close();
auto act_iter = this->cl_handle_to_request.find(cr->get_handle());
if (act_iter != this->cl_handle_to_request.end()) {
curl_multi_remove_handle(this->cl_curl_multi,
cr->get_handle());
curl_multi_remove_handle(this->cl_curl_multi, cr->get_handle());
this->cl_handle_to_request.erase(act_iter);
}
auto poll_iter = find_if(this->cl_poll_queue.begin(),
@ -174,8 +173,7 @@ void curl_looper::check_for_new_requests() {
this->cl_poll_queue.erase(poll_iter);
}
this->cl_all_requests.erase(all_iter);
}
else {
} else {
log_error("Unable to find request with the name -- %s",
name.c_str());
}
@ -184,13 +182,14 @@ void curl_looper::check_for_new_requests() {
}
}
void curl_looper::check_for_finished_requests()
void
curl_looper::check_for_finished_requests()
{
CURLMsg* msg;
int msgs_left;
while ((msg = curl_multi_info_read(this->cl_curl_multi, &msgs_left)) !=
nullptr) {
while ((msg = curl_multi_info_read(this->cl_curl_multi, &msgs_left))
!= nullptr) {
if (msg->msg != CURLMSG_DONE) {
continue;
}
@ -207,15 +206,15 @@ void curl_looper::check_for_finished_requests()
delay_ms = cr->complete(msg->data.result);
if (delay_ms < 0) {
log_info("%s:curl_request %p finished, deleting...",
cr->get_name().c_str(), cr.get());
cr->get_name().c_str(),
cr.get());
auto all_iter = find(this->cl_all_requests.begin(),
this->cl_all_requests.end(),
cr);
if (all_iter != this->cl_all_requests.end()) {
this->cl_all_requests.erase(all_iter);
}
}
else {
} else {
log_debug("%s:curl_request %p is polling, requeueing in %d",
cr->get_name().c_str(),
cr.get(),
@ -227,16 +226,18 @@ void curl_looper::check_for_finished_requests()
}
}
std::chrono::milliseconds curl_looper::compute_timeout(mstime_t current_time) const
std::chrono::milliseconds
curl_looper::compute_timeout(mstime_t current_time) const
{
std::chrono::milliseconds retval = 1s;
if (!this->cl_handle_to_request.empty()) {
retval = 1ms;
} else if (!this->cl_poll_queue.empty()) {
retval = std::max(
1ms,
std::chrono::milliseconds(this->cl_poll_queue.front().first - current_time));
retval
= std::max(1ms,
std::chrono::milliseconds(
this->cl_poll_queue.front().first - current_time));
}
ensure(retval.count() > 0);

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
@ -32,6 +32,8 @@
#ifndef curl_looper_hh
#define curl_looper_hh
#include "config.h"
#include <atomic>
#include <map>
#include <string>
@ -46,8 +48,7 @@ typedef int CURLcode;
class curl_request {
public:
curl_request(const std::string &name) {
};
curl_request(const std::string& name){};
};
class curl_looper : public isc::service<curl_looper> {
@ -60,9 +61,9 @@ public:
};
#else
# include <condition_variable>
# include <mutex>
# include <thread>
#include <condition_variable>
# include <curl/curl.h>
@ -73,18 +74,19 @@ public:
class curl_request {
public:
curl_request(std::string name)
: cr_name(std::move(name)),
cr_open(true),
cr_handle(curl_easy_cleanup),
cr_completions(0) {
: cr_name(std::move(name)), cr_open(true), cr_handle(curl_easy_cleanup),
cr_completions(0)
{
this->cr_handle.reset(curl_easy_init());
curl_easy_setopt(this->cr_handle, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt(this->cr_handle, CURLOPT_ERRORBUFFER, this->cr_error_buffer);
curl_easy_setopt(
this->cr_handle, CURLOPT_ERRORBUFFER, this->cr_error_buffer);
curl_easy_setopt(this->cr_handle, CURLOPT_DEBUGFUNCTION, debug_cb);
curl_easy_setopt(this->cr_handle, CURLOPT_DEBUGDATA, this);
curl_easy_setopt(this->cr_handle, CURLOPT_VERBOSE, 1);
if (getenv("SSH_AUTH_SOCK") != nullptr) {
curl_easy_setopt(this->cr_handle, CURLOPT_SSH_AUTH_TYPES,
curl_easy_setopt(this->cr_handle,
CURLOPT_SSH_AUTH_TYPES,
# ifdef CURLSSH_AUTH_AGENT
CURLSSH_AUTH_AGENT |
# endif
@ -94,47 +96,52 @@ public:
virtual ~curl_request() = default;
const std::string &get_name() const {
const std::string& get_name() const
{
return this->cr_name;
};
virtual void close() {
virtual void close()
{
this->cr_open = false;
};
bool is_open() const {
bool is_open() const
{
return this->cr_open;
};
CURL *get_handle() const {
CURL* get_handle() const
{
return this->cr_handle;
};
int get_completions() const {
int get_completions() const
{
return this->cr_completions;
};
virtual long complete(CURLcode result) {
virtual long complete(CURLcode result)
{
double total_time = 0, download_size = 0, download_speed = 0;
this->cr_completions += 1;
curl_easy_getinfo(this->cr_handle, CURLINFO_TOTAL_TIME, &total_time);
log_debug("%s: total_time=%f", this->cr_name.c_str(), total_time);
curl_easy_getinfo(this->cr_handle, CURLINFO_SIZE_DOWNLOAD, &download_size);
curl_easy_getinfo(
this->cr_handle, CURLINFO_SIZE_DOWNLOAD, &download_size);
log_debug("%s: download_size=%f", this->cr_name.c_str(), download_size);
curl_easy_getinfo(this->cr_handle, CURLINFO_SPEED_DOWNLOAD, &download_speed);
log_debug("%s: download_speed=%f", this->cr_name.c_str(), download_speed);
curl_easy_getinfo(
this->cr_handle, CURLINFO_SPEED_DOWNLOAD, &download_speed);
log_debug(
"%s: download_speed=%f", this->cr_name.c_str(), download_speed);
return -1;
};
protected:
static int debug_cb(CURL *handle,
curl_infotype type,
char *data,
size_t size,
void *userp);
static int debug_cb(
CURL* handle, curl_infotype type, char* data, size_t size, void* userp);
const std::string cr_name;
bool cr_open;
@ -145,12 +152,13 @@ protected:
class curl_looper : public isc::service<curl_looper> {
public:
curl_looper()
: cl_curl_multi(curl_multi_cleanup) {
curl_looper() : cl_curl_multi(curl_multi_cleanup)
{
this->cl_curl_multi.reset(curl_multi_init());
};
void process_all() {
void process_all()
{
this->check_for_new_requests();
this->requeue_requests(LONG_MAX);
@ -162,14 +170,16 @@ public:
}
};
void add_request(const std::shared_ptr<curl_request>& cr) {
void add_request(const std::shared_ptr<curl_request>& cr)
{
require(cr != nullptr);
this->cl_all_requests.emplace_back(cr);
this->cl_new_requests.emplace_back(cr);
};
void close_request(const std::string &name) {
void close_request(const std::string& name)
{
this->cl_close_requests.emplace_back(name);
};
@ -181,14 +191,16 @@ private:
void check_for_new_requests();
void check_for_finished_requests();
void requeue_requests(mstime_t up_to_time);
std::chrono::milliseconds compute_timeout(mstime_t current_time) const override;
std::chrono::milliseconds compute_timeout(
mstime_t current_time) const override;
auto_mem<CURLM> cl_curl_multi;
std::vector<std::shared_ptr<curl_request> > cl_all_requests;
std::vector<std::shared_ptr<curl_request> > cl_new_requests;
std::vector<std::string> cl_close_requests;
std::map<CURL*, std::shared_ptr<curl_request> > cl_handle_to_request;
std::vector<std::pair<mstime_t, std::shared_ptr<curl_request>>> cl_poll_queue;
std::vector<std::pair<mstime_t, std::shared_ptr<curl_request> > >
cl_poll_queue;
};
#endif

View File

@ -21,19 +21,19 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <algorithm>
#include "spookyhash/SpookyV2.h"
#include "data_parser.hh"
#include "config.h"
#include "spookyhash/SpookyV2.h"
using namespace std;
data_format data_parser::FORMAT_SEMI("semi", DT_COMMA, DT_SEMI);
@ -42,19 +42,19 @@ data_format data_parser::FORMAT_PLAIN("plain", DT_INVALID, DT_INVALID);
data_parser::data_parser(data_scanner* ds)
: dp_errors("dp_errors", __FILE__, __LINE__),
dp_pairs("dp_pairs", __FILE__, __LINE__),
dp_msg_format(nullptr),
dp_msg_format_begin(ds->get_input().pi_offset),
dp_scanner(ds)
dp_pairs("dp_pairs", __FILE__, __LINE__), dp_msg_format(nullptr),
dp_msg_format_begin(ds->get_input().pi_offset), dp_scanner(ds)
{
if (TRACE_FILE != nullptr) {
fprintf(TRACE_FILE, "input %s\n", ds->get_input().get_string());
}
}
void data_parser::pairup(data_parser::schema_id_t *schema,
void
data_parser::pairup(data_parser::schema_id_t* schema,
data_parser::element_list_t& pairs_out,
data_parser::element_list_t &in_list, int group_depth)
data_parser::element_list_t& in_list,
int group_depth)
{
element_list_t ELEMENT_LIST_T(el_stack), ELEMENT_LIST_T(free_row),
ELEMENT_LIST_T(key_comps), ELEMENT_LIST_T(value),
@ -67,14 +67,12 @@ void data_parser::pairup(data_parser::schema_id_t *schema,
FORMAT_TRACE(in_list);
for (auto iter = in_list.begin();
iter != in_list.end();
++iter) {
for (auto iter = in_list.begin(); iter != in_list.end(); ++iter) {
if (iter->e_token == DNT_GROUP) {
element_list_t ELEMENT_LIST_T(group_pairs);
this->pairup(nullptr, group_pairs, *iter->e_sub_elements,
group_depth + 1);
this->pairup(
nullptr, group_pairs, *iter->e_sub_elements, group_depth + 1);
if (!group_pairs.empty()) {
iter->assign_elements(group_pairs);
}
@ -87,15 +85,13 @@ void data_parser::pairup(data_parser::schema_id_t *schema,
el_stack.PUSH_BACK(*iter);
}
} else if (iter->e_token == in_list.el_format.df_terminator) {
this->end_of_value(el_stack, key_comps, value, in_list,
group_depth);
this->end_of_value(
el_stack, key_comps, value, in_list, group_depth);
key_comps.PUSH_BACK(*iter);
} else if (iter->e_token == in_list.el_format.df_qualifier) {
value.SPLICE(value.end(),
key_comps,
key_comps.begin(),
key_comps.end());
value.SPLICE(
value.end(), key_comps, key_comps.begin(), key_comps.end());
strip(value, element_if(DT_WHITE));
if (!value.empty()) {
el_stack.PUSH_BACK(element(value, DNT_VALUE));
@ -107,8 +103,7 @@ void data_parser::pairup(data_parser::schema_id_t *schema,
if (!key_comps.empty()) {
do {
--key_iter;
if (key_iter->e_token ==
in_list.el_format.df_appender) {
if (key_iter->e_token == in_list.el_format.df_appender) {
++key_iter;
value.SPLICE(value.end(),
key_comps,
@ -116,8 +111,8 @@ void data_parser::pairup(data_parser::schema_id_t *schema,
key_iter);
key_comps.POP_FRONT();
found = true;
} else if (key_iter->e_token ==
in_list.el_format.df_terminator) {
} else if (key_iter->e_token
== in_list.el_format.df_terminator) {
std::vector<element> key_copy;
value.SPLICE(value.end(),
@ -148,24 +143,21 @@ void data_parser::pairup(data_parser::schema_id_t *schema,
if (!found && !el_stack.empty() && !key_comps.empty()) {
element_list_t::iterator value_iter;
if (el_stack.size() > 1 &&
in_list.el_format.df_appender != DT_INVALID &&
in_list.el_format.df_terminator != DT_INVALID) {
if (el_stack.size() > 1
&& in_list.el_format.df_appender != DT_INVALID
&& in_list.el_format.df_terminator != DT_INVALID)
{
/* If we're expecting a terminator and haven't found it */
/* then this is part of the value. */
continue;
}
value.SPLICE(value.end(),
key_comps,
key_comps.begin(),
key_comps.end());
value.SPLICE(
value.end(), key_comps, key_comps.begin(), key_comps.end());
value_iter = value.end();
std::advance(value_iter, -1);
key_comps.SPLICE(key_comps.begin(),
value,
value_iter,
value.end());
key_comps.SPLICE(
key_comps.begin(), value, value_iter, value.end());
key_comps.resize(1);
}
@ -198,8 +190,8 @@ void data_parser::pairup(data_parser::schema_id_t *schema,
// Only perform the free-row logic at the top level, if we're in a group
// assume it is a list.
if (group_depth < 1 && el_stack.empty()) {
free_row.SPLICE(free_row.begin(),
key_comps, key_comps.begin(), key_comps.end());
free_row.SPLICE(
free_row.begin(), key_comps, key_comps.begin(), key_comps.end());
} else {
this->end_of_value(el_stack, key_comps, value, in_list, group_depth);
}
@ -216,9 +208,8 @@ void data_parser::pairup(data_parser::schema_id_t *schema,
element_list_t ELEMENT_LIST_T(free_pair_subs);
struct element blank;
blank.e_capture.c_begin = blank.e_capture.c_end =
el_stack.front().e_capture.
c_begin;
blank.e_capture.c_begin = blank.e_capture.c_end
= el_stack.front().e_capture.c_begin;
blank.e_token = DNT_KEY;
free_pair_subs.PUSH_BACK(blank);
free_pair_subs.PUSH_BACK(el_stack.front());
@ -240,8 +231,8 @@ void data_parser::pairup(data_parser::schema_id_t *schema,
if (schema != nullptr) {
size_t key_len;
const char *key_val =
this->get_element_string(el_stack.front(), key_len);
const char* key_val
= this->get_element_string(el_stack.front(), key_len);
context.Update(key_val, key_len);
}
@ -249,9 +240,8 @@ void data_parser::pairup(data_parser::schema_id_t *schema,
element_list_t ELEMENT_LIST_T(free_pair_subs);
struct element blank;
blank.e_capture.c_begin = blank.e_capture.c_end =
free_row.front().e_capture.
c_begin;
blank.e_capture.c_begin = blank.e_capture.c_end
= free_row.front().e_capture.c_begin;
blank.e_token = DNT_KEY;
free_pair_subs.PUSH_BACK(blank);
free_pair_subs.PUSH_BACK(free_row.front());
@ -266,10 +256,8 @@ void data_parser::pairup(data_parser::schema_id_t *schema,
has_value = true;
}
pair_subs.SPLICE(pair_subs.begin(),
el_stack,
el_stack.begin(),
kv_iter);
pair_subs.SPLICE(
pair_subs.begin(), el_stack, el_stack.begin(), kv_iter);
if (!has_value) {
element_list_t ELEMENT_LIST_T(blank_value);
@ -278,10 +266,11 @@ void data_parser::pairup(data_parser::schema_id_t *schema,
struct element blank;
blank.e_token = DT_QUOTED_STRING;
blank.e_capture.c_begin = blank.e_capture.c_end =
pair_subs.front().e_capture.c_end;
if ((blank.e_capture.c_begin >= 0) &&
((size_t) blank.e_capture.c_begin < pi.pi_length)) {
blank.e_capture.c_begin = blank.e_capture.c_end
= pair_subs.front().e_capture.c_end;
if ((blank.e_capture.c_begin >= 0)
&& ((size_t) blank.e_capture.c_begin < pi.pi_length))
{
switch (str[blank.e_capture.c_begin]) {
case '=':
case ':':
@ -301,9 +290,9 @@ void data_parser::pairup(data_parser::schema_id_t *schema,
element& pair = pairs_out.front();
element& evalue = pair.e_sub_elements->back();
if (evalue.e_token == DNT_VALUE &&
evalue.e_sub_elements != nullptr &&
evalue.e_sub_elements->size() > 1) {
if (evalue.e_token == DNT_VALUE && evalue.e_sub_elements != nullptr
&& evalue.e_sub_elements->size() > 1)
{
element_list_t::iterator next_sub;
next_sub = pair.e_sub_elements->begin();
@ -355,8 +344,8 @@ void data_parser::pairup(data_parser::schema_id_t *schema,
element_list_t ELEMENT_LIST_T(pair_subs);
struct element blank;
blank.e_capture.c_begin = blank.e_capture.c_end =
free_row.front().e_capture.c_begin;
blank.e_capture.c_begin = blank.e_capture.c_end
= free_row.front().e_capture.c_begin;
blank.e_token = DNT_KEY;
pair_subs.PUSH_BACK(blank);
pair_subs.PUSH_BACK(free_row.front());
@ -367,17 +356,15 @@ void data_parser::pairup(data_parser::schema_id_t *schema,
// use the token ID since some columns values might vary
// between rows.
context.Update(" ", 1);
}
break;
} break;
default: {
size_t key_len;
const char *key_val = this->get_element_string(
free_row.front(), key_len);
const char* key_val
= this->get_element_string(free_row.front(), key_len);
context.Update(key_val, key_len);
}
break;
} break;
}
free_row.POP_FRONT();
@ -388,8 +375,8 @@ void data_parser::pairup(data_parser::schema_id_t *schema,
element_list_t ELEMENT_LIST_T(pair_subs);
struct element blank;
blank.e_capture.c_begin = blank.e_capture.c_end =
prefix.front().e_capture.c_begin;
blank.e_capture.c_begin = blank.e_capture.c_end
= prefix.front().e_capture.c_begin;
blank.e_token = DNT_KEY;
pair_subs.PUSH_BACK(blank);
pair_subs.PUSH_BACK(prefix.front());
@ -426,7 +413,8 @@ void data_parser::pairup(data_parser::schema_id_t *schema,
}
}
void data_parser::discover_format()
void
data_parser::discover_format()
{
pcre_context_static<30> pc;
std::stack<discover_format_state> state_stack;
@ -486,15 +474,16 @@ void data_parser::discover_format()
auto riter = this->dp_group_stack.rbegin();
++riter;
state_stack.top().finalize();
this->dp_group_stack.back().el_format =
state_stack.top().dfs_format;
this->dp_group_stack.back().el_format
= state_stack.top().dfs_format;
state_stack.pop();
if (!this->dp_group_stack.back().empty()) {
(*riter).PUSH_BACK(element(this->dp_group_stack.back(),
DNT_GROUP));
(*riter).PUSH_BACK(
element(this->dp_group_stack.back(), DNT_GROUP));
} else {
(*riter).PUSH_BACK(element());
riter->back().e_capture.c_begin = elem.e_capture.c_begin;
riter->back().e_capture.c_begin
= elem.e_capture.c_begin;
riter->back().e_capture.c_end = elem.e_capture.c_begin;
riter->back().e_token = DNT_GROUP;
riter->back().assign_elements(
@ -519,10 +508,10 @@ void data_parser::discover_format()
++riter;
if (!this->dp_group_stack.back().empty()) {
state_stack.top().finalize();
this->dp_group_stack.back().el_format = state_stack.top().dfs_format;
this->dp_group_stack.back().el_format
= state_stack.top().dfs_format;
state_stack.pop();
(*riter).PUSH_BACK(element(this->dp_group_stack.back(),
DNT_GROUP));
(*riter).PUSH_BACK(element(this->dp_group_stack.back(), DNT_GROUP));
}
this->dp_group_stack.pop_back();
}
@ -531,7 +520,8 @@ void data_parser::discover_format()
this->dp_group_stack.back().el_format = state_stack.top().dfs_format;
}
void data_parser::end_of_value(data_parser::element_list_t &el_stack,
void
data_parser::end_of_value(data_parser::element_list_t& el_stack,
data_parser::element_list_t& key_comps,
data_parser::element_list_t& value,
const data_parser::element_list_t& in_list,
@ -543,24 +533,24 @@ void data_parser::end_of_value(data_parser::element_list_t &el_stack,
value.remove_if(element_if(DT_COMMA));
strip(key_comps, element_if(DT_WHITE));
strip(value, element_if(DT_WHITE));
if ((el_stack.empty() || el_stack.back().e_token != DNT_KEY) &&
value.empty() && key_comps.size() > 1 &&
(key_comps.front().e_token == DT_WORD ||
key_comps.front().e_token == DT_SYMBOL)) {
if ((el_stack.empty() || el_stack.back().e_token != DNT_KEY)
&& value.empty() && key_comps.size() > 1
&& (key_comps.front().e_token == DT_WORD
|| key_comps.front().e_token == DT_SYMBOL))
{
element_list_t::iterator key_iter, key_end;
bool found_value = false;
int word_count = 0;
key_iter = key_comps.begin();
key_end = key_comps.begin();
for (; key_iter != key_comps.end(); ++key_iter) {
if (key_iter->e_token == DT_WORD ||
key_iter->e_token == DT_SYMBOL) {
if (key_iter->e_token == DT_WORD || key_iter->e_token == DT_SYMBOL)
{
word_count += 1;
if (found_value) {
key_end = key_comps.begin();
}
} else if (key_iter->e_token == DT_WHITE) {
} else {
if (!found_value) {
key_end = key_iter;
@ -571,20 +561,15 @@ void data_parser::end_of_value(data_parser::element_list_t &el_stack,
if (word_count != 1) {
key_end = key_comps.begin();
}
value.SPLICE(value.end(),
key_comps,
key_end,
key_comps.end());
value.SPLICE(value.end(), key_comps, key_end, key_comps.end());
strip(key_comps, element_if(DT_WHITE));
if (!key_comps.empty()) {
el_stack.PUSH_BACK(element(key_comps, DNT_KEY, false));
}
key_comps.CLEAR();
} else {
value.SPLICE(value.end(),
key_comps,
key_comps.begin(),
key_comps.end());
value.SPLICE(
value.end(), key_comps, key_comps.begin(), key_comps.end());
}
strip(value, element_if(DT_WHITE));
strip(value, element_if(DT_COLON));
@ -602,13 +587,13 @@ void data_parser::end_of_value(data_parser::element_list_t &el_stack,
value.CLEAR();
}
void data_parser::parse()
void
data_parser::parse()
{
this->discover_format();
this->pairup(&this->dp_schema_id,
this->dp_pairs,
this->dp_group_stack.front());
this->pairup(
&this->dp_schema_id, this->dp_pairs, this->dp_group_stack.front());
}
std::string
@ -623,8 +608,8 @@ std::string
data_parser::get_string_up_to_value(const data_parser::element& elem)
{
pcre_input& pi = this->dp_scanner->get_input();
const element &val_elem = elem.e_token == DNT_PAIR ?
elem.e_sub_elements->back() : elem;
const element& val_elem
= elem.e_token == DNT_PAIR ? elem.e_sub_elements->back() : elem;
if (this->dp_msg_format_begin <= val_elem.e_capture.c_begin) {
pcre_context::capture_t leading_and_key = pcre_context::capture_t(
@ -658,7 +643,8 @@ data_parser::get_string_up_to_value(const data_parser::element &elem)
return "";
}
const char *data_parser::get_element_string(const data_parser::element &elem,
const char*
data_parser::get_element_string(const data_parser::element& elem,
size_t& len_out)
{
pcre_input& pi = this->dp_scanner->get_input();
@ -667,10 +653,11 @@ const char *data_parser::get_element_string(const data_parser::element &elem,
return pi.get_substr_start(&elem.e_capture);
}
void data_parser::print(FILE *out, data_parser::element_list_t &el)
void
data_parser::print(FILE* out, data_parser::element_list_t& el)
{
fprintf(out, " %s\n",
this->dp_scanner->get_input().get_string());
fprintf(
out, " %s\n", this->dp_scanner->get_input().get_string());
for (auto& iter : el) {
iter.print(out, this->dp_scanner->get_input());
}
@ -678,8 +665,8 @@ void data_parser::print(FILE *out, data_parser::element_list_t &el)
FILE* data_parser::TRACE_FILE;
data_format_state_t dfs_prefix_next(data_format_state_t state,
data_token_t next_token)
data_format_state_t
dfs_prefix_next(data_format_state_t state, data_token_t next_token)
{
data_format_state_t retval = state;
@ -722,8 +709,8 @@ data_format_state_t dfs_prefix_next(data_format_state_t state,
return retval;
}
data_format_state_t dfs_semi_next(data_format_state_t state,
data_token_t next_token)
data_format_state_t
dfs_semi_next(data_format_state_t state, data_token_t next_token)
{
data_format_state_t retval = state;
@ -777,8 +764,8 @@ data_format_state_t dfs_semi_next(data_format_state_t state,
return retval;
}
data_format_state_t dfs_comma_next(data_format_state_t state,
data_token_t next_token)
data_format_state_t
dfs_comma_next(data_format_state_t state, data_token_t next_token)
{
data_format_state_t retval = state;
@ -872,18 +859,15 @@ data_format_state_t dfs_comma_next(data_format_state_t state,
}
data_parser::element::element()
: e_capture(-1, -1),
e_token(DT_INVALID),
e_sub_elements(nullptr)
: e_capture(-1, -1), e_token(DT_INVALID), e_sub_elements(nullptr)
{
}
data_parser::element::element(data_parser::element_list_t& subs,
data_token_t token, bool assign_subs_elements)
: e_capture(subs.front().e_capture.c_begin,
subs.back().e_capture.c_end),
e_token(token),
e_sub_elements(nullptr)
data_token_t token,
bool assign_subs_elements)
: e_capture(subs.front().e_capture.c_begin, subs.back().e_capture.c_end),
e_token(token), e_sub_elements(nullptr)
{
if (assign_subs_elements) {
this->assign_elements(subs);
@ -920,41 +904,43 @@ data_parser::element::operator=(const data_parser::element &other)
return *this;
}
void data_parser::element::assign_elements(data_parser::element_list_t &subs)
void
data_parser::element::assign_elements(data_parser::element_list_t& subs)
{
if (this->e_sub_elements == nullptr) {
this->e_sub_elements = new element_list_t("_sub_", __FILE__,
__LINE__);
this->e_sub_elements = new element_list_t("_sub_", __FILE__, __LINE__);
this->e_sub_elements->el_format = subs.el_format;
}
this->e_sub_elements->SWAP(subs);
this->update_capture();
}
void data_parser::element::update_capture()
void
data_parser::element::update_capture()
{
if (this->e_sub_elements != nullptr && !this->e_sub_elements->empty()) {
this->e_capture.c_begin =
this->e_sub_elements->front().e_capture.c_begin;
this->e_capture.c_end =
this->e_sub_elements->back().e_capture.c_end;
this->e_capture.c_begin
= this->e_sub_elements->front().e_capture.c_begin;
this->e_capture.c_end = this->e_sub_elements->back().e_capture.c_end;
}
}
const data_parser::element &data_parser::element::get_pair_value() const
const data_parser::element&
data_parser::element::get_pair_value() const
{
require(this->e_token == DNT_PAIR);
return this->e_sub_elements->back();
}
data_token_t data_parser::element::value_token() const
data_token_t
data_parser::element::value_token() const
{
data_token_t retval = DT_INVALID;
if (this->e_token == DNT_VALUE) {
if (this->e_sub_elements != nullptr &&
this->e_sub_elements->size() == 1) {
if (this->e_sub_elements != nullptr
&& this->e_sub_elements->size() == 1) {
retval = this->e_sub_elements->front().e_token;
} else {
retval = DT_SYMBOL;
@ -965,18 +951,20 @@ data_token_t data_parser::element::value_token() const
return retval;
}
const data_parser::element &data_parser::element::get_value_elem() const
const data_parser::element&
data_parser::element::get_value_elem() const
{
if (this->e_token == DNT_VALUE) {
if (this->e_sub_elements != nullptr &&
this->e_sub_elements->size() == 1) {
if (this->e_sub_elements != nullptr
&& this->e_sub_elements->size() == 1) {
return this->e_sub_elements->front();
}
}
return *this;
}
const data_parser::element &data_parser::element::get_pair_elem() const
const data_parser::element&
data_parser::element::get_pair_elem() const
{
if (this->e_token == DNT_VALUE) {
return this->e_sub_elements->front();
@ -984,7 +972,8 @@ const data_parser::element &data_parser::element::get_pair_elem() const
return *this;
}
void data_parser::element::print(FILE *out, pcre_input &pi, int offset) const
void
data_parser::element::print(FILE* out, pcre_input& pi, int offset) const
{
int lpc;
@ -994,7 +983,8 @@ void data_parser::element::print(FILE *out, pcre_input &pi, int offset) const
}
}
fprintf(out, "%4s %3d:%-3d ",
fprintf(out,
"%4s %3d:%-3d ",
data_scanner::token2name(this->e_token),
this->e_capture.c_begin,
this->e_capture.c_end);
@ -1018,18 +1008,18 @@ void data_parser::element::print(FILE *out, pcre_input &pi, int offset) const
}
data_parser::discover_format_state::discover_format_state()
: dfs_prefix_state(DFS_INIT),
dfs_semi_state(DFS_INIT),
: dfs_prefix_state(DFS_INIT), dfs_semi_state(DFS_INIT),
dfs_comma_state(DFS_INIT)
{
memset(this->dfs_hist, 0, sizeof(this->dfs_hist));
}
void data_parser::discover_format_state::update_for_element(
void
data_parser::discover_format_state::update_for_element(
const data_parser::element& elem)
{
this->dfs_prefix_state = dfs_prefix_next(this->dfs_prefix_state,
elem.e_token);
this->dfs_prefix_state
= dfs_prefix_next(this->dfs_prefix_state, elem.e_token);
this->dfs_semi_state = dfs_semi_next(this->dfs_semi_state, elem.e_token);
this->dfs_comma_state = dfs_comma_next(this->dfs_comma_state, elem.e_token);
if (this->dfs_prefix_state != DFS_ERROR) {
@ -1043,7 +1033,8 @@ void data_parser::discover_format_state::update_for_element(
this->dfs_hist[elem.e_token] += 1;
}
void data_parser::discover_format_state::finalize()
void
data_parser::discover_format_state::finalize()
{
data_token_t qualifier = this->dfs_format.df_qualifier;
data_token_t separator = this->dfs_format.df_separator;
@ -1060,9 +1051,10 @@ void data_parser::discover_format_state::finalize()
} else if (this->dfs_comma_state != DFS_ERROR) {
this->dfs_format = FORMAT_COMMA;
if (separator == DT_COLON && this->dfs_hist[DT_COMMA] > 0) {
if (!((this->dfs_hist[DT_COLON] == this->dfs_hist[DT_COMMA]) ||
((this->dfs_hist[DT_COLON] - 1) ==
this->dfs_hist[DT_COMMA]))) {
if (!((this->dfs_hist[DT_COLON] == this->dfs_hist[DT_COMMA])
|| ((this->dfs_hist[DT_COLON] - 1)
== this->dfs_hist[DT_COMMA])))
{
separator = DT_INVALID;
if (this->dfs_hist[DT_COLON] == 1) {
prefix_term = DT_COLON;

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@ -30,17 +30,17 @@
#ifndef data_parser_hh
#define data_parser_hh
#include <stdio.h>
#include <iterator>
#include <list>
#include <stack>
#include <vector>
#include <iterator>
#include <stdio.h>
#include "base/lnav_log.hh"
#include "pcrepp/pcrepp.hh"
#include "byte_array.hh"
#include "data_scanner.hh"
#include "pcrepp/pcrepp.hh"
#define ELEMENT_LIST_T(var) var("" #var, __FILE__, __LINE__, group_depth)
#define PUSH_FRONT(elem) push_front(elem, __FILE__, __LINE__)
@ -49,11 +49,12 @@
#define POP_BACK(elem) pop_back(__FILE__, __LINE__)
#define CLEAR(elem) clear2(__FILE__, __LINE__)
#define SWAP(other) swap(other, __FILE__, __LINE__)
#define SPLICE(pos, other, first, last) splice(pos, other, first, last, \
__FILE__, __LINE__)
#define SPLICE(pos, other, first, last) \
splice(pos, other, first, last, __FILE__, __LINE__)
template<class Container, class UnaryPredicate>
void strip(Container &container, UnaryPredicate p)
void
strip(Container& container, UnaryPredicate p)
{
while (!container.empty() && p(container.front())) {
container.POP_FRONT();
@ -75,13 +76,9 @@ struct data_format {
data_format(const char* name = nullptr,
data_token_t appender = DT_INVALID,
data_token_t terminator = DT_INVALID) noexcept
: df_name(name),
df_appender(appender),
df_terminator(terminator),
df_qualifier(DT_INVALID),
df_separator(DT_COLON),
df_prefix_terminator(DT_INVALID)
{};
: df_name(name), df_appender(appender), df_terminator(terminator),
df_qualifier(DT_INVALID), df_separator(DT_COLON),
df_prefix_terminator(DT_INVALID){};
const char* df_name;
data_token_t df_appender;
@ -104,7 +101,8 @@ data_format_state_t dfs_comma_next(data_format_state_t state,
fprintf(TRACE_FILE, \
"%p %s:%d %s %s %d\n", \
this, \
fn, line, \
fn, \
line, \
__func__, \
varname, \
group_depth); \
@ -114,11 +112,7 @@ data_format_state_t dfs_comma_next(data_format_state_t state,
#define LIST_DEINIT_TRACE \
do { \
if (TRACE_FILE != NULL) { \
fprintf(TRACE_FILE, \
"%p %s:%d %s\n", \
this, \
fn, line, \
__func__); \
fprintf(TRACE_FILE, "%p %s:%d %s\n", this, fn, line, __func__); \
} \
} while (false)
@ -128,7 +122,8 @@ data_format_state_t dfs_comma_next(data_format_state_t state,
fprintf(TRACE_FILE, \
"%p %s:%d %s %s %d:%d\n", \
this, \
fn, line, \
fn, \
line, \
__func__, \
data_scanner::token2name(elem.e_token), \
elem.e_capture.c_begin, \
@ -139,11 +134,7 @@ data_format_state_t dfs_comma_next(data_format_state_t state,
#define LIST_TRACE \
do { \
if (TRACE_FILE != NULL) { \
fprintf(TRACE_FILE, \
"%p %s:%d %s\n", \
this, \
fn, line, \
__func__); \
fprintf(TRACE_FILE, "%p %s:%d %s\n", this, fn, line, __func__); \
} \
} while (false)
@ -153,7 +144,8 @@ data_format_state_t dfs_comma_next(data_format_state_t state,
fprintf(TRACE_FILE, \
"%p %s:%d %s %d %p %d:%d\n", \
this, \
fn, line, \
fn, \
line, \
__func__, \
(int) std::distance(this->begin(), pos), \
&other, \
@ -168,7 +160,8 @@ data_format_state_t dfs_comma_next(data_format_state_t state,
fprintf(TRACE_FILE, \
"%p %s:%d %s %p\n", \
this, \
fn, line, \
fn, \
line, \
__func__, \
&other); \
} \
@ -177,10 +170,8 @@ data_format_state_t dfs_comma_next(data_format_state_t state,
#define POINT_TRACE(name) \
do { \
if (TRACE_FILE) { \
fprintf(TRACE_FILE, \
"0x0 %s:%d point %s\n", \
__FILE__, __LINE__, \
name); \
fprintf( \
TRACE_FILE, "0x0 %s:%d point %s\n", __FILE__, __LINE__, name); \
} \
} while (false);
@ -191,7 +182,8 @@ data_format_state_t dfs_comma_next(data_format_state_t state,
fprintf(TRACE_FILE, \
"%p %s:%d format %d %s %s %s %s %s\n", \
&elist, \
__FILE__, __LINE__, \
__FILE__, \
__LINE__, \
group_depth, \
data_scanner::token2name(df.df_appender), \
data_scanner::token2name(df.df_terminator), \
@ -207,7 +199,8 @@ data_format_state_t dfs_comma_next(data_format_state_t state,
fprintf(TRACE_FILE, \
"%p %s:%d consumed\n", \
&elist, \
__FILE__, __LINE__); \
__FILE__, \
__LINE__); \
} \
} while (false);
@ -226,7 +219,10 @@ public:
class element_list_t : public std::list<element> {
public:
element_list_t(const char *varname, const char *fn, int line, int group_depth = -1)
element_list_t(const char* varname,
const char* fn,
int line,
int group_depth = -1)
{
LIST_INIT_TRACE;
}
@ -241,7 +237,8 @@ public:
LIST_INIT_TRACE;
};
element_list_t(const element_list_t &other) : std::list<element>(other) {
element_list_t(const element_list_t& other) : std::list<element>(other)
{
this->el_format = other.el_format;
}
@ -290,7 +287,8 @@ public:
this->std::list<element>::clear();
};
void swap(element_list_t &other, const char *fn, int line) {
void swap(element_list_t& other, const char* fn, int line)
{
SWAP_TRACE(other);
this->std::list<element>::swap(other);
@ -385,8 +383,10 @@ private:
data_parser(data_scanner* ds);
void pairup(schema_id_t *schema, element_list_t &pairs_out,
element_list_t &in_list, int group_depth = 0);
void pairup(schema_id_t* schema,
element_list_t& pairs_out,
element_list_t& in_list,
int group_depth = 0);
void discover_format();

View File

@ -21,20 +21,20 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "data_scanner.hh"
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include "config.h"
#include "pcrepp/pcrepp.hh"
#include "data_scanner.hh"
using namespace std;
@ -42,112 +42,194 @@ static struct {
const char* name;
pcrepp pcre;
} MATCHERS[DT_TERMINAL_MAX] = {
{ "quot", pcrepp("\\A(?:(?:u|r)?\"((?:\\\\.|[^\"])+)\"|"
"(?:u|r)?'((?:\\\\.|[^'])+)')"), },
{ "url", pcrepp("\\A([\\w]+://[^\\s'\"\\[\\](){}]+[/a-zA-Z0-9\\-=&])"),
{
"quot",
pcrepp("\\A(?:(?:u|r)?\"((?:\\\\.|[^\"])+)\"|"
"(?:u|r)?'((?:\\\\.|[^'])+)')"),
},
{ "path", pcrepp("\\A((?:/|\\./|\\.\\./)[\\w\\.\\-_\\~/]*)"),
{
"url",
pcrepp("\\A([\\w]+://[^\\s'\"\\[\\](){}]+[/a-zA-Z0-9\\-=&])"),
},
{ "mac", pcrepp(
"\\A([0-9a-fA-F][0-9a-fA-F](?::[0-9a-fA-F][0-9a-fA-F]){5})(?!:)"), },
{ "date",
{
"path",
pcrepp("\\A((?:/|\\./|\\.\\./)[\\w\\.\\-_\\~/]*)"),
},
{
"mac",
pcrepp(
"\\A([0-9a-fA-F][0-9a-fA-F](?::[0-9a-fA-F][0-9a-fA-F]){5})(?!:)"),
},
{
"date",
pcrepp("\\A("
"\\d{4}/\\d{1,2}/\\d{1,2}|"
"\\d{4}-\\d{1,2}-\\d{1,2}|"
"\\d{2}/\\w{3}/\\d{4}"
")T?"), },
{ "time", pcrepp(
"\\A([\\s\\d]\\d:\\d\\d(?:(?!:\\d)|:\\d\\d(?:[\\.,]\\d{3,6})?Z?))\\b"), },
")T?"),
},
{
"time",
pcrepp("\\A([\\s\\d]\\d:\\d\\d(?:(?!:\\d)|:\\d\\d(?:[\\.,]\\d{3,6})?Z?)"
")\\b"),
},
/* { "qual", pcrepp("\\A([^\\s:=]+:[^\\s:=,]+(?!,)(?::[^\\s:=,]+)*)"), }, */
{ "ipv6", pcrepp("\\A(::|[:\\da-fA-F\\.]+[a-fA-F\\d](?:%\\w+)?)"), },
{ "hexd", pcrepp(
"\\A([0-9a-fA-F][0-9a-fA-F](?::[0-9a-fA-F][0-9a-fA-F])+)"), },
{
"ipv6",
pcrepp("\\A(::|[:\\da-fA-F\\.]+[a-fA-F\\d](?:%\\w+)?)"),
},
{
"hexd",
pcrepp("\\A([0-9a-fA-F][0-9a-fA-F](?::[0-9a-fA-F][0-9a-fA-F])+)"),
},
{ "xmlt", pcrepp(
"\\A(<\\??[\\w:]+\\s*(?:[\\w:]+(?:\\s*=\\s*"
{
"xmlt",
pcrepp("\\A(<\\??[\\w:]+\\s*(?:[\\w:]+(?:\\s*=\\s*"
"(?:\"((?:\\\\.|[^\"])+)\"|'((?:\\\\.|[^'])+)'|[^>]+)"
"))*\\s*(?:/|\\?)>)"), },
{ "xmlo", pcrepp(
"\\A(<[\\w:]+\\s*(?:[\\w:]+(?:\\s*=\\s*"
"))*\\s*(?:/|\\?)>)"),
},
{
"xmlo",
pcrepp("\\A(<[\\w:]+\\s*(?:[\\w:]+(?:\\s*=\\s*"
"(?:\"((?:\\\\.|[^\"])+)\"|'((?:\\\\.|[^'])+)'|[^>]+)"
"))*\\s*>)"), },
{ "xmlc", pcrepp("\\A(</[\\w:]+\\s*>)"), },
{ "coln", pcrepp("\\A(:)"),
},
{ "eq", pcrepp("\\A(=)"),
},
{ "comm", pcrepp("\\A(,)"),
},
{ "semi", pcrepp("\\A(;)"),
"))*\\s*>)"),
},
{ "empt", pcrepp("\\A(\\(\\)|\\{\\}|\\[\\])"),
{
"xmlc",
pcrepp("\\A(</[\\w:]+\\s*>)"),
},
{ "lcurly", pcrepp("\\A({)"),
{
"coln",
pcrepp("\\A(:)"),
},
{ "rcurly", pcrepp("\\A(})"),
{
"eq",
pcrepp("\\A(=)"),
},
{
"comm",
pcrepp("\\A(,)"),
},
{
"semi",
pcrepp("\\A(;)"),
},
{ "lsquare", pcrepp("\\A(\\[)"),
},
{ "rsquare", pcrepp("\\A(\\])"),
{
"empt",
pcrepp("\\A(\\(\\)|\\{\\}|\\[\\])"),
},
{ "lparen", pcrepp("\\A(\\()"),
{
"lcurly",
pcrepp("\\A({)"),
},
{ "rparen", pcrepp("\\A(\\))"),
{
"rcurly",
pcrepp("\\A(})"),
},
{ "langle", pcrepp("\\A(\\<)"),
{
"lsquare",
pcrepp("\\A(\\[)"),
},
{ "rangle", pcrepp("\\A(\\>)"),
{
"rsquare",
pcrepp("\\A(\\])"),
},
{ "ipv4", pcrepp("\\A("
{
"lparen",
pcrepp("\\A(\\()"),
},
{
"rparen",
pcrepp("\\A(\\))"),
},
{
"langle",
pcrepp("\\A(\\<)"),
},
{
"rangle",
pcrepp("\\A(\\>)"),
},
{
"ipv4",
pcrepp("\\A("
"(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\\.){3}"
"(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(?![\\d]))"),
},
{ "uuid", pcrepp(
"\\A([0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12})"), },
{
"uuid",
pcrepp("\\A([0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12})"),
},
{ "vers", pcrepp(
"\\A("
{
"vers",
pcrepp("\\A("
"[0-9]+(?:\\.[0-9]+\\w*){2,}(?:-\\w+)?|"
"[0-9]+(?:\\.[0-9]+\\w*)+(?<!\\d[eE])-\\w+?"
")\\b"),
},
{ "oct", pcrepp("\\A(-?0[0-7]+\\b)"),
{
"oct",
pcrepp("\\A(-?0[0-7]+\\b)"),
},
{ "pcnt", pcrepp("\\A(-?[0-9]+(\\.[0-9]+)?[ ]*%\\b)"),
{
"pcnt",
pcrepp("\\A(-?[0-9]+(\\.[0-9]+)?[ ]*%\\b)"),
},
{
"num",
pcrepp("\\A(-?[0-9]+(\\.[0-9]+)?([eE][\\-+][0-9]+)?)"
"\\b(?![\\._\\-][a-zA-Z])"),
},
{
"hex",
pcrepp("\\A(-?(?:0x|[0-9])[0-9a-fA-F]+)"
"\\b(?![\\._\\-][a-zA-Z])"),
},
{ "num", pcrepp("\\A(-?[0-9]+(\\.[0-9]+)?([eE][\\-+][0-9]+)?)"
"\\b(?![\\._\\-][a-zA-Z])"), },
{ "hex", pcrepp("\\A(-?(?:0x|[0-9])[0-9a-fA-F]+)"
"\\b(?![\\._\\-][a-zA-Z])"), },
{ "mail", pcrepp(
"\\A([a-zA-Z0-9\\._%+-]+@[a-zA-Z0-9\\.-]+\\.[a-zA-Z]+)\\b"), },
{ "cnst",
pcrepp("\\A(true|True|TRUE|false|False|FALSE|None|null)\\b") },
{ "word", pcrepp(
"\\A([a-zA-Z][a-z']+(?=[\\s\\(\\)!\\*:;'\\\"\\?,]|[\\.\\!,\\?]\\s|$))"),
{
"mail",
pcrepp("\\A([a-zA-Z0-9\\._%+-]+@[a-zA-Z0-9\\.-]+\\.[a-zA-Z]+)\\b"),
},
{ "sym", pcrepp(
{"cnst", pcrepp("\\A(true|True|TRUE|false|False|FALSE|None|null)\\b")},
{
"word",
pcrepp("\\A([a-zA-Z][a-z']+(?=[\\s\\(\\)!\\*:;'\\\"\\?,]|[\\.\\!,\\?]"
"\\s|$))"),
},
{
"sym",
pcrepp(
"\\A([^\";\\s:=,\\(\\)\\{\\}\\[\\]\\+#!@%\\^&\\*'\\?<>\\~`\\|\\\\]+"
"(?:::[^\";\\s:=,\\(\\)\\{\\}\\[\\]\\+#!@%\\^&\\*'\\?<>\\~`\\|\\\\]+)*)"),
"(?:::[^\";\\s:=,\\(\\)\\{\\}\\[\\]\\+#!@%\\^&\\*'\\?<>\\~`\\|\\\\]"
"+)*)"),
},
{ "line", pcrepp("\\A(\r?\n|\r|;)"),
{
"line",
pcrepp("\\A(\r?\n|\r|;)"),
},
{ "wspc", pcrepp("\\A([ \\r\\t\\n]+)"),
{
"wspc",
pcrepp("\\A([ \\r\\t\\n]+)"),
},
{ "dot", pcrepp("\\A(\\.)"),
{
"dot",
pcrepp("\\A(\\.)"),
},
{ "gbg", pcrepp("\\A(.)"),
{
"gbg",
pcrepp("\\A(.)"),
},
};
@ -164,24 +246,22 @@ const char *DNT_NAMES[DNT_MAX - DNT_KEY] = {
"grp",
};
const char *data_scanner::token2name(data_token_t token)
const char*
data_scanner::token2name(data_token_t token)
{
if (token < 0) {
return "inv";
}
else if (token < DT_TERMINAL_MAX) {
} else if (token < DT_TERMINAL_MAX) {
return MATCHERS[token].name;
}
else if (token == DT_ANY) {
} else if (token == DT_ANY) {
return "any";
}
else{
} else {
return DNT_NAMES[token - DNT_KEY];
}
}
static
bool find_string_end(const char *str, size_t &start, size_t length, char term)
static bool
find_string_end(const char* str, size_t& start, size_t length, char term)
{
for (; start < length; start++) {
if (str[start] == term) {
@ -198,8 +278,8 @@ bool find_string_end(const char *str, size_t &start, size_t length, char term)
return false;
}
static
void single_char_capture(pcre_context &pc, pcre_input &pi)
static void
single_char_capture(pcre_context& pc, pcre_input& pi)
{
pc.all()[0].c_begin = pi.pi_offset;
pc.all()[0].c_end = pi.pi_offset + 1;
@ -208,7 +288,8 @@ void single_char_capture(pcre_context &pc, pcre_input &pi)
pi.pi_next_offset = pi.pi_offset + 1;
}
bool data_scanner::tokenize(pcre_context &pc, data_token_t &token_out)
bool
data_scanner::tokenize(pcre_context& pc, data_token_t& token_out)
{
const char* str = this->ds_pcre_input.get_string();
pcre_input& pi = this->ds_pcre_input;
@ -218,9 +299,8 @@ bool data_scanner::tokenize(pcre_context &pc, data_token_t &token_out)
if (this->ds_pcre_input.pi_next_offset > this->ds_pcre_input.pi_length) {
return false;
}
else if (this->ds_pcre_input.pi_next_offset ==
this->ds_pcre_input.pi_length) {
} else if (this->ds_pcre_input.pi_next_offset
== this->ds_pcre_input.pi_length) {
this->ds_pcre_input.pi_next_offset += 1;
token_out = DT_LINE;
return false;
@ -237,9 +317,10 @@ bool data_scanner::tokenize(pcre_context &pc, data_token_t &token_out)
switch (str[pi.pi_offset]) {
case 'u':
case 'r':
if (pi.pi_offset + 1 < pi.pi_length &&
(str[pi.pi_offset + 1] == '\'' ||
str[pi.pi_offset + 1] == '\"')) {
if (pi.pi_offset + 1 < pi.pi_length
&& (str[pi.pi_offset + 1] == '\''
|| str[pi.pi_offset + 1] == '\"'))
{
str_start += 1;
str_end += 1;
found = find_string_end(str,
@ -251,10 +332,8 @@ bool data_scanner::tokenize(pcre_context &pc, data_token_t &token_out)
case '\'':
case '\"':
found = find_string_end(str,
str_end,
pi.pi_length,
str[pi.pi_offset]);
found = find_string_end(
str, str_end, pi.pi_length, str[pi.pi_offset]);
break;
}
if (found) {
@ -267,8 +346,7 @@ bool data_scanner::tokenize(pcre_context &pc, data_token_t &token_out)
pc.set_count(2);
return true;
}
}
break;
} break;
case DT_COLON: {
pi.pi_offset = pi.pi_next_offset;
@ -278,8 +356,7 @@ bool data_scanner::tokenize(pcre_context &pc, data_token_t &token_out)
single_char_capture(pc, pi);
return true;
}
}
break;
} break;
case DT_EQUALS: {
pi.pi_offset = pi.pi_next_offset;
@ -289,8 +366,7 @@ bool data_scanner::tokenize(pcre_context &pc, data_token_t &token_out)
single_char_capture(pc, pi);
return true;
}
}
break;
} break;
case DT_COMMA: {
pi.pi_offset = pi.pi_next_offset;
@ -300,8 +376,7 @@ bool data_scanner::tokenize(pcre_context &pc, data_token_t &token_out)
single_char_capture(pc, pi);
return true;
}
}
break;
} break;
case DT_SEMI: {
pi.pi_offset = pi.pi_next_offset;
@ -311,27 +386,27 @@ bool data_scanner::tokenize(pcre_context &pc, data_token_t &token_out)
single_char_capture(pc, pi);
return true;
}
}
break;
} break;
default:
if (MATCHERS[lpc].pcre.match(pc, this->ds_pcre_input,
PCRE_ANCHORED)) {
if (MATCHERS[lpc].pcre.match(
pc, this->ds_pcre_input, PCRE_ANCHORED)) {
switch (lpc) {
case DT_IPV6_ADDRESS:
if (pc.all()->length() <= INET6_ADDRSTRLEN) {
char in6str[INET6_ADDRSTRLEN];
char buf[sizeof(struct in6_addr)];
this->ds_pcre_input.get_substr(pc.all(), in6str);
this->ds_pcre_input.get_substr(pc.all(),
in6str);
if (inet_pton(AF_INET6, in6str, buf) == 1) {
token_out = data_token_t(lpc);
return true;
}
}
this->ds_pcre_input.pi_next_offset =
this->ds_pcre_input.pi_offset;
this->ds_pcre_input.pi_next_offset
= this->ds_pcre_input.pi_offset;
break;
default:

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@ -111,17 +111,22 @@ class data_scanner {
public:
static const char* token2name(data_token_t token);
data_scanner(const std::string &line, size_t off = 0, size_t len = (size_t) -1)
: ds_line(line),
ds_pcre_input(ds_line.c_str(), off, len)
data_scanner(const std::string& line,
size_t off = 0,
size_t len = (size_t) -1)
: ds_line(line), ds_pcre_input(ds_line.c_str(), off, len)
{
if (!line.empty() && line[line.length() - 1] == '.') {
this->ds_pcre_input.pi_length -= 1;
}
};
data_scanner(shared_buffer_ref &line, size_t off = 0, size_t len = (size_t) -1)
: ds_sbr(line), ds_pcre_input(line.get_data(), off, len == (size_t) -1 ? line.length() : len)
data_scanner(shared_buffer_ref& line,
size_t off = 0,
size_t len = (size_t) -1)
: ds_sbr(line),
ds_pcre_input(
line.get_data(), off, len == (size_t) -1 ? line.length() : len)
{
require(len == (size_t) -1 || len <= line.length());
if (line.length() > 0 && line.get_data()[line.length() - 1] == '.') {
@ -132,9 +137,13 @@ public:
bool tokenize(pcre_context& pc, data_token_t& token_out);
bool tokenize2(pcre_context& pc, data_token_t& token_out);
pcre_input &get_input() { return this->ds_pcre_input; };
pcre_input& get_input()
{
return this->ds_pcre_input;
};
void reset() {
void reset()
{
this->ds_pcre_input.reset_next_offset();
};

File diff suppressed because it is too large Load Diff

View File

@ -21,27 +21,28 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <regex>
#include "db_sub_source.hh"
#include "base/date_time_scanner.hh"
#include "base/time_util.hh"
#include "config.h"
#include "yajlpp/json_ptr.hh"
#include "db_sub_source.hh"
const char* db_label_source::NULL_STR = "<NULL>";
constexpr size_t MAX_COLUMN_WIDTH = 120;
void db_label_source::text_value_for_line(textview_curses &tc, int row,
void
db_label_source::text_value_for_line(textview_curses& tc,
int row,
std::string& label_out,
text_sub_source::line_flags_t flags)
{
@ -59,8 +60,8 @@ void db_label_source::text_value_for_line(textview_curses &tc, int row,
return;
}
for (int lpc = 0; lpc < (int) this->dls_rows[row].size(); lpc++) {
auto actual_col_size = std::min(MAX_COLUMN_WIDTH,
this->dls_headers[lpc].hm_column_size);
auto actual_col_size
= std::min(MAX_COLUMN_WIDTH, this->dls_headers[lpc].hm_column_size);
auto raw_cell_str = std::string(this->dls_rows[row][lpc]);
std::string cell_str;
@ -83,8 +84,8 @@ void db_label_source::text_value_for_line(textview_curses &tc, int row,
truncate_to(cell_str, MAX_COLUMN_WIDTH);
auto cell_length = utf8_string_length(cell_str)
.unwrapOr(actual_col_size);
auto cell_length
= utf8_string_length(cell_str).unwrapOr(actual_col_size);
auto padding = actual_col_size - cell_length;
this->dls_cell_width[lpc] = cell_str.length() + padding;
if (this->dls_headers[lpc].hm_column_type != SQLITE3_TEXT) {
@ -98,7 +99,9 @@ void db_label_source::text_value_for_line(textview_curses &tc, int row,
}
}
void db_label_source::text_attrs_for_line(textview_curses &tc, int row,
void
db_label_source::text_attrs_for_line(textview_curses& tc,
int row,
string_attrs_t& sa)
{
struct line_range lr(0, 0);
@ -126,23 +129,28 @@ void db_label_source::text_attrs_for_line(textview_curses &tc, int row,
double num_value;
if (sscanf(row_value, "%lf", &num_value) == 1) {
this->dls_chart.chart_attrs_for_value(tc, left, this->dls_headers[lpc].hm_name, num_value, sa);
this->dls_chart.chart_attrs_for_value(
tc, left, this->dls_headers[lpc].hm_name, num_value, sa);
}
}
if (row_len > 2 && row_len < MAX_COLUMN_WIDTH &&
((row_value[0] == '{' && row_value[row_len - 1] == '}') ||
(row_value[0] == '[' && row_value[row_len - 1] == ']'))) {
if (row_len > 2 && row_len < MAX_COLUMN_WIDTH
&& ((row_value[0] == '{' && row_value[row_len - 1] == '}')
|| (row_value[0] == '[' && row_value[row_len - 1] == ']')))
{
json_ptr_walk jpw;
if (jpw.parse(row_value, row_len) == yajl_status_ok &&
jpw.complete_parse() == yajl_status_ok) {
if (jpw.parse(row_value, row_len) == yajl_status_ok
&& jpw.complete_parse() == yajl_status_ok)
{
for (auto& jpw_value : jpw.jpw_values) {
double num_value;
if (jpw_value.wt_type == yajl_t_number &&
sscanf(jpw_value.wt_value.c_str(), "%lf", &num_value) == 1) {
this->dls_chart.chart_attrs_for_value(tc, left,
jpw_value.wt_ptr, num_value, sa);
if (jpw_value.wt_type == yajl_t_number
&& sscanf(jpw_value.wt_value.c_str(), "%lf", &num_value)
== 1)
{
this->dls_chart.chart_attrs_for_value(
tc, left, jpw_value.wt_ptr, num_value, sa);
}
}
}
@ -150,7 +158,9 @@ void db_label_source::text_attrs_for_line(textview_curses &tc, int row,
}
}
void db_label_source::push_header(const std::string &colstr, int type,
void
db_label_source::push_header(const std::string& colstr,
int type,
bool graphable)
{
this->dls_headers.emplace_back(colstr);
@ -166,7 +176,8 @@ void db_label_source::push_header(const std::string &colstr, int type,
}
}
void db_label_source::push_column(const char *colstr)
void
db_label_source::push_column(const char* colstr)
{
view_colors& vc = view_colors::singleton();
int index = this->dls_rows.back().size();
@ -175,8 +186,7 @@ void db_label_source::push_column(const char *colstr)
if (colstr == nullptr) {
colstr = NULL_STR;
}
else {
} else {
colstr = strdup(colstr);
if (colstr == nullptr) {
throw "out of memory";
@ -192,18 +202,18 @@ void db_label_source::push_column(const char *colstr)
tv.tv_sec = -1;
tv.tv_usec = -1;
}
if (!this->dls_time_column.empty() && tv < this->dls_time_column.back()) {
if (!this->dls_time_column.empty() && tv < this->dls_time_column.back())
{
this->dls_time_column_index = -1;
this->dls_time_column.clear();
}
else {
} else {
this->dls_time_column.push_back(tv);
}
}
this->dls_rows.back().push_back(colstr);
this->dls_headers[index].hm_column_size =
std::max(this->dls_headers[index].hm_column_size,
this->dls_headers[index].hm_column_size
= std::max(this->dls_headers[index].hm_column_size,
utf8_string_length(colstr, value_len).unwrapOr(value_len));
if (colstr != nullptr && this->dls_headers[index].hm_graphable) {
@ -211,17 +221,20 @@ void db_label_source::push_column(const char *colstr)
num_value = 0.0;
}
this->dls_chart.add_value(this->dls_headers[index].hm_name, num_value);
}
else if (value_len > 2 &&
((colstr[0] == '{' && colstr[value_len - 1] == '}') ||
(colstr[0] == '[' && colstr[value_len - 1] == ']'))) {
} else if (value_len > 2
&& ((colstr[0] == '{' && colstr[value_len - 1] == '}')
|| (colstr[0] == '[' && colstr[value_len - 1] == ']')))
{
json_ptr_walk jpw;
if (jpw.parse(colstr, value_len) == yajl_status_ok &&
jpw.complete_parse() == yajl_status_ok) {
if (jpw.parse(colstr, value_len) == 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) {
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);
this->dls_chart.with_attrs_for_ident(
jpw_value.wt_ptr, vc.attrs_for_ident(jpw_value.wt_ptr));
@ -231,7 +244,8 @@ void db_label_source::push_column(const char *colstr)
}
}
void db_label_source::clear()
void
db_label_source::clear()
{
this->dls_chart.clear();
this->dls_headers.clear();
@ -247,13 +261,12 @@ void db_label_source::clear()
this->dls_cell_width.clear();
}
long db_label_source::column_name_to_index(const std::string &name) const
long
db_label_source::column_name_to_index(const std::string& name) const
{
std::vector<header_meta>::const_iterator iter;
iter = std::find(this->dls_headers.begin(),
this->dls_headers.end(),
name);
iter = std::find(this->dls_headers.begin(), this->dls_headers.end(), name);
if (iter == this->dls_headers.end()) {
return -1;
}
@ -261,7 +274,8 @@ long db_label_source::column_name_to_index(const std::string &name) const
return std::distance(this->dls_headers.begin(), iter);
}
nonstd::optional<vis_line_t> db_label_source::row_for_time(struct timeval time_bucket)
nonstd::optional<vis_line_t>
db_label_source::row_for_time(struct timeval time_bucket)
{
std::vector<struct timeval>::iterator iter;
@ -274,7 +288,8 @@ nonstd::optional<vis_line_t> db_label_source::row_for_time(struct timeval time_b
return nonstd::nullopt;
}
size_t db_overlay_source::list_overlay_count(const listview_curses &lv)
size_t
db_overlay_source::list_overlay_count(const listview_curses& lv)
{
size_t retval = 1;
@ -297,19 +312,21 @@ size_t db_overlay_source::list_overlay_count(const listview_curses &lv)
const char* col_value = cols[col];
size_t col_len = strlen(col_value);
if (!(col_len >= 2 &&
((col_value[0] == '{' && col_value[col_len - 1] == '}') ||
(col_value[0] == '[' && col_value[col_len - 1] == ']')))) {
if (!(col_len >= 2
&& ((col_value[0] == '{' && col_value[col_len - 1] == '}')
|| (col_value[0] == '[' && col_value[col_len - 1] == ']'))))
{
continue;
}
json_ptr_walk jpw;
if (jpw.parse(col_value, col_len) == yajl_status_ok &&
jpw.complete_parse() == yajl_status_ok) {
if (jpw.parse(col_value, col_len) == yajl_status_ok
&& jpw.complete_parse() == yajl_status_ok)
{
const std::string &header = this->dos_labels->dls_headers[col].hm_name;
{
const std::string& header
= this->dos_labels->dls_headers[col].hm_name;
this->dos_lines.emplace_back(" JSON Column: " + header);
retval += 1;
@ -318,12 +335,11 @@ size_t db_overlay_source::list_overlay_count(const listview_curses &lv)
stacked_bar_chart<std::string> chart;
int start_line = this->dos_lines.size();
chart.with_stacking_enabled(false)
.with_margins(3, 0);
chart.with_stacking_enabled(false).with_margins(3, 0);
for (auto& jpw_value : jpw.jpw_values) {
this->dos_lines.emplace_back(" " + jpw_value.wt_ptr + " = " +
jpw_value.wt_value);
this->dos_lines.emplace_back(" " + jpw_value.wt_ptr + " = "
+ jpw_value.wt_value);
string_attrs_t& sa = this->dos_lines.back().get_attrs();
struct line_range lr(1, 2);
@ -335,8 +351,10 @@ size_t db_overlay_source::list_overlay_count(const listview_curses &lv)
double num_value = 0.0;
if (jpw_value.wt_type == yajl_t_number &&
sscanf(jpw_value.wt_value.c_str(), "%lf", &num_value) == 1) {
if (jpw_value.wt_type == yajl_t_number
&& sscanf(jpw_value.wt_value.c_str(), "%lf", &num_value)
== 1)
{
int attrs = vc.attrs_for_ident(jpw_value.wt_ptr);
chart.add_value(jpw_value.wt_ptr, num_value);
@ -349,15 +367,18 @@ size_t db_overlay_source::list_overlay_count(const listview_curses &lv)
int curr_line = start_line;
for (auto iter = jpw.jpw_values.begin();
iter != jpw.jpw_values.end();
++iter, curr_line++) {
++iter, curr_line++)
{
double num_value = 0.0;
if (iter->wt_type == yajl_t_number &&
sscanf(iter->wt_value.c_str(), "%lf", &num_value) == 1) {
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();
int left = 3;
chart.chart_attrs_for_value(lv, left, iter->wt_ptr, num_value, sa);
chart.chart_attrs_for_value(
lv, left, iter->wt_ptr, num_value, sa);
}
}
}
@ -380,8 +401,11 @@ size_t db_overlay_source::list_overlay_count(const listview_curses &lv)
return retval;
}
bool db_overlay_source::list_value_for_overlay(const listview_curses &lv, int y,
int bottom, vis_line_t row,
bool
db_overlay_source::list_value_for_overlay(const listview_curses& lv,
int y,
int bottom,
vis_line_t row,
attr_line_t& value_out)
{
view_colors& vc = view_colors::singleton();
@ -392,17 +416,16 @@ bool db_overlay_source::list_value_for_overlay(const listview_curses &lv, int y,
db_label_source* dls = this->dos_labels;
string_attrs_t& sa = value_out.get_attrs();
for (size_t lpc = 0;
lpc < this->dos_labels->dls_headers.size();
lpc++) {
for (size_t lpc = 0; lpc < this->dos_labels->dls_headers.size(); lpc++)
{
auto actual_col_size = std::min(
MAX_COLUMN_WIDTH, dls->dls_headers[lpc].hm_column_size);
std::string cell_title = dls->dls_headers[lpc].hm_name;
truncate_to(cell_title, MAX_COLUMN_WIDTH);
auto cell_length = utf8_string_length(cell_title)
.unwrapOr(actual_col_size);
auto cell_length
= utf8_string_length(cell_title).unwrapOr(actual_col_size);
int before, total_fill = actual_col_size - cell_length;
auto line_len_before = line.length();
@ -415,8 +438,8 @@ bool db_overlay_source::list_value_for_overlay(const listview_curses &lv, int y,
struct line_range header_range(line_len_before, line.length());
int attrs =
vc.attrs_for_ident(dls->dls_headers[lpc].hm_name) | A_REVERSE;
int attrs
= vc.attrs_for_ident(dls->dls_headers[lpc].hm_name) | A_REVERSE;
if (!this->dos_labels->dls_headers[lpc].hm_graphable) {
attrs = A_UNDERLINE;
}
@ -427,8 +450,9 @@ bool db_overlay_source::list_value_for_overlay(const listview_curses &lv, int y,
sa.emplace_back(lr, &view_curses::VC_STYLE, A_BOLD | A_UNDERLINE);
return true;
}
else if (this->dos_active && y >= 2 && ((size_t) y) < (this->dos_lines.size() + 2)) {
} else if (this->dos_active && y >= 2
&& ((size_t) y) < (this->dos_lines.size() + 2))
{
value_out = this->dos_lines[y - 2];
return true;
}

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@ -30,34 +30,41 @@
#ifndef db_sub_source_hh
#define db_sub_source_hh
#include <iterator>
#include <string>
#include <vector>
#include <iterator>
#include <sqlite3.h>
#include "textview_curses.hh"
#include "hist_source.hh"
#include "textview_curses.hh"
class db_label_source : public text_sub_source, public text_time_translator {
class db_label_source
: public text_sub_source
, public text_time_translator {
public:
~db_label_source() {
~db_label_source()
{
this->clear();
}
bool has_log_time_column() const {
bool has_log_time_column() const
{
return !this->dls_time_column.empty();
};
size_t text_line_count() {
size_t text_line_count()
{
return this->dls_rows.size();
};
size_t text_size_for_line(textview_curses &tc, int line, line_flags_t flags) {
size_t text_size_for_line(textview_curses& tc, int line, line_flags_t flags)
{
return this->text_line_width(tc);
};
size_t text_line_width(textview_curses &curses) {
size_t text_line_width(textview_curses& curses)
{
size_t retval = 0;
for (auto& dls_header : this->dls_headers) {
@ -83,7 +90,8 @@ public:
nonstd::optional<vis_line_t> row_for_time(struct timeval time_bucket);
nonstd::optional<struct timeval> time_for_row(vis_line_t row) {
nonstd::optional<struct timeval> time_for_row(vis_line_t row)
{
if ((row < 0_vl) || (((size_t) row) >= this->dls_time_column.size())) {
return nonstd::nullopt;
}
@ -93,15 +101,13 @@ public:
struct header_meta {
explicit header_meta(std::string name)
: hm_name(std::move(name)),
hm_column_type(SQLITE3_TEXT),
hm_graphable(false),
hm_log_time(false),
hm_column_size(0) {
: hm_name(std::move(name)), hm_column_type(SQLITE3_TEXT),
hm_graphable(false), hm_log_time(false), hm_column_size(0){
};
bool operator==(const std::string &name) const {
bool operator==(const std::string& name) const
{
return this->hm_name == name;
};
@ -128,7 +134,8 @@ public:
size_t list_overlay_count(const listview_curses& lv);
bool list_value_for_overlay(const listview_curses& lv,
int y, int bottom,
int y,
int bottom,
vis_line_t row,
attr_line_t& value_out) override;

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@ -34,8 +34,7 @@
#include "statusview_curses.hh"
class doc_status_source
: public status_data_source {
class doc_status_source : public status_data_source {
public:
typedef enum {
TSF_TITLE,
@ -45,7 +44,8 @@ public:
TSF__MAX
} field_t;
doc_status_source() {
doc_status_source()
{
this->tss_fields[TSF_TITLE].set_width(14);
this->tss_fields[TSF_TITLE].set_left_pad(1);
this->tss_fields[TSF_TITLE].set_role(view_colors::VCR_STATUS_TITLE);
@ -57,19 +57,23 @@ public:
this->tss_fields[TSF_DESCRIPTION].set_role(view_colors::VCR_STATUS);
};
size_t statusview_fields() override {
size_t statusview_fields() override
{
return TSF__MAX;
};
status_field &statusview_value_for_field(int field) override {
status_field& statusview_value_for_field(int field) override
{
return this->tss_fields[field];
};
void set_title(const std::string &title) {
void set_title(const std::string& title)
{
this->tss_fields[TSF_TITLE].set_value(title);
}
void set_description(const std::string &description) {
void set_description(const std::string& description)
{
this->tss_fields[TSF_DESCRIPTION].set_value(description);
}

View File

@ -21,23 +21,23 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <algorithm>
#include "elem_to_json.hh"
#include "config.h"
#include "yajlpp/yajlpp.hh"
using namespace std;
static
void element_to_json(yajl_gen gen, data_parser &dp, const data_parser::element &elem)
static void
element_to_json(yajl_gen gen, data_parser& dp, const data_parser::element& elem)
{
size_t value_len;
const char* value_str = dp.get_element_string(elem, value_len);
@ -48,20 +48,21 @@ void element_to_json(yajl_gen gen, data_parser &dp, const data_parser::element &
break;
}
case DNT_GROUP: {
elements_to_json(gen, dp, elem.get_value_elem().e_sub_elements, false);
elements_to_json(
gen, dp, elem.get_value_elem().e_sub_elements, false);
break;
}
case DNT_PAIR: {
const data_parser::element& pair_elem = elem.get_pair_elem();
string key_str = dp.get_element_string(pair_elem.e_sub_elements->front());
string key_str
= dp.get_element_string(pair_elem.e_sub_elements->front());
if (!key_str.empty()) {
yajlpp_map singleton_map(gen);
singleton_map.gen(key_str);
element_to_json(gen, dp, pair_elem.get_pair_value());
}
else {
} else {
element_to_json(gen, dp, pair_elem.get_pair_value());
}
break;
@ -69,11 +70,9 @@ void element_to_json(yajl_gen gen, data_parser &dp, const data_parser::element &
case DT_CONSTANT: {
if (strncasecmp("true", value_str, value_len) == 0) {
yajl_gen_bool(gen, true);
}
else if (strncasecmp("false", value_str, value_len) == 0) {
} else if (strncasecmp("false", value_str, value_len) == 0) {
yajl_gen_bool(gen, false);
}
else {
} else {
yajl_gen_null(gen);
}
break;
@ -84,8 +83,10 @@ void element_to_json(yajl_gen gen, data_parser &dp, const data_parser::element &
}
}
static
void map_elements_to_json2(yajl_gen gen, data_parser &dp, data_parser::element_list_t *el)
static void
map_elements_to_json2(yajl_gen gen,
data_parser& dp,
data_parser::element_list_t* el)
{
yajlpp_map root_map(gen);
int col = 0;
@ -98,8 +99,8 @@ void map_elements_to_json2(yajl_gen gen, data_parser &dp, data_parser::element_l
// continue;
}
std::string key_str = dp.get_element_string(
iter.e_sub_elements->front());
std::string key_str
= dp.get_element_string(iter.e_sub_elements->front());
if (key_str.empty()) {
char buffer[32];
@ -113,24 +114,30 @@ void map_elements_to_json2(yajl_gen gen, data_parser &dp, data_parser::element_l
}
}
static
void list_body_elements_to_json(yajl_gen gen, data_parser &dp, data_parser::element_list_t *el)
static void
list_body_elements_to_json(yajl_gen gen,
data_parser& dp,
data_parser::element_list_t* el)
{
for (auto& iter : *el) {
element_to_json(gen, dp, iter);
}
}
static
void list_elements_to_json(yajl_gen gen, data_parser &dp, data_parser::element_list_t *el)
static void
list_elements_to_json(yajl_gen gen,
data_parser& dp,
data_parser::element_list_t* el)
{
yajlpp_array root_array(gen);
list_body_elements_to_json(gen, dp, el);
}
static
void map_elements_to_json(yajl_gen gen, data_parser &dp, data_parser::element_list_t *el)
static void
map_elements_to_json(yajl_gen gen,
data_parser& dp,
data_parser::element_list_t* el)
{
bool unique_names = el->size() > 1;
vector<string> names;
@ -143,16 +150,15 @@ void map_elements_to_json(yajl_gen gen, data_parser &dp, data_parser::element_li
// continue;
}
std::string key_str = dp.get_element_string(
iter.e_sub_elements->front());
std::string key_str
= dp.get_element_string(iter.e_sub_elements->front());
if (key_str.empty()) {
continue;
}
if (find(names.begin(), names.end(), key_str) != names.end()) {
unique_names = false;
break;
}
else {
} else {
names.push_back(key_str);
}
}
@ -161,30 +167,33 @@ void map_elements_to_json(yajl_gen gen, data_parser &dp, data_parser::element_li
if (unique_names) {
map_elements_to_json2(gen, dp, el);
}
else {
} else {
list_elements_to_json(gen, dp, el);
}
}
void elements_to_json(yajl_gen gen, data_parser &dp, data_parser::element_list_t *el, bool root)
void
elements_to_json(yajl_gen gen,
data_parser& dp,
data_parser::element_list_t* el,
bool root)
{
if (el->empty()) {
yajl_gen_null(gen);
}
else {
} else {
switch (el->front().e_token) {
case DNT_PAIR: {
if (root && el->size() == 1) {
const data_parser::element &pair_elem = el->front().get_pair_elem();
const data_parser::element& pair_elem
= el->front().get_pair_elem();
std::string key_str = dp.get_element_string(
pair_elem.e_sub_elements->front());
if (key_str.empty() &&
el->front().get_pair_value().value_token() == DNT_GROUP) {
if (key_str.empty()
&& el->front().get_pair_value().value_token()
== DNT_GROUP) {
element_to_json(gen, dp, el->front().get_pair_value());
}
else {
} else {
yajlpp_map singleton_map(gen);
if (key_str.empty()) {
@ -193,8 +202,7 @@ void elements_to_json(yajl_gen gen, data_parser &dp, data_parser::element_list_t
singleton_map.gen(key_str);
element_to_json(gen, dp, pair_elem.get_pair_value());
}
}
else {
} else {
map_elements_to_json(gen, dp, el);
}
break;

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@ -30,9 +30,12 @@
#ifndef elem_to_json_hh
#define elem_to_json_hh
#include "yajl/api/yajl_gen.h"
#include "data_parser.hh"
#include "yajl/api/yajl_gen.h"
void elements_to_json(yajl_gen gen, data_parser &dp, data_parser::element_list_t *el, bool root = true);
void elements_to_json(yajl_gen gen,
data_parser& dp,
data_parser::element_list_t* el,
bool root = true);
#endif

View File

@ -21,20 +21,20 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "environ_vtab.hh"
#include <stdlib.h>
#include <string.h>
#include "auto_mem.hh"
#include "base/lnav_log.hh"
#include "environ_vtab.hh"
#include "config.h"
using namespace std;
@ -60,9 +60,11 @@ struct vtab_cursor {
static int vt_destructor(sqlite3_vtab* p_svt);
static int vt_create(sqlite3 *db,
static int
vt_create(sqlite3* db,
void* pAux,
int argc, const char *const *argv,
int argc,
const char* const* argv,
sqlite3_vtab** pp_vt,
char** pzErr)
{
@ -85,8 +87,8 @@ static int vt_create(sqlite3 *db,
return rc;
}
static int vt_destructor(sqlite3_vtab *p_svt)
static int
vt_destructor(sqlite3_vtab* p_svt)
{
vtab* p_vt = (vtab*) p_svt;
@ -96,26 +98,33 @@ static int vt_destructor(sqlite3_vtab *p_svt)
return SQLITE_OK;
}
static int vt_connect(sqlite3 *db, void *p_aux,
int argc, const char *const *argv,
sqlite3_vtab **pp_vt, char **pzErr)
static int
vt_connect(sqlite3* db,
void* p_aux,
int argc,
const char* const* argv,
sqlite3_vtab** pp_vt,
char** pzErr)
{
return vt_create(db, p_aux, argc, argv, pp_vt, pzErr);
}
static int vt_disconnect(sqlite3_vtab *pVtab)
static int
vt_disconnect(sqlite3_vtab* pVtab)
{
return vt_destructor(pVtab);
}
static int vt_destroy(sqlite3_vtab *p_vt)
static int
vt_destroy(sqlite3_vtab* p_vt)
{
return vt_destructor(p_vt);
}
static int vt_next(sqlite3_vtab_cursor* cur);
static int vt_open(sqlite3_vtab *p_svt, sqlite3_vtab_cursor **pp_cursor)
static int
vt_open(sqlite3_vtab* p_svt, sqlite3_vtab_cursor** pp_cursor)
{
vtab* p_vt = (vtab*) p_svt;
@ -135,7 +144,8 @@ static int vt_open(sqlite3_vtab *p_svt, sqlite3_vtab_cursor **pp_cursor)
return SQLITE_OK;
}
static int vt_close(sqlite3_vtab_cursor *cur)
static int
vt_close(sqlite3_vtab_cursor* cur)
{
vtab_cursor* p_cur = (vtab_cursor*) cur;
@ -145,14 +155,16 @@ static int vt_close(sqlite3_vtab_cursor *cur)
return SQLITE_OK;
}
static int vt_eof(sqlite3_vtab_cursor *cur)
static int
vt_eof(sqlite3_vtab_cursor* cur)
{
vtab_cursor* vc = (vtab_cursor*) cur;
return vc->env_cursor[0] == NULL;
}
static int vt_next(sqlite3_vtab_cursor *cur)
static int
vt_next(sqlite3_vtab_cursor* cur)
{
vtab_cursor* vc = (vtab_cursor*) cur;
@ -163,7 +175,8 @@ static int vt_next(sqlite3_vtab_cursor *cur)
return SQLITE_OK;
}
static int vt_column(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int col)
static int
vt_column(sqlite3_vtab_cursor* cur, sqlite3_context* ctx, int col)
{
vtab_cursor* vc = (vtab_cursor*) cur;
const char* eq = strchr(vc->env_cursor[0], '=');
@ -171,7 +184,8 @@ static int vt_column(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int col)
switch (col) {
case 0:
sqlite3_result_text(ctx,
vc->env_cursor[0], eq - vc->env_cursor[0],
vc->env_cursor[0],
eq - vc->env_cursor[0],
SQLITE_TRANSIENT);
break;
case 1:
@ -182,7 +196,8 @@ static int vt_column(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int col)
return SQLITE_OK;
}
static int vt_rowid(sqlite3_vtab_cursor *cur, sqlite_int64 *p_rowid)
static int
vt_rowid(sqlite3_vtab_cursor* cur, sqlite_int64* p_rowid)
{
vtab_cursor* p_cur = (vtab_cursor*) cur;
@ -191,33 +206,38 @@ static int vt_rowid(sqlite3_vtab_cursor *cur, sqlite_int64 *p_rowid)
return SQLITE_OK;
}
static int vt_best_index(sqlite3_vtab *tab, sqlite3_index_info *p_info)
static int
vt_best_index(sqlite3_vtab* tab, sqlite3_index_info* p_info)
{
return SQLITE_OK;
}
static int vt_filter(sqlite3_vtab_cursor *p_vtc,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv)
static int
vt_filter(sqlite3_vtab_cursor* p_vtc,
int idxNum,
const char* idxStr,
int argc,
sqlite3_value** argv)
{
return SQLITE_OK;
}
static int vt_update(sqlite3_vtab *tab,
static int
vt_update(sqlite3_vtab* tab,
int argc,
sqlite3_value** argv,
sqlite_int64* rowid)
{
const char *name = (
argc > 2 ? (const char *)sqlite3_value_text(argv[2]) : nullptr);
const char* name
= (argc > 2 ? (const char*) sqlite3_value_text(argv[2]) : nullptr);
vtab* p_vt = (vtab*) tab;
int retval = SQLITE_ERROR;
if (argc != 1 &&
(argc < 3 ||
sqlite3_value_type(argv[2]) == SQLITE_NULL ||
sqlite3_value_type(argv[3]) == SQLITE_NULL ||
sqlite3_value_text(argv[2])[0] == '\0')) {
if (argc != 1
&& (argc < 3 || sqlite3_value_type(argv[2]) == SQLITE_NULL
|| sqlite3_value_type(argv[3]) == SQLITE_NULL
|| sqlite3_value_text(argv[2])[0] == '\0'))
{
tab->zErrMsg = sqlite3_mprintf(
"A non-empty name and value must be provided when inserting an "
"environment variable");
@ -298,16 +318,22 @@ static sqlite3_module vtab_module = {
NULL, /* xFindFunction - function overloading */
};
int register_environ_vtab(sqlite3 *db)
int
register_environ_vtab(sqlite3* db)
{
auto_mem<char, sqlite3_free> errmsg;
int rc;
rc = sqlite3_create_module(db, "environ_vtab_impl", &vtab_module, NULL);
ensure(rc == SQLITE_OK);
if ((rc = sqlite3_exec(db,
if ((rc = sqlite3_exec(
db,
"CREATE VIRTUAL TABLE environ USING environ_vtab_impl()",
NULL, NULL, errmsg.out())) != SQLITE_OK) {
NULL,
NULL,
errmsg.out()))
!= SQLITE_OK)
{
fprintf(stderr, "unable to create environ table %s\n", errmsg.in());
}
return rc;

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

File diff suppressed because it is too large Load Diff

View File

@ -21,30 +21,31 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "base/humanize.time.hh"
#include "lnav_util.hh"
#include "ansi_scrubber.hh"
#include "vtab_module.hh"
#include "relative_time.hh"
#include "field_overlay_source.hh"
#include "readline_highlighters.hh"
#include "vtab_module_json.hh"
#include "ansi_scrubber.hh"
#include "base/humanize.time.hh"
#include "config.h"
#include "lnav_util.hh"
#include "log_format_ext.hh"
#include "log_vtab_impl.hh"
#include "readline_highlighters.hh"
#include "relative_time.hh"
#include "vtab_module.hh"
#include "vtab_module_json.hh"
using namespace std;
json_string extract(const char* str);
void field_overlay_source::build_summary_lines(const listview_curses &lv)
void
field_overlay_source::build_summary_lines(const listview_curses& lv)
{
auto& tc = dynamic_cast<const textview_curses&>(lv);
textfile_sub_source& tss = this->fos_tss;
@ -53,8 +54,8 @@ void field_overlay_source::build_summary_lines(const listview_curses &lv)
this->fos_summary_lines.clear();
{
vis_line_t filled_rows = lv.rows_available(
lv.get_top(), listview_curses::RD_DOWN);
vis_line_t filled_rows
= lv.rows_available(lv.get_top(), listview_curses::RD_DOWN);
vis_line_t height, free_rows;
unsigned long width;
long rate_len = 0;
@ -63,21 +64,20 @@ void field_overlay_source::build_summary_lines(const listview_curses &lv)
free_rows = height - filled_rows - vis_line_t(this->fos_lines.size());
if (free_rows < 2 || !this->fos_show_status) {
this->fos_summary_lines.clear();
}
else {
} else {
string time_span;
double error_rate = 0.0;
if (lv.get_inner_height() == 0) {
time_span = "None";
}
else {
} else {
logline *first_line, *last_line;
time_t now = time(nullptr);
first_line = lss.find_line(lss.at(vis_line_t(0)));
last_line = lss.find_line(lss.at(lv.get_bottom()));
time_span = humanize::time::duration::from_tv(
time_span
= humanize::time::duration::from_tv(
last_line->get_timeval() - first_line->get_timeval())
.to_string();
@ -85,47 +85,51 @@ void field_overlay_source::build_summary_lines(const listview_curses &lv)
time_t five_minutes_ago = local_now - (5 * 60 * 60);
time_t ten_secs_ago = local_now - 10;
auto from_five_min_ago_opt = lss.find_from_time(five_minutes_ago);
auto from_five_min_ago_opt
= lss.find_from_time(five_minutes_ago);
auto from_ten_secs_ago_opt = lss.find_from_time(ten_secs_ago);
auto& bm = tc.get_bookmarks();
auto error_bm_iter = bm.find(&logfile_sub_source::BM_ERRORS);
if (now > last_line->get_time() && from_five_min_ago_opt &&
error_bm_iter != bm.end()) {
if (now > last_line->get_time() && from_five_min_ago_opt
&& error_bm_iter != bm.end())
{
auto& error_bookmarks = error_bm_iter->second;
auto five_min_lower =
lower_bound(error_bookmarks.begin(),
auto five_min_lower
= lower_bound(error_bookmarks.begin(),
error_bookmarks.end(),
from_five_min_ago_opt.value());
if (five_min_lower != error_bookmarks.end()) {
double error_count = distance(
five_min_lower, error_bookmarks.end());
double error_count
= distance(five_min_lower, error_bookmarks.end());
double time_diff = 5.0;
if (first_line->get_time() > five_minutes_ago) {
time_diff = (double) (local_now - first_line->get_time()) /
60.0;
time_diff
= (double) (local_now - first_line->get_time())
/ 60.0;
}
error_rate = error_count / time_diff;
if (from_ten_secs_ago_opt) {
auto ten_sec_lower =
lower_bound(error_bookmarks.begin(),
auto ten_sec_lower
= lower_bound(error_bookmarks.begin(),
error_bookmarks.end(),
from_ten_secs_ago_opt.value());
if (ten_sec_lower != error_bookmarks.end()) {
double recent_error_count = distance(
ten_sec_lower, error_bookmarks.end());
double recent_error_rate =
recent_error_count / 10.0;
double long_error_rate =
error_count / (time_diff * 60.0 / 10.0);
double recent_error_rate
= recent_error_count / 10.0;
double long_error_rate
= error_count / (time_diff * 60.0 / 10.0);
if (long_error_rate == 0.0) {
long_error_rate = 1.0;
}
long computed_rate_len = lrint(ceil(
(recent_error_rate * 40.0) / long_error_rate));
long computed_rate_len
= lrint(ceil((recent_error_rate * 40.0)
/ long_error_rate));
rate_len = min(10L, computed_rate_len);
}
}
@ -161,40 +165,31 @@ void field_overlay_source::build_summary_lines(const listview_curses &lv)
time_span.c_str());
}
string& sum_msg = sum_line.get_string();
sum_line.with_attr(string_attr(
sum_line
.with_attr(string_attr(
line_range(sum_msg.find("Error rate"),
sum_msg.find("Error rate") + rate_len),
&view_curses::VC_STYLE,
A_REVERSE
))
A_REVERSE))
.with_attr(string_attr(
line_range(1, 2),
&view_curses::VC_GRAPHIC,
ACS_ULCORNER
))
line_range(1, 2), &view_curses::VC_GRAPHIC, ACS_ULCORNER))
.with_attr(string_attr(
line_range(2, 6),
&view_curses::VC_GRAPHIC,
ACS_HLINE
))
line_range(2, 6), &view_curses::VC_GRAPHIC, ACS_HLINE))
.with_attr(string_attr(
line_range(sum_msg.length() + 1,
sum_msg.length() + 5),
line_range(sum_msg.length() + 1, sum_msg.length() + 5),
&view_curses::VC_GRAPHIC,
ACS_HLINE
))
ACS_HLINE))
.with_attr(string_attr(
line_range(sum_msg.length() + 5,
sum_msg.length() + 6),
line_range(sum_msg.length() + 5, sum_msg.length() + 6),
&view_curses::VC_GRAPHIC,
ACS_URCORNER
))
ACS_URCORNER))
.right_justify(width - 2);
}
}
}
void field_overlay_source::build_field_lines(const listview_curses &lv)
void
field_overlay_source::build_field_lines(const listview_curses& lv)
{
logfile_sub_source& lss = this->fos_lss;
view_colors& vc = view_colors::singleton();
@ -213,8 +208,8 @@ void field_overlay_source::build_field_lines(const listview_curses &lv)
auto format = file->get_format();
bool display = false;
if (ll->is_time_skewed() ||
ll->get_msg_level() == log_level_t::LEVEL_INVALID) {
if (ll->is_time_skewed()
|| ll->get_msg_level() == log_level_t::LEVEL_INVALID) {
display = true;
}
if (!this->fos_contexts.empty()) {
@ -256,7 +251,8 @@ void field_overlay_source::build_field_lines(const listview_curses &lv)
string& time_str = time_line.get_string();
struct line_range time_lr;
sql_strftime(curr_timestamp, sizeof(curr_timestamp),
sql_strftime(curr_timestamp,
sizeof(curr_timestamp),
ll->get_time(),
ll->get_millis(),
'T');
@ -264,13 +260,13 @@ void field_overlay_source::build_field_lines(const listview_curses &lv)
if (ll->is_time_skewed()) {
time_lr.lr_start = 1;
time_lr.lr_end = 2;
time_line.with_attr(string_attr(time_lr, &view_curses::VC_GRAPHIC,
ACS_LLCORNER));
time_line.with_attr(
string_attr(time_lr, &view_curses::VC_GRAPHIC, ACS_LLCORNER));
time_str.append(" Out-Of-Time-Order Message");
time_lr.lr_start = 3;
time_lr.lr_end = time_str.length();
time_line.with_attr(string_attr(time_lr, &view_curses::VC_ROLE,
view_colors::VCR_SKEWED_TIME));
time_line.with_attr(string_attr(
time_lr, &view_curses::VC_ROLE, view_colors::VCR_SKEWED_TIME));
time_str.append(" --");
}
@ -292,62 +288,65 @@ void field_overlay_source::build_field_lines(const listview_curses &lv)
curr_tv = this->fos_log_helper.ldh_line->get_timeval();
if (ll->is_time_skewed() && time_range.lr_end != -1) {
const char *time_src = this->fos_log_helper.ldh_msg.get_data() +
time_range.lr_start;
const char* time_src
= this->fos_log_helper.ldh_msg.get_data() + time_range.lr_start;
struct timeval actual_tv;
date_time_scanner dts;
struct exttm tm;
dts.set_base_time(format->lf_date_time.dts_base_time);
if (format->lf_date_time.scan(time_src, time_range.length(),
if (format->lf_date_time.scan(time_src,
time_range.length(),
format->get_timestamp_formats(),
&tm, actual_tv,
false) ||
dts.scan(time_src, time_range.length(),
nullptr,
&tm, actual_tv,
false)) {
sql_strftime(orig_timestamp, sizeof(orig_timestamp), actual_tv, 'T');
&tm,
actual_tv,
false)
|| dts.scan(
time_src, time_range.length(), nullptr, &tm, actual_tv, false))
{
sql_strftime(
orig_timestamp, sizeof(orig_timestamp), actual_tv, 'T');
time_str.append("; Actual Time: ");
time_lr.lr_start = time_str.length();
time_str.append(orig_timestamp);
time_lr.lr_end = time_str.length();
time_line.with_attr(string_attr(
time_lr,
&view_curses::VC_ROLE,
view_colors::VCR_SKEWED_TIME));
time_lr, &view_curses::VC_ROLE, view_colors::VCR_SKEWED_TIME));
timersub(&curr_tv, &actual_tv, &diff_tv);
time_str.append("; Diff: ");
time_lr.lr_start = time_str.length();
time_str.append(humanize::time::duration::from_tv(diff_tv)
.to_string());
time_str.append(
humanize::time::duration::from_tv(diff_tv).to_string());
time_lr.lr_end = time_str.length();
time_line.with_attr(string_attr(
time_lr,
&view_curses::VC_STYLE,
A_BOLD));
time_line.with_attr(
string_attr(time_lr, &view_curses::VC_STYLE, A_BOLD));
}
}
offset_tv = this->fos_log_helper.ldh_file->get_time_offset();
timersub(&curr_tv, &offset_tv, &orig_tv);
sql_strftime(old_timestamp, sizeof(old_timestamp),
orig_tv.tv_sec, orig_tv.tv_usec / 1000,
sql_strftime(old_timestamp,
sizeof(old_timestamp),
orig_tv.tv_sec,
orig_tv.tv_usec / 1000,
'T');
if (offset_tv.tv_sec || offset_tv.tv_usec) {
char offset_str[32];
time_str.append(" Pre-adjust Time: ");
time_str.append(old_timestamp);
snprintf(offset_str, sizeof(offset_str),
snprintf(offset_str,
sizeof(offset_str),
" Offset: %+d.%03d",
(int)offset_tv.tv_sec, (int)(offset_tv.tv_usec / 1000));
(int) offset_tv.tv_sec,
(int) (offset_tv.tv_usec / 1000));
time_str.append(offset_str);
}
if ((!this->fos_contexts.empty() && this->fos_contexts.top().c_show) ||
diff_tv.tv_sec > 0) {
if ((!this->fos_contexts.empty() && this->fos_contexts.top().c_show)
|| diff_tv.tv_sec > 0)
{
this->fos_lines.emplace_back(time_line);
}
@ -376,13 +375,15 @@ void field_overlay_source::build_field_lines(const listview_curses &lv)
for (auto iter = this->fos_log_helper.ldh_parser->dp_pairs.begin();
iter != this->fos_log_helper.ldh_parser->dp_pairs.end();
++iter) {
std::string colname = this->fos_log_helper.ldh_parser->get_element_string(
++iter)
{
std::string colname
= this->fos_log_helper.ldh_parser->get_element_string(
iter->e_sub_elements->front());
colname = this->fos_log_helper.ldh_namer->add_column(colname);
this->fos_unknown_key_size = max(
this->fos_unknown_key_size, (int)colname.length());
this->fos_unknown_key_size
= max(this->fos_unknown_key_size, (int) colname.length());
}
auto lf = this->fos_log_helper.ldh_file->get_format();
@ -396,7 +397,6 @@ void field_overlay_source::build_field_lines(const listview_curses &lv)
this->fos_lines.emplace_back(pattern_al);
}
if (this->fos_log_helper.ldh_line_values.empty()) {
this->fos_lines.emplace_back(" No known message fields");
}
@ -415,11 +415,10 @@ void field_overlay_source::build_field_lines(const listview_curses &lv)
string str, value_str = lv.to_string();
if (curr_format != last_format) {
this->fos_lines.emplace_back(" Known message fields for table " +
format_name +
":");
this->fos_lines.back().with_attr(string_attr(
line_range(32, 32 + format_name.length()),
this->fos_lines.emplace_back(" Known message fields for table "
+ format_name + ":");
this->fos_lines.back().with_attr(
string_attr(line_range(32, 32 + format_name.length()),
&view_curses::VC_STYLE,
vc.attrs_for_ident(format_name) | A_BOLD));
last_format = curr_format;
@ -429,7 +428,8 @@ void field_overlay_source::build_field_lines(const listview_curses &lv)
if (lv.lv_meta.lvm_struct_name.empty()) {
if (curr_elf && curr_elf->elf_body_field == lv.lv_meta.lvm_name) {
field_name = LOG_BODY;
} else if (curr_elf && curr_elf->lf_timestamp_field == lv.lv_meta.lvm_name) {
} else if (curr_elf
&& curr_elf->lf_timestamp_field == lv.lv_meta.lvm_name) {
field_name = LOG_TIME;
} else {
field_name = lv.lv_meta.lvm_name.to_string();
@ -476,16 +476,18 @@ void field_overlay_source::build_field_lines(const listview_curses &lv)
&view_curses::VC_STYLE,
vc.attrs_for_ident(lv.lv_meta.lvm_name))
.append(")")
.append(this->fos_known_key_size - lv.lv_meta.lvm_name.size() - 9 + 3, ' ')
.append(this->fos_known_key_size - lv.lv_meta.lvm_name.size()
- 9 + 3,
' ')
.append(" = ")
.append((const char*) js.js_content.in(), js.js_len);
this->fos_lines.emplace_back(al);
this->add_key_line_attrs(this->fos_known_key_size);
}
}
std::map<const intern_string_t, json_ptr_walk::walk_list_t>::iterator json_iter;
std::map<const intern_string_t, json_ptr_walk::walk_list_t>::iterator
json_iter;
if (!this->fos_log_helper.ldh_json_pairs.empty()) {
this->fos_lines.emplace_back(" JSON fields:");
@ -493,14 +495,15 @@ void field_overlay_source::build_field_lines(const listview_curses &lv)
for (json_iter = this->fos_log_helper.ldh_json_pairs.begin();
json_iter != this->fos_log_helper.ldh_json_pairs.end();
++json_iter) {
++json_iter)
{
json_ptr_walk::walk_list_t& jpairs = json_iter->second;
for (size_t lpc = 0; lpc < jpairs.size(); lpc++) {
this->fos_lines.emplace_back(
" " +
this->fos_log_helper.format_json_getter(json_iter->first, lpc) + " = " +
jpairs[lpc].wt_value);
" "
+ this->fos_log_helper.format_json_getter(json_iter->first, lpc)
+ " = " + jpairs[lpc].wt_value);
this->add_key_line_attrs(0);
}
}
@ -514,59 +517,57 @@ void field_overlay_source::build_field_lines(const listview_curses &lv)
auto_mem<char, sqlite3_free> xp_call;
qname = sql_quote_ident(xml_pair.first.first.get());
xp_call = sqlite3_mprintf("xpath(%Q, %s)",
xml_pair.first.second.c_str(),
qname.in());
this->fos_lines.emplace_back(fmt::format(
" {} = {}", xp_call, xml_pair.second));
xp_call = sqlite3_mprintf(
"xpath(%Q, %s)", xml_pair.first.second.c_str(), qname.in());
this->fos_lines.emplace_back(
fmt::format(" {} = {}", xp_call, xml_pair.second));
this->add_key_line_attrs(0);
}
if (!this->fos_contexts.empty() &&
!this->fos_contexts.top().c_show_discovered) {
if (!this->fos_contexts.empty()
&& !this->fos_contexts.top().c_show_discovered) {
return;
}
if (this->fos_log_helper.ldh_parser->dp_pairs.empty()) {
this->fos_lines.emplace_back(" No discovered message fields");
}
else {
this->fos_lines.emplace_back(" Discovered fields for logline table from message format: ");
this->fos_lines.back().with_attr(string_attr(
line_range(23, 23 + 7),
} else {
this->fos_lines.emplace_back(
" Discovered fields for logline table from message format: ");
this->fos_lines.back().with_attr(
string_attr(line_range(23, 23 + 7),
&view_curses::VC_STYLE,
vc.attrs_for_ident("logline")
));
vc.attrs_for_ident("logline")));
auto& al = this->fos_lines.back();
auto& disc_str = al.get_string();
al.with_attr(string_attr(
line_range(disc_str.length(), -1),
&view_curses::VC_STYLE,
A_BOLD));
line_range(disc_str.length(), -1), &view_curses::VC_STYLE, A_BOLD));
disc_str.append(this->fos_log_helper.ldh_msg_format);
}
auto iter = this->fos_log_helper.ldh_parser->dp_pairs.begin();
for (size_t lpc = 0;
lpc < this->fos_log_helper.ldh_parser->dp_pairs.size(); lpc++, ++iter) {
for (size_t lpc = 0; lpc < this->fos_log_helper.ldh_parser->dp_pairs.size();
lpc++, ++iter)
{
auto& name = this->fos_log_helper.ldh_namer->cn_names[lpc];
auto val = this->fos_log_helper.ldh_parser->get_element_string(
iter->e_sub_elements->back());
attr_line_t al(fmt::format(" {} = {}", name, val));
al.with_attr(string_attr(
line_range(3, 3 + name.length()),
al.with_attr(string_attr(line_range(3, 3 + name.length()),
&view_curses::VC_STYLE,
vc.attrs_for_ident(name)));
this->fos_lines.emplace_back(al);
this->add_key_line_attrs(this->fos_unknown_key_size,
this->add_key_line_attrs(
this->fos_unknown_key_size,
lpc == (this->fos_log_helper.ldh_parser->dp_pairs.size() - 1));
}
}
void field_overlay_source::build_meta_line(const listview_curses &lv,
void
field_overlay_source::build_meta_line(const listview_curses& lv,
std::vector<attr_line_t>& dst,
vis_line_t row)
{
@ -586,8 +587,7 @@ void field_overlay_source::build_meta_line(const listview_curses &lv,
.with_attr(string_attr(
line_range(1, 2),
&view_curses::VC_GRAPHIC,
line_meta.bm_tags.empty() ? ACS_LLCORNER : ACS_LTEE
))
line_meta.bm_tags.empty() ? ACS_LLCORNER : ACS_LTEE))
.append(line_meta.bm_comment);
al.insert(0, filename_width, ' ');
dst.emplace_back(al);
@ -595,15 +595,11 @@ void field_overlay_source::build_meta_line(const listview_curses &lv,
if (!line_meta.bm_tags.empty()) {
attr_line_t al;
al.with_string(" +")
.with_attr(string_attr(
line_range(1, 2),
&view_curses::VC_GRAPHIC,
ACS_LLCORNER
));
al.with_string(" +").with_attr(string_attr(
line_range(1, 2), &view_curses::VC_GRAPHIC, ACS_LLCORNER));
for (const auto& str : line_meta.bm_tags) {
al.append(1, ' ')
.append(str, &view_curses::VC_STYLE, vc.attrs_for_ident(str));
al.append(1, ' ').append(
str, &view_curses::VC_STYLE, vc.attrs_for_ident(str));
}
const auto* tc = dynamic_cast<const textview_curses*>(&lv);

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@ -40,15 +40,18 @@
class field_overlay_source : public list_overlay_source {
public:
explicit field_overlay_source(logfile_sub_source &lss, textfile_sub_source &tss)
explicit field_overlay_source(logfile_sub_source& lss,
textfile_sub_source& tss)
: fos_lss(lss), fos_tss(tss), fos_log_helper(lss){
};
void add_key_line_attrs(int key_size, bool last_line = false) {
void add_key_line_attrs(int key_size, bool last_line = false)
{
string_attrs_t& sa = this->fos_lines.back().get_attrs();
struct line_range lr(1, 2);
sa.emplace_back(lr, &view_curses::VC_GRAPHIC, last_line ? ACS_LLCORNER : ACS_LTEE);
sa.emplace_back(
lr, &view_curses::VC_GRAPHIC, last_line ? ACS_LLCORNER : ACS_LTEE);
lr.lr_start = 3 + key_size + 3;
lr.lr_end = -1;
@ -56,9 +59,11 @@ public:
};
bool list_value_for_overlay(const listview_curses& lv,
int y, int bottom,
int y,
int bottom,
vis_line_t row,
attr_line_t &value_out) override {
attr_line_t& value_out) override
{
if (y == 0) {
this->build_field_lines(lv);
this->build_summary_lines(lv);
@ -99,7 +104,8 @@ public:
context(std::string prefix, bool show, bool show_discovered)
: c_prefix(std::move(prefix)), c_show(show),
c_show_discovered(show_discovered)
{}
{
}
std::string c_prefix;
bool c_show{false};

View File

@ -21,35 +21,36 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @file file_collection.cc
*/
#include "config.h"
#include <unordered_map>
#include "file_collection.hh"
#include <glob.h>
#include <unordered_map>
#include "base/opt_util.hh"
#include "base/humanize.network.hh"
#include "base/isc.hh"
#include "logfile.hh"
#include "file_collection.hh"
#include "pcrepp/pcrepp.hh"
#include "tailer/tailer.looper.hh"
#include "service_tags.hh"
#include "base/opt_util.hh"
#include "config.h"
#include "lnav_util.hh"
#include "logfile.hh"
#include "pcap_manager.hh"
#include "pcrepp/pcrepp.hh"
#include "service_tags.hh"
#include "tailer/tailer.looper.hh"
static std::mutex REALPATH_CACHE_MUTEX;
static std::unordered_map<std::string, std::string> REALPATH_CACHE;
child_poll_result_t child_poller::poll(file_collection& fc)
child_poll_result_t
child_poller::poll(file_collection& fc)
{
if (!this->cp_child) {
return child_poll_result_t::FINISHED;
@ -58,18 +59,18 @@ child_poll_result_t child_poller::poll(file_collection& fc)
auto poll_res = std::move(this->cp_child.value()).poll();
this->cp_child = nonstd::nullopt;
return poll_res.match(
[this](auto_pid<process_state::RUNNING>& alive) {
[this](auto_pid<process_state::running>& alive) {
this->cp_child = std::move(alive);
return child_poll_result_t::ALIVE;
},
[this, &fc](auto_pid<process_state::FINISHED>& finished) {
[this, &fc](auto_pid<process_state::finished>& finished) {
this->cp_finalizer(fc, finished);
return child_poll_result_t::FINISHED;
}
);
});
}
void file_collection::close_files(const std::vector<std::shared_ptr<logfile>> &files)
void
file_collection::close_files(const std::vector<std::shared_ptr<logfile>>& files)
{
for (const auto& lf : files) {
auto actual_path_opt = lf->get_actual_path();
@ -89,9 +90,7 @@ void file_collection::close_files(const std::vector<std::shared_ptr<logfile>> &f
} else {
this->fc_file_names.erase(lf->get_filename());
}
auto file_iter = find(this->fc_files.begin(),
this->fc_files.end(),
lf);
auto file_iter = find(this->fc_files.begin(), this->fc_files.end(), lf);
if (file_iter != this->fc_files.end()) {
this->fc_files.erase(file_iter);
}
@ -101,7 +100,8 @@ void file_collection::close_files(const std::vector<std::shared_ptr<logfile>> &f
this->regenerate_unique_file_names();
}
void file_collection::regenerate_unique_file_names()
void
file_collection::regenerate_unique_file_names()
{
unique_path_generator upg;
@ -148,7 +148,8 @@ void file_collection::regenerate_unique_file_names()
}
}
void file_collection::merge(file_collection &other)
void
file_collection::merge(file_collection& other)
{
this->fc_recursive = this->fc_recursive || other.fc_recursive;
this->fc_rotated = this->fc_rotated || other.fc_rotated;
@ -163,9 +164,8 @@ void file_collection::merge(file_collection &other)
for (const auto& lf : other.fc_files) {
this->fc_name_to_errors.erase(lf->get_filename());
}
this->fc_files.insert(this->fc_files.end(),
other.fc_files.begin(),
other.fc_files.end());
this->fc_files.insert(
this->fc_files.end(), other.fc_files.begin(), other.fc_files.end());
this->fc_files_generation += 1;
}
for (auto& pair : other.fc_renamed_files) {
@ -198,9 +198,8 @@ struct same_file {
*/
bool operator()(const std::shared_ptr<logfile>& lf) const
{
return !lf->is_closed() &&
this->sf_stat.st_dev == lf->get_stat().st_dev &&
this->sf_stat.st_ino == lf->get_stat().st_ino;
return !lf->is_closed() && this->sf_stat.st_dev == lf->get_stat().st_dev
&& this->sf_stat.st_ino == lf->get_stat().st_ino;
};
const struct stat& sf_stat;
@ -217,7 +216,8 @@ struct same_file {
*/
std::future<file_collection>
file_collection::watch_logfile(const std::string& filename,
logfile_open_options &loo, bool required)
logfile_open_options& loo,
bool required)
{
file_collection retval;
struct stat st;
@ -237,8 +237,8 @@ file_collection::watch_logfile(const std::string &filename,
if (S_ISDIR(st.st_mode) && this->fc_recursive) {
std::string wilddir = filename + "/*";
if (this->fc_file_names.find(wilddir) ==
this->fc_file_names.end()) {
if (this->fc_file_names.find(wilddir) == this->fc_file_names.end())
{
retval.fc_file_names.emplace(wilddir, logfile_open_options());
}
return lnav::futures::make_ready_future(std::move(retval));
@ -260,7 +260,8 @@ file_collection::watch_logfile(const std::string &filename,
}
if (rc == -1) {
if (required) {
retval.fc_name_to_errors.emplace(filename, file_error_info{
retval.fc_name_to_errors.emplace(filename,
file_error_info{
time(nullptr),
std::string(strerror(errno)),
});
@ -271,8 +272,8 @@ file_collection::watch_logfile(const std::string &filename,
auto stat_iter = find_if(this->fc_new_stats.begin(),
this->fc_new_stats.end(),
[&st](auto& elem) {
return st.st_ino == elem.st_ino &&
st.st_dev == elem.st_dev;
return st.st_ino == elem.st_ino
&& st.st_dev == elem.st_dev;
});
if (stat_iter != this->fc_new_stats.end()) {
// this file is probably a link that we have already scanned in this
@ -281,16 +282,19 @@ file_collection::watch_logfile(const std::string &filename,
}
this->fc_new_stats.emplace_back(st);
auto file_iter = find_if(this->fc_files.begin(),
this->fc_files.end(),
same_file(st));
auto file_iter
= find_if(this->fc_files.begin(), this->fc_files.end(), same_file(st));
if (file_iter == this->fc_files.end()) {
if (this->fc_other_files.find(filename) != this->fc_other_files.end()) {
return lnav::futures::make_ready_future(std::move(retval));
}
auto func = [filename, st, loo, prog = this->fc_progress, errs = this->fc_name_to_errors]() mutable {
auto func = [filename,
st,
loo,
prog = this->fc_progress,
errs = this->fc_name_to_errors]() mutable {
file_collection retval;
if (errs.find(filename) != errs.end()) {
@ -315,15 +319,26 @@ file_collection::watch_logfile(const std::string &filename,
loo.loo_fd = std::move(convert_res.cr_destination);
retval.fc_child_pollers.emplace_back(child_poller{
std::move(convert_res.cr_child),
[filename, st, error_queue = convert_res.cr_error_queue](auto& fc, auto& child) {
if (child.was_normal_exit() && child.exit_status() == EXIT_SUCCESS) {
log_info("pcap[%d] exited normally", child.in());
[filename,
st,
error_queue = convert_res.cr_error_queue](
auto& fc, auto& child) {
if (child.was_normal_exit()
&& child.exit_status() == EXIT_SUCCESS) {
log_info("pcap[%d] exited normally",
child.in());
return;
}
log_error("pcap[%d] exited with %d", child.in(), child.status());
fc.fc_name_to_errors.emplace(filename, file_error_info{
log_error("pcap[%d] exited with %d",
child.in(),
child.status());
fc.fc_name_to_errors.emplace(
filename,
file_error_info{
st.st_mtime,
fmt::format("{}", fmt::join(*error_queue, "\n")),
fmt::format(
"{}",
fmt::join(*error_queue, "\n")),
});
},
});
@ -332,13 +347,15 @@ file_collection::watch_logfile(const std::string &filename,
retval.fc_files.push_back(open_res.unwrap());
} else {
retval.fc_name_to_errors.emplace(
filename, file_error_info{
filename,
file_error_info{
st.st_mtime,
open_res.unwrapErr(),
});
}
} else {
retval.fc_name_to_errors.emplace(filename, file_error_info{
retval.fc_name_to_errors.emplace(filename,
file_error_info{
st.st_mtime,
res.unwrapErr(),
});
@ -347,7 +364,8 @@ file_collection::watch_logfile(const std::string &filename,
}
case file_format_t::FF_ARCHIVE: {
nonstd::optional<std::list<archive_manager::extract_progress>::iterator>
nonstd::optional<
std::list<archive_manager::extract_progress>::iterator>
prog_iter_opt;
if (loo.loo_source == logfile_name_source::ARCHIVE) {
@ -357,8 +375,7 @@ file_collection::watch_logfile(const std::string &filename,
auto res = archive_manager::walk_archive_files(
filename,
[prog, &prog_iter_opt](
const auto &path,
[prog, &prog_iter_opt](const auto& path,
const auto total) {
safe::WriteAccess<safe_scan_progress> sp(*prog);
@ -366,14 +383,12 @@ file_collection::watch_logfile(const std::string &filename,
sp->sp_extractions.erase(prog_iter);
};
auto prog_iter = sp->sp_extractions.emplace(
sp->sp_extractions.begin(),
path, total);
sp->sp_extractions.begin(), path, total);
prog_iter_opt = prog_iter;
return &(*prog_iter);
},
[&filename, &retval](
const auto &tmp_path,
[&filename, &retval](const auto& tmp_path,
const auto& entry) {
auto arc_path = ghc::filesystem::relative(
entry.path(), tmp_path);
@ -400,8 +415,7 @@ file_collection::watch_logfile(const std::string &filename,
log_error("archive extraction failed: %s",
res.unwrapErr().c_str());
retval.clear();
retval.fc_name_to_errors.emplace(
filename,
retval.fc_name_to_errors.emplace(filename,
file_error_info{
st.st_mtime,
res.unwrapErr(),
@ -410,8 +424,7 @@ file_collection::watch_logfile(const std::string &filename,
retval.fc_other_files[filename] = ff;
}
{
prog_iter_opt |
[&prog](auto prog_iter) {
prog_iter_opt | [&prog](auto prog_iter) {
prog->writeAccess()->sp_extractions.erase(
prog_iter);
};
@ -425,10 +438,10 @@ file_collection::watch_logfile(const std::string &filename,
auto open_res = logfile::open(filename, loo);
if (open_res.isOk()) {
retval.fc_files.push_back(open_res.unwrap());
}
else {
} else {
retval.fc_name_to_errors.emplace(
filename, file_error_info{
filename,
file_error_info{
st.st_mtime,
open_res.unwrapErr(),
});
@ -460,7 +473,9 @@ file_collection::watch_logfile(const std::string &filename,
* @param path The glob pattern to expand.
* @param required Passed to watch_logfile.
*/
void file_collection::expand_filename(lnav::futures::future_queue<file_collection> &fq,
void
file_collection::expand_filename(
lnav::futures::future_queue<file_collection>& fq,
const std::string& path,
logfile_open_options& loo,
bool required)
@ -499,26 +514,25 @@ void file_collection::expand_filename(lnav::futures::future_queue<file_collectio
file_collection retval;
isc::to<tailer::looper &, services::remote_tailer_t>()
.send([=](auto &tlooper) {
tlooper.add_remote(rp, loo);
});
isc::to<tailer::looper&, services::remote_tailer_t>().send(
[=](auto& tlooper) { tlooper.add_remote(rp, loo); });
retval.fc_other_files[path] = file_format_t::FF_REMOTE;
{
this->fc_progress->writeAccess()->
sp_tailers[fmt::format("{}", rp.home())].tp_message =
"Initializing...";
this->fc_progress->writeAccess()
->sp_tailers[fmt::format("{}", rp.home())]
.tp_message
= "Initializing...";
}
fq.push_back(lnav::futures::make_ready_future(std::move(retval)));
fq.push_back(
lnav::futures::make_ready_future(std::move(retval)));
return;
}
required = false;
}
}
if (gl->gl_pathc > 1 ||
strcmp(path.c_str(), gl->gl_pathv[0]) != 0) {
if (gl->gl_pathc > 1 || strcmp(path.c_str(), gl->gl_pathv[0]) != 0) {
required = false;
}
@ -530,13 +544,15 @@ void file_collection::expand_filename(lnav::futures::future_queue<file_collectio
if (iter == REALPATH_CACHE.end()) {
auto_mem<char> abspath;
if ((abspath = realpath(gl->gl_pathv[lpc], nullptr)) ==
nullptr) {
if ((abspath = realpath(gl->gl_pathv[lpc], nullptr)) == nullptr)
{
auto errmsg = strerror(errno);
if (required) {
fprintf(stderr, "Cannot find file: %s -- %s",
gl->gl_pathv[lpc], errmsg);
fprintf(stderr,
"Cannot find file: %s -- %s",
gl->gl_pathv[lpc],
errmsg);
} else if (loo.loo_source != logfile_name_source::REMOTE) {
// XXX The remote code path adds the file name before
// the file exists... not sure checking for that here
@ -544,19 +560,20 @@ void file_collection::expand_filename(lnav::futures::future_queue<file_collectio
file_collection retval;
if (gl->gl_pathc == 1) {
retval.fc_name_to_errors.emplace(
path, file_error_info{
retval.fc_name_to_errors.emplace(path,
file_error_info{
time(nullptr),
errmsg,
});
} else {
retval.fc_name_to_errors.emplace(
path_str, file_error_info{
retval.fc_name_to_errors.emplace(path_str,
file_error_info{
time(nullptr),
errmsg,
});
}
fq.push_back(lnav::futures::make_ready_future(std::move(retval)));
fq.push_back(lnav::futures::make_ready_future(
std::move(retval)));
}
continue;
} else {
@ -573,12 +590,12 @@ void file_collection::expand_filename(lnav::futures::future_queue<file_collectio
}
}
file_collection file_collection::rescan_files(bool required)
file_collection
file_collection::rescan_files(bool required)
{
file_collection retval;
lnav::futures::future_queue<file_collection> fq([&retval](auto &fc) {
retval.merge(fc);
});
lnav::futures::future_queue<file_collection> fq(
[&retval](auto& fc) { retval.merge(fc); });
for (auto& pair : this->fc_file_names) {
if (pair.second.loo_fd == -1) {

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
@ -32,19 +32,18 @@
#ifndef lnav_file_collection_hh
#define lnav_file_collection_hh
#include <forward_list>
#include <list>
#include <map>
#include <set>
#include <list>
#include <string>
#include <utility>
#include <forward_list>
#include "safe/safe.h"
#include "base/future_util.hh"
#include "logfile_fwd.hh"
#include "archive_manager.hh"
#include "base/future_util.hh"
#include "file_format.hh"
#include "logfile_fwd.hh"
#include "safe/safe.h"
#include "tailer/tailer.looper.hh"
struct tailer_progress {
@ -64,7 +63,9 @@ struct other_file_descriptor {
other_file_descriptor(file_format_t format = file_format_t::FF_UNKNOWN,
std::string description = "")
: ofd_format(format), ofd_description(std::move(description)) {}
: ofd_format(format), ofd_description(std::move(description))
{
}
};
struct file_error_info {
@ -81,16 +82,22 @@ enum class child_poll_result_t {
class child_poller {
public:
explicit child_poller(auto_pid<process_state::RUNNING> child,
std::function<void(file_collection&, auto_pid<process_state::FINISHED>&)> finalizer)
: cp_child(std::move(child)), cp_finalizer(std::move(finalizer)) {
explicit child_poller(
auto_pid<process_state::running> child,
std::function<void(file_collection&,
auto_pid<process_state::finished>&)> finalizer)
: cp_child(std::move(child)), cp_finalizer(std::move(finalizer))
{
}
child_poller(child_poller&& other) noexcept
: cp_child(std::move(other.cp_child)),
cp_finalizer(std::move(other.cp_finalizer)) {}
cp_finalizer(std::move(other.cp_finalizer))
{
}
child_poller& operator=(child_poller&& other) noexcept {
child_poller& operator=(child_poller&& other) noexcept
{
this->cp_child = std::move(other.cp_child);
this->cp_finalizer = std::move(other.cp_finalizer);
@ -100,9 +107,11 @@ public:
~child_poller() noexcept = default;
child_poll_result_t poll(file_collection& fc);
private:
nonstd::optional<auto_pid<process_state::RUNNING>> cp_child;
std::function<void(file_collection&, auto_pid<process_state::FINISHED>&)> cp_finalizer;
nonstd::optional<auto_pid<process_state::running>> cp_child;
std::function<void(file_collection&, auto_pid<process_state::finished>&)>
cp_finalizer;
};
struct file_collection {
@ -127,7 +136,8 @@ struct file_collection {
file_collection()
: fc_progress(std::make_shared<safe::Safe<scan_progress>>())
{}
{
}
void clear()
{
@ -141,14 +151,13 @@ struct file_collection {
file_collection rescan_files(bool required = false);
void
expand_filename(lnav::futures::future_queue<file_collection> &fq,
void expand_filename(lnav::futures::future_queue<file_collection>& fq,
const std::string& path,
logfile_open_options& loo,
bool required);
std::future<file_collection>
watch_logfile(const std::string &filename, logfile_open_options &loo,
std::future<file_collection> watch_logfile(const std::string& filename,
logfile_open_options& loo,
bool required);
void merge(file_collection& other);
@ -158,5 +167,4 @@ struct file_collection {
void regenerate_unique_file_names();
};
#endif

View File

@ -21,81 +21,76 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @file file_format.hh
*/
#include "config.h"
#include <unordered_map>
#include "file_format.hh"
#include "archive_manager.hh"
#include "auto_fd.hh"
#include "base/fs_util.hh"
#include "base/intern_string.hh"
#include "base/lnav_log.hh"
#include "auto_fd.hh"
#include "file_format.hh"
#include "archive_manager.hh"
#include "config.h"
static bool is_pcap_header(uint8_t *buffer)
static bool
is_pcap_header(uint8_t* buffer)
{
size_t offset = 0;
if (buffer[0] == 0x0a &&
buffer[1] == 0x0d &&
buffer[2] == 0x0d &&
buffer[3] == 0x0a) {
if (buffer[0] == 0x0a && buffer[1] == 0x0d && buffer[2] == 0x0d
&& buffer[3] == 0x0a)
{
offset += sizeof(uint32_t) * 2;
if (buffer[offset + 0] == 0x1a &&
buffer[offset + 1] == 0x2b &&
buffer[offset + 2] == 0x3c &&
buffer[offset + 3] == 0x4d) {
if (buffer[offset + 0] == 0x1a && buffer[offset + 1] == 0x2b
&& buffer[offset + 2] == 0x3c && buffer[offset + 3] == 0x4d)
{
return true;
}
if (buffer[offset + 0] == 0x4d &&
buffer[offset + 1] == 0x3c &&
buffer[offset + 2] == 0x2b &&
buffer[offset + 3] == 0x1a) {
if (buffer[offset + 0] == 0x4d && buffer[offset + 1] == 0x3c
&& buffer[offset + 2] == 0x2b && buffer[offset + 3] == 0x1a)
{
return true;
}
return false;
}
if (buffer[0] == 0xa1 &&
buffer[1] == 0xb2 &&
buffer[2] == 0xc3 &&
buffer[3] == 0xd4) {
if (buffer[0] == 0xa1 && buffer[1] == 0xb2 && buffer[2] == 0xc3
&& buffer[3] == 0xd4)
{
return true;
}
if (buffer[0] == 0xd4 &&
buffer[1] == 0xc3 &&
buffer[2] == 0xb2 &&
buffer[3] == 0xa1) {
if (buffer[0] == 0xd4 && buffer[1] == 0xc3 && buffer[2] == 0xb2
&& buffer[3] == 0xa1)
{
return true;
}
if (buffer[0] == 0xa1 &&
buffer[1] == 0xb2 &&
buffer[2] == 0x3c &&
buffer[3] == 0x4d) {
if (buffer[0] == 0xa1 && buffer[1] == 0xb2 && buffer[2] == 0x3c
&& buffer[3] == 0x4d)
{
return true;
}
if (buffer[0] == 0x4d &&
buffer[1] == 0x3c &&
buffer[2] == 0xb2 &&
buffer[3] == 0xa1) {
if (buffer[0] == 0x4d && buffer[1] == 0x3c && buffer[2] == 0xb2
&& buffer[3] == 0xa1)
{
return true;
}
return false;
}
file_format_t detect_file_format(const ghc::filesystem::path &filename)
file_format_t
detect_file_format(const ghc::filesystem::path& filename)
{
if (archive_manager::is_archive(filename)) {
return file_format_t::FF_ARCHIVE;

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
@ -71,6 +71,6 @@ struct formatter<file_format_t> : formatter<string_view> {
return formatter<string_view>::format(name, ctx);
}
};
}
} // namespace fmt
#endif

View File

@ -21,26 +21,25 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <unistd.h>
#include <string.h>
#include <unistd.h>
#include "base/injector.bind.hh"
#include "base/lnav.gzip.hh"
#include "base/lnav_log.hh"
#include "config.h"
#include "file_collection.hh"
#include "file_vtab.cfg.hh"
#include "log_format.hh"
#include "logfile.hh"
#include "session_data.hh"
#include "vtab_module.hh"
#include "log_format.hh"
#include "file_vtab.cfg.hh"
using namespace std;
@ -63,24 +62,26 @@ CREATE TABLE lnav_file (
);
)";
explicit lnav_file(file_collection& fc) : lf_collection(fc) {
}
explicit lnav_file(file_collection& fc) : lf_collection(fc) {}
iterator begin() {
iterator begin()
{
return this->lf_collection.fc_files.begin();
}
iterator end() {
iterator end()
{
return this->lf_collection.fc_files.end();
}
int get_column(const cursor &vc, sqlite3_context *ctx, int col) {
int get_column(const cursor& vc, sqlite3_context* ctx, int col)
{
auto lf = *vc.iter;
const struct stat& st = lf->get_stat();
const string& name = lf->get_filename();
auto format = lf->get_format();
const char *format_name =
format != nullptr ? format->get_name().get() : nullptr;
const char* format_name = format != nullptr ? format->get_name().get()
: nullptr;
switch (col) {
case 0:
@ -124,28 +125,25 @@ CREATE TABLE lnav_file (
auto errmsg = fmt::format("unable to read file: {}",
strerror(errno));
sqlite3_result_error(ctx, errmsg.c_str(),
errmsg.length());
sqlite3_result_error(
ctx, errmsg.c_str(), errmsg.length());
} else if (rc != lf_stat.st_size) {
auto errmsg = fmt::format("short read of file: {} < {}",
rc, lf_stat.st_size);
auto errmsg = fmt::format(
"short read of file: {} < {}", rc, lf_stat.st_size);
sqlite3_result_error(ctx, errmsg.c_str(),
errmsg.length());
sqlite3_result_error(
ctx, errmsg.c_str(), errmsg.length());
} else if (lnav::gzip::is_gzipped(buf, rc)) {
lnav::gzip::uncompress(lf->get_unique_path(), buf, rc)
.then([ctx](auto uncomp) {
auto pair = uncomp.release();
sqlite3_result_blob64(ctx,
pair.first,
pair.second,
free);
sqlite3_result_blob64(
ctx, pair.first, pair.second, free);
})
.otherwise([ctx](auto msg) {
sqlite3_result_error(ctx,
msg.c_str(),
msg.size());
sqlite3_result_error(
ctx, msg.c_str(), msg.size());
});
} else {
sqlite3_result_blob64(ctx, buf.release(), rc, free);
@ -161,15 +159,16 @@ CREATE TABLE lnav_file (
return SQLITE_OK;
}
int delete_row(sqlite3_vtab *vt, sqlite3_int64 rowid) {
vt->zErrMsg = sqlite3_mprintf(
"Rows cannot be deleted from this table");
int delete_row(sqlite3_vtab* vt, sqlite3_int64 rowid)
{
vt->zErrMsg = sqlite3_mprintf("Rows cannot be deleted from this table");
return SQLITE_ERROR;
};
int insert_row(sqlite3_vtab *tab, sqlite3_int64 &rowid_out) {
tab->zErrMsg = sqlite3_mprintf(
"Rows cannot be inserted into this table");
int insert_row(sqlite3_vtab* tab, sqlite3_int64& rowid_out)
{
tab->zErrMsg
= sqlite3_mprintf("Rows cannot be inserted into this table");
return SQLITE_ERROR;
};
@ -182,7 +181,8 @@ CREATE TABLE lnav_file (
const char* format,
int64_t lines,
int64_t time_offset,
const char *content) {
const char* content)
{
auto lf = this->lf_collection.fc_files[rowid];
struct timeval tv = {
(int) (time_offset / 1000LL),
@ -197,7 +197,8 @@ CREATE TABLE lnav_file (
"real file paths cannot be updated, only symbolic ones");
}
auto iter = this->lf_collection.fc_file_names.find(lf->get_filename());
auto iter
= this->lf_collection.fc_file_names.find(lf->get_filename());
if (iter != this->lf_collection.fc_file_names.end()) {
auto loo = std::move(iter->second);
@ -224,5 +225,5 @@ struct injectable_lnav_file : vtab_module<lnav_file> {
using injectable = injectable_lnav_file(file_collection&);
};
static auto file_binder = injector::bind_multiple<vtab_module_base>()
.add<injectable_lnav_file>();
static auto file_binder
= injector::bind_multiple<vtab_module_base>().add<injectable_lnav_file>();

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
@ -38,6 +38,6 @@ struct config {
int64_t fvc_max_content_size{32 * 1024 * 1024};
};
}
} // namespace file_vtab
#endif

View File

@ -21,25 +21,25 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "files_sub_source.hh"
#include "base/humanize.hh"
#include "base/humanize.network.hh"
#include "base/opt_util.hh"
#include "base/string_util.hh"
#include "config.h"
#include "lnav.hh"
#include "mapbox/variant.hpp"
#include "lnav.hh"
#include "files_sub_source.hh"
namespace files_model {
files_list_selection from_selection(vis_line_t sel_vis)
files_list_selection
from_selection(vis_line_t sel_vis)
{
auto& fc = lnav_data.ld_active_files;
int sel = (int) sel_vis;
@ -71,22 +71,19 @@ files_list_selection from_selection(vis_line_t sel_vis)
return no_selection{};
}
}
} // namespace files_model
files_sub_source::files_sub_source()
{
files_sub_source::files_sub_source() {}
}
bool files_sub_source::list_input_handle_key(listview_curses &lv, int ch)
bool
files_sub_source::list_input_handle_key(listview_curses& lv, int ch)
{
switch (ch) {
case KEY_ENTER:
case '\r': {
auto sel = files_model::from_selection(lv.get_selection());
sel.match(
[](files_model::no_selection) {},
sel.match([](files_model::no_selection) {},
[](files_model::error_selection) {},
[](files_model::other_selection) {},
[&](files_model::file_selection& fs) {
@ -100,7 +97,8 @@ bool files_sub_source::list_input_handle_key(listview_curses &lv, int ch)
if (lf->get_format() != nullptr) {
auto& log_view = lnav_data.ld_views[LNV_LOG];
lss.row_for_time(lf->front().get_timeval()) | [](auto row) {
lss.row_for_time(lf->front().get_timeval()) |
[](auto row) {
lnav_data.ld_views[LNV_LOG].set_top(row);
};
ensure_view(&log_view);
@ -115,8 +113,7 @@ bool files_sub_source::list_input_handle_key(listview_curses &lv, int ch)
lv.reload_data();
lnav_data.ld_mode = LNM_PAGING;
}
);
});
return true;
}
@ -124,8 +121,7 @@ bool files_sub_source::list_input_handle_key(listview_curses &lv, int ch)
case ' ': {
auto sel = files_model::from_selection(lv.get_selection());
sel.match(
[](files_model::no_selection) {},
sel.match([](files_model::no_selection) {},
[](files_model::error_selection) {},
[](files_model::other_selection) {},
[&](files_model::file_selection& fs) {
@ -145,8 +141,7 @@ bool files_sub_source::list_input_handle_key(listview_curses &lv, int ch)
}
lv.reload_data();
}
);
});
return true;
}
case 'n': {
@ -158,15 +153,13 @@ bool files_sub_source::list_input_handle_key(listview_curses &lv, int ch)
return true;
}
case '/': {
execute_command(lnav_data.ld_exec_context,
"prompt search-files");
execute_command(lnav_data.ld_exec_context, "prompt search-files");
return true;
}
case 'X': {
auto sel = files_model::from_selection(lv.get_selection());
sel.match(
[](files_model::no_selection) {},
sel.match([](files_model::no_selection) {},
[&](files_model::error_selection& es) {
auto& fc = lnav_data.ld_active_files;
@ -179,14 +172,17 @@ bool files_sub_source::list_input_handle_key(listview_curses &lv, int ch)
continue;
}
auto rp_opt = humanize::network::path::from_str(name_iter->first);
auto rp_opt = humanize::network::path::from_str(
name_iter->first);
if (rp_opt) {
auto rp = *rp_opt;
if (fmt::format("{}", rp.home()) == es.sb_iter->first) {
if (fmt::format("{}", rp.home())
== es.sb_iter->first) {
fc.fc_other_files.erase(name_iter->first);
name_iter = fc.fc_file_names.erase(name_iter);
name_iter
= fc.fc_file_names.erase(name_iter);
continue;
}
}
@ -198,42 +194,45 @@ bool files_sub_source::list_input_handle_key(listview_curses &lv, int ch)
lv.reload_data();
},
[](files_model::other_selection) {},
[](files_model::file_selection) {}
);
[](files_model::file_selection) {});
return true;
}
}
return false;
}
void files_sub_source::list_input_handle_scroll_out(listview_curses &lv)
void
files_sub_source::list_input_handle_scroll_out(listview_curses& lv)
{
lnav_data.ld_mode = LNM_PAGING;
lnav_data.ld_filter_view.reload_data();
}
size_t files_sub_source::text_line_count()
size_t
files_sub_source::text_line_count()
{
const auto& fc = lnav_data.ld_active_files;
return fc.fc_name_to_errors.size() +
fc.fc_other_files.size() +
fc.fc_files.size();
return fc.fc_name_to_errors.size() + fc.fc_other_files.size()
+ fc.fc_files.size();
}
size_t files_sub_source::text_line_width(textview_curses &curses)
size_t
files_sub_source::text_line_width(textview_curses& curses)
{
return 512;
}
void files_sub_source::text_value_for_line(textview_curses &tc, int line,
void
files_sub_source::text_value_for_line(textview_curses& tc,
int line,
std::string& value_out,
text_sub_source::line_flags_t flags)
{
const auto dim = tc.get_dimensions();
const auto& fc = lnav_data.ld_active_files;
auto filename_width =
std::min(fc.fc_largest_path_length,
auto filename_width
= std::min(fc.fc_largest_path_length,
std::max((size_t) 40, (size_t) dim.second - 30));
if (line < fc.fc_name_to_errors.size()) {
@ -243,9 +242,10 @@ void files_sub_source::text_value_for_line(textview_curses &tc, int line,
auto fn = path.filename().string();
truncate_to(fn, filename_width);
value_out = fmt::format(
FMT_STRING(" {:<{}} {}"),
fn, filename_width, iter->second.fei_description);
value_out = fmt::format(FMT_STRING(" {:<{}} {}"),
fn,
filename_width,
iter->second.fei_description);
return;
}
@ -258,9 +258,10 @@ void files_sub_source::text_value_for_line(textview_curses &tc, int line,
auto fn = path.string();
truncate_to(fn, filename_width);
value_out = fmt::format(
FMT_STRING(" {:<{}} {:14} {}"),
fn, filename_width, iter->second.ofd_format,
value_out = fmt::format(FMT_STRING(" {:<{}} {:14} {}"),
fn,
filename_width,
iter->second.ofd_format,
iter->second.ofd_description);
return;
}
@ -280,31 +281,34 @@ void files_sub_source::text_value_for_line(textview_curses &tc, int line,
for (const auto& pair : lf->get_notes()) {
file_notes.push_back(pair.second);
}
value_out = fmt::format(
FMT_STRING(" {:<{}} {:>8} {} \u2014 {} {}"),
value_out = fmt::format(FMT_STRING(" {:<{}} {:>8} {} \u2014 {} {}"),
fn,
filename_width,
humanize::file_size(lf->get_index_size()),
start_time,
end_time,
fmt::join(file_notes, "; "));
this->fss_last_line_len =
filename_width + 23 + strlen(start_time) + strlen(end_time);
this->fss_last_line_len
= filename_width + 23 + strlen(start_time) + strlen(end_time);
}
void files_sub_source::text_attrs_for_line(textview_curses &tc, int line,
void
files_sub_source::text_attrs_for_line(textview_curses& tc,
int line,
string_attrs_t& value_out)
{
bool selected = lnav_data.ld_mode == LNM_FILES && line == tc.get_selection();
bool selected
= lnav_data.ld_mode == LNM_FILES && line == tc.get_selection();
const auto& fc = lnav_data.ld_active_files;
auto& vcolors = view_colors::singleton();
const auto dim = tc.get_dimensions();
auto filename_width =
std::min(fc.fc_largest_path_length,
auto filename_width
= std::min(fc.fc_largest_path_length,
std::max((size_t) 40, (size_t) dim.second - 30));
if (selected) {
value_out.emplace_back(line_range{0, 1}, &view_curses::VC_GRAPHIC, ACS_RARROW);
value_out.emplace_back(
line_range{0, 1}, &view_curses::VC_GRAPHIC, ACS_RARROW);
}
if (line < fc.fc_name_to_errors.size()) {
@ -328,9 +332,8 @@ void files_sub_source::text_attrs_for_line(textview_curses &tc, int line,
view_colors::VCR_DISABLED_FOCUSED);
}
if (line == fc.fc_other_files.size() - 1) {
value_out.emplace_back(line_range{0, -1},
&view_curses::VC_STYLE,
A_UNDERLINE);
value_out.emplace_back(
line_range{0, -1}, &view_curses::VC_STYLE, A_UNDERLINE);
}
return;
}
@ -338,9 +341,8 @@ void files_sub_source::text_attrs_for_line(textview_curses &tc, int line,
line -= fc.fc_other_files.size();
if (selected) {
value_out.emplace_back(line_range{0, -1},
&view_curses::VC_ROLE,
view_colors::VCR_FOCUSED);
value_out.emplace_back(
line_range{0, -1}, &view_curses::VC_ROLE, view_colors::VCR_FOCUSED);
}
auto& lss = lnav_data.ld_log_source;
@ -353,7 +355,8 @@ void files_sub_source::text_attrs_for_line(textview_curses &tc, int line,
}
value_out.emplace_back(line_range{2, 3}, &view_curses::VC_GRAPHIC, visible);
if (visible == ACS_DIAMOND) {
value_out.emplace_back(line_range{2, 3}, &view_curses::VC_FOREGROUND,
value_out.emplace_back(line_range{2, 3},
&view_curses::VC_FOREGROUND,
vcolors.ansi_to_theme_color(COLOR_GREEN));
}
@ -365,28 +368,35 @@ void files_sub_source::text_attrs_for_line(textview_curses &tc, int line,
lr.lr_start = this->fss_last_line_len;
lr.lr_end = -1;
value_out.emplace_back(lr, &view_curses::VC_FOREGROUND,
value_out.emplace_back(lr,
&view_curses::VC_FOREGROUND,
vcolors.ansi_to_theme_color(COLOR_YELLOW));
}
size_t files_sub_source::text_size_for_line(textview_curses &tc, int line,
size_t
files_sub_source::text_size_for_line(textview_curses& tc,
int line,
text_sub_source::line_flags_t raw)
{
return 0;
}
static
auto spinner_index()
static auto
spinner_index()
{
auto now = ui_clock::now();
return std::chrono::duration_cast<std::chrono::milliseconds>(
now.time_since_epoch()).count() / 100;
now.time_since_epoch())
.count()
/ 100;
}
bool
files_overlay_source::list_value_for_overlay(const listview_curses &lv, int y,
int bottom, vis_line_t line,
files_overlay_source::list_value_for_overlay(const listview_curses& lv,
int y,
int bottom,
vis_line_t line,
attr_line_t& value_out)
{
if (y == 0) {
@ -401,8 +411,7 @@ files_overlay_source::list_value_for_overlay(const listview_curses &lv, int y,
const auto& prog = sp->sp_extractions.front();
value_out.with_ansi_string(fmt::format(
"{} Extracting "
ANSI_COLOR(COLOR_CYAN) "{}" ANSI_NORM
"{} Extracting " ANSI_COLOR(COLOR_CYAN) "{}" ANSI_NORM
"... {:>8}/{}",
PROG[spinner_index() % PROG_SIZE],
prog.ep_path.filename().string(),
@ -414,8 +423,7 @@ files_overlay_source::list_value_for_overlay(const listview_curses &lv, int y,
auto first_iter = sp->sp_tailers.begin();
value_out.with_ansi_string(fmt::format(
"{} Connecting to "
ANSI_COLOR(COLOR_CYAN) "{}" ANSI_NORM
"{} Connecting to " ANSI_COLOR(COLOR_CYAN) "{}" ANSI_NORM
": {}",
PROG[spinner_index() % PROG_SIZE],
first_iter->first,

View File

@ -21,8 +21,8 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@ -30,11 +30,12 @@
#ifndef files_sub_source_hh
#define files_sub_source_hh
#include "textview_curses.hh"
#include "file_collection.hh"
#include "textview_curses.hh"
class files_sub_source
: public text_sub_source, public list_input_delegate {
: public text_sub_source
, public list_input_delegate {
public:
files_sub_source();
@ -46,15 +47,18 @@ public:
size_t text_line_width(textview_curses& curses) override;
void
text_value_for_line(textview_curses &tc, int line, std::string &value_out,
void text_value_for_line(textview_curses& tc,
int line,
std::string& value_out,
line_flags_t flags) override;
void text_attrs_for_line(textview_curses &tc, int line,
void text_attrs_for_line(textview_curses& tc,
int line,
string_attrs_t& value_out) override;
size_t
text_size_for_line(textview_curses &tc, int line, line_flags_t raw) override;
size_t text_size_for_line(textview_curses& tc,
int line,
line_flags_t raw) override;
bool fss_editing{false};
bool fss_filter_state{false};
@ -62,21 +66,25 @@ public:
};
struct files_overlay_source : public list_overlay_source {
bool list_value_for_overlay(const listview_curses &lv, int y, int bottom,
bool list_value_for_overlay(const listview_curses& lv,
int y,
int bottom,
vis_line_t line,
attr_line_t& value_out) override;
};
namespace files_model {
struct no_selection {};
struct no_selection {
};
template<typename C, typename T>
struct selection_base {
int sb_index{0};
T sb_iter;
static C build(int index, T iter) {
static C build(int index, T iter)
{
C retval;
retval.sb_index = index;
@ -86,22 +94,26 @@ struct selection_base {
};
struct error_selection
: public selection_base<error_selection, std::map<std::string, file_error_info>::iterator> {
: public selection_base<error_selection,
std::map<std::string, file_error_info>::iterator> {
};
struct other_selection
: public selection_base<other_selection, std::map<std::string, other_file_descriptor>::iterator> {
: public selection_base<
other_selection,
std::map<std::string, other_file_descriptor>::iterator> {
};
struct file_selection
: public selection_base<file_selection, std::vector<std::shared_ptr<logfile>>::iterator> {
: public selection_base<file_selection,
std::vector<std::shared_ptr<logfile>>::iterator> {
};
using files_list_selection = mapbox::util::variant<
no_selection, error_selection, other_selection, file_selection>;
using files_list_selection = mapbox::util::
variant<no_selection, error_selection, other_selection, file_selection>;
files_list_selection from_selection(vis_line_t sel_vis);
}
} // namespace files_model
#endif

View File

@ -21,19 +21,19 @@
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "log_format.hh"
#include "filter_observer.hh"
void line_filter_observer::logline_new_lines(const logfile &lf,
#include "config.h"
#include "log_format.hh"
void
line_filter_observer::logline_new_lines(const logfile& lf,
logfile::const_iterator ll_begin,
logfile::const_iterator ll_end,
shared_buffer_ref& sbr)
@ -55,15 +55,17 @@ void line_filter_observer::logline_new_lines(const logfile &lf,
if (filter->lf_deleted) {
continue;
}
if (offset >=
this->lfo_filter_state.tfs_filter_count[filter->get_index()]) {
if (offset
>= this->lfo_filter_state.tfs_filter_count[filter->get_index()])
{
filter->add_line(this->lfo_filter_state, ll_begin, sbr);
}
}
}
}
void line_filter_observer::logline_eof(const logfile &lf)
void
line_filter_observer::logline_eof(const logfile& lf)
{
for (auto& iter : this->lfo_filter_stack) {
if (iter->lf_deleted) {

Some files were not shown because too many files have changed in this diff Show More