#pragma once #include #include #include class Utf8StringDecoder { public: Utf8StringDecoder(const char* str); usize byte_length() const { return m_byte_length; } Result code_points() const; // The caller must ensure that 'buf' is at least code_points() + a NULL wide. Result decode(wchar_t* buf) const; Result decode(wchar_t* buf, usize max) const; private: const char* m_str; usize m_byte_length; }; class Utf8StringEncoder { public: Utf8StringEncoder(const wchar_t* str); usize code_points() const { return m_code_points; } Result byte_length() const; // The caller must ensure that 'buf' is at least byte_length() + a NULL wide. Result encode(char* buf) const; Result encode(char* buf, usize max) const; private: const wchar_t* m_str; usize m_code_points; }; class Utf8StateDecoder { public: Utf8StateDecoder(); Result feed(char c); Result extract(); void reset(); private: char m_state[4]; usize m_state_len = 0; usize m_state_index = 0; wchar_t m_decoded_character; bool m_has_character_ready { false }; }; class Utf8Encoder { public: // Does not null-terminate. Returns the number of bytes written. Result encode(wchar_t c, char buf[4]); };