refactor: new string splitting implementation

This commit is contained in:
Marcus Holland-Moritz 2024-08-01 18:13:05 +02:00
parent b66ddc0273
commit 767519949b
6 changed files with 91 additions and 30 deletions

View File

@ -1072,7 +1072,7 @@ foreach(tgt dwarfs_common dwarfs_reader dwarfs_writer dwarfs_extractor dwarfs_to
set_target_properties(${tgt} PROPERTIES EXPORT_COMPILE_COMMANDS ON)
target_link_libraries(${tgt} PUBLIC Boost::boost)
target_link_libraries(${tgt} PRIVATE dwarfs_folly_lite dwarfs_thrift_lite)
target_link_libraries(${tgt} PRIVATE dwarfs_folly_lite dwarfs_thrift_lite range-v3::range-v3)
if(USE_JEMALLOC)
target_link_libraries(${tgt} PRIVATE PkgConfig::JEMALLOC)

73
include/dwarfs/string.h Normal file
View File

@ -0,0 +1,73 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/**
* \author Marcus Holland-Moritz (github@mhxnet.de)
* \copyright Copyright (c) Marcus Holland-Moritz
*
* This file is part of dwarfs.
*
* dwarfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* dwarfs is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with dwarfs. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <iterator>
#include <type_traits>
#include <utility>
#include <range/v3/algorithm/copy.hpp>
#include <range/v3/range/conversion.hpp>
#include <range/v3/view/map.hpp>
#include <range/v3/view/split.hpp>
namespace dwarfs {
template <typename T, typename Input, typename Delim>
auto split_view(Input&& input, Delim&& delim) {
return std::forward<Input>(input) |
ranges::views::split(std::forward<Delim>(delim)) |
ranges::views::transform([](auto&& rng) {
return T(&*rng.begin(), ranges::distance(rng));
});
}
template <typename T, typename Delim>
auto split_view(char const* input, Delim&& delim) {
return split_view<T>(std::string_view(input), std::forward<Delim>(delim));
}
template <typename R, typename Input, typename Delim>
R split_to(Input&& input, Delim&& delim) {
return split_view<typename R::value_type>(std::forward<Input>(input),
std::forward<Delim>(delim)) |
ranges::to<R>;
}
template <typename R, typename Delim>
R split_to(char const* input, Delim&& delim) {
return split_to<R>(std::string_view(input), std::forward<Delim>(delim));
}
template <typename Input, typename Delim, typename Container>
void split_to(Input&& input, Delim&& delim, Container& container) {
ranges::copy(split_view<typename Container::value_type>(
std::forward<Input>(input), std::forward<Delim>(delim)),
std::inserter(container, container.end()));
}
template <typename Delim, typename Container>
void split_to(char const* input, Delim&& delim, Container& container) {
split_to(std::string_view(input), std::forward<Delim>(delim), container);
}
} // namespace dwarfs

View File

@ -26,10 +26,9 @@
#include <fmt/format.h>
#include <range/v3/view/split.hpp>
#include <dwarfs/error.h>
#include <dwarfs/options.h>
#include <dwarfs/string.h>
namespace dwarfs {
@ -147,15 +146,13 @@ fsinfo_features fsinfo_features::for_level(int level) {
fsinfo_features fsinfo_features::parse(std::string_view features) {
fsinfo_features result;
for (auto const& f : features | ranges::views::split(',')) {
// TODO: This should be much simpler with C++23
std::string_view fsv(&*f.begin(), ranges::distance(f));
for (auto const& f : split_view<std::string_view>(features, ',')) {
auto const it =
std::find_if(fsinfo_feature_names.begin(), fsinfo_feature_names.end(),
[&fsv](auto const& p) { return fsv == p.second; });
[&f](auto const& p) { return f == p.second; });
if (it == fsinfo_feature_names.end()) {
DWARFS_THROW(runtime_error, fmt::format("invalid feature: \"{}\"", fsv));
DWARFS_THROW(runtime_error, fmt::format("invalid feature: \"{}\"", f));
}
result |= it->first;

View File

@ -45,7 +45,6 @@
#include <fmt/format.h>
#include <folly/String.h>
#include <folly/experimental/symbolizer/SignalHandler.h>
#include <folly/portability/Fcntl.h>
@ -95,6 +94,7 @@
#include <dwarfs/options.h>
#include <dwarfs/os_access.h>
#include <dwarfs/performance_monitor.h>
#include <dwarfs/string.h>
#include <dwarfs/tool.h>
#include <dwarfs/util.h>
#include <dwarfs/version.h>
@ -1431,9 +1431,7 @@ void load_filesystem(dwarfs_userdata& userdata) {
std::optional<std::filesystem::path> perfmon_trace_file;
#if DWARFS_PERFMON_ENABLED
if (opts.perfmon_enabled_str) {
folly::splitTo<std::string>(
'+', opts.perfmon_enabled_str,
std::inserter(perfmon_enabled, perfmon_enabled.begin()));
split_to(opts.perfmon_enabled_str, '+', perfmon_enabled);
}
if (opts.perfmon_trace_file_str) {
perfmon_trace_file = userdata.iol.os->canonical(std::filesystem::path(

View File

@ -26,8 +26,6 @@
#include <boost/program_options.hpp>
#include <folly/String.h>
#include <dwarfs/filesystem_extractor.h>
#include <dwarfs/filesystem_v2.h>
#include <dwarfs/iolayer.h>
@ -38,6 +36,7 @@
#include <dwarfs/os_access.h>
#include <dwarfs/performance_monitor.h>
#include <dwarfs/program_options_helpers.h>
#include <dwarfs/string.h>
#include <dwarfs/tool.h>
#include <dwarfs/util.h>
#include <dwarfs_tool_main.h>
@ -156,9 +155,7 @@ int dwarfsextract_main(int argc, sys_char** argv, iolayer const& iol) {
std::optional<std::filesystem::path> perfmon_trace_file;
#if DWARFS_PERFMON_ENABLED
if (!perfmon_str.empty()) {
folly::splitTo<std::string>(
',', perfmon_str,
std::inserter(perfmon_enabled, perfmon_enabled.begin()));
split_to(perfmon_str, ',', perfmon_enabled);
}
if (!trace_file.empty()) {
perfmon_trace_file = iol.os->canonical(trace_file);

View File

@ -46,15 +46,12 @@
#include <boost/algorithm/string/join.hpp>
#include <boost/program_options.hpp>
#include <folly/String.h>
#include <fmt/format.h>
#if FMT_VERSION >= 110000
#include <fmt/ranges.h>
#endif
#include <range/v3/view/enumerate.hpp>
#include <range/v3/view/map.hpp>
#include <dwarfs/block_compressor.h>
#include <dwarfs/block_compressor_parser.h>
@ -84,6 +81,7 @@
#include <dwarfs/scanner.h>
#include <dwarfs/script.h>
#include <dwarfs/segmenter_factory.h>
#include <dwarfs/string.h>
#include <dwarfs/terminal.h>
#include <dwarfs/thread_pool.h>
#include <dwarfs/tool.h>
@ -865,10 +863,8 @@ int mkdwarfs_main(int argc, sys_char** argv, iolayer const& iol) {
rw_opts.recompress_categories_exclude = true;
input.remove_prefix(1);
}
folly::splitTo<std::string>(
',', input,
std::inserter(rw_opts.recompress_categories,
rw_opts.recompress_categories.end()));
rw_opts.recompress_categories =
split_to<std::unordered_set<std::string>>(input, ',');
}
}
@ -956,8 +952,8 @@ int mkdwarfs_main(int argc, sys_char** argv, iolayer const& iol) {
chmod_str = "ug-st,=Xr";
}
std::vector<std::string_view> chmod_exprs;
folly::split(',', chmod_str, chmod_exprs);
auto chmod_exprs =
split_to<std::vector<std::string_view>>(chmod_str, ',');
auto mask = get_current_umask();
@ -1021,8 +1017,8 @@ int mkdwarfs_main(int argc, sys_char** argv, iolayer const& iol) {
options.pack_symlinks = true;
options.pack_symlinks_index = false;
} else {
std::vector<std::string_view> pack_opts;
folly::split(',', pack_metadata, pack_opts);
auto pack_opts =
split_to<std::vector<std::string_view>>(pack_metadata, ',');
for (auto const& opt : pack_opts) {
if (opt == "chunk_table") {
options.pack_chunk_table = true;
@ -1156,8 +1152,8 @@ int mkdwarfs_main(int argc, sys_char** argv, iolayer const& iol) {
}
if (!categorizer_list.value.empty()) {
std::vector<std::string> categorizers;
folly::split(',', categorizer_list.value, categorizers);
auto categorizers =
split_to<std::vector<std::string>>(categorizer_list.value, ',');
options.inode.categorizer_mgr = std::make_shared<categorizer_manager>(lgr);