From fc4547b412e28164af1bf8981234c6af959ccc0b Mon Sep 17 00:00:00 2001 From: Joel Klinghed Date: Tue, 13 Jun 2023 10:07:16 +0200 Subject: WIP --- utf/src/utf16.cc | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 utf/src/utf16.cc (limited to 'utf/src/utf16.cc') diff --git a/utf/src/utf16.cc b/utf/src/utf16.cc new file mode 100644 index 0000000..43595bf --- /dev/null +++ b/utf/src/utf16.cc @@ -0,0 +1,67 @@ +#include "utf16.hh" + +#include "utf_error.hh" + +namespace utf { + +namespace { + +inline bool is_high_surrogate(uint16_t c) { + return c >= 0xd800 && c <= 0xdbff; +} + +inline bool is_low_surrogate(uint16_t c) { + return c >= 0xdc00 && c <= 0xdfff; +} + +} // namespace + +uint32_t read16be(std::string_view data, std::size_t& offset) { + if (offset > data.size() || data.size() - offset < 2) + return NEED_MORE; + uint16_t c = static_cast(data[offset]) << 8 + | static_cast(data[offset + 1] & 0xff); + if (is_high_surrogate(c)) { + if (data.size() - offset < 4) + return NEED_MORE; + uint16_t d = static_cast(data[offset + 2]) << 8 + | static_cast(data[offset + 3] & 0xff); + if (is_low_surrogate(d)) { + offset += 4; + return 0x10000 + + (static_cast(c & 0x3ff) << 10 + | (d & 0x3ff)); + } + return INVALID; + } else if (is_low_surrogate(c)) { + return INVALID; + } + offset += 2; + return c; +} + +uint32_t read16le(std::string_view data, std::size_t& offset) { + if (offset > data.size() || data.size() - offset < 2) + return NEED_MORE; + uint16_t c = static_cast(data[offset + 1]) << 8 + | static_cast(data[offset] & 0xff); + if (is_high_surrogate(c)) { + if (data.size() - offset < 4) + return NEED_MORE; + uint16_t d = static_cast(data[offset + 3]) << 8 + | static_cast(data[offset + 2] & 0xff); + if (is_low_surrogate(d)) { + offset += 4; + return 0x10000 + + (static_cast(c & 0x3ff) << 10 + | (d & 0x3ff)); + } + return INVALID; + } else if (is_low_surrogate(c)) { + return INVALID; + } + offset += 2; + return c; +} + +} // namespace utf -- cgit v1.2.3-70-g09d2