Skip to content

Commit ada1a1c

Browse files
committed
Making utf_util properly support input iterators
1 parent 25bc1da commit ada1a1c

File tree

1 file changed

+51
-33
lines changed

1 file changed

+51
-33
lines changed

lib/inc/sys_string/impl/unicode/utf_util.h

Lines changed: 51 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -18,27 +18,27 @@ namespace sysstr
1818
class utf_converter
1919
{
2020
private:
21-
template<std::forward_iterator It, std::sentinel_for<It> EndIt>
21+
template<std::input_iterator It, std::sentinel_for<It> EndIt>
2222
static void reading(It first, EndIt last) noexcept(noexcept(*first++) && noexcept(first != last));
23-
template<std::ranges::forward_range Range>
23+
template<std::ranges::input_range Range>
2424
static void reading(Range && range) noexcept(noexcept(reading(std::ranges::begin(range), std::ranges::end(range))));
2525
template<std::output_iterator<utf_char_of<To>> OutIt>
2626
static void writing(OutIt dest) noexcept(noexcept(*dest++ = utf_char_of<To>()));
2727
template<class Func>
2828
static void applying(Func func) noexcept(noexcept(func(utf_char_of<To>())));
2929
public:
30-
template<std::ranges::forward_range Range, class Func>
30+
template<std::ranges::input_range Range, class Func>
3131
static Func for_each_converted(Range && range, Func func) noexcept(noexcept(reading(std::forward<Range>(range))) && noexcept(applying(func)));
3232

33-
template<std::ranges::forward_range Range, std::output_iterator<utf_char_of<To>> OutIt>
33+
template<std::ranges::input_range Range, std::output_iterator<utf_char_of<To>> OutIt>
3434
SYS_STRING_FORCE_INLINE
3535
static OutIt convert(Range && range, OutIt dest) noexcept(noexcept(reading(std::forward<Range>(range))) && noexcept(writing(dest)))
3636
{
3737
for_each_converted(std::forward<Range>(range), [&](auto c) { *dest++ = c; });
3838
return dest;
3939
}
4040

41-
template<std::ranges::forward_range Range>
41+
template<std::ranges::input_range Range>
4242
SYS_STRING_FORCE_INLINE
4343
static size_t converted_length(Range && range) noexcept(noexcept(reading(std::forward<Range>(range))))
4444
{
@@ -47,7 +47,7 @@ namespace sysstr
4747
return ret;
4848
}
4949

50-
template<std::forward_iterator It, std::sentinel_for<It> EndIt, class Func>
50+
template<std::input_iterator It, std::sentinel_for<It> EndIt, class Func>
5151
SYS_STRING_FORCE_INLINE
5252
static Func for_each_converted(It first, EndIt last, Func func) noexcept(noexcept(reading(first, last)) && noexcept(applying(func)))
5353
{
@@ -56,15 +56,15 @@ namespace sysstr
5656
}
5757

5858

59-
template<std::forward_iterator It, std::sentinel_for<It> EndIt, std::output_iterator<utf_char_of<To>> OutIt>
59+
template<std::input_iterator It, std::sentinel_for<It> EndIt, std::output_iterator<utf_char_of<To>> OutIt>
6060
SYS_STRING_FORCE_INLINE
6161
static OutIt convert(It first, EndIt last, OutIt dest) noexcept(noexcept(reading(first, last)) && noexcept(writing(dest)))
6262
{
6363
for_each_converted(first, last, [&](auto c) { *dest++ = c; });
6464
return dest;
6565
}
6666

67-
template<std::forward_iterator It, std::sentinel_for<It> EndIt>
67+
template<std::input_iterator It, std::sentinel_for<It> EndIt>
6868
SYS_STRING_FORCE_INLINE
6969
static size_t converted_length(It first, EndIt last) noexcept(noexcept(reading(first, last)))
7070
{
@@ -79,26 +79,26 @@ namespace sysstr
7979
class utf32_input
8080
{
8181
private:
82-
template<std::forward_iterator It, std::sentinel_for<It> EndIt>
82+
template<std::input_iterator It, std::sentinel_for<It> EndIt>
8383
static void reading(It first, EndIt last) noexcept(noexcept(*first++) && noexcept(first != last));
84-
template<std::ranges::forward_range Range>
84+
template<std::ranges::input_range Range>
8585
static void reading(Range && range) noexcept(noexcept(reading(std::ranges::begin(range), std::ranges::end(range))));
8686

8787
public:
88-
template<std::forward_iterator It, std::sentinel_for<It> EndIt>
88+
template<std::input_iterator It, std::sentinel_for<It> EndIt>
8989
static char32_t read(It & first, EndIt last) noexcept(noexcept(reading(first,last)));
9090

91-
template<std::forward_iterator It, std::sentinel_for<It> EndIt>
91+
template<std::input_iterator It, std::sentinel_for<It> EndIt>
9292
static char32_t read_reversed(It & first, EndIt last) noexcept(noexcept(reading(first,last)));
9393

94-
template<std::ranges::forward_range Range, class Sink>
94+
template<std::ranges::input_range Range, class Sink>
9595
SYS_STRING_FORCE_INLINE
9696
static Sink read(Range && range, Sink sink) noexcept(noexcept(reading(std::forward<Range>(range))) && noexcept(sink(char32_t())))
9797
{
9898
return read(std::ranges::begin(std::forward<Range>(range)), std::ranges::end(std::forward<Range>(range)), sink);
9999
}
100100

101-
template<std::forward_iterator It, std::sentinel_for<It> EndIt, class Sink>
101+
template<std::input_iterator It, std::sentinel_for<It> EndIt, class Sink>
102102
SYS_STRING_FORCE_INLINE
103103
static Sink read(It first, EndIt last, Sink sink) noexcept(noexcept(reading(first,last)) && noexcept(sink(char32_t())))
104104
{
@@ -248,7 +248,7 @@ namespace sysstr
248248
};
249249

250250
template<utf_encoding From, utf_encoding To>
251-
template<std::ranges::forward_range Range, class Func>
251+
template<std::ranges::input_range Range, class Func>
252252
SYS_STRING_FORCE_INLINE
253253
Func utf_converter<From, To>::for_each_converted(Range && range, Func func)
254254
noexcept(noexcept(reading(std::forward<Range>(range))) && noexcept(applying(func)))
@@ -258,7 +258,7 @@ namespace sysstr
258258

259259

260260
template<utf_encoding From>
261-
template<std::forward_iterator It, std::sentinel_for<It> EndIt>
261+
template<std::input_iterator It, std::sentinel_for<It> EndIt>
262262
SYS_STRING_FORCE_INLINE
263263
char32_t utf32_input<From>::read(It & first, EndIt last) noexcept(noexcept(reading(first,last)))
264264
{
@@ -318,7 +318,7 @@ namespace sysstr
318318
}
319319

320320
template<utf_encoding From>
321-
template<std::forward_iterator It, std::sentinel_for<It> EndIt>
321+
template<std::input_iterator It, std::sentinel_for<It> EndIt>
322322
SYS_STRING_FORCE_INLINE
323323
char32_t utf32_input<From>::read_reversed(It & first, EndIt last) noexcept(noexcept(reading(first, last)))
324324
{
@@ -334,24 +334,42 @@ namespace sysstr
334334
if (decoder.error() || first == last)
335335
return char32_t{U'\uFFFD'};
336336

337-
It rewind_point = first;
338-
for ( ; ; )
337+
if constexpr (std::forward_iterator<It>)
339338
{
340-
byte = uint8_t(*first);
341-
++first;
342-
decoder.put(byte);
343-
344-
if (decoder.done())
345-
return char32_t{decoder.value()};
346-
347-
if (decoder.error())
348-
{
349-
first = std::move(rewind_point);
350-
return char32_t{U'\uFFFD'};
339+
It rewind_point = first;
340+
for ( ; ; )
341+
{
342+
byte = uint8_t(*first);
343+
++first;
344+
decoder.put(byte);
345+
346+
if (decoder.done())
347+
return char32_t{decoder.value()};
348+
349+
if (decoder.error())
350+
{
351+
first = std::move(rewind_point);
352+
return char32_t{U'\uFFFD'};
353+
}
354+
355+
if (first == last)
356+
return char32_t{u'\uFFFD'};
357+
}
358+
}
359+
else
360+
{
361+
for ( ; ; )
362+
{
363+
byte = uint8_t(*first);
364+
decoder.put(byte);
365+
if (decoder.error())
366+
return char32_t{U'\uFFFD'};
367+
++first;
368+
if (decoder.done())
369+
return char32_t{decoder.value()};
370+
if (first == last)
371+
return char32_t{U'\uFFFD'};
351372
}
352-
353-
if (first == last)
354-
return char32_t{u'\uFFFD'};
355373
}
356374
}
357375
else if constexpr (From == utf16)

0 commit comments

Comments
 (0)