mirror of
https://github.com/mhx/dwarfs.git
synced 2025-08-04 02:06:22 -04:00
refactor: slightly sleeker variant matching
This commit is contained in:
parent
905ac667e6
commit
22c079a4ca
@ -33,7 +33,7 @@
|
|||||||
#include <folly/Conv.h>
|
#include <folly/Conv.h>
|
||||||
#include <folly/String.h>
|
#include <folly/String.h>
|
||||||
|
|
||||||
#include "dwarfs/overloaded.h"
|
#include "dwarfs/match.h"
|
||||||
|
|
||||||
namespace dwarfs {
|
namespace dwarfs {
|
||||||
|
|
||||||
@ -51,30 +51,29 @@ class integral_value_parser {
|
|||||||
T parse(std::string_view arg) const {
|
T parse(std::string_view arg) const {
|
||||||
auto val = folly::to<T>(arg);
|
auto val = folly::to<T>(arg);
|
||||||
|
|
||||||
std::visit(overloaded{
|
valid_ | match{
|
||||||
[](std::monostate const&) {},
|
[](std::monostate const&) {},
|
||||||
[val](std::pair<T, T> const& minmax) {
|
[val](std::pair<T, T> const& minmax) {
|
||||||
if (val < minmax.first || val > minmax.second) {
|
if (val < minmax.first || val > minmax.second) {
|
||||||
throw std::range_error(
|
throw std::range_error(
|
||||||
fmt::format("value {} out of range [{}..{}]", val,
|
fmt::format("value {} out of range [{}..{}]", val,
|
||||||
minmax.first, minmax.second));
|
minmax.first, minmax.second));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[val](std::set<T> const& choices) {
|
[val](std::set<T> const& choices) {
|
||||||
if (auto it = choices.find(val); it == choices.end()) {
|
if (auto it = choices.find(val); it == choices.end()) {
|
||||||
throw std::range_error(
|
throw std::range_error(
|
||||||
fmt::format("invalid value {}, must be one of [{}]",
|
fmt::format("invalid value {}, must be one of [{}]",
|
||||||
val, folly::join(", ", choices)));
|
val, folly::join(", ", choices)));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[val](std::function<bool(T)> const& check) {
|
[val](std::function<bool(T)> const& check) {
|
||||||
if (!check(val)) {
|
if (!check(val)) {
|
||||||
throw std::range_error(
|
throw std::range_error(
|
||||||
fmt::format("value {} out of range", val));
|
fmt::format("value {} out of range", val));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
};
|
||||||
valid_);
|
|
||||||
|
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
@ -21,14 +21,41 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
namespace dwarfs {
|
namespace dwarfs {
|
||||||
|
|
||||||
template <typename... Ts>
|
template <typename... Ts>
|
||||||
struct overloaded : Ts... {
|
struct match : Ts... {
|
||||||
using Ts::operator()...;
|
using Ts::operator()...;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename... Ts>
|
template <typename... Ts>
|
||||||
overloaded(Ts...) -> overloaded<Ts...>;
|
match(Ts...) -> match<Ts...>;
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_a_variant : std::false_type {};
|
||||||
|
|
||||||
|
template <typename... Ts>
|
||||||
|
struct is_a_variant<std::variant<Ts...>> : std::true_type {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_a_match : std::false_type {};
|
||||||
|
|
||||||
|
template <typename... Ts>
|
||||||
|
struct is_a_match<match<Ts...>> : std::true_type {};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template <typename T, typename U>
|
||||||
|
[[nodiscard]] constexpr decltype(auto) operator|(T&& v, U&& m)
|
||||||
|
requires(detail::is_a_variant<std::decay_t<T>>::value &&
|
||||||
|
detail::is_a_match<std::decay_t<U>>::value)
|
||||||
|
{
|
||||||
|
return std::visit(std::forward<U>(m), std::forward<T>(v));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace dwarfs
|
} // namespace dwarfs
|
@ -49,11 +49,11 @@
|
|||||||
#include "dwarfs/inode_manager.h"
|
#include "dwarfs/inode_manager.h"
|
||||||
#include "dwarfs/inode_ordering.h"
|
#include "dwarfs/inode_ordering.h"
|
||||||
#include "dwarfs/logger.h"
|
#include "dwarfs/logger.h"
|
||||||
|
#include "dwarfs/match.h"
|
||||||
#include "dwarfs/mmif.h"
|
#include "dwarfs/mmif.h"
|
||||||
#include "dwarfs/nilsimsa.h"
|
#include "dwarfs/nilsimsa.h"
|
||||||
#include "dwarfs/options.h"
|
#include "dwarfs/options.h"
|
||||||
#include "dwarfs/os_access.h"
|
#include "dwarfs/os_access.h"
|
||||||
#include "dwarfs/overloaded.h"
|
|
||||||
#include "dwarfs/progress.h"
|
#include "dwarfs/progress.h"
|
||||||
#include "dwarfs/promise_receiver.h"
|
#include "dwarfs/promise_receiver.h"
|
||||||
#include "dwarfs/scanner_progress.h"
|
#include "dwarfs/scanner_progress.h"
|
||||||
@ -273,37 +273,33 @@ class inode_ : public inode {
|
|||||||
|
|
||||||
os << " similarity: ";
|
os << " similarity: ";
|
||||||
|
|
||||||
auto basic_hash_visitor = [&os](uint32_t sh) {
|
auto basic_hash_matcher = [&os](uint32_t sh) {
|
||||||
os << fmt::format("basic ({0:08x})\n", sh);
|
os << fmt::format("basic ({0:08x})\n", sh);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto nilsimsa_hash_visitor = [&os](nilsimsa::hash_type const& nh) {
|
auto nilsimsa_hash_matcher = [&os](nilsimsa::hash_type const& nh) {
|
||||||
os << fmt::format("nilsimsa ({0:016x}{1:016x}{2:016x}{3:016x})\n", nh[0],
|
os << fmt::format("nilsimsa ({0:016x}{1:016x}{2:016x}{3:016x})\n", nh[0],
|
||||||
nh[1], nh[2], nh[3]);
|
nh[1], nh[2], nh[3]);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto similarity_map_visitor = [&](similarity_map_type const& map) {
|
auto similarity_map_matcher = [&](similarity_map_type const& map) {
|
||||||
os << "map\n";
|
os << "map\n";
|
||||||
for (auto const& [cat, val] : map) {
|
for (auto const& [cat, val] : map) {
|
||||||
os << " ";
|
os << " ";
|
||||||
dump_category(cat);
|
dump_category(cat);
|
||||||
std::visit(
|
val | match{
|
||||||
overloaded{
|
basic_hash_matcher,
|
||||||
basic_hash_visitor,
|
nilsimsa_hash_matcher,
|
||||||
nilsimsa_hash_visitor,
|
};
|
||||||
},
|
|
||||||
val);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::visit(
|
similarity_ | match{
|
||||||
overloaded{
|
[&os](std::monostate const&) { os << "none\n"; },
|
||||||
[&os](std::monostate const&) { os << "none\n"; },
|
basic_hash_matcher,
|
||||||
basic_hash_visitor,
|
nilsimsa_hash_matcher,
|
||||||
nilsimsa_hash_visitor,
|
similarity_map_matcher,
|
||||||
similarity_map_visitor,
|
};
|
||||||
},
|
|
||||||
similarity_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_scan_error(file const* fp, std::exception_ptr ep) override {
|
void set_scan_error(file const* fp, std::exception_ptr ep) override {
|
||||||
|
@ -28,8 +28,8 @@
|
|||||||
|
|
||||||
#include "dwarfs/error.h"
|
#include "dwarfs/error.h"
|
||||||
#include "dwarfs/logger.h"
|
#include "dwarfs/logger.h"
|
||||||
|
#include "dwarfs/match.h"
|
||||||
#include "dwarfs/metadata_types.h"
|
#include "dwarfs/metadata_types.h"
|
||||||
#include "dwarfs/overloaded.h"
|
|
||||||
#include "dwarfs/util.h"
|
#include "dwarfs/util.h"
|
||||||
|
|
||||||
#include "dwarfs/gen-cpp2/metadata_types_custom_protocol.h"
|
#include "dwarfs/gen-cpp2/metadata_types_custom_protocol.h"
|
||||||
@ -590,39 +590,34 @@ auto inode_view::getgid() const -> gid_type {
|
|||||||
// TODO: pretty certain some of this stuff can be simplified
|
// TODO: pretty certain some of this stuff can be simplified
|
||||||
|
|
||||||
std::string dir_entry_view::name() const {
|
std::string dir_entry_view::name() const {
|
||||||
return std::visit(overloaded{
|
return v_ |
|
||||||
[this](DirEntryView const& dev) {
|
match{
|
||||||
return g_->names()[dev.name_index()];
|
[this](DirEntryView const& dev) {
|
||||||
},
|
return g_->names()[dev.name_index()];
|
||||||
[this](InodeView const& iv) {
|
},
|
||||||
return std::string(
|
[this](InodeView const& iv) {
|
||||||
g_->meta().names()[iv.name_index_v2_2()]);
|
return std::string(g_->meta().names()[iv.name_index_v2_2()]);
|
||||||
},
|
},
|
||||||
},
|
};
|
||||||
v_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inode_view dir_entry_view::inode() const {
|
inode_view dir_entry_view::inode() const {
|
||||||
return std::visit(overloaded{
|
return v_ | match{
|
||||||
[this](DirEntryView const& dev) {
|
[this](DirEntryView const& dev) {
|
||||||
return inode_view(
|
return inode_view(g_->meta().inodes()[dev.inode_num()],
|
||||||
g_->meta().inodes()[dev.inode_num()],
|
dev.inode_num(), g_->meta());
|
||||||
dev.inode_num(), g_->meta());
|
},
|
||||||
},
|
[this](InodeView const& iv) {
|
||||||
[this](InodeView const& iv) {
|
return inode_view(iv, iv.inode_v2_2(), g_->meta());
|
||||||
return inode_view(iv, iv.inode_v2_2(), g_->meta());
|
},
|
||||||
},
|
};
|
||||||
},
|
|
||||||
v_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dir_entry_view::is_root() const {
|
bool dir_entry_view::is_root() const {
|
||||||
return std::visit(
|
return v_ | match{
|
||||||
overloaded{
|
[](DirEntryView const& dev) { return dev.inode_num() == 0; },
|
||||||
[](DirEntryView const& dev) { return dev.inode_num() == 0; },
|
[](InodeView const& iv) { return iv.inode_v2_2() == 0; },
|
||||||
[](InodeView const& iv) { return iv.inode_v2_2() == 0; },
|
};
|
||||||
},
|
|
||||||
v_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -73,11 +73,11 @@
|
|||||||
#include "dwarfs/integral_value_parser.h"
|
#include "dwarfs/integral_value_parser.h"
|
||||||
#include "dwarfs/iolayer.h"
|
#include "dwarfs/iolayer.h"
|
||||||
#include "dwarfs/logger.h"
|
#include "dwarfs/logger.h"
|
||||||
|
#include "dwarfs/match.h"
|
||||||
#include "dwarfs/mmap.h"
|
#include "dwarfs/mmap.h"
|
||||||
#include "dwarfs/options.h"
|
#include "dwarfs/options.h"
|
||||||
#include "dwarfs/options_interface.h"
|
#include "dwarfs/options_interface.h"
|
||||||
#include "dwarfs/os_access.h"
|
#include "dwarfs/os_access.h"
|
||||||
#include "dwarfs/overloaded.h"
|
|
||||||
#include "dwarfs/program_options_helpers.h"
|
#include "dwarfs/program_options_helpers.h"
|
||||||
#include "dwarfs/progress.h"
|
#include "dwarfs/progress.h"
|
||||||
#include "dwarfs/scanner.h"
|
#include "dwarfs/scanner.h"
|
||||||
@ -1248,14 +1248,13 @@ int mkdwarfs_main(int argc, sys_char** argv, iolayer const& iol) {
|
|||||||
std::unique_ptr<filesystem_writer> fsw;
|
std::unique_ptr<filesystem_writer> fsw;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
std::ostream& fsw_os = std::visit(
|
std::ostream& fsw_os =
|
||||||
overloaded{
|
os |
|
||||||
[&](std::monostate) -> std::ostream& { return iol.out; },
|
match{[&](std::monostate) -> std::ostream& { return iol.out; },
|
||||||
[&](std::unique_ptr<output_stream>& os) -> std::ostream& {
|
[&](std::unique_ptr<output_stream>& os) -> std::ostream& {
|
||||||
return os->os();
|
return os->os();
|
||||||
},
|
},
|
||||||
[&](std::ostringstream& oss) -> std::ostream& { return oss; }},
|
[&](std::ostringstream& oss) -> std::ostream& { return oss; }};
|
||||||
os);
|
|
||||||
|
|
||||||
fsw = std::make_unique<filesystem_writer>(
|
fsw = std::make_unique<filesystem_writer>(
|
||||||
fsw_os, lgr, wg_compress, prog, schema_bc, metadata_bc, history_bc,
|
fsw_os, lgr, wg_compress, prog, schema_bc, metadata_bc, history_bc,
|
||||||
@ -1339,24 +1338,22 @@ int mkdwarfs_main(int argc, sys_char** argv, iolayer const& iol) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto ec = std::visit(
|
auto ec = os | match{[](std::monostate) -> int { return 0; },
|
||||||
overloaded{[](std::monostate) -> int { return 0; },
|
[&](std::unique_ptr<output_stream>& os) -> int {
|
||||||
[&](std::unique_ptr<output_stream>& os) -> int {
|
std::error_code ec;
|
||||||
std::error_code ec;
|
os->close(ec);
|
||||||
os->close(ec);
|
if (ec) {
|
||||||
if (ec) {
|
LOG_ERROR << "failed to close output file '"
|
||||||
LOG_ERROR << "failed to close output file '" << output
|
<< output << "': " << ec.message();
|
||||||
<< "': " << ec.message();
|
return 1;
|
||||||
return 1;
|
}
|
||||||
}
|
os.reset();
|
||||||
os.reset();
|
return 0;
|
||||||
return 0;
|
},
|
||||||
},
|
[](std::ostringstream& oss [[maybe_unused]]) -> int {
|
||||||
[](std::ostringstream& oss [[maybe_unused]]) -> int {
|
assert(oss.str().empty());
|
||||||
assert(oss.str().empty());
|
return 0;
|
||||||
return 0;
|
}};
|
||||||
}},
|
|
||||||
os);
|
|
||||||
|
|
||||||
if (ec != 0) {
|
if (ec != 0) {
|
||||||
return ec;
|
return ec;
|
||||||
|
@ -33,8 +33,8 @@
|
|||||||
#include <folly/String.h>
|
#include <folly/String.h>
|
||||||
#include <folly/portability/Unistd.h>
|
#include <folly/portability/Unistd.h>
|
||||||
|
|
||||||
|
#include "dwarfs/match.h"
|
||||||
#include "dwarfs/os_access_generic.h"
|
#include "dwarfs/os_access_generic.h"
|
||||||
#include "dwarfs/overloaded.h"
|
|
||||||
#include "dwarfs/util.h"
|
#include "dwarfs/util.h"
|
||||||
#include "loremipsum.h"
|
#include "loremipsum.h"
|
||||||
#include "mmap_mock.h"
|
#include "mmap_mock.h"
|
||||||
@ -448,16 +448,15 @@ os_access_mock::map_file(fs::path const& path, size_t size) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return std::make_unique<mmap_mock>(
|
return std::make_unique<mmap_mock>(
|
||||||
std::visit(overloaded{
|
de->v | match{
|
||||||
[this](std::string const& str) { return str; },
|
[this](std::string const& str) { return str; },
|
||||||
[this](std::function<std::string()> const& fun) {
|
[this](std::function<std::string()> const& fun) {
|
||||||
return fun();
|
return fun();
|
||||||
},
|
},
|
||||||
[this](auto const&) -> std::string {
|
[this](auto const&) -> std::string {
|
||||||
throw std::runtime_error("oops in overloaded");
|
throw std::runtime_error("oops in match");
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
de->v),
|
|
||||||
size);
|
size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user