Skip to content

Commit

Permalink
Fix range-adaptor handling of an incomplete sequence.
Browse files Browse the repository at this point in the history
  • Loading branch information
paulhuggett committed Jan 13, 2024
1 parent 18585f9 commit a3ee81c
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 2 deletions.
10 changes: 9 additions & 1 deletion include/icubaby/icubaby.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1045,7 +1045,9 @@ class transcode_view<FromEncoding, ToEncoding, View>::iterator {
constexpr std::ranges::iterator_t<View> const& base () const& noexcept { return current_; }
constexpr std::ranges::iterator_t<View> base () && { return std::move (current_); }

constexpr value_type const& operator* () const { return state_.front (); }
constexpr value_type const& operator* () const {
return state_.empty () ? replacement : state_.front ();
}
constexpr std::ranges::iterator_t<View> operator->() const { return state_.front (); }

constexpr iterator& operator++ () {
Expand Down Expand Up @@ -1085,6 +1087,7 @@ class transcode_view<FromEncoding, ToEncoding, View>::iterator {
private:
std::ranges::iterator_t<View> current_{};
transcode_view const* parent_ = nullptr;
static value_type const replacement = icubaby::replacement_char;

class state {
public:
Expand Down Expand Up @@ -1117,6 +1120,11 @@ class transcode_view<FromEncoding, ToEncoding, View>::iterator {
mutable state state_{};
};

template <unicode_char_type FromEncoding, unicode_char_type ToEncoding, std::ranges::input_range View>
requires std::ranges::view<View>
transcode_view<FromEncoding, ToEncoding, View>::iterator::value_type const
transcode_view<FromEncoding, ToEncoding, View>::iterator::replacement;

template <unicode_char_type FromEncoding, unicode_char_type ToEncoding, std::ranges::input_range View>
requires std::ranges::view<View>
constexpr std::ranges::iterator_t<View> transcode_view<FromEncoding, ToEncoding, View>::iterator::state::fill (
Expand Down
17 changes: 16 additions & 1 deletion unittests/test_u8_32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -277,8 +277,23 @@ TEST (Utf8To32, RangesCopy) {
};
// clang-format on
std::vector<char32_t> out32;
std::ranges::copy (in | icubaby::ranges::transcode<char8_t, char32_t>, std::back_inserter (out32));
auto const r = in | icubaby::ranges::transcode<char8_t, char32_t>;
std::ranges::copy (r, std::back_inserter (out32));
EXPECT_THAT (out32, testing::ElementsAre (char32_t{0x3053}, char32_t{0x3093}, char32_t{0x306B}, char32_t{0x3061},
char32_t{0x306F}, char32_t{0x4E16}, char32_t{0x754C}, char32_t{0x000A}));
EXPECT_TRUE (r.well_formed());
}
TEST (Utf8To32, RangesBadInput) {
// clang-format off
std::vector const in{
char8_t{0xF3}, char8_t{0x81},
};
// clang-format on
std::vector<char32_t> out32;
auto const r = in | icubaby::ranges::transcode<char8_t, char32_t>;
std::ranges::copy (r, std::back_inserter (out32));
EXPECT_THAT (out32, testing::ElementsAre (char32_t{icubaby::replacement_char}));
EXPECT_FALSE (r.well_formed());
}

#endif // __cpp_lib_ranges

0 comments on commit a3ee81c

Please sign in to comment.