Skip to content

Commit

Permalink
[utils] add string utils
Browse files Browse the repository at this point in the history
  • Loading branch information
yangli committed Sep 23, 2022
1 parent 3df25ae commit b9bb7ee
Show file tree
Hide file tree
Showing 9 changed files with 106 additions and 53 deletions.
2 changes: 1 addition & 1 deletion library/include/binary/algorithm/experimental.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ namespace binary::algorithm::tree::v1_shared_ptr {
void insert_node(pointer_type node);

template <typename... Args>
requires std::constructible_from<node_type, Args...>
requires std::constructible_from<node_type, Args...>
void insert_node(Args &&...args) {
insert_node(std::make_shared<node_type>(std::forward<Args>(args)...));
}
Expand Down
31 changes: 16 additions & 15 deletions library/include/binary/algorithm/interval_tree.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,22 @@ namespace binary::algorithm::tree {
/** Interval Node and Interval Tree */

template <typename Interval>
concept IntervalConcept = requires(Interval const &interval) {
requires std::semiregular<Interval>;
requires std::movable<Interval>;
requires std::same_as<decltype(interval.low), decltype(interval.high)>;
interval.low <= interval.high;
typename Interval::key_type;
};
concept IntervalConcept
= requires(Interval const &interval) {
requires std::semiregular<Interval>;
requires std::movable<Interval>;
requires std::same_as<decltype(interval.low), decltype(interval.high)>;
interval.low <= interval.high;
typename Interval::key_type;
};

template <typename Node>
concept IntervalNodeConcept = requires(Node &node) {
requires NodeConcept<Node>;
typename Node::interval_type;
node.max;
node.interval;
};
requires NodeConcept<Node>;
typename Node::interval_type;
node.max;
node.interval;
};

/** Interval Tree node
*
Expand All @@ -64,7 +65,7 @@ namespace binary::algorithm::tree {
constexpr IntervalNode &operator=(IntervalNode &&other) noexcept = default;

template <typename... Arg>
requires std::constructible_from<Interval, Arg...>
requires std::constructible_from<Interval, Arg...>
explicit constexpr IntervalNode(Arg &&...args)
: interval{std::forward<Arg>(args)...}, max{interval.high}, key{interval.low} {}

Expand Down Expand Up @@ -153,7 +154,7 @@ namespace binary::algorithm::tree {
-> std::optional<interval_type>;

template <typename... Args>
requires binary::concepts::ArgsConstructible<interval_type, Args...>
requires binary::concepts::ArgsConstructible<interval_type, Args...>
[[nodiscard]] auto find_overlap(Args &&...args) const -> std::optional<interval_type> {
return find_overlap(interval_type{std::forward<Args>(args)...});
}
Expand All @@ -162,7 +163,7 @@ namespace binary::algorithm::tree {
-> std::vector<interval_type>;

template <typename... Args>
requires binary::concepts::ArgsConstructible<interval_type, Args...>
requires binary::concepts::ArgsConstructible<interval_type, Args...>
[[nodiscard]] auto find_overlaps(Args &&...args) const -> std::vector<interval_type> {
return find_overlaps(interval_type{std::forward<Args>(args)...});
}
Expand Down
30 changes: 15 additions & 15 deletions library/include/binary/algorithm/rb_tree.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,19 @@ namespace binary::algorithm::tree {

template <typename Node>
concept NodeConcept = requires(Node &node) {
requires std::movable<Node> && std::default_initializable<Node>;
typename Node::key_type;
typename Node::pointer;
typename Node::reference_pointer;
typename Node::raw_pointer;
node.key;
node.left;
node.right;
node.parent;
node.color_;
node.is_black();
node.is_red();
};
requires std::movable<Node> && std::default_initializable<Node>;
typename Node::key_type;
typename Node::pointer;
typename Node::reference_pointer;
typename Node::raw_pointer;
node.key;
node.left;
node.right;
node.parent;
node.color_;
node.is_black();
node.is_red();
};

enum class Color { Red, Black };

Expand Down Expand Up @@ -109,7 +109,7 @@ namespace binary::algorithm::tree {
virtual ~RbTree() = default;

template <std::ranges::input_range R>
requires std::constructible_from<NodeType, std::ranges::range_value_t<R>>
requires std::constructible_from<NodeType, std::ranges::range_value_t<R>>
void insert_node(R &&range) {
for (auto &&item : range) {
insert_node(std::forward<decltype(item)>(item));
Expand Down Expand Up @@ -143,7 +143,7 @@ namespace binary::algorithm::tree {
[[maybe_unused]] void insert_node(pointer node);

template <typename... Args>
requires std::constructible_from<NodeType, Args...>
requires std::constructible_from<NodeType, Args...>
void insert_node(Args &&...args) {
insert_node(std::make_unique<NodeType>(std::forward<Args>(args)...));
}
Expand Down
2 changes: 1 addition & 1 deletion library/include/binary/concepts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace binary::concepts {

template <typename T, typename... Args>
concept ArgsConstructible
= std::constructible_from<T, Args...> &&(!IsAnyOf<T, std::remove_cvref_t<Args>...>);
= std::constructible_from<T, Args...> && (!IsAnyOf<T, std::remove_cvref_t<Args>...>);

} // namespace binary::concepts

Expand Down
34 changes: 17 additions & 17 deletions library/include/binary/parser/vcf.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ namespace binary::parser::vcf {
constexpr int BINARY_BCF_HT_LONG = (BINARY_BCF_HT_INT | 0x100);

template <typename Datatype>
requires binary::concepts::IsAnyOf<Datatype, int, float, char, pos_t, int64_t>
requires binary::concepts::IsAnyOf<Datatype, int, float, char, pos_t, int64_t>
struct InfoGetter {
Datatype* data{nullptr};
int32_t count{};
Expand Down Expand Up @@ -162,20 +162,20 @@ namespace binary::parser::vcf {

template <typename T>
concept InfoFieldConcept = requires(T t) {
requires std::semiregular<T>;
requires std::movable<T>;
requires std::derived_from<T, details::BaseInfoField>;
t.update(std::shared_ptr<details::DataImpl>{});
std::cout << t;
};
requires std::semiregular<T>;
requires std::movable<T>;
requires std::derived_from<T, details::BaseInfoField>;
t.update(std::shared_ptr<details::DataImpl>{});
std::cout << t;
};

template <typename... T> struct InfoFieldFactory : public details::BaseInfoField {
std::tuple<decltype(InfoGetter<T>::result_type())...> data_tuple{};
std::array<std::string, sizeof...(T)> keys_array{};

template <typename... U>
requires(std::convertible_to<U, std::string>&&...) explicit InfoFieldFactory(U... args)
: keys_array{args...} {
requires(std::convertible_to<U, std::string> && ...)
explicit InfoFieldFactory(U... args) : keys_array{args...} {
static_assert(sizeof...(T) == sizeof...(U), "Number of keys and values do not match");
}
InfoFieldFactory(InfoFieldFactory const&) = default;
Expand Down Expand Up @@ -306,14 +306,14 @@ namespace binary::parser::vcf {

template <typename T>
concept RecordConcept = requires(T record) {
requires std::semiregular<T>;
requires std::movable<T>;
record.chrom;
record.pos;
record.rlen;
record.info;
std::cout << record;
};
requires std::semiregular<T>;
requires std::movable<T>;
record.chrom;
record.pos;
record.rlen;
record.info;
std::cout << record;
};

template <RecordConcept RecordType> class VcfRanges {
public:
Expand Down
17 changes: 15 additions & 2 deletions library/include/binary/utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace binary::utils {

// TODO: use binary search if range is sorted
template <std::ranges::input_range Container, typename Value>
requires std::equality_comparable_with<std::ranges::range_value_t<Container>, Value>
requires std::equality_comparable_with<std::ranges::range_value_t<Container>, Value>
auto index(Container const& container, Value&& value) -> std::size_t {
auto it = std::ranges::find(container, std::forward<Value>(value));
if (it == std::ranges::end(container)) {
Expand All @@ -39,7 +39,7 @@ namespace binary::utils {
}

template <std::ranges::input_range StringRange>
requires std::convertible_to<std::ranges::range_value_t<StringRange>, std::string>
requires std::convertible_to<std::ranges::range_value_t<StringRange>, std::string>
void merge_files(StringRange&& files, std::string_view output_file, std::string_view header = "",
bool is_deleted = true, bool is_skipped_header = true) {
auto output = std::ofstream(output_file.data());
Expand Down Expand Up @@ -72,6 +72,19 @@ namespace binary::utils {
[[maybe_unused]] inline void set_trace() { spdlog::set_level(spdlog::level::trace); }
[[maybe_unused]] inline void set_info() { spdlog::set_level(spdlog::level::info); }

// trim from left
inline constexpr auto trim_front = std::ranges::views::drop_while(::isspace);

inline constexpr auto trim_back = std::ranges::views::reverse
| std::ranges::views::drop_while(::isspace)
| std::ranges::views::reverse;

inline constexpr auto trim = trim_front | trim_back;

auto split_str(std::string_view str, char delim) -> std::vector<std::string>;

std::string trim_str(std::string_view str);

} // namespace binary::utils

#endif // BINARY_LIBRARY_INCLUDE_BINARY_UTLS_HPP_
15 changes: 15 additions & 0 deletions library/source/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,19 @@ namespace binary::utils {
return std::filesystem::exists(file_path);
}

std::string trim_str(std::string_view str) {
auto temp = str | trim;
return {temp.begin(), temp.end()};
}

auto split_str(std::string_view str, char delim) -> std::vector<std::string> {
auto temp_view = str | std::ranges::views::split(delim);
auto result = std::vector<std::string>{};

for (auto const& sub_str : temp_view) {
result.emplace_back(sub_str.begin(), sub_str.end());
}
return result;
}

} // namespace binary::utils
4 changes: 2 additions & 2 deletions standalone/sv2nl/include/writer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ namespace sv2nl {
}

template <std::ranges::input_range Sv2nlRecordRange>
requires std::same_as<std::ranges::range_value_t<Sv2nlRecordRange>, Sv2nlVcfRecord>
requires std::same_as<std::ranges::range_value_t<Sv2nlRecordRange>, Sv2nlVcfRecord>
void write(Sv2nlRecordRange&& records) {
if (records.size() < 2) return;
auto key_line = format_keys(records[0]);
Expand All @@ -38,7 +38,7 @@ namespace sv2nl {
}

template <std::ranges::input_range Sv2nlRecordRange>
requires std::same_as<std::ranges::range_value_t<Sv2nlRecordRange>, Sv2nlVcfRecord>
requires std::same_as<std::ranges::range_value_t<Sv2nlRecordRange>, Sv2nlVcfRecord>
void write_trans(Sv2nlRecordRange&& records) {
if (records.size() < 2) return;
auto key_line = format_keys(records[0]);
Expand Down
24 changes: 24 additions & 0 deletions test/source/test_utils/test_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,28 @@ TEST_SUITE("test binary utils") {
std::tuple t1{1, "test", 3.0};
CHECK_NOTHROW(binary::utils::print_tuple(t1));
}

TEST_CASE("test trim view") {
using namespace binary::utils;

std::string_view str = " test ";
auto temp = trim_str(str);
CHECK_EQ(temp, "test");
}

TEST_CASE("test split string") {
using namespace binary::utils;

std::string_view str = "test1,test2,test3";
auto temp = split_str(str, ',');
CHECK_EQ(temp.size(), 3);
CHECK_EQ(temp[0], "test1");
CHECK_EQ(temp[1], "test2");
CHECK_EQ(temp[2], "test3");

std::string_view str2 = " test1 , test2 , test3 ";
auto temp2 = split_str(str2, ',');
CHECK_EQ(temp2.size(), 3);
CHECK_EQ(temp2[0], " test1 ");
}
}

0 comments on commit b9bb7ee

Please sign in to comment.