[build] some tidying up of the headers

pull/1179/head
Tim Stack 10 months ago
parent 8df83d562a
commit 0361ed5700

@ -532,6 +532,7 @@ add_library(
spectro_impls.hh
spectro_source.hh
sqlitepp.hh
sql_execute.hh
sql_help.hh
sql_util.hh
static_file_vtab.hh

@ -291,6 +291,7 @@ noinst_HEADERS = \
spectro_source.hh \
sqlitepp.hh \
sqlitepp.client.hh \
sql_execute.hh \
sql_help.hh \
sql_util.hh \
sqlite-extension-func.hh \

@ -4,6 +4,7 @@ add_library(
ansi_scrubber.cc
attr_line.cc
attr_line.builder.cc
auto_fd.cc
auto_pid.cc
date_time_scanner.cc
fs_util.cc
@ -25,6 +26,7 @@ add_library(
time_util.cc
ansi_scrubber.hh
ansi_vars.hh
attr_line.hh
attr_line.builder.hh
auto_fd.hh
@ -57,6 +59,7 @@ add_library(
string_attr_type.hh
strnatcmp.h
time_util.hh
types.hh
../third-party/xxHash/xxhash.h
../third-party/xxHash/xxhash.c

@ -22,6 +22,7 @@ noinst_LIBRARIES = libbase.a
noinst_HEADERS = \
ansi_scrubber.hh \
ansi_vars.hh \
attr_line.hh \
attr_line.builder.hh \
auto_fd.hh \
@ -58,12 +59,14 @@ noinst_HEADERS = \
string_attr_type.hh \
string_util.hh \
strnatcmp.h \
time_util.hh
time_util.hh \
types.hh
libbase_a_SOURCES = \
ansi_scrubber.cc \
attr_line.cc \
attr_line.builder.cc \
auto_fd.cc \
auto_pid.cc \
date_time_scanner.cc \
fs_util.cc \

@ -33,6 +33,7 @@
#include "ansi_scrubber.hh"
#include "ansi_vars.hh"
#include "base/opt_util.hh"
#include "config.h"
#include "pcrepp/pcre2pp.hh"

@ -36,7 +36,6 @@
#include <string>
#include "attr_line.hh"
#include "shlex.resolver.hh"
#define ANSI_CSI "\x1b["
#define ANSI_CHAR_ATTR "m"
@ -66,10 +65,4 @@ void scrub_ansi_string(std::string& str, string_attrs_t* sa);
size_t erase_ansi_escapes(string_fragment input);
/**
* Populate a variable map with strings that contain escape sequences that
* might be useful to script writers.
*/
void add_ansi_vars(std::map<std::string, scoped_value_t>& vars);
#endif

@ -0,0 +1,41 @@
/**
* Copyright (c) 2023, Timothy Stack
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Timothy Stack nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* 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
* (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 lnav_ansi_vars_hh
#define lnav_ansi_vars_hh
#include "shlex.resolver.hh"
/**
* Populate a variable map with strings that contain escape sequences that
* might be useful to script writers.
*/
void add_ansi_vars(std::map<std::string, scoped_value_t>& vars);
#endif

@ -0,0 +1,206 @@
/**
* Copyright (c) 2023, Timothy Stack
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Timothy Stack nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* 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
* (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 auto_fd.cc
*/
#include "auto_fd.hh"
#include <fcntl.h>
#include <unistd.h>
#include "lnav_log.hh"
int
auto_fd::pipe(auto_fd* af)
{
int retval, fd[2];
require(af != nullptr);
if ((retval = ::pipe(fd)) == 0) {
af[0] = fd[0];
af[1] = fd[1];
}
return retval;
}
auto_fd
auto_fd::dup_of(int fd)
{
if (fd == -1) {
return auto_fd{};
}
auto new_fd = ::dup(fd);
if (new_fd == -1) {
throw std::bad_alloc();
}
return auto_fd(new_fd);
}
auto_fd::auto_fd(int fd) : af_fd(fd)
{
require(fd >= -1);
}
auto_fd::auto_fd(auto_fd&& af) noexcept : af_fd(af.release()) {}
auto_fd
auto_fd::dup() const
{
int new_fd;
if (this->af_fd == -1 || (new_fd = ::dup(this->af_fd)) == -1) {
throw std::bad_alloc();
}
return auto_fd{new_fd};
}
auto_fd::~auto_fd()
{
this->reset();
}
void
auto_fd::reset(int fd)
{
require(fd >= -1);
if (this->af_fd != fd) {
if (this->af_fd != -1) {
switch (this->af_fd) {
case STDIN_FILENO:
case STDOUT_FILENO:
case STDERR_FILENO:
break;
default:
close(this->af_fd);
break;
}
}
this->af_fd = fd;
}
}
void
auto_fd::close_on_exec() const
{
if (this->af_fd == -1) {
return;
}
log_perror(fcntl(this->af_fd, F_SETFD, FD_CLOEXEC));
}
auto_fd&
auto_fd::operator=(int fd)
{
require(fd >= -1);
this->reset(fd);
return *this;
}
Result<auto_pipe, std::string>
auto_pipe::for_child_fd(int child_fd)
{
auto_pipe retval(child_fd);
if (retval.open() == -1) {
return Err(std::string(strerror(errno)));
}
return Ok(std::move(retval));
}
auto_pipe::auto_pipe(int child_fd, int child_flags)
: ap_child_flags(child_flags), ap_child_fd(child_fd)
{
switch (child_fd) {
case STDIN_FILENO:
this->ap_child_flags = O_RDONLY;
break;
case STDOUT_FILENO:
case STDERR_FILENO:
this->ap_child_flags = O_WRONLY;
break;
}
}
void
auto_pipe::after_fork(pid_t child_pid)
{
int new_fd;
switch (child_pid) {
case -1:
this->close();
break;
case 0:
if (this->ap_child_flags == O_RDONLY) {
this->write_end().reset();
if (this->read_end().get() == -1) {
this->read_end() = ::open("/dev/null", O_RDONLY);
}
new_fd = this->read_end().get();
} else {
this->read_end().reset();
if (this->write_end().get() == -1) {
this->write_end() = ::open("/dev/null", O_WRONLY);
}
new_fd = this->write_end().get();
}
if (this->ap_child_fd != -1) {
if (new_fd != this->ap_child_fd) {
dup2(new_fd, this->ap_child_fd);
this->close();
}
}
break;
default:
if (this->ap_child_flags == O_RDONLY) {
this->read_end().reset();
} else {
this->write_end().reset();
}
break;
}
}
int
auto_pipe::open()
{
int retval = auto_fd::pipe(this->ap_fd);
this->ap_fd[0].close_on_exec();
this->ap_fd[1].close_on_exec();
return retval;
}

@ -32,16 +32,10 @@
#ifndef auto_fd_hh
#define auto_fd_hh
#include <exception>
#include <new>
#include <string>
#include <errno.h>
#include <fcntl.h>
#include <sys/select.h>
#include <unistd.h>
#include "base/lnav_log.hh"
#include "base/result.h"
/**
@ -59,19 +53,7 @@ public:
* contains the reader end of the pipe and the second contains the writer.
* @return The result of the pipe(2) function.
*/
static int pipe(auto_fd* af)
{
int retval, fd[2];
require(af != nullptr);
if ((retval = ::pipe(fd)) == 0) {
af[0] = fd[0];
af[1] = fd[1];
}
return retval;
}
static int pipe(auto_fd* af);
/**
* dup(2) the given file descriptor and wrap it in an auto_fd.
@ -79,27 +61,14 @@ 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)
{
if (fd == -1) {
return auto_fd{};
}
auto new_fd = ::dup(fd);
if (new_fd == -1) {
throw std::bad_alloc();
}
return auto_fd(new_fd);
}
static auto_fd dup_of(int fd);
/**
* Construct an auto_fd to manage the given file descriptor.
*
* @param fd The file descriptor to be managed.
*/
explicit auto_fd(int fd = -1) : af_fd(fd) { require(fd >= -1); }
explicit auto_fd(int fd = -1);
/**
* Non-const copy constructor. Management of the file descriptor will be
@ -108,7 +77,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;
/**
* Const copy constructor. The file descriptor from the source will be
@ -118,21 +87,12 @@ public:
*/
auto_fd(const auto_fd& af) = delete;
auto_fd dup() const
{
int new_fd;
if (this->af_fd == -1 || (new_fd = ::dup(this->af_fd)) == -1) {
throw std::bad_alloc();
}
return auto_fd{new_fd};
}
auto_fd dup() const;
/**
* Destructor that will close the file descriptor managed by this object.
*/
~auto_fd() { this->reset(); }
~auto_fd();
/** @return The file descriptor as a plain integer. */
operator int() const { return this->af_fd; }
@ -144,13 +104,7 @@ public:
* @param fd The file descriptor to store in this object.
* @return *this
*/
auto_fd& operator=(int fd)
{
require(fd >= -1);
this->reset(fd);
return *this;
}
auto_fd& operator=(int fd);
/**
* Transfer management of the given file descriptor to this object.
@ -202,33 +156,9 @@ public:
*
* @param fd The new file descriptor to be managed.
*/
void reset(int fd = -1)
{
require(fd >= -1);
void reset(int fd = -1);
if (this->af_fd != fd) {
if (this->af_fd != -1) {
switch (this->af_fd) {
case STDIN_FILENO:
case STDOUT_FILENO:
case STDERR_FILENO:
break;
default:
close(this->af_fd);
break;
}
}
this->af_fd = fd;
}
}
void close_on_exec() const
{
if (this->af_fd == -1) {
return;
}
log_perror(fcntl(this->af_fd, F_SETFD, FD_CLOEXEC));
}
void close_on_exec() const;
private:
int af_fd; /*< The managed file descriptor. */
@ -236,38 +166,11 @@ private:
class auto_pipe {
public:
static Result<auto_pipe, std::string> for_child_fd(int child_fd)
{
auto_pipe retval(child_fd);
if (retval.open() == -1) {
return Err(std::string(strerror(errno)));
}
return Ok(std::move(retval));
}
static Result<auto_pipe, std::string> for_child_fd(int child_fd);
explicit auto_pipe(int child_fd = -1, int child_flags = O_RDONLY)
: ap_child_flags(child_flags), ap_child_fd(child_fd)
{
switch (child_fd) {
case STDIN_FILENO:
this->ap_child_flags = O_RDONLY;
break;
case STDOUT_FILENO:
case STDERR_FILENO:
this->ap_child_flags = O_WRONLY;
break;
}
}
explicit auto_pipe(int child_fd = -1, int child_flags = O_RDONLY);
int open()
{
int retval = auto_fd::pipe(this->ap_fd);
this->ap_fd[0].close_on_exec();
this->ap_fd[1].close_on_exec();
return retval;
}
int open();
void close()
{
@ -279,44 +182,7 @@ public:
auto_fd& write_end() { return this->ap_fd[1]; }
void after_fork(pid_t child_pid)
{
int new_fd;
switch (child_pid) {
case -1:
this->close();
break;
case 0:
if (this->ap_child_flags == O_RDONLY) {
this->write_end().reset();
if (this->read_end().get() == -1) {
this->read_end() = ::open("/dev/null", O_RDONLY);
}
new_fd = this->read_end().get();
} else {
this->read_end().reset();
if (this->write_end().get() == -1) {
this->write_end() = ::open("/dev/null", O_WRONLY);
}
new_fd = this->write_end().get();
}
if (this->ap_child_fd != -1) {
if (new_fd != this->ap_child_fd) {
dup2(new_fd, this->ap_child_fd);
this->close();
}
}
break;
default:
if (this->ap_child_flags == O_RDONLY) {
this->read_end().reset();
} else {
this->write_end().reset();
}
break;
}
}
void after_fork(pid_t child_pid);
int ap_child_flags;
int ap_child_fd;

@ -33,6 +33,7 @@
#include <string>
#include "auto_fd.hh"
#include "optional.hpp"
#include "result.h"
namespace network {

@ -0,0 +1,35 @@
/**
* Copyright (c) 2023, Timothy Stack
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Timothy Stack nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* 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
* (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 lnav_base_types_hh
#define lnav_base_types_hh
struct null_value_t {};
#endif

@ -41,11 +41,6 @@ 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){
};
bool reserve(size_t size)
{
if (size < this->ba_capacity) {
@ -71,17 +66,11 @@ struct big_array {
this->ba_ptr = (T*) result;
return true;
};
}
void clear()
{
this->ba_size = 0;
};
void clear() { this->ba_size = 0; }
size_t size() const
{
return this->ba_size;
};
size_t size() const { return this->ba_size; }
void shrink_to(size_t new_size)
{
@ -90,47 +79,29 @@ struct big_array {
this->ba_size = new_size;
}
bool empty() const
{
return this->ba_size == 0;
};
bool empty() const { return this->ba_size == 0; }
void push_back(const T& val)
{
this->ba_ptr[this->ba_size] = val;
this->ba_size += 1;
};
}
T& operator[](size_t index)
{
return this->ba_ptr[index];
};
T& operator[](size_t index) { return this->ba_ptr[index]; }
const T& operator[](size_t index) const
{
return this->ba_ptr[index];
};
const T& operator[](size_t index) const { return this->ba_ptr[index]; }
T& back()
{
return this->ba_ptr[this->ba_size - 1];
}
T& back() { return this->ba_ptr[this->ba_size - 1]; }
typedef T* iterator;
using iterator = T*;
iterator begin()
{
return this->ba_ptr;
};
iterator begin() { return this->ba_ptr; }
iterator end()
{
return this->ba_ptr + this->ba_size;
};
iterator end() { return this->ba_ptr + this->ba_size; }
T* ba_ptr;
size_t ba_size;
size_t ba_capacity;
T* ba_ptr{nullptr};
size_t ba_size{0};
size_t ba_capacity{0};
};
#endif

@ -32,6 +32,7 @@
#include "command_executor.hh"
#include "base/ansi_scrubber.hh"
#include "base/ansi_vars.hh"
#include "base/fs_util.hh"
#include "base/injector.hh"
#include "base/itertools.hh"
@ -608,7 +609,7 @@ execute_file(exec_context& ec, const std::string& path_and_args, bool multiline)
log_info("Executing file: %s", path_and_args.c_str());
if (!lexer.split(split_args, ec.ec_local_vars.top())) {
if (!lexer.split(split_args, scoped_resolver{&ec.ec_local_vars.top()})) {
return ec.make_error("unable to parse path");
}
if (split_args.empty()) {
@ -1021,7 +1022,7 @@ add_global_vars(exec_context& ec)
shlex subber(iter.second);
std::string str;
if (!subber.eval(str, ec.ec_global_vars)) {
if (!subber.eval(str, scoped_resolver{&ec.ec_global_vars})) {
log_error("Unable to evaluate global variable value: %s",
iter.second.c_str());
continue;

@ -38,7 +38,6 @@
#include "base/auto_fd.hh"
#include "base/lnav.console.hh"
#include "bookmarks.hh"
#include "fmt/format.h"
#include "ghc/filesystem.hpp"
#include "help_text.hh"

@ -50,7 +50,7 @@ public:
}
void logline_new_lines(const logfile& lf,
logfile::const_iterator ll_begin,
logfile::const_iterator ll_baegin,
logfile::const_iterator ll_end,
const shared_buffer_ref& sbr) override;

@ -46,7 +46,6 @@
#include "base/auto_mem.hh"
#include "base/file_range.hh"
#include "base/is_utf8.hh"
#include "base/lnav_log.hh"
#include "base/result.h"
#include "log_level.hh"
#include "safe/safe.h"

@ -75,6 +75,7 @@
#include "all_logs_vtab.hh"
#include "base/ansi_scrubber.hh"
#include "base/ansi_vars.hh"
#include "base/fs_util.hh"
#include "base/func_util.hh"
#include "base/future_util.hh"

@ -1877,7 +1877,7 @@ detect_mime_type(const ghc::filesystem::path& filename)
auto hexbuf = auto_buffer::alloc(buffer_size * 2);
for (int lpc = 0; lpc < buffer_size; lpc++) {
for (size_t lpc = 0; lpc < buffer_size; lpc++) {
fmt::format_to(
std::back_inserter(hexbuf), FMT_STRING("{:02x}"), buffer[lpc]);
}

@ -53,6 +53,7 @@
#include "fmt/format.h"
#include "lnav_config.hh"
#include "log_format_ext.hh"
#include "sql_execute.hh"
#include "sql_util.hh"
#include "yajlpp/yajlpp.hh"
#include "yajlpp/yajlpp_def.hh"

@ -35,8 +35,7 @@
#include <sqlite3.h>
#include "base/ansi_scrubber.hh"
#include "base/humanize.time.hh"
#include "base/injector.hh"
#include "base/ansi_vars.hh"
#include "base/itertools.hh"
#include "base/string_util.hh"
#include "bound_tags.hh"
@ -140,6 +139,30 @@ logfile_sub_source::find(const char* fn, content_line_t& line_base)
return retval;
}
struct filtered_logline_cmp {
filtered_logline_cmp(const logfile_sub_source& lc) : llss_controller(lc) {}
bool operator()(const uint32_t& lhs, const uint32_t& rhs) const
{
content_line_t cl_lhs = (content_line_t) llss_controller.lss_index[lhs];
content_line_t cl_rhs = (content_line_t) llss_controller.lss_index[rhs];
logline* ll_lhs = this->llss_controller.find_line(cl_lhs);
logline* ll_rhs = this->llss_controller.find_line(cl_rhs);
return (*ll_lhs) < (*ll_rhs);
}
bool operator()(const uint32_t& lhs, const struct timeval& rhs) const
{
content_line_t cl_lhs = (content_line_t) llss_controller.lss_index[lhs];
logline* ll_lhs = this->llss_controller.find_line(cl_lhs);
return (*ll_lhs) < rhs;
}
const logfile_sub_source& llss_controller;
};
nonstd::optional<vis_line_t>
logfile_sub_source::find_from_time(const struct timeval& start) const
{
@ -596,6 +619,53 @@ logfile_sub_source::text_attrs_for_line(textview_curses& lv,
}
}
struct logline_cmp {
logline_cmp(logfile_sub_source& lc) : llss_controller(lc) {}
bool operator()(const content_line_t& lhs, const content_line_t& rhs) const
{
logline* ll_lhs = this->llss_controller.find_line(lhs);
logline* ll_rhs = this->llss_controller.find_line(rhs);
return (*ll_lhs) < (*ll_rhs);
}
bool operator()(const uint32_t& lhs, const uint32_t& rhs) const
{
content_line_t cl_lhs = (content_line_t) llss_controller.lss_index[lhs];
content_line_t cl_rhs = (content_line_t) llss_controller.lss_index[rhs];
logline* ll_lhs = this->llss_controller.find_line(cl_lhs);
logline* ll_rhs = this->llss_controller.find_line(cl_rhs);
return (*ll_lhs) < (*ll_rhs);
}
#if 0
bool operator()(const indexed_content &lhs, const indexed_content &rhs)
{
logline *ll_lhs = this->llss_controller.find_line(lhs.ic_value);
logline *ll_rhs = this->llss_controller.find_line(rhs.ic_value);
return (*ll_lhs) < (*ll_rhs);
}
#endif
bool operator()(const content_line_t& lhs, const time_t& rhs) const
{
logline* ll_lhs = this->llss_controller.find_line(lhs);
return *ll_lhs < rhs;
}
bool operator()(const content_line_t& lhs, const struct timeval& rhs) const
{
logline* ll_lhs = this->llss_controller.find_line(lhs);
return *ll_lhs < rhs;
}
logfile_sub_source& llss_controller;
};
logfile_sub_source::rebuild_result
logfile_sub_source::rebuild_index(
nonstd::optional<ui_clock::time_point> deadline)
@ -1211,6 +1281,24 @@ logfile_sub_source::get_grepper()
(grep_proc_sink<vis_line_t>*) &this->lss_meta_grepper);
}
/**
* Functor for comparing the ld_file field of the logfile_data struct.
*/
struct logfile_data_eq {
explicit logfile_data_eq(std::shared_ptr<logfile> lf)
: lde_file(std::move(lf))
{
}
bool operator()(
const std::unique_ptr<logfile_sub_source::logfile_data>& ld) const
{
return this->lde_file == ld->get_file();
}
std::shared_ptr<logfile> lde_file;
};
bool
logfile_sub_source::insert_file(const std::shared_ptr<logfile>& lf)
{
@ -2418,3 +2506,113 @@ logfile_sub_source::clear_bookmark_metadata()
ld->get_file_ptr()->get_bookmark_metadata().clear();
}
}
void
logfile_sub_source::increase_line_context()
{
auto old_flags = this->lss_flags;
if (this->lss_flags & F_FILENAME) {
// Nothing to do
} else if (this->lss_flags & F_BASENAME) {
this->lss_flags &= ~F_NAME_MASK;
this->lss_flags |= F_FILENAME;
} else {
this->lss_flags |= F_BASENAME;
}
if (old_flags != this->lss_flags) {
this->clear_line_size_cache();
}
}
bool
logfile_sub_source::decrease_line_context()
{
auto old_flags = this->lss_flags;
if (this->lss_flags & F_FILENAME) {
this->lss_flags &= ~F_NAME_MASK;
this->lss_flags |= F_BASENAME;
} else if (this->lss_flags & F_BASENAME) {
this->lss_flags &= ~F_NAME_MASK;
}
if (old_flags != this->lss_flags) {
this->clear_line_size_cache();
return true;
}
return false;
}
size_t
logfile_sub_source::get_filename_offset() const
{
if (this->lss_flags & F_FILENAME) {
return this->lss_filename_width;
} else if (this->lss_flags & F_BASENAME) {
return this->lss_basename_width;
}
return 0;
}
void
logfile_sub_source::clear_min_max_log_times()
{
if (this->lss_min_log_time.tv_sec != 0
|| this->lss_min_log_time.tv_usec != 0
|| this->lss_max_log_time.tv_sec != std::numeric_limits<time_t>::max()
|| this->lss_max_log_time.tv_usec != 0)
{
memset(&this->lss_min_log_time, 0, sizeof(this->lss_min_log_time));
this->lss_max_log_time.tv_sec = std::numeric_limits<time_t>::max();
this->lss_max_log_time.tv_usec = 0;
this->text_filters_changed();
}
}
size_t
logfile_sub_source::file_count() const
{
size_t retval = 0;
const_iterator iter;
for (iter = this->cbegin(); iter != this->cend(); ++iter) {
if (*iter != nullptr && (*iter)->get_file() != nullptr) {
retval += 1;
}
}
return retval;
}
size_t
logfile_sub_source::text_size_for_line(textview_curses& tc,
int row,
text_sub_source::line_flags_t flags)
{
size_t index = row % LINE_SIZE_CACHE_SIZE;
if (this->lss_line_size_cache[index].first != row) {
std::string value;
this->text_value_for_line(tc, row, value, flags);
this->lss_line_size_cache[index].second = value.size();
this->lss_line_size_cache[index].first = row;
}
return this->lss_line_size_cache[index].second;
}
int
logfile_sub_source::get_filtered_count_for(size_t filter_index) const
{
int retval = 0;
for (const auto& ld : this->lss_files) {
retval += ld->ld_filter_state.lfo_filter_state
.tfs_filter_hits[filter_index];
}
return retval;
}

@ -253,52 +253,11 @@ public:
~logfile_sub_source() = default;
void increase_line_context()
{
auto old_flags = this->lss_flags;
if (this->lss_flags & F_FILENAME) {
// Nothing to do
} else if (this->lss_flags & F_BASENAME) {
this->lss_flags &= ~F_NAME_MASK;
this->lss_flags |= F_FILENAME;
} else {
this->lss_flags |= F_BASENAME;
}
if (old_flags != this->lss_flags) {
this->clear_line_size_cache();
}
}
bool decrease_line_context()
{
auto old_flags = this->lss_flags;
void increase_line_context();
if (this->lss_flags & F_FILENAME) {
this->lss_flags &= ~F_NAME_MASK;
this->lss_flags |= F_BASENAME;
} else if (this->lss_flags & F_BASENAME) {
this->lss_flags &= ~F_NAME_MASK;
}
if (old_flags != this->lss_flags) {
this->clear_line_size_cache();
return true;
}
return false;
}
size_t get_filename_offset() const
{
if (this->lss_flags & F_FILENAME) {
return this->lss_filename_width;
} else if (this->lss_flags & F_BASENAME) {
return this->lss_basename_width;
}
bool decrease_line_context();
return 0;
}
size_t get_filename_offset() const;
bool is_filename_enabled() const
{
@ -353,20 +312,7 @@ public:
}
}
void clear_min_max_log_times()
{
if (this->lss_min_log_time.tv_sec != 0
|| this->lss_min_log_time.tv_usec != 0
|| this->lss_max_log_time.tv_sec
!= std::numeric_limits<time_t>::max()
|| this->lss_max_log_time.tv_usec != 0)
{
memset(&this->lss_min_log_time, 0, sizeof(this->lss_min_log_time));
this->lss_max_log_time.tv_sec = std::numeric_limits<time_t>::max();
this->lss_max_log_time.tv_usec = 0;
this->text_filters_changed();
}
}
void clear_min_max_log_times();
bool list_input_handle_key(listview_curses& lv, int ch);
@ -387,19 +333,7 @@ public:
return this->lss_longest_line;
}
size_t file_count() const
{
size_t retval = 0;
const_iterator iter;
for (iter = this->cbegin(); iter != this->cend(); ++iter) {
if (*iter != nullptr && (*iter)->get_file() != nullptr) {
retval += 1;
}
}
return retval;
}
size_t file_count() const;
bool empty() const { return this->lss_filtered_index.empty(); }
@ -412,19 +346,7 @@ public:
int row,
string_attrs_t& value_out);
size_t text_size_for_line(textview_curses& tc, int row, line_flags_t flags)
{
size_t index = row % LINE_SIZE_CACHE_SIZE;
if (this->lss_line_size_cache[index].first != row) {
std::string value;
this->text_value_for_line(tc, row, value, flags);
this->lss_line_size_cache[index].second = value.size();
this->lss_line_size_cache[index].first = row;
}
return this->lss_line_size_cache[index].second;
}
size_t text_size_for_line(textview_curses& tc, int row, line_flags_t flags);
void text_mark(const bookmark_type_t* bm, vis_line_t line, bool added);
@ -485,17 +407,7 @@ public:
return this->lss_index.size() - this->lss_filtered_index.size();
}
int get_filtered_count_for(size_t filter_index) const
{
int retval = 0;
for (const auto& ld : this->lss_files) {
retval += ld->ld_filter_state.lfo_filter_state
.tfs_filter_hits[filter_index];
}
return retval;
}
int get_filtered_count_for(size_t filter_index) const;
Result<void, lnav::console::user_message> set_sql_filter(
std::string stmt_str, sqlite3_stmt* stmt);
@ -813,6 +725,21 @@ public:
void quiesce();
struct __attribute__((__packed__)) indexed_content {
indexed_content() = default;
indexed_content(content_line_t cl) : ic_value(cl) {}
operator content_line_t() const
{
return content_line_t(this->ic_value);
}
uint64_t ic_value : 40;
};
big_array<indexed_content> lss_index;
protected:
void text_accel_display_changed() { this->clear_line_size_cache(); }
@ -838,116 +765,6 @@ private:
F_NAME_MASK = (F_FILENAME | F_BASENAME),
};
struct __attribute__((__packed__)) indexed_content {
indexed_content() = default;
indexed_content(content_line_t cl) : ic_value(cl) {}
operator content_line_t() const
{
return content_line_t(this->ic_value);
}
uint64_t ic_value : 40;
};
struct logline_cmp {
logline_cmp(logfile_sub_source& lc) : llss_controller(lc) {}
bool operator()(const content_line_t& lhs,
const content_line_t& rhs) const
{
logline* ll_lhs = this->llss_controller.find_line(lhs);
logline* ll_rhs = this->llss_controller.find_line(rhs);
return (*ll_lhs) < (*ll_rhs);
}
bool operator()(const uint32_t& lhs, const uint32_t& rhs) const
{
content_line_t cl_lhs
= (content_line_t) llss_controller.lss_index[lhs];
content_line_t cl_rhs
= (content_line_t) llss_controller.lss_index[rhs];
logline* ll_lhs = this->llss_controller.find_line(cl_lhs);
logline* ll_rhs = this->llss_controller.find_line(cl_rhs);
return (*ll_lhs) < (*ll_rhs);
}
#if 0
bool operator()(const indexed_content &lhs, const indexed_content &rhs)
{
logline *ll_lhs = this->llss_controller.find_line(lhs.ic_value);
logline *ll_rhs = this->llss_controller.find_line(rhs.ic_value);
return (*ll_lhs) < (*ll_rhs);
}
#endif
bool operator()(const content_line_t& lhs, const time_t& rhs) const
{
logline* ll_lhs = this->llss_controller.find_line(lhs);
return *ll_lhs < rhs;
}
bool operator()(const content_line_t& lhs,
const struct timeval& rhs) const
{
logline* ll_lhs = this->llss_controller.find_line(lhs);
return *ll_lhs < rhs;
}
logfile_sub_source& llss_controller;
};
struct filtered_logline_cmp {
filtered_logline_cmp(const logfile_sub_source& lc) : llss_controller(lc)
{
}
bool operator()(const uint32_t& lhs, const uint32_t& rhs) const
{
content_line_t cl_lhs
= (content_line_t) llss_controller.lss_index[lhs];
content_line_t cl_rhs
= (content_line_t) llss_controller.lss_index[rhs];
logline* ll_lhs = this->llss_controller.find_line(cl_lhs);
logline* ll_rhs = this->llss_controller.find_line(cl_rhs);
return (*ll_lhs) < (*ll_rhs);
}
bool operator()(const uint32_t& lhs, const struct timeval& rhs) const
{
content_line_t cl_lhs
= (content_line_t) llss_controller.lss_index[lhs];
logline* ll_lhs = this->llss_controller.find_line(cl_lhs);
return (*ll_lhs) < rhs;
}
const logfile_sub_source& llss_controller;
};
/**
* Functor for comparing the ld_file field of the logfile_data struct.
*/
struct logfile_data_eq {
explicit logfile_data_eq(std::shared_ptr<logfile> lf)
: lde_file(std::move(lf))
{
}
bool operator()(const std::unique_ptr<logfile_data>& ld) const
{
return this->lde_file == ld->get_file();
}
std::shared_ptr<logfile> lde_file;
};
void clear_line_size_cache()
{
this->lss_line_size_cache.fill(std::make_pair(0, 0));
@ -962,7 +779,6 @@ private:
bool lss_force_rebuild{false};
std::vector<std::unique_ptr<logfile_data>> lss_files;
big_array<indexed_content> lss_index;
std::vector<uint32_t> lss_filtered_index;
auto_mem<sqlite3_stmt> lss_preview_filter_stmt{sqlite3_finalize};

@ -52,12 +52,12 @@ write_timestamp(int fd, log_level_t level, off_t woff)
struct timeval tv;
gettimeofday(&tv, nullptr);
snprintf(time_str,
sizeof(time_str),
"%ld.%d:%c;",
tv.tv_sec,
tv.tv_usec,
level_names[level][0]);
fmt::format_to_n(time_str,
sizeof(time_str),
FMT_STRING("{}.{}:{};"),
tv.tv_sec,
tv.tv_usec,
level_names[level][0]);
return pwrite(fd, time_str, strlen(time_str), woff);
}

@ -235,10 +235,10 @@ readline_context::completion_generator(const char* text_in, int state)
if (arg_needs_shlex) {
shlex arg_lexer(text_str);
std::map<std::string, std::string> scope;
std::map<std::string, scoped_value_t> scope;
std::string result;
if (arg_lexer.eval(result, scope)) {
if (arg_lexer.eval(result, scoped_resolver{&scope})) {
text_str = result;
}
}
@ -381,11 +381,11 @@ readline_context::attempted_completion(const char* text, int start, int end)
point -= 1;
}
shlex lexer(rl_line_buffer, point);
std::map<std::string, std::string> scope;
std::map<std::string, scoped_value_t> scope;
arg_possibilities = nullptr;
rl_completion_append_character = 0;
if (lexer.split(prefix, scope)) {
if (lexer.split(prefix, scoped_resolver{&scope})) {
auto prefix2
= fmt::format(FMT_STRING("{}"), fmt::join(prefix, "\x1f"));
auto prefix_iter = loaded_context->rc_prefixes.find(prefix2);
@ -425,7 +425,7 @@ readline_context::attempted_completion(const char* text, int start, int end)
shlex fn_lexer(rl_line_buffer, rl_point);
std::vector<std::string> fn_list;
fn_lexer.split(fn_list, scope);
fn_lexer.split(fn_list, scoped_resolver{&scope});
const auto& last_fn = fn_list.size() <= 1 ? ""
: fn_list.back();
@ -450,7 +450,7 @@ readline_context::attempted_completion(const char* text, int start, int end)
std::vector<std::string> fn_list;
int found = 0;
fn_lexer.split(fn_list, scope);
fn_lexer.split(fn_list, scoped_resolver{&scope});
const auto& last_fn = fn_list.size() <= 1 ? ""
: fn_list.back();

@ -194,20 +194,6 @@ public:
std::vector<shared_buffer_ref*> sb_refs;
};
struct tmp_shared_buffer {
explicit tmp_shared_buffer(const char* str, size_t len = -1)
{
if (len == (size_t) -1) {
len = strlen(str);
}
this->tsb_ref.share(this->tsb_manager, (char*) str, len);
};
shared_buffer tsb_manager;
shared_buffer_ref tsb_ref;
};
inline std::string
to_string(const shared_buffer_ref& sbr)
{

@ -216,3 +216,125 @@ shlex::resolve_home_dir(std::string& result, string_fragment cap) const
}
}
}
bool
shlex::eval(std::string& result, const scoped_resolver& vars)
{
result.clear();
string_fragment cap;
shlex_token_t token;
int last_index = 0;
while (this->tokenize(cap, token)) {
result.append(&this->s_str[last_index], cap.sf_begin - last_index);
switch (token) {
case shlex_token_t::ST_ERROR:
return false;
case shlex_token_t::ST_ESCAPE:
result.append(1, this->s_str[cap.sf_begin + 1]);
break;
case shlex_token_t::ST_WHITESPACE:
result.append(&this->s_str[cap.sf_begin], cap.length());
break;
case shlex_token_t::ST_VARIABLE_REF:
case shlex_token_t::ST_QUOTED_VARIABLE_REF: {
int extra = token == shlex_token_t::ST_VARIABLE_REF ? 0 : 1;
const std::string var_name(
&this->s_str[cap.sf_begin + 1 + extra],
cap.length() - 1 - extra * 2);
auto local_var = vars.find(var_name);
const char* var_value = getenv(var_name.c_str());
if (local_var != vars.end()) {
result.append(fmt::to_string(local_var->second));
} else if (var_value != nullptr) {
result.append(var_value);
}
break;
}
case shlex_token_t::ST_TILDE:
this->resolve_home_dir(result, cap);
break;
case shlex_token_t::ST_DOUBLE_QUOTE_START:
case shlex_token_t::ST_DOUBLE_QUOTE_END:
result.append("\"");
break;
case shlex_token_t::ST_SINGLE_QUOTE_START:
case shlex_token_t::ST_SINGLE_QUOTE_END:
result.append("'");
break;
default:
break;
}
last_index = cap.sf_end;
}
result.append(&this->s_str[last_index], this->s_len - last_index);
return true;
}
bool
shlex::split(std::vector<std::string>& result, const scoped_resolver& vars)
{
result.clear();
string_fragment cap;
shlex_token_t token;
int last_index = 0;
bool start_new = true;
while (isspace(this->s_str[this->s_index])) {
this->s_index += 1;
}
while (this->tokenize(cap, token)) {
if (start_new) {
result.emplace_back("");
start_new = false;
}
result.back().append(&this->s_str[last_index],
cap.sf_begin - last_index);
switch (token) {
case shlex_token_t::ST_ERROR:
return false;
case shlex_token_t::ST_ESCAPE:
result.back().append(1, this->s_str[cap.sf_begin + 1]);
break;
case shlex_token_t::ST_WHITESPACE:
start_new = true;
break;
case shlex_token_t::ST_VARIABLE_REF:
case shlex_token_t::ST_QUOTED_VARIABLE_REF: {
int extra = token == shlex_token_t::ST_VARIABLE_REF ? 0 : 1;
std::string var_name(&this->s_str[cap.sf_begin + 1 + extra],
cap.length() - 1 - extra * 2);
auto local_var = vars.find(var_name);
const char* var_value = getenv(var_name.c_str());
if (local_var != vars.end()) {
result.back().append(fmt::to_string(local_var->second));
} else if (var_value != nullptr) {
result.back().append(var_value);
}
break;
}
case shlex_token_t::ST_TILDE:
this->resolve_home_dir(result.back(), cap);
break;
default:
break;
}
last_index = cap.sf_end;
}
if (last_index < this->s_len) {
if (start_new || result.empty()) {
result.emplace_back("");
}
result.back().append(&this->s_str[last_index],
this->s_len - last_index);
}
return true;
}

