Repository: LadybirdBrowser/ladybird
File: AK/Utf16View.h (C/C++)

Code before:

        if (has_ascii_storage()) {
            ++m_iterator.ascii;
            --m_remaining_code_units;
        } else {
            auto length = min(length_in_code_units(), remaining_code_units);

            m_iterator.utf16 += length;
            m_remaining_code_units -= length;
        }

        return *this;
    }

    constexpr Utf16CodePointIterator& operator--()
    {
        VERIFY(!at_start());

        if (has_ascii_storage()) {
            --m_iterator.ascii;
            ++m_remaining_code_units;
        } else {
            --m_iterator.utf16;
            ++m_remaining_code_units;

            if (m_remaining_code_units > 1) {
                auto current_code_unit = *m_iterator.utf16;
                if (UnicodeUtils::is_utf16_low_surrogate(current_code_unit)) {
                    auto prev_code_unit = *(m_iterator.utf16 - 1);
                    if (UnicodeUtils::is_utf16_high_surrogate(prev_code_unit)) {
                        --m_iterator.utf16;
                        ++m_remaining_code_units;
                    }
                }
            }
        }

        return *this;
    }

    constexpr u32 operator*() const
    {
        auto remaining_code_units = this->remaining_code_units();
        VERIFY(remaining_code_units > 0);

        if (has_ascii_storage())
            return *m_iterator.ascii;

        auto code_unit = *m_iterator.utf16;

        if (UnicodeUtils::is_utf16_high_surrogate(code_unit)) {

Review comment (bug):
Shouldn't this be `if (!at_start())` ? The following currently crashes instead of printing all 4 code points:
```c++
auto view = u"\xdc00 :)"sv;
auto iterator = view.end();
dbgln("U+{:04X}", *(--iterator));
dbgln("U+{:04X}", *(--iterator));
dbgln("U+{:04X}", *(--iterator));
dbgln("U+{:04X}", *(--iterator));
```

Code after:

        if (has_ascii_storage()) {
            ++m_iterator.ascii;
            --m_remaining_code_units;
        } else {
            auto length = min(length_in_code_units(), remaining_code_units);

            m_iterator.utf16 += length;
            m_remaining_code_units -= length;
        }

        return *this;
    }

    constexpr u32 operator*() const
    {
        auto remaining_code_units = this->remaining_code_units();
        VERIFY(remaining_code_units > 0);

        if (has_ascii_storage())
            return *m_iterator.ascii;

        auto code_unit = *m_iterator.utf16;

        if (UnicodeUtils::is_utf16_high_surrogate(code_unit)) {
            if (remaining_code_units > 1) {
                auto next_code_unit = *(m_iterator.utf16 + 1);

                if (UnicodeUtils::is_utf16_low_surrogate(next_code_unit))
                    return UnicodeUtils::decode_utf16_surrogate_pair(code_unit, next_code_unit);
            }
        }

        return static_cast<u32>(code_unit);
    }

    constexpr Optional<u32> peek(size_t code_point_offset) const
    {
        if (code_point_offset == 0) {
            if (remaining_code_units() == 0)
                return {};
            return this->operator*();
        }

        auto it = *this;

        for (size_t index = 0; index < code_point_offset; ++index) {
            ++it;
            if (it.remaining_code_units() == 0)
                return {};
        }