Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Footnote fundamentals #8

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,11 @@ jobs:
meson introspect --targets build | jq '.[] | select(.type == "executable" and .subproject == null) | .filename[]' | xargs ldd
continue-on-error: true

- if: ${{ matrix.flavor == 'ubuntu' }}
name: Verify valid json
run: |
jq . res/*.json

- if: ${{ matrix.flavor == 'mac' }}
name: ldd macos
run: otool -L build/src/dregarnuhr
Expand Down
3 changes: 2 additions & 1 deletion debian/control
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ Build-Depends: debhelper-compat (= 13),
libctre-dev,
libmagicenum-dev,
libminiz3-dev,
libxml++5.0-dev
libxml++5.0-dev,
libjsoncpp-dev
Standards-Version: 4.6.0
Section: libs
Homepage: https://github.com/talisein/dregarnuhr
Expand Down
1 change: 1 addition & 0 deletions dregarnuhr.spec
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ BuildRequires: libpng-devel
BuildRequires: libjpeg-turbo-devel
BuildRequires: miniz-devel
BuildRequires: outcome-devel
BuildRequires: jsoncpp-devel
BuildRequires: libxml++50-devel >= 5.0.2
BuildRequires: boost-ext-ut-static
BuildRequires: ctre-static
Expand Down
10 changes: 9 additions & 1 deletion meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ else
cpp23_args += '-fexperimental-library'
add_global_link_arguments('-stdlib=libc++', language: 'cpp')

if get_option('buildtype') == 'debug'
if get_option('buildtype') == 'debug' and cpp_compiler.get_linker_id() == 'ld.bfd'
cpp23_args += '-gdwarf-4'
add_global_arguments('-gdwarf-4', language: 'c')
endif
Expand All @@ -50,8 +50,13 @@ cpp_compiler.has_header_symbol('version', '__cpp_lib_integer_comparison_function
cpp_compiler.has_header_symbol('version', '__cpp_lib_expected', required: true, args: cpp23_args)
cpp_compiler.has_header_symbol('version', '__cpp_size_t_suffix', args: cpp23_args)
cpp_compiler.has_header_symbol('version', '__cpp_lib_ranges_zip', args: cpp23_args)
cpp_compiler.has_header_symbol('version', '__cpp_lib_ranges_enumerate', args: cpp23_args)
cpp_compiler.has_header_symbol('version', '__cpp_lib_ranges_to_container', args: cpp23_args)
cpp_compiler.has_header_symbol('version', '__cpp_lib_ranges_to', args: cpp23_args)
cpp_compiler.has_header_symbol('version', '__cpp_lib_stacktrace', args: cpp23_args)
cpp_compiler.has_header_symbol('version', '__cpp_lib_spanstream', args: cpp23_args)
cpp_compiler.has_header_symbol('version', '__cpp_lib_print', args: cpp23_args)


has_chrono = 1 == cpp_compiler.compute_int('__cpp_lib_chrono >= 201907L', prefix: '#include<chrono>', args: cpp23_args)

Expand Down Expand Up @@ -136,5 +141,8 @@ ctre_dep = dependency('ctre',
magic_enum_dep = dependency('magic_enum',
fallback: ['magic_enum'])

json_dep = dependency('jsoncpp',
fallback: ['jsoncpp'])

subdir('src')
subdir('test')
15 changes: 15 additions & 0 deletions res/dieties.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[
{
"name": "Angriff",
"text": "God of War, subordinate to Liedenshaft",
"subordinateTo": "Liedenshaft",
"spoilerUntil": "P3V3",
"pattern": "Angriff",
"antiPattern": "God of War Angriff"
}, {
"name": "Vantole",
"text": "God of Alcohol",
"spoilerUntil": "P1V3",
"pattern": "Vantole"
}
]
18 changes: 18 additions & 0 deletions res/retainers.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[
{
"name": "Leberecht",
"text": "Scholar retainer for Florencia, Hartmut's father, and husband to Ottilie.",
"lord": "Florencia",
"spoilerUntil": "P4V7",
"profession": "Scholar",
"pattern": "Leberecht"
}, {
"name": "Alexis",
"text": "Knight retainer for Wilfried. Son of Geibe Kirnberger.",
"lord": "Wilfried",
"spoilerUntil": "P4V2",
"profession": "Knight",
"pattern": "Alexis",
"divineProtections": ["Angriff", "Steifebrise"]
}
]
91 changes: 56 additions & 35 deletions src/args.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
#include <ranges>
#include <string>
#include <locale>
#include <vector>
#include <algorithm>
#include <cctype>
#include <expected>
#include <iostream>
#include <locale>
#include <ranges>
#include <string>
#include <system_error>
#include <cctype>
#include <vector>

#include <magic_enum.hpp>

#include "args.h"
#include "ctre.hpp"
#include "config.h"
#include "args.h"
#include "log.h"
#include "miniz.h"
#include "updates.h"
Expand Down Expand Up @@ -160,7 +164,7 @@ namespace {
} // anonymous namespace


std::expected<void, std::error_code>
outcome::result<void>
parse(int argc, char** argv)
{
using namespace std::string_view_literals;
Expand All @@ -171,7 +175,7 @@ parse(int argc, char** argv)
options.command = args::command_e::NORMAL;
if (argc < 2) {
usage(argv[0]);
return std::unexpected(std::make_error_code(std::errc::invalid_argument));
return std::errc::invalid_argument;
}
auto args_options { views::filter(args_sv, [](const auto &sv) { return sv.starts_with("--"sv); }) };
auto args_files { views::filter(args_sv, [](const auto &sv) { return !sv.starts_with("--"sv); }) };
Expand Down Expand Up @@ -208,7 +212,7 @@ parse(int argc, char** argv)
log_info("Filename prefix set to ", std::quoted(*options.prefix));
if (options.prefix->empty() && (!options.suffix || options.suffix->empty())) {
log_error("No suffix and empty prefix defined. This would create files with the same name as the input; that will make things too confusing!");
return std::unexpected(std::make_error_code(std::errc::invalid_argument));
return std::errc::invalid_argument;
}
}

Expand Down Expand Up @@ -239,10 +243,10 @@ parse(int argc, char** argv)
});
} catch (std::system_error &e) {
log_error("Failed to prepare regex name filter: ", e.what());
return std::unexpected(e.code());
return e.code();
} catch (std::exception &e) {
log_error("Failed to prepare regex name filter: ", e.what());
return std::unexpected(std::make_error_code(std::errc::invalid_argument));
return std::errc::invalid_argument;
}
}

Expand All @@ -252,7 +256,7 @@ parse(int argc, char** argv)
if (q.has_value()) {
options.jpg_quality = std::clamp<int>(q.value(), 1, 100);
} else {
return std::unexpected(q.error());
return q.error();
}
}

Expand All @@ -261,15 +265,15 @@ parse(int argc, char** argv)
if (s.has_value()) {
options.jpg_scale = std::clamp<int>(s.value(), 1, 16);
} else {
return std::unexpected(s.error());
return s.error();
}
}

options.title = utils::find_if_optarg(args_options, "--title="sv);
if (options.title) {
if (options.title.value().size() == 0) {
log_error("Can not set a blank title");
return std::unexpected(std::make_error_code(std::errc::invalid_argument));
return std::errc::invalid_argument;
}
log_info("Title set to ", std::quoted(options.title.value()));
}
Expand All @@ -294,7 +298,7 @@ parse(int argc, char** argv)
options.omnibus_type = omnibus::ALL;
} else {
log_error("Unrecognized omnibus value: ", type);
return std::unexpected(std::make_error_code(std::errc::invalid_argument));
return std::errc::invalid_argument;
}
log_info("Omnibus ", *options.omnibus_type, " selected.");
}
Expand Down Expand Up @@ -331,22 +335,22 @@ parse(int argc, char** argv)
auto status = fs::status(path, ec);
if (ec) {
log_error("Cover ", path, " can't be read: ", ec);
return std::unexpected(ec);
return ec;
}

if (!fs::exists(status)) {
log_error("Cover ", path, " doesn't exist.");
return std::unexpected(std::make_error_code(std::errc::no_such_file_or_directory));
return std::errc::no_such_file_or_directory;
}

if (!fs::is_regular_file(status)) {
log_error("Cover ", path, " isn't a regular file.");
return std::unexpected(std::make_error_code(std::errc::invalid_argument));
return std::errc::invalid_argument;
}

if (!ctre::match<"[.]jpg", ctre::case_insensitive>(path.extension().string())) {
log_error("Cover ", path, " isn't a .jpg");
return std::unexpected(std::make_error_code(std::errc::invalid_argument));
return std::errc::invalid_argument;
}
options.cover = path;
}
Expand All @@ -362,13 +366,13 @@ parse(int argc, char** argv)
if (ec == std::errc()) { // success
if (ptr != std::to_address(std::end(*level))) {
log_error("Compression level ", std::quoted(*level), " is invalid.");
return std::unexpected(std::make_error_code(std::errc::invalid_argument));
return std::errc::invalid_argument;
}
options.compression_level = std::clamp<mz_uint>(l, MZ_NO_COMPRESSION, MZ_UBER_COMPRESSION);
log_info("Compression level set to ", *options.compression_level);
} else {
log_error("Compression level ", std::quoted(*level), " is invalid: ", std::make_error_code(ec));
return std::unexpected(std::make_error_code(ec));
return std::make_error_code(ec);
}
}
}
Expand All @@ -392,6 +396,16 @@ parse(int argc, char** argv)
log_info("This executable works.");
options.command = args::command_e::TEST;
}

options.search_pattern = utils::find_if_optarg<std::string>(args_options, "--search="sv).and_then([](std::string&& pattern) -> std::optional<std::regex> {
return std::make_optional<std::regex>(std::move(pattern), std::regex_constants::icase);
});

if (options.search_pattern) {
options.command = args::command_e::SEARCH;
}

/* End of option checking, now set defaults */
if (options.omnibus_type) {
options.do_nested = true;
if (find (args_options, "--no-nested"sv) != args_options.end()) {
Expand All @@ -416,7 +430,7 @@ parse(int argc, char** argv)
const auto num_files = std::distance(args_files.begin(), args_files.end());
if (num_files == 0) {
usage(argv[0]);
return std::unexpected(std::make_error_code(std::errc::invalid_argument));
return std::errc::invalid_argument;
}
auto it = args_files.begin();

Expand All @@ -428,41 +442,48 @@ parse(int argc, char** argv)
}

if (auto res = verify_input_file(options.input_file); !res.has_value()) {
return res;
return res.error();
}
}