@ -75,126 +75,9 @@ public:
bool tokenize(string_fragment& cap_out, shlex_token_t& token_out);
template<typename Resolver = scoped_resolver>
bool eval(std::string& result, const Resolver& vars)
{
result.clear();
string_fragment cap;
shlex_token_t token;
int last_index = 0;
while (this->tokenize(cap, token)) {
result.append(&this->s_str[last_index], cap.sf_begin - last_index);
switch (token) {
case shlex_token_t::ST_ERROR:
return false;
case shlex_token_t::ST_ESCAPE:
result.append(1, this->s_str[cap.sf_begin + 1]);
break;
case shlex_token_t::ST_WHITESPACE:
result.append(&this->s_str[cap.sf_begin], cap.length());
break;
case shlex_token_t::ST_VARIABLE_REF:
case shlex_token_t::ST_QUOTED_VARIABLE_REF: {
int extra = token == shlex_token_t::ST_VARIABLE_REF ? 0 : 1;
std::string var_name(&this->s_str[cap.sf_begin + 1 + extra],
cap.length() - 1 - extra * 2);
auto local_var = vars.find(var_name);
const char* var_value = getenv(var_name.c_str());
if (local_var != vars.end()) {
result.append(fmt::to_string(local_var->second));
} else if (var_value != nullptr) {
result.append(var_value);
}
break;
}
case shlex_token_t::ST_TILDE:
this->resolve_home_dir(result, cap);
break;
case shlex_token_t::ST_DOUBLE_QUOTE_START:
case shlex_token_t::ST_DOUBLE_QUOTE_END:
result.append("\"");
break;
case shlex_token_t::ST_SINGLE_QUOTE_START:
case shlex_token_t::ST_SINGLE_QUOTE_END:
result.append("'");
break;
default:
break;
}
last_index = cap.sf_end;
}
result.append(&this->s_str[last_index], this->s_len - last_index);
return true;
}
bool eval(std::string& result, const scoped_resolver& vars);
template<typename Resolver>
bool split(std::vector<std::string>& result, const Resolver& vars)
{
result.clear();
string_fragment cap;
shlex_token_t token;
int last_index = 0;
bool start_new = true;
while (isspace(this->s_str[this->s_index])) {
this->s_index += 1;
}
while (this->tokenize(cap, token)) {
if (start_new) {
result.emplace_back("");
start_new = false;
}
result.back().append(&this->s_str[last_index],
cap.sf_begin - last_index);
switch (token) {
case shlex_token_t::ST_ERROR:
return false;
case shlex_token_t::ST_ESCAPE:
result.back().append(1, this->s_str[cap.sf_begin + 1]);
break;
case shlex_token_t::ST_WHITESPACE:
start_new = true;
break;
case shlex_token_t::ST_VARIABLE_REF:
case shlex_token_t::ST_QUOTED_VARIABLE_REF: {
int extra = token == shlex_token_t::ST_VARIABLE_REF ? 0 : 1;
std::string var_name(&this->s_str[cap.sf_begin + 1 + extra],
cap.length() - 1 - extra * 2);
auto local_var = vars.find(var_name);
const char* var_value = getenv(var_name.c_str());
if (local_var != vars.end()) {
result.back().append(fmt::to_string(local_var->second));
} else if (var_value != nullptr) {
result.back().append(var_value);
}
break;
}
case shlex_token_t::ST_TILDE:
this->resolve_home_dir(result.back(), cap);
break;
default:
break;
}
last_index = cap.sf_end;
}
if (last_index < this->s_len) {
if (start_new || result.empty()) {
result.emplace_back("");
}
result.back().append(&this->s_str[last_index],
this->s_len - last_index);
}
return true;
}
bool split(std::vector<std::string>& result, const scoped_resolver& vars);
void reset()
{

@ -37,10 +37,10 @@
#include <vector>
#include "base/intern_string.hh"
#include "base/types.hh"
#include "fmt/format.h"
#include "mapbox/variant.hpp"
struct null_value_t {};
using scoped_value_t = mapbox::util::
variant<std::string, string_fragment, int64_t, double, null_value_t>;
@ -65,7 +65,7 @@ struct formatter<scoped_value_t> : formatter<std::string> {
class scoped_resolver {
public:
scoped_resolver(
std::initializer_list<std::map<std::string, scoped_value_t>*> l)
std::initializer_list<const std::map<std::string, scoped_value_t>*> l)
{
this->sr_stack.insert(this->sr_stack.end(), l.begin(), l.end());
}

@ -0,0 +1,47 @@
/**
* Copyright (c) 2023, Timothy Stack
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Timothy Stack nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* 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
* (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 lnav_sql_execute_hh
#define lnav_sql_execute_hh
#include <vector>
#include <sqlite3.h>
#include "base/lnav.console.hh"
#include "shlex.resolver.hh"
void sql_execute_script(
sqlite3* db,
const std::map<std::string, scoped_value_t>& global_vars,
const char* src_name,
const char* script,
std::vector<lnav::console::user_message>& errors);
#endif

@ -36,7 +36,6 @@
#include "sql_util.hh"
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include "base/auto_mem.hh"
@ -50,7 +49,7 @@
#include "pcrepp/pcre2pp.hh"
#include "readline_context.hh"
#include "readline_highlighters.hh"
#include "shlex.resolver.hh"
#include "sql_execute.hh"
#include "sql_help.hh"
#include "sqlite-extension-func.hh"

@ -109,13 +109,6 @@ char* sql_quote_ident(const char* ident);
std::string sql_safe_ident(const string_fragment& ident);
void sql_execute_script(
sqlite3* db,
const std::map<std::string, scoped_value_t>& global_vars,
const char* src_name,
const char* script,
std::vector<lnav::console::user_message>& errors);
int guess_type_from_pcre(const std::string& pattern, std::string& collator);
const char* sqlite3_type_to_string(int type);

@ -37,8 +37,9 @@
#include <sqlite3.h>
#include "base/auto_mem.hh"
#include "base/intern_string.hh"
#include "base/types.hh"
#include "optional.hpp"
#include "shlex.resolver.hh"
/* XXX figure out how to do this with the template */
void sqlite_close_wrapper(void* mem);

@ -208,11 +208,13 @@ textview_curses::reload_config(error_reporter& reporter)
iter = this->tc_highlights.erase(iter);
}
std::map<std::string, std::string> vars;
std::map<std::string, scoped_value_t> vars;
auto curr_theme_iter
= lnav_config.lc_ui_theme_defs.find(lnav_config.lc_ui_theme);
if (curr_theme_iter != lnav_config.lc_ui_theme_defs.end()) {
vars = curr_theme_iter->second.lt_vars;
for (const auto& vpair : curr_theme_iter->second.lt_vars) {
vars[vpair.first] = vpair.second;
}
}
for (const auto& theme_name : {DEFAULT_THEME_NAME, lnav_config.lc_ui_theme})
@ -247,8 +249,8 @@ textview_curses::reload_config(error_reporter& reporter)
fg1 = sc.sc_color;
bg1 = sc.sc_background_color;
shlex(fg1).eval(fg_color, vars);
shlex(bg1).eval(bg_color, vars);
shlex(fg1).eval(fg_color, scoped_resolver{&vars});
shlex(bg1).eval(bg_color, scoped_resolver{&vars});
auto fg = styling::color_unit::from_str(fg_color).unwrapOrElse(
[&](const auto& msg) {

@ -35,7 +35,6 @@
#include "md2attr_line.hh"
#include "md4cpp.hh"
#include "shlex.hh"
#include "shlex.resolver.hh"
#include "sql_util.hh"
#include "sqlitepp.client.hh"
#include "top_status_source.cfg.hh"
@ -99,7 +98,8 @@ top_status_source::update_user_msg()
std::string user_note;
lexer.with_ignore_quotes(true).eval(
user_note, lnav_data.ld_exec_context.ec_global_vars);
user_note,
scoped_resolver{&lnav_data.ld_exec_context.ec_global_vars});
md2attr_line mdal;
auto parse_res = md4cpp::parse(user_note, mdal);

@ -619,8 +619,12 @@ view_colors::to_attrs(const lnav_theme& lt,
fg1 = sc.sc_color;
bg1 = sc.sc_background_color;
shlex(fg1).eval(fg_color, lt.lt_vars);
shlex(bg1).eval(bg_color, lt.lt_vars);
std::map<std::string, scoped_value_t> vars;
for (const auto& vpair : lt.lt_vars) {
vars[vpair.first] = vpair.second;
}
shlex(fg1).eval(fg_color, scoped_resolver{&vars});
shlex(bg1).eval(bg_color, scoped_resolver{&vars});
auto fg = styling::color_unit::from_str(fg_color).unwrapOrElse(
[&](const auto& msg) {

@ -461,7 +461,8 @@ build_all_help_text()
std::string sub_help_text;
lexer.with_ignore_quotes(true).eval(
sub_help_text, lnav_data.ld_exec_context.ec_global_vars);
sub_help_text,
scoped_resolver{&lnav_data.ld_exec_context.ec_global_vars});
md2attr_line mdal;
auto parse_res = md4cpp::parse(sub_help_text, mdal);

@ -41,11 +41,11 @@
#include "base/lnav.console.hh"
#include "base/lnav_log.hh"
#include "base/string_util.hh"
#include "base/types.hh"
#include "fmt/format.h"
#include "help_text_formatter.hh"
#include "mapbox/variant.hpp"
#include "optional.hpp"
#include "shlex.resolver.hh"
#include "sqlite-extension-func.hh"
lnav::console::user_message sqlite3_error_to_user_message(sqlite3*);
@ -67,10 +67,7 @@ struct sqlite_func_error : std::exception {
{
}
const char* what() const noexcept override
{
return this->e_what.c_str();
}
const char* what() const noexcept override { return this->e_what.c_str(); }
const std::string e_what;
};
@ -83,12 +80,10 @@ struct nullable {
};
template<typename>
struct is_nullable : std::false_type {
};
struct is_nullable : std::false_type {};
template<typename T>
struct is_nullable<nullable<T>> : std::true_type {
};
struct is_nullable<nullable<T>> : std::true_type {};
} // namespace vtab_types
@ -296,7 +291,7 @@ to_sqlite(sqlite3_context* ctx, double val)
inline void
to_sqlite(sqlite3_context* ctx, auto_mem<char> str)
{
auto free_func = str.get_free_func<void(*)(void*)>();
auto free_func = str.get_free_func<void (*)(void*)>();
sqlite3_result_text(ctx, str.release(), -1, free_func);
}
@ -372,8 +367,7 @@ struct optional_counter<Arg> {
};
template<typename Arg1, typename... Args>
struct optional_counter<Arg1, Args...> : optional_counter<Args...> {
};
struct optional_counter<Arg1, Args...> : optional_counter<Args...> {};
template<typename... Args>
struct variadic_counter {
@ -391,8 +385,7 @@ struct variadic_counter<Arg> {
};
template<typename Arg1, typename... Args>
struct variadic_counter<Arg1, Args...> : variadic_counter<Args...> {
};
struct variadic_counter<Arg1, Args...> : variadic_counter<Args...> {};
template<typename F, F f>
struct sqlite_func_adapter;
@ -821,10 +814,7 @@ struct vtab_module : public vtab_module_base {
return sqlite3_exec(db, create_stmt.c_str(), nullptr, nullptr, nullptr);
}
int create(sqlite3* db) override
{
return this->create(db, T::NAME);
}
int create(sqlite3* db) override { return this->create(db, T::NAME); }
sqlite3_module vm_module;
T vm_impl;

@ -80,12 +80,13 @@ main(int argc, char* argv[])
lexer.reset();
std::string result;
if (lexer.eval(result, map<string, string>())) {
std::map<std::string, scoped_value_t> vars;
if (lexer.eval(result, scoped_resolver{&vars})) {
printf("eval -- %s\n", result.c_str());
}
lexer.reset();
std::vector<std::string> sresult;
if (lexer.split(sresult, map<string, string>())) {
if (lexer.split(sresult, scoped_resolver{&vars})) {
printf("split:\n");
for (size_t lpc = 0; lpc < sresult.size(); lpc++) {
printf(" %zu -- %s\n", lpc, sresult[lpc].c_str());

Loading…
Cancel
Save