Skip to content

Commit 31195f0

Browse files
committed
Cleaning up slicing constructors
1 parent 97ea2df commit 31195f0

File tree

2 files changed

+88
-0
lines changed

2 files changed

+88
-0
lines changed

lib/inc/sys_string/sys_string.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,9 +165,12 @@ namespace sysstr
165165
sys_string_t & operator=(const sys_string_t &) noexcept = default;
166166
sys_string_t & operator=(sys_string_t &&) noexcept = default;
167167
~sys_string_t() noexcept = default;
168+
169+
//Inherit any storage specific constructors
168170

169171
using storage::storage;
170172

173+
//Constructors from raw strings and character ranges
171174

172175
template<has_utf_encoding Char>
173176
sys_string_t(const Char * str, size_t len) :
@@ -190,13 +193,41 @@ namespace sysstr
190193
sys_string_t(std::ranges::data(val), std::ranges::size(val))
191194
{}
192195

196+
//Slice constructors from utf32_access::iterators
197+
193198
sys_string_t(const typename utf32_access::iterator & first, const typename utf32_access::iterator & last):
194199
sys_string_t(first.storage_current(), last.storage_current())
195200
{}
196201

202+
sys_string_t(const typename utf32_access::reverse_iterator & first, const typename utf32_access::reverse_iterator & last):
203+
sys_string_t(first.storage_current(), last.storage_current())
204+
{}
205+
197206
sys_string_t(const typename utf32_access::iterator & first, std::default_sentinel_t):
198207
sys_string_t(first.storage_current(), first.storage_last())
199208
{}
209+
210+
sys_string_t(const typename utf32_access::reverse_iterator & first, std::default_sentinel_t):
211+
sys_string_t(first.storage_current(), first.storage_last())
212+
{}
213+
214+
template<std::ranges::range Range>
215+
requires(std::is_same_v<std::ranges::iterator_t<Range>, typename utf32_access::iterator> &&
216+
(std::is_same_v<std::ranges::sentinel_t<Range>, typename utf32_access::iterator> ||
217+
std::is_same_v<std::ranges::sentinel_t<Range>, std::default_sentinel_t>))
218+
sys_string_t(const Range & range):
219+
sys_string_t(std::begin(range), std::end(range))
220+
{}
221+
222+
template<std::ranges::range Range>
223+
requires(std::is_same_v<std::ranges::iterator_t<Range>, typename utf32_access::reverse_iterator> &&
224+
(std::is_same_v<std::ranges::sentinel_t<Range>, typename utf32_access::reverse_iterator> ||
225+
std::is_same_v<std::ranges::sentinel_t<Range>, std::default_sentinel_t>))
226+
sys_string_t(const Range & range):
227+
sys_string_t(std::begin(range), std::end(range))
228+
{}
229+
230+
//Slice constructors from char_access::iterators
200231

201232
template<std::sized_sentinel_for<typename char_access::iterator> EndIt>
202233
sys_string_t(const typename char_access::iterator & first, const EndIt & last):
@@ -208,6 +239,23 @@ namespace sysstr
208239
sys_string_t(first.base() - (last - first), first.base())
209240
{}
210241

242+
template<std::ranges::range Range>
243+
requires(std::is_same_v<std::ranges::iterator_t<Range>, typename char_access::iterator> &&
244+
std::sized_sentinel_for<std::ranges::sentinel_t<Range>, typename char_access::iterator> &&
245+
(!std::ranges::contiguous_range<Range> || !has_utf_encoding<std::ranges::range_value_t<Range>>))
246+
sys_string_t(const Range & range):
247+
sys_string_t(std::begin(range), std::end(range))
248+
{}
249+
250+
template<std::ranges::range Range>
251+
requires(std::is_same_v<std::ranges::iterator_t<Range>, typename char_access::reverse_iterator> &&
252+
std::sized_sentinel_for<std::ranges::sentinel_t<Range>, typename char_access::reverse_iterator>)
253+
sys_string_t(const Range & range):
254+
sys_string_t(std::begin(range), std::end(range))
255+
{}
256+
257+
// Construct moving from underlying storage
258+
211259
explicit sys_string_t(storage && st) noexcept : storage(std::move(st))
212260
{}
213261

test/test_general.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,46 @@ TEST_CASE( "Creation" ) {
9797
CHECK(from_long_char == S("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"));
9898
}
9999

100+
TEST_CASE( "Slicing" ) {
101+
{
102+
sys_string str = S("a水𐀀𝄞");
103+
sys_string::utf32_access access(str);
104+
105+
auto first = std::begin(access);
106+
++first;
107+
CHECK(sys_string(first, std::end(access)) == S("水𐀀𝄞"));
108+
auto last = first;
109+
++last;
110+
CHECK(sys_string(first, last) == S(""));
111+
CHECK(sys_string(std::ranges::subrange(first, last)) == S(""));
112+
113+
auto rfirst = ranges::make_reverse_iterator(access, last);
114+
CHECK(sys_string(rfirst, std::rend(access)) == S("a水"));
115+
auto rlast = ranges::make_reverse_iterator(access, first);
116+
CHECK(sys_string(rfirst, rlast) == S(""));
117+
CHECK(sys_string(std::ranges::subrange(rfirst, rlast)) == S(""));
118+
}
119+
120+
{
121+
sys_string str = S("abc");
122+
sys_string::char_access access(str);
123+
124+
auto first = std::begin(access);
125+
++first;
126+
CHECK(sys_string(first, std::end(access)) == S("bc"));
127+
auto last = first;
128+
++last;
129+
CHECK(sys_string(first, last) == S("b"));
130+
CHECK(sys_string(std::ranges::subrange(first, last)) == S("b"));
131+
132+
auto rfirst = ranges::make_reverse_iterator(access, last);
133+
CHECK(sys_string(rfirst, std::rend(access)) == S("ab"));
134+
auto rlast = ranges::make_reverse_iterator(access, first);
135+
CHECK(sys_string(rfirst, rlast) == S("b"));
136+
CHECK(sys_string(std::ranges::subrange(rfirst, rlast)) == S("b"));
137+
}
138+
}
139+
100140
TEST_CASE( "Iteration" ) {
101141
sys_string str = S("a水𐀀𝄞");
102142
sys_string empty = S("");

0 commit comments

Comments
 (0)