if (args::command_e::NORMAL == options.command) {
if (std::distance(args_files.begin(), args_files.end()) != 2) {
usage(argv[0]);
return std::unexpected(std::make_error_code(std::errc::invalid_argument));
return std::errc::invalid_argument;
}

auto it = args_files.begin();
options.input_dir = *it++;
options.output_dir = *it;

if (auto res = verify_input_directory(options.input_dir); !res.has_value()) {
return res;
return res.error();
}
log_verbose("Verified input dir: ", options.input_dir.string());
if (auto res = verify_output_directory(options.input_dir, options.output_dir); !res) {
return std::unexpected(res.error());
return res.error();
}
log_verbose("Verified output dir: ", options.output_dir.string());
}
return {};

if (args::command_e::SEARCH == options.command) {
if (std::distance(args_files.begin(), args_files.end()) != 1) {
usage(argv[0]);
return std::errc::invalid_argument;
}

auto it = args_files.begin();
options.input_dir = *it;
if (auto res = verify_input_directory(options.input_dir); !res.has_value()) {
return res.error();
}
log_verbose("Verified input dir: ", options.input_dir.string());
}
return outcome::success();
}

std::ostream&
operator<<(std::ostream& os, args::command_e c)
{
switch (c) {
case args::command_e::DUMP: os << "Command::DUMP"; break;
case args::command_e::NORMAL: os << "Command::NORMAL"; break;
case args::command_e::TEST: os << "Command::TEST"; break;
default:
os << "Command:UNIMPLMENTED?"; break;
}
return os;
return magic_enum::ostream_operators::operator<<(os, c);
}
6 changes: 4 additions & 2 deletions src/args.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#include <optional>
#include <regex>
#include <string>
#include <expected>
#include "outcome/result.hpp"
#include "volumes.h"

Expand All @@ -18,6 +17,7 @@ struct args
{
NORMAL,
DUMP,
SEARCH,
TEST
} command;

Expand All @@ -40,10 +40,12 @@ struct args
std::optional<int> jpg_scale;
std::optional<omnibus> omnibus_type;
std::optional<unsigned int> compression_level;
std::optional<std::regex> search_pattern;
std::optional<std::regex> search_antipattern;
};

std::ostream& operator<<(std::ostream& os, args::command_e c);

const args* get_options();

std::expected<void, std::error_code> parse(int argc, char **argv);
outcome::result<void> parse(int argc, char **argv);
Loading