di 0.1.0
Loading...
Searching...
No Matches
constant_path_interface.h
Go to the documentation of this file.
1#pragma once
2
10
11namespace di::container {
12template<concepts::Encoding Enc>
13class PathViewImpl;
14
15template<typename Self, concepts::Encoding Enc>
17private:
18 using View = string::StringViewImpl<Enc>;
19 using CodePoint = meta::EncodingCodePoint<Enc>;
20 using ViewIter = meta::ContainerIterator<View>;
21 using PathView = PathViewImpl<Enc>;
22 using Iterator = PathIterator<Enc>;
23
24 constexpr auto self() -> Self& { return static_cast<Self&>(*this); }
25 constexpr auto self() const -> Self const& { return static_cast<Self const&>(*this); }
26
27 constexpr auto data() const -> View { return self().data(); }
28
29public:
30 constexpr auto empty() const -> bool { return data().empty(); }
31
32 constexpr auto view() const& -> PathView { return PathView(data()); }
33 constexpr operator PathView() const& { return view(); }
34
35 constexpr auto front() const {
36 return lift_bool(!empty()) % [&] {
37 return *begin();
38 };
39 }
40 constexpr auto back() const {
41 return lift_bool(!empty()) % [&] {
42 return *--end();
43 };
44 }
45
46 constexpr auto begin() const { return PathIterator(data(), { data().begin(), m_first_component_end }); }
47 constexpr auto end() const { return PathIterator(data(), { data().end(), data().end() }); }
48
49 constexpr auto is_absolute() const -> bool { return data().starts_with(CodePoint('/')); }
50 constexpr auto is_relative() const -> bool { return !is_absolute(); }
51
52 constexpr auto filename() const -> Optional<View> {
53 return lift_bool(!empty() && !data().ends_with(CodePoint('/'))) % [&] {
54 auto trailing_slash = data().rfind(CodePoint('/'));
55 if (!trailing_slash) {
56 return data();
57 }
58 return data().substr(trailing_slash.end());
59 };
60 }
61
62 constexpr auto extension() const -> Optional<View> {
63 auto filename = this->filename();
64 if (!filename) {
65 return nullopt;
66 }
67 auto split = split_filename(*filename);
68 return util::get<1>(split);
69 }
70
71 constexpr auto stem() const -> Optional<View> {
72 auto filename = this->filename();
73 if (!filename) {
74 return nullopt;
75 }
76 auto split = split_filename(*filename);
77 return util::get<0>(split);
78 }
79
80 constexpr auto parent_path() const -> Optional<PathView> {
81 return lift_bool(!empty() && !container::all_of(data(), function::equal(CodePoint('/')))) >> [&] {
82 auto result = PathView(strip_filename(data()));
83 return lift_bool(!result.empty()) % [&] {
84 return result;
85 };
86 };
87 }
88
89 constexpr auto starts_with(PathView prefix) const -> bool { return container::starts_with(*this, prefix); }
90 constexpr auto ends_with(PathView suffix) const -> bool { return container::ends_with(*this, suffix); }
91
92 constexpr auto filename_ends_with(View suffix) const -> bool {
93 return filename() % [&](auto filename) {
94 return filename.ends_with(suffix);
95 } == true;
96 }
97
98 constexpr auto strip_prefix(PathView prefix) -> Optional<PathView> {
99 auto [a, b] = container::mismatch(*this, prefix);
100 if (b != prefix.end()) {
101 return nullopt;
102 }
103 return PathView(View(a.current_data(), this->end().current_data()));
104 }
105
106protected:
108 if (data().starts_with(CodePoint('/'))) {
109 m_first_component_end = container::next(data().begin());
110 } else {
111 m_first_component_end = container::find(data(), CodePoint('/'));
112 }
113 }
114
115private:
116 constexpr friend auto operator==(Self const& a, Self const& b) -> bool { return container::equal(a, b); }
117 constexpr friend auto operator<=>(Self const& a, Self const& b) { return container::compare(a, b); }
118
120 Iterator last) -> PathView {
121 return PathView(util::move(first), util::move(last));
122 }
123
124 constexpr static auto split_filename(View filename) -> Tuple<Optional<View>, Optional<View>> {
125 auto last_dot_view = filename.rfind(CodePoint('.'));
126 if (!last_dot_view || last_dot_view.begin() == filename.begin()) {
127 return { filename, nullopt };
128 }
129 return { filename.substr(filename.begin(), last_dot_view.begin()), filename.substr(last_dot_view.end()) };
130 }
131
132 constexpr static auto strip_filename(View view) -> View {
133 while (view.ends_with(CodePoint('/'))) {
134 view.replace_end(container::prev(view.end()));
135 }
136 while (!view.empty() && !view.ends_with(CodePoint('/'))) {
137 view.replace_end(container::prev(view.end()));
138 }
139 while (view.size() > 2 && view.ends_with(CodePoint('/'))) {
140 view.replace_end(container::prev(view.end()));
141 }
142 return view;
143 }
144
145 ViewIter m_first_component_end {};
146};
147}
Definition constant_path_interface.h:16
constexpr auto starts_with(PathView prefix) const -> bool
Definition constant_path_interface.h:89
constexpr auto filename_ends_with(View suffix) const -> bool
Definition constant_path_interface.h:92
constexpr auto front() const
Definition constant_path_interface.h:35
constexpr auto filename() const -> Optional< View >
Definition constant_path_interface.h:52
constexpr auto extension() const -> Optional< View >
Definition constant_path_interface.h:62
constexpr auto is_absolute() const -> bool
Definition constant_path_interface.h:49
constexpr auto begin() const
Definition constant_path_interface.h:46
constexpr auto back() const
Definition constant_path_interface.h:40
constexpr auto view() const &-> PathView
Definition constant_path_interface.h:32
constexpr auto stem() const -> Optional< View >
Definition constant_path_interface.h:71
constexpr void compute_first_component_end()
Definition constant_path_interface.h:107
constexpr auto is_relative() const -> bool
Definition constant_path_interface.h:50
constexpr auto ends_with(PathView suffix) const -> bool
Definition constant_path_interface.h:90
constexpr friend auto operator<=>(Self const &a, Self const &b)
Definition constant_path_interface.h:117
constexpr auto strip_prefix(PathView prefix) -> Optional< PathView >
Definition constant_path_interface.h:98
constexpr auto empty() const -> bool
Definition constant_path_interface.h:30
constexpr auto parent_path() const -> Optional< PathView >
Definition constant_path_interface.h:80
constexpr auto end() const
Definition constant_path_interface.h:47
constexpr friend auto operator==(Self const &a, Self const &b) -> bool
Definition constant_path_interface.h:116
constexpr friend auto tag_invoke(types::Tag< container::reconstruct >, InPlaceType< Self >, Iterator first, Iterator last) -> PathView
Definition constant_path_interface.h:119
Definition path_iterator.h:17
Definition path_view_impl.h:22
Definition view.h:35
Definition string_view_impl.h:19
Definition optional_forward_declaration.h:5
Definition tuple.h:27
Definition sequence.h:12
constexpr auto prev
Definition prev.h:28
constexpr auto next
Definition next.h:35
constexpr auto find
Definition find.h:35
constexpr auto starts_with
Definition starts_with.h:30
constexpr auto ends_with
Definition ends_with.h:41
constexpr auto mismatch
Definition mismatch.h:40
constexpr auto equal
Definition equal.h:46
constexpr auto compare
Definition compare.h:40
constexpr auto all_of
Definition all_of.h:24
constexpr auto equal
Definition equal.h:23
RemoveCVRef< T >::CodePoint EncodingCodePoint
Definition encoding.h:19
decltype(container::begin(util::declval< T & >())) ContainerIterator
Definition container_iterator.h:8
di::meta::Decay< decltype(T)> Tag
Definition tag_invoke.h:28
constexpr auto get(T &&value) -> decltype(auto)
Definition get.h:8
constexpr auto nullopt
Definition nullopt.h:15
constexpr auto lift_bool
Definition lift_bool.h:13
Definition in_place_type.h:5