[build] compress data files embedded in the binary to save some space

Fixes #763
This commit is contained in:
Timothy Stack 2020-12-30 13:49:29 -08:00
parent 63c31838eb
commit 1d17ac7f29
17 changed files with 253 additions and 138 deletions

View File

@ -13,7 +13,8 @@ set(VCS_PACKAGE_STRING "test")
configure_file(config.cmake.h.in config.h)
add_executable(bin2c bin2c.h bin2c.c)
add_executable(bin2c bin2c.hh bin2c.c)
target_link_libraries(bin2c ZLIB::zlib)
add_executable(ptimec ptimec.hh ptimec.c)
@ -89,7 +90,7 @@ function(bin2c)
list(TRANSFORM BIN2C_UNPARSED_ARGUMENTS "\\." "-")
add_custom_command(
OUTPUT "${DST_FILE}.h" "${DST_FILE}.c"
OUTPUT "${DST_FILE}.h" "${DST_FILE}.cc"
COMMAND bin2c "${DST_FILE}" "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_TO_LINK}"
DEPENDS bin2c "${FILE_TO_LINK}"
)
@ -102,14 +103,14 @@ foreach(FILE_TO_LINK
init.sql)
string(REPLACE "." "-" DST_FILE "${FILE_TO_LINK}")
add_custom_command(
OUTPUT "${DST_FILE}.h" "${DST_FILE}.c"
OUTPUT "${DST_FILE}.h" "${DST_FILE}.cc"
COMMAND bin2c "${DST_FILE}" "${CMAKE_CURRENT_SOURCE_DIR}/${FILE_TO_LINK}"
DEPENDS bin2c "${FILE_TO_LINK}"
)
list(
APPEND GEN_SRCS
"${CMAKE_CURRENT_BINARY_DIR}/${DST_FILE}.h"
"${CMAKE_CURRENT_BINARY_DIR}/${DST_FILE}.c"
"${CMAKE_CURRENT_BINARY_DIR}/${DST_FILE}.cc"
)
endforeach(FILE_TO_LINK)
@ -156,11 +157,11 @@ set(FORMAT_FILE_PATHS ${FORMAT_FILES})
list(TRANSFORM FORMAT_FILE_PATHS PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/")
add_custom_command(
OUTPUT default-formats.h default-formats.c
OUTPUT default-formats.h default-formats.cc
COMMAND bin2c -n lnav_format_json default-formats ${FORMAT_FILE_PATHS}
DEPENDS bin2c ${FORMAT_FILES}
)
list(APPEND GEN_SRCS default-formats.h default-formats.c)
list(APPEND GEN_SRCS default-formats.h default-formats.cc)
set(CONFIG_FILES
root-config.json
@ -182,11 +183,11 @@ set(CONFIG_FILE_PATHS ${CONFIG_FILES})
list(TRANSFORM CONFIG_FILE_PATHS PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/")
add_custom_command(
OUTPUT default-config.h default-config.c
OUTPUT default-config.h default-config.cc
COMMAND bin2c -n lnav_config_json default-config ${CONFIG_FILE_PATHS}
DEPENDS bin2c ${CONFIG_FILES}
)
list(APPEND GEN_SRCS default-config.h default-config.c)
list(APPEND GEN_SRCS default-config.h default-config.cc)
set(BUILTIN_LNAV_SCRIPTS
@ -201,11 +202,11 @@ set(BUILTIN_LNAV_SCRIPT_PATHS ${BUILTIN_LNAV_SCRIPTS})
list(TRANSFORM BUILTIN_LNAV_SCRIPT_PATHS PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/")
add_custom_command(
OUTPUT builtin-scripts.h builtin-scripts.c
OUTPUT builtin-scripts.h builtin-scripts.cc
COMMAND bin2c -n lnav_scripts builtin-scripts ${BUILTIN_LNAV_SCRIPT_PATHS}
DEPENDS bin2c ${BUILTIN_LNAV_SCRIPTS}
)
list(APPEND GEN_SRCS builtin-scripts.h builtin-scripts.c)
list(APPEND GEN_SRCS builtin-scripts.h builtin-scripts.cc)
set(BUILTIN_SH_SCRIPTS
scripts/dhclient-summary.lnav
@ -218,11 +219,11 @@ set(BUILTIN_SH_SCRIPT_PATHS ${BUILTIN_SH_SCRIPTS})
list(TRANSFORM BUILTIN_SH_SCRIPT_PATHS PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/")
add_custom_command(
OUTPUT builtin-sh-scripts.h builtin-sh-scripts.c
OUTPUT builtin-sh-scripts.h builtin-sh-scripts.cc
COMMAND bin2c -n lnav_sh_scripts builtin-sh-scripts ${BUILTIN_SH_SCRIPT_PATHS}
DEPENDS bin2c ${BUILTIN_SH_SCRIPTS}
)
list(APPEND GEN_SRCS builtin-sh-scripts.h builtin-sh-scripts.c)
list(APPEND GEN_SRCS builtin-sh-scripts.h builtin-sh-scripts.cc)
add_library(diag STATIC
${GEN_SRCS}
@ -233,7 +234,7 @@ add_library(diag STATIC
ansi_scrubber.cc
archive_manager.cc
attr_line.cc
bin2c.h
bin2c.hh
bookmarks.cc
bottom_status_source.cc
collation-functions.cc

View File

@ -57,7 +57,7 @@ FORMAT_FILES = \
$(srcdir)/formats/xmlrpc_log.json \
$()
default-formats.h default-formats.c: bin2c$(BUILD_EXEEXT) $(FORMAT_FILES)
default-formats.h default-formats.cc: bin2c$(BUILD_EXEEXT) $(FORMAT_FILES)
$(BIN2C_V)./bin2c$(BUILD_EXEEXT) -n lnav_format_json default-formats $(FORMAT_FILES)
CONFIG_FILES = \
@ -75,7 +75,7 @@ CONFIG_FILES = \
$(srcdir)/themes/solarized-light.json \
$()
default-config.h default-config.c: bin2c$(BUILD_EXEEXT) $(CONFIG_FILES)
default-config.h default-config.cc: bin2c$(BUILD_EXEEXT) $(CONFIG_FILES)
$(BIN2C_V)./bin2c$(BUILD_EXEEXT) -n lnav_config_json default-config $(CONFIG_FILES)
BUILTIN_LNAVSCRIPTS = \
@ -86,29 +86,29 @@ BUILTIN_LNAVSCRIPTS = \
$(srcdir)/scripts/search-for.lnav \
$()
builtin-scripts.h builtin-scripts.c: bin2c$(BUILD_EXEEXT) $(BUILTIN_LNAVSCRIPTS)
builtin-scripts.h builtin-scripts.cc: bin2c$(BUILD_EXEEXT) $(BUILTIN_LNAVSCRIPTS)
$(BIN2C_V)./bin2c$(BUILD_EXEEXT) -n lnav_scripts builtin-scripts $(BUILTIN_LNAVSCRIPTS)
BUILTIN_SHSCRIPTS = \
$(srcdir)/scripts/dump-pid.sh \
$()
builtin-sh-scripts.h builtin-sh-scripts.c: bin2c$(BUILD_EXEEXT) $(BUILTIN_SHSCRIPTS)
builtin-sh-scripts.h builtin-sh-scripts.cc: bin2c$(BUILD_EXEEXT) $(BUILTIN_SHSCRIPTS)
$(BIN2C_V)./bin2c$(BUILD_EXEEXT) -n lnav_sh_scripts builtin-sh-scripts $(BUILTIN_SHSCRIPTS)
%-sh.c: $(srcdir)/%.sh bin2c$(BUILD_EXEEXT)
%-sh.cc: $(srcdir)/%.sh bin2c$(BUILD_EXEEXT)
$(BIN2C_V)./bin2c$(BUILD_EXEEXT) $(*)-sh $<
%-txt.c %-txt.h: $(srcdir)/%.txt bin2c$(BUILD_EXEEXT)
%-txt.cc %-txt.h: $(srcdir)/%.txt bin2c$(BUILD_EXEEXT)
$(BIN2C_V)./bin2c$(BUILD_EXEEXT) $(*)-txt $<
%-sql.c %-sql.h: $(srcdir)/%.sql bin2c$(BUILD_EXEEXT)
%-sql.cc %-sql.h: $(srcdir)/%.sql bin2c$(BUILD_EXEEXT)
$(BIN2C_V)./bin2c$(BUILD_EXEEXT) $(*)-sql $<
%-lnav.c %-lnav.h: $(srcdir)/%.lnav bin2c$(BUILD_EXEEXT)
%-lnav.cc %-lnav.h: $(srcdir)/%.lnav bin2c$(BUILD_EXEEXT)
$(BIN2C_V)./bin2c$(BUILD_EXEEXT) $(*)-lnav $<
%-json.c %-json.h: $(srcdir)/%.json bin2c$(BUILD_EXEEXT)
%-json.cc %-json.h: $(srcdir)/%.json bin2c$(BUILD_EXEEXT)
$(BIN2C_V)./bin2c$(BUILD_EXEEXT) $(*)-json $<
TIME_FORMATS = \
@ -186,22 +186,22 @@ view_helpers.$(OBJEXT): help-txt.h
LNAV_BUILT_FILES = \
ansi-palette-json.h \
ansi-palette-json.c \
ansi-palette-json.cc \
builtin-scripts.h \
builtin-scripts.c \
builtin-scripts.cc \
builtin-sh-scripts.h \
builtin-sh-scripts.c \
builtin-sh-scripts.cc \
default-config.h \
default-config.c \
default-config.cc \
default-formats.h \
default-formats.c \
default-formats.cc \
help-txt.h \
help-txt.c \
help-txt.cc \
init-sql.h \
init-sql.c \
init-sql.cc \
time_fmts.cc \
xterm-palette-json.h \
xterm-palette-json.c
xterm-palette-json.cc
AM_LDFLAGS = \
$(STATIC_LDFLAGS) \
@ -254,7 +254,7 @@ noinst_HEADERS = \
auto_mem.hh \
auto_pid.hh \
big_array.hh \
bin2c.h \
bin2c.hh \
bookmarks.hh \
bottom_status_source.hh \
byte_array.hh \
@ -497,10 +497,10 @@ lnav_SOURCES = lnav.cc
lnav_test_SOURCES = lnav.cc test_override.c
bin2c$(BUILD_EXEEXT): bin2c.c
$(AM_V_CC) $(CC_FOR_BUILD) -o $@ $?
$(AM_V_CC) $(CC_FOR_BUILD) -g3 -o $@ $? -lz
ptimec$(BUILD_EXEEXT): ptimec.c
$(AM_V_CC) $(CC_FOR_BUILD) -o $@ $?
$(AM_V_CC) $(CC_FOR_BUILD) -g3 -o $@ $?
if HAVE_RE2C
RE2C_FILES = data_scanner_re.cc log_level_re.cc

View File

@ -8,13 +8,15 @@
// worth it, you can buy me a beer in return. Sandro Sigala
#include <ctype.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <libgen.h>
#include "bin2c.h"
#include <unistd.h>
#include <sys/stat.h>
#include <zlib.h>
#ifndef PATH_MAX
#define PATH_MAX 1024
@ -26,15 +28,19 @@ static const char *HEADER_FMT =
"#ifndef bin2c_%s_h\n"
"#define bin2c_%s_h\n"
"\n"
"#include \"bin2c.h\"\n"
"#include \"bin2c.hh\"\n"
"\n"
"extern \"C\" {\n"
"extern struct bin_src_file %s%s;\n"
"}\n"
"\n"
"#endif\n"
"\n";
struct file_meta {
const char *fm_name;
unsigned int fm_compressed_size;
unsigned int fm_size;
};
void symname(char *dst, const char *fname)
{
strcpy(dst, fname);
@ -45,24 +51,40 @@ void symname(char *dst, const char *fname)
}
}
void process(struct bin_src_file *bsf, FILE *ofile)
void process(struct file_meta *fm, FILE *ofile)
{
FILE *ifile;
struct stat st;
ifile = fopen(bsf->bsf_name, "rb");
if (ifile == NULL)
{
fprintf(stderr, "cannot open %s for reading\n", bsf->bsf_name);
exit(1);
}
if (stat(fm->fm_name, &st) == -1) {
perror("unable to stat file");
exit(1);
}
unsigned char *buf = malloc(st.st_size);
unsigned char *dest = malloc(st.st_size);
int fd = open(fm->fm_name, O_RDONLY);
if (fd == -1) {
perror("unable to open file");
exit(1);
}
int rc;
while ((rc = read(fd, &buf[fm->fm_size], (st.st_size - fm->fm_size))) > 0) {
fm->fm_size += rc;
}
uLongf destLen = st.st_size;
compress(dest, &destLen, buf, st.st_size);
fm->fm_compressed_size = destLen;
int c, col = 1;
char sym[1024];
symname(sym, basename((char *) bsf->bsf_name));
symname(sym, basename((char *) fm->fm_name));
fprintf(ofile, "static const unsigned char %s_data[] = {\n", sym);
while ((c = fgetc(ifile)) != EOF)
{
for (int lpc = 0; lpc < destLen; lpc++) {
c = dest[lpc];
if (col >= 78 - 6)
{
fputc('\n', ofile);
@ -70,15 +92,15 @@ void process(struct bin_src_file *bsf, FILE *ofile)
}
fprintf(ofile, "0x%.2x, ", c);
col += 6;
bsf->bsf_size += 1;
}
fprintf(ofile, "0x00\n");
fprintf(ofile, "\n};\n");
fclose(ifile);
free(buf);
free(dest);
}
void usage(void)
void usage()
{
fprintf(stderr, "usage: bin2c [-n name] <output_file> [input_file1 ...]\n");
exit(1);
@ -121,7 +143,7 @@ int main(int argc, char **argv)
exit(1);
}
snprintf(cname, sizeof(cname), "%s.c", out_base_name);
snprintf(cname, sizeof(cname), "%s.cc", out_base_name);
FILE *cfile = fopen(cname, "wb");
if (cfile == NULL)
{
@ -139,43 +161,53 @@ int main(int argc, char **argv)
}
int array = argc > 1 || name;
char trailer[16];
if (array) {
snprintf(trailer, sizeof(trailer), "[%d]", argc);
} else {
trailer[0] = '\0';
}
fprintf(hfile, HEADER_FMT,
sym,
sym,
sym,
array ? "[]" : "");
sym,
sym,
sym,
trailer);
fclose(hfile);
fprintf(cfile, "#include \"bin2c.h\"\n");
fprintf(cfile, "#include \"bin2c.hh\"\n");
fprintf(cfile, "\n");
struct bin_src_file *meta = alloca(sizeof(struct bin_src_file) * argc);
struct file_meta *meta = alloca(sizeof(struct file_meta) * argc);
memset(meta, 0, sizeof(struct bin_src_file) * argc);
memset(meta, 0, sizeof(struct file_meta) * argc);
for (int lpc = 0; lpc < argc; lpc++) {
meta[lpc].bsf_name = argv[lpc];
meta[lpc].fm_name = argv[lpc];
process(&meta[lpc], cfile);
}
fprintf(cfile, "struct bin_src_file %s%s = {\n", sym, array ? "[]" : "");
fprintf(cfile,
"struct bin_src_file %s%s = {\n",
sym,
trailer);
for (int lpc = 0; lpc < argc; lpc++) {
char sym[1024];
symname(sym, basename((char *) meta[lpc].bsf_name));
symname(sym, basename((char *) meta[lpc].fm_name));
fprintf(cfile, " ");
if (array) {
fprintf(cfile, "{ ");
}
fprintf(cfile, "\"%s\", %s_data, %d",
basename((char *) meta[lpc].bsf_name), sym, meta[lpc].bsf_size);
fprintf(cfile, "\"%s\", %s_data, %d, %d",
basename((char *) meta[lpc].fm_name),
sym,
meta[lpc].fm_compressed_size,
meta[lpc].fm_size);
if (array) {
fprintf(cfile, " },");
}
fprintf(cfile, "\n");
}
if (array) {
fprintf(cfile, " { 0 }\n");
}
fprintf(cfile, "};\n");
fclose(cfile);

View File

@ -1,11 +0,0 @@
#ifndef lnav_bin2c_h
#define lnav_bin2c_h
struct bin_src_file {
const char *bsf_name;
const unsigned char *bsf_data;
unsigned int bsf_size;
};
#endif

69
src/bin2c.hh Normal file
View File

@ -0,0 +1,69 @@
/**
* Copyright (c) 2020, 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 bin2c.hh
*/
#ifndef lnav_bin2c_hh
#define lnav_bin2c_hh
#include <zlib.h>
#include <assert.h>
#include <sys/types.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)
: 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);
assert(rc == Z_OK);
assert(zsize == size);
this->bsf_data[size] = '\0';
};
string_fragment to_string_fragment() const
{
return string_fragment{this->bsf_data.get(), 0, (int) this->bsf_size};
}
const char *get_name() const
{
return this->bsf_name;
}
private:
const char *bsf_name;
std::unique_ptr<unsigned char[]> bsf_data;
ssize_t bsf_size;
};
#endif

View File

@ -6,11 +6,16 @@
"url": "http://docs.openstack.org/openstack-ops/content/logging_monitoring.html",
"regex": {
"std": {
"pattern": "^(?<timestamp>\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}.\\d{3}) (?<pid>\\d+) (?<level>\\w+) (?<logger>.+) \\[(?<tid>.+)\\] (?<body>.*)"
"pattern": "^(?<timestamp>\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}.\\d{3}) (?<pid>\\d+) (?<level>\\w+) (?<logger>\\S+) \\[(?<tid>[^\\]]+)\\] (?<body>.*)"
},
"mod-std": {
"module-format": true,
"pattern": "^(?<level>\\w+) (?<logger>\\S+) \\[(?<tid>[^\\]]+)\\] (?<body>.*)"
}
},
"level-field": "level",
"level": {
"critical": "CRITICAL",
"error": "ERROR",
"info": "INFO",
"warning": "WARNING",

View File

@ -1331,7 +1331,7 @@ static void looper()
define_key("\033Oc", KEY_END);
view_colors &vc = view_colors::singleton();
vc.init();
view_colors::init();
{
setup_highlights(lnav_data.ld_views[LNV_LOG].get_highlights());
@ -2197,7 +2197,7 @@ int main(int argc, char *argv[])
auto_mem<char, sqlite3_free> errmsg;
if (sqlite3_exec(lnav_data.ld_db.in(),
(const char *) init_sql.bsf_data,
init_sql.to_string_fragment().data(),
nullptr,
nullptr,
errmsg.out()) != SQLITE_OK) {
@ -2611,6 +2611,7 @@ int main(int argc, char *argv[])
textview_curses *log_tc, *text_tc, *tc;
bool found_error = false;
view_colors::init();
rescan_files(true);
if (!lnav_data.ld_active_files.fc_name_to_errors.empty()) {
for (const auto& pair : lnav_data.ld_active_files.fc_name_to_errors) {

View File

@ -57,7 +57,7 @@
#include "yajlpp/yajlpp.hh"
#include "yajlpp/yajlpp_def.hh"
#include "styling.hh"
#include "bin2c.h"
#include "bin2c.hh"
#include "default-config.h"
using namespace std;
@ -990,10 +990,10 @@ static void load_config_from(const ghc::filesystem::path &path, vector<string> &
static void load_default_config(struct _lnav_config &config_obj,
const std::string &path,
struct bin_src_file &bsf,
const bin_src_file &bsf,
vector<string> &errors)
{
yajlpp_parse_context ypc_builtin(bsf.bsf_name, &lnav_config_handlers);
yajlpp_parse_context ypc_builtin(bsf.get_name(), &lnav_config_handlers);
auto_mem<yajl_handle_t> handle(yajl_free);
struct userdata ud(errors);
@ -1011,18 +1011,17 @@ static void load_default_config(struct _lnav_config &config_obj,
yajl_config(handle, yajl_allow_comments, 1);
yajl_config(handle, yajl_allow_multiple_values, 1);
if (ypc_builtin.parse(bsf.bsf_data, bsf.bsf_size) == yajl_status_ok) {
if (ypc_builtin.parse(bsf.to_string_fragment()) == yajl_status_ok) {
ypc_builtin.complete_parse();
}
}
static void load_default_configs(struct _lnav_config &config_obj,
const std::string &path,
struct bin_src_file bsf[],
vector<string> &errors)
{
for (int lpc = 0; bsf[lpc].bsf_name; lpc++) {
load_default_config(config_obj, path, bsf[lpc], errors);
for (auto& bsf : lnav_config_json) {
load_default_config(config_obj, path, bsf, errors);
}
}
@ -1030,22 +1029,22 @@ void load_config(const vector<ghc::filesystem::path> &extra_paths, vector<string
{
auto user_config = dotlnav_path() / "config.json";
for (int lpc = 0; lnav_config_json[lpc].bsf_name; lpc++) {
auto &bsf = lnav_config_json[lpc];
for (auto& bsf : lnav_config_json) {
auto sample_path = dotlnav_path() /
"configs" /
"default" /
fmt::format("{}.sample", bsf.bsf_name);
fmt::format("{}.sample", bsf.get_name());
auto fd = auto_fd(openp(sample_path, O_WRONLY|O_TRUNC|O_CREAT, 0644));
if (fd == -1 || write(fd.get(), bsf.bsf_data, bsf.bsf_size) == -1) {
auto sf = bsf.to_string_fragment();
if (fd == -1 || write(fd.get(), sf.data(), sf.length()) == -1) {
perror("error: unable to write default config file");
}
}
{
load_default_configs(lnav_default_config, "*", lnav_config_json, errors);
load_default_configs(lnav_config, "*", lnav_config_json, errors);
load_default_configs(lnav_default_config, "*", errors);
load_default_configs(lnav_config, "*", errors);
for (const auto &extra_path : extra_paths) {
auto config_path = extra_path / "configs/*/*.json";
@ -1080,7 +1079,7 @@ void reset_config(const std::string &path)
{
vector<string> errors;
load_default_configs(lnav_config, path, lnav_config_json, errors);
load_default_configs(lnav_config, path, errors);
reload_config(errors);

View File

@ -55,7 +55,7 @@
#include "default-formats.h"
#include "log_format_loader.hh"
#include "bin2c.h"
#include "bin2c.hh"
using namespace std;
@ -756,50 +756,47 @@ struct json_path_container root_format_handler = json_path_container {
static void write_sample_file()
{
for (int lpc = 0; lnav_format_json[lpc].bsf_name; lpc++) {
auto &bsf = lnav_format_json[lpc];
for (const auto& bsf : lnav_format_json) {
auto sample_path = dotlnav_path() /
fmt::format("formats/default/{}.sample", bsf.bsf_name);
fmt::format("formats/default/{}.sample", bsf.get_name());
auto sf = bsf.to_string_fragment();
auto_fd sample_fd;
if ((sample_fd = openp(sample_path,
O_WRONLY | O_TRUNC | O_CREAT,
0644)) == -1 ||
(write(sample_fd.get(), bsf.bsf_data, bsf.bsf_size) == -1)) {
(write(sample_fd.get(), sf.data(), sf.length()) == -1)) {
perror("error: unable to write default format file");
}
}
for (int lpc = 0; lnav_sh_scripts[lpc].bsf_name; lpc++) {
struct bin_src_file &bsf = lnav_sh_scripts[lpc];
auto sh_path = dotlnav_path() / fmt::format("formats/default/{}", bsf.bsf_name);
for (const auto& bsf : lnav_sh_scripts) {
auto sh_path = dotlnav_path() / fmt::format("formats/default/{}", bsf.get_name());
auto sf = bsf.to_string_fragment();
auto_fd sh_fd;
if ((sh_fd = openp(sh_path, O_WRONLY|O_TRUNC|O_CREAT, 0755)) == -1 ||
write(sh_fd.get(), bsf.bsf_data, strlen((const char *) bsf.bsf_data)) == -1) {
write(sh_fd.get(), sf.data(), sf.length()) == -1) {
perror("error: unable to write default text file");
}
}
for (int lpc = 0; lnav_scripts[lpc].bsf_name; lpc++) {
for (const auto& bsf : lnav_scripts) {
struct script_metadata meta;
struct bin_src_file &bsf = lnav_scripts[lpc];
const char *script_content = reinterpret_cast<const char *>(bsf.bsf_data);
auto sf = bsf.to_string_fragment();
auto_fd script_fd;
char path[2048];
size_t script_len;
struct stat st;
script_len = strlen(script_content);
extract_metadata(script_content, script_len, meta);
extract_metadata(sf.data(), sf.length(), meta);
snprintf(path, sizeof(path), "formats/default/%s.lnav", meta.sm_name.c_str());
auto script_path = dotlnav_path() / path;
if (statp(script_path, &st) == 0 && (size_t) st.st_size == script_len) {
if (statp(script_path, &st) == 0 && (size_t) st.st_size == sf.length()) {
// Assume it's the right contents and move on...
continue;
}
if ((script_fd = openp(script_path, O_WRONLY|O_TRUNC|O_CREAT, 0755)) == -1 ||
write(script_fd.get(), script_content, script_len) == -1) {
write(script_fd.get(), sf.data(), sf.length()) == -1) {
perror("error: unable to write default text file");
}
}
@ -922,8 +919,7 @@ void load_formats(const std::vector<ghc::filesystem::path> &extra_paths,
write_sample_file();
log_debug("Loading default formats");
for (int lpc = 0; lnav_format_json[lpc].bsf_name; lpc++) {
auto &bsf = lnav_format_json[lpc];
for (const auto& bsf : lnav_format_json) {
handle = yajl_alloc(&ypc_builtin.ypc_callbacks, nullptr, &ypc_builtin);
ud.ud_format_names = &retval;
ud.ud_errors = &errors;
@ -933,11 +929,12 @@ void load_formats(const std::vector<ghc::filesystem::path> &extra_paths,
.with_error_reporter(format_error_reporter)
.ypc_userdata = &ud;
yajl_config(handle, yajl_allow_comments, 1);
if (ypc_builtin.parse(bsf.bsf_data, bsf.bsf_size) != yajl_status_ok) {
auto sf = bsf.to_string_fragment();
if (ypc_builtin.parse(sf) != yajl_status_ok) {
errors.push_back("builtin: invalid json -- " +
string((char *) yajl_get_error(handle, 1,
bsf.bsf_data,
bsf.bsf_size)));
(const unsigned char *) sf.data(),
sf.length())));
}
ypc_builtin.complete_parse();
yajl_free(handle);

View File

@ -31,7 +31,6 @@
#include <ctype.h>
#include "base/lnav_log.hh"
#include "log_level.hh"
const char *level_names[LEVEL__MAX + 1] = {

View File

@ -88,6 +88,10 @@ public:
s_len(len) {
};
explicit shlex(const string_fragment &sf)
: s_str(sf.data()), s_len(sf.length()) {
}
explicit shlex(const std::string &str)
: s_str(str.c_str()),
s_len(str.size()) {

View File

@ -69,10 +69,19 @@ static struct json_path_container root_color_handler = {
.with_children(term_color_handler)
};
term_color_palette xterm_colors(xterm_palette_json.bsf_data);
term_color_palette ansi_colors(ansi_palette_json.bsf_data);
term_color_palette *xterm_colors()
{
static term_color_palette retval(xterm_palette_json.to_string_fragment());
term_color_palette *ACTIVE_PALETTE = &ansi_colors;
return &retval;
}
term_color_palette *ansi_colors()
{
static term_color_palette retval(ansi_palette_json.to_string_fragment());
return &retval;
}
bool rgb_color::from_str(const string_fragment &color,
rgb_color &rgb_out,
@ -104,7 +113,7 @@ bool rgb_color::from_str(const string_fragment &color,
return false;
}
for (const auto &xc : xterm_colors.tc_palette) {
for (const auto &xc : xterm_colors()->tc_palette) {
if (color.iequal(xc.xc_name)) {
rgb_out = xc.xc_color;
return true;
@ -156,7 +165,7 @@ bool rgb_color::operator!=(const rgb_color &rhs) const
return !(rhs == *this);
}
term_color_palette::term_color_palette(const unsigned char *json)
term_color_palette::term_color_palette(const string_fragment& json)
{
yajlpp_parse_context ypc_xterm("palette.json", &root_color_handler);
yajl_handle handle;
@ -166,7 +175,7 @@ term_color_palette::term_color_palette(const unsigned char *json)
.with_ignore_unused(true)
.with_obj(this->tc_palette)
.with_handle(handle);
yajl_status st = ypc_xterm.parse(json, strlen((const char *) json));
yajl_status st = ypc_xterm.parse(json);
ensure(st == yajl_status_ok);
st = ypc_xterm.complete_parse();
ensure(st == yajl_status_ok);

View File

@ -108,7 +108,7 @@ struct term_color {
};
struct term_color_palette {
explicit term_color_palette(const unsigned char *json);
explicit term_color_palette(const string_fragment& json);
short match_color(const lab_color &to_match);
@ -173,9 +173,7 @@ struct lnav_theme {
std::map<std::string, highlighter_config> lt_highlights;
};
extern term_color_palette xterm_colors;
extern term_color_palette ansi_colors;
extern term_color_palette *ACTIVE_PALETTE;
extern term_color_palette *xterm_colors();
extern term_color_palette *ansi_colors();
#endif

View File

@ -369,7 +369,8 @@ view_colors &view_colors::singleton()
return s_vc;
}
view_colors::view_colors() : vc_color_pair_end(0)
view_colors::view_colors()
: vc_color_pair_end(0)
{
}
@ -389,6 +390,10 @@ static string COLOR_NAMES[] = {
class color_listener : public lnav_config_listener {
public:
void reload_config(error_reporter &reporter) override {
if (!view_colors::initialized) {
return;
}
auto &vc = view_colors::singleton();
for (const auto &pair : lnav_config.lc_ui_theme_defs) {
@ -412,9 +417,11 @@ public:
};
static color_listener _COLOR_LISTENER;
term_color_palette *view_colors::vc_active_palette;
void view_colors::init()
{
vc_active_palette = ansi_colors();
if (has_colors()) {
static int ansi_colors_to_curses[] = {
COLOR_BLACK,
@ -442,7 +449,7 @@ void view_colors::init()
}
}
if (COLORS >= 256) {
ACTIVE_PALETTE = &xterm_colors;
vc_active_palette = xterm_colors();
}
}
@ -552,7 +559,7 @@ void view_colors::init_roles(const lnav_theme &lt,
if (!rgb_color::from_str(bg_color, rgb_bg, errmsg)) {
reporter(&ident_sc.sc_background_color, errmsg);
}
ident_bg = ACTIVE_PALETTE->match_color(lab_color(rgb_bg));
ident_bg = vc_active_palette->match_color(lab_color(rgb_bg));
}
for (int z = 0; z < 6; z++) {
for (int x = 1; x < 6; x += 2) {
@ -599,8 +606,8 @@ void view_colors::init_roles(const lnav_theme &lt,
return;
}
short fg = ACTIVE_PALETTE->match_color(lab_color(rgb_fg));
short bg = ACTIVE_PALETTE->match_color(lab_color(rgb_bg));
short fg = vc_active_palette->match_color(lab_color(rgb_fg));
short bg = vc_active_palette->match_color(lab_color(rgb_bg));
if (rgb_fg.empty()) {
fg = ansi_fg;
@ -837,7 +844,7 @@ int view_colors::ensure_color_pair(int &pair_base, short fg, short bg)
fg == -1 ? def_fg : fg,
bg == -1 ? def_bg : bg));
if (this->initialized) {
if (initialized) {
this->vc_dyn_pairs[index_pair] = retval;
}
@ -858,7 +865,7 @@ int view_colors::match_color(const rgb_color &color)
return -1;
}
return ACTIVE_PALETTE->match_color(lab_color(color));
return vc_active_palette->match_color(lab_color(color));
}
attr_t view_colors::attrs_for_ident(const char *str, size_t len) const

View File

@ -332,6 +332,7 @@ public:
static bool initialized;
private:
static term_color_palette *vc_active_palette;
/** Private constructor that initializes the member fields. */
view_colors();

View File

@ -167,7 +167,7 @@ static void build_all_help_text()
}
attr_line_t all_help_text;
shlex lexer((const char *) help_txt.bsf_data, help_txt.bsf_size);
shlex lexer(help_txt.to_string_fragment());
string sub_help_text;
lexer.with_ignore_quotes(true)

View File

@ -295,6 +295,10 @@ public:
yajl_status parse(const unsigned char *jsonText, size_t jsonTextLen);
yajl_status parse(const string_fragment& sf) {
return this->parse((const unsigned char *) sf.data(), sf.length());
}
int get_line_number() const;
yajl_status complete_parse();