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

Code before:

    [[nodiscard]] constexpr bool operator==(Utf16CodePointIterator const& other) const
    {
        // Note that this also protects against iterators with different underlying storage.
        if (m_remaining_code_units != other.m_remaining_code_units)
            return false;

        if (has_ascii_storage())
            return m_iterator.ascii == other.m_iterator.ascii;
        return m_iterator.utf16 == other.m_iterator.utf16;
    }

    [[nodiscard]] constexpr size_t length_in_code_units()
    {
        if (has_ascii_storage())
            return 1;
        return UnicodeUtils::code_unit_length_for_code_point(**this);
    }

    [[nodiscard]] constexpr bool at_start() const
    {
        if (has_ascii_storage()) {
            return m_iterator.ascii == m_start.ascii;
        } else {
            return m_iterator.utf16 == m_start.utf16;
        }
    }

    [[nodiscard]] constexpr bool done() const
    {
        return this->remaining_code_units() <= 0;
    }

private:
    friend Utf16View;

    constexpr Utf16CodePointIterator(char const* iterator, size_t length, char const* start = nullptr)
        : m_iterator { .ascii = iterator }
        , m_remaining_code_units(length)
        , m_start { .ascii = start ? start : iterator }
    {
    }

    constexpr Utf16CodePointIterator(char16_t const* iterator, size_t length, char16_t const* start = nullptr)
        : m_iterator { .utf16 = iterator }
        , m_remaining_code_units(length)
        , m_start { .utf16 = start ? start : iterator }
    {
        m_remaining_code_units |= 1uz << Detail::UTF16_FLAG;
    }


Review comment (suggestion):
You don't need an `else` when the `if` branch always returns:
```c++
if (has_ascii_storage()) 
    return m_iterator.ascii == m_start.ascii;
return m_iterator.utf16 == m_start.utf16;
```

Code after:
    }

    constexpr Utf16CodePointIterator(char16_t const* iterator, size_t length)
        : m_iterator { .utf16 = iterator }
        , m_remaining_code_units(length)
    {
        m_remaining_code_units |= 1uz << Detail::UTF16_FLAG;
    }

    constexpr bool has_ascii_storage() const { return m_remaining_code_units >> Detail::UTF16_FLAG == 0; }
    constexpr size_t remaining_code_units() const { return m_remaining_code_units & ~(1uz << Detail::UTF16_FLAG); }

    union {
        char const* ascii;
        char16_t const* utf16;
    } m_iterator { .ascii = nullptr };

    // Just like Utf16StringData, we store whether this string has ASCII or UTF-16 storage by setting the most
    // significant bit of m_remaining_code_units for UTF-16 storage.
    size_t m_remaining_code_units { 0 };
};

class Utf16View {
public:
    using Iterator = Utf16CodePointIterator;

    Utf16View() = default;
    ~Utf16View() = default;

    constexpr Utf16View(char16_t const* string, size_t length_in_code_units)
        : m_string { .utf16 = string }
        , m_length_in_code_units(length_in_code_units)
    {
        m_length_in_code_units |= 1uz << Detail::UTF16_FLAG;
    }

    consteval Utf16View(StringView string)
        : m_string { .ascii = string.characters_without_null_termination() }
        , m_length_in_code_units(string.length())
    {
        VERIFY(all_of(string, AK::is_ascii));
    }

    ErrorOr<String> to_utf8(AllowLonelySurrogates = AllowLonelySurrogates::Yes) const;
    ErrorOr<ByteString> to_byte_string(AllowLonelySurrogates = AllowLonelySurrogates::Yes) const;

    ALWAYS_INLINE String to_utf8_but_should_be_ported_to_utf16(AllowLonelySurrogates allow_lonely_surrogates = AllowLonelySurrogates::Yes) const
    {
        return MUST(to_utf8(allow_lonely_surrogates));
    }