32#include "Exception.hpp"
44 static void SkipUtf8Bom(FILE* fp);
51 const unsigned char ch =
static_cast<unsigned char>(*str);
52 if ((ch & 0xF0) == 0xE0) {
54 }
else if ((ch & 0x80) == 0x00) {
56 }
else if ((ch & 0xE0) == 0xC0) {
58 }
else if ((ch & 0xF8) == 0xF0) {
60 }
else if ((ch & 0xFC) == 0xF8) {
62 }
else if ((ch & 0xFE) == 0xFC) {
72 size_t length = NextCharLengthNoException(str);
83 const char* candidate = str - 1;
85 while (distance < 6) {
86 const unsigned char ch =
static_cast<unsigned char>(*candidate);
87 if ((ch & 0xC0) != 0x80) {
94 const size_t length = NextCharLengthNoException(candidate);
95 if (length == distance) {
105 return str + NextCharLength(str);
112 return str - PrevCharLength(str);
121 static const uint32_t kFirstIdeographicDescriptionOperator = 0x2FF0;
122 static const uint32_t kLastIdeographicDescriptionOperator = 0x2FFF;
124 static size_t IdeographicDescriptionOperatorArity(uint32_t codePoint) {
150 static size_t NextIdeographicDescriptionSequenceLength(
const char* str,
152 const size_t kMaxIDSDepth = 16;
153 const size_t kMaxIDSCodePoints = 64;
157 const size_t charLen = NextCharLengthNoException(str);
158 if (charLen == 0 || charLen > len) {
161 const uint32_t codePoint = CodePointNoException(str, charLen);
162 if (IdeographicDescriptionOperatorArity(codePoint) == 0) {
167 size_t codePoints = 0;
168 if (ConsumeIdeographicDescriptionSequence(
169 str, len, kMaxIDSDepth, kMaxIDSCodePoints, &consumed,
170 &codePoints) == IDSParseStatus::Complete) {
176 static bool IsIncompleteIdeographicDescriptionSequencePrefix(
const char* str,
178 const size_t kMaxIDSDepth = 16;
179 const size_t kMaxIDSCodePoints = 64;
183 const size_t charLen = NextCharLengthNoException(str);
184 if (charLen == 0 || charLen > len) {
187 const uint32_t codePoint = CodePointNoException(str, charLen);
188 if (IdeographicDescriptionOperatorArity(codePoint) == 0) {
193 size_t codePoints = 0;
194 return ConsumeIdeographicDescriptionSequence(
195 str, len, kMaxIDSDepth, kMaxIDSCodePoints, &consumed,
196 &codePoints) == IDSParseStatus::Incomplete;
199 static bool IsVariationSelector(uint32_t codePoint) {
200 return (codePoint >= 0xFE00 && codePoint <= 0xFE0F) ||
201 (codePoint >= 0xE0100 && codePoint <= 0xE01EF);
204 static bool ContainsVariationSelector(
const char* str,
size_t len) {
205 const char* pStr = str;
206 const char* strEnd = str + len;
207 while (pStr < strEnd) {
208 const size_t remainingLength = strEnd - pStr;
209 const size_t charLen = NextCharLengthNoException(pStr);
214 if (charLen > remainingLength) {
217 if (IsVariationSelector(CodePointNoException(pStr, charLen))) {
233 while (*str !=
'\0') {
234 const size_t charLen = NextCharLengthNoException(str);
242 while (i < charLen && str[i] !=
'\0') {
261 while (!IsLineEndingOrFileEnding(*str) && *str != ch) {
271 return ch ==
'\0' || ch ==
'\n' || ch ==
'\r';
277 static std::string
FromSubstr(
const char* str,
size_t length) {
279 newStr.resize(length);
280 memcpy(newStr.data(), str, length);
289 while (byteLength > 0) {
303 static std::string
TruncateUTF8(
const char* str,
size_t maxByteLength) {
304 std::string wordTrunc;
305 if (NotShorterThan(str, maxByteLength)) {
307 const char* pStr = str;
309 const size_t charLength = NextCharLength(pStr);
310 if (len + charLength > maxByteLength) {
316 wordTrunc = FromSubstr(str, len);
326 static void ReplaceAll(std::string& str,
const char* from,
const char* to) {
327 std::string::size_type pos = 0;
328 std::string::size_type fromLen = strlen(from);
329 std::string::size_type toLen = strlen(to);
330 while ((pos = str.find(from, pos)) != std::string::npos) {
331 str.replace(pos, fromLen, to);
339 static std::string
Join(
const std::vector<std::string>& strings,
340 const std::string& separator) {
341 std::ostringstream buffer;
343 for (
const auto& str : strings) {
356 static std::string
Join(
const std::vector<std::string>& strings) {
357 std::ostringstream buffer;
358 for (
const auto& str : strings) {
364 static void GetByteMap(
const char* str,
const size_t utf8Length,
365 std::vector<size_t>* byteMap) {
366 if (byteMap->size() < utf8Length) {
367 byteMap->resize(utf8Length);
369 const char* pstr = str;
370 for (
size_t i = 0; i < utf8Length; i++) {
371 (*byteMap)[i] = pstr - str;
372 pstr = NextChar(pstr);
377 static std::wstring GetPlatformString(
const std::string& str) {
381 static std::string GetPlatformString(
const std::string& str) {
return str; }
385 static std::string U16ToU8(
const std::wstring& wstr) {
387 int length =
static_cast<int>(wstr.length());
388 int convcnt = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), length, NULL, 0,
392 WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), length, &ret[0], convcnt,
398 static std::wstring U8ToU16(
const std::string& str) {
400 int length =
static_cast<int>(str.length());
401 int convcnt = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), length, NULL, 0);
404 MultiByteToWideChar(CP_UTF8, 0, str.c_str(), length, &ret[0], convcnt);
411 enum class IDSParseStatus {
417 static uint32_t CodePointNoException(
const char* str,
size_t charLen) {
418 const unsigned char first =
static_cast<unsigned char>(str[0]);
423 uint32_t codePoint = first & ((1U << (7 - charLen)) - 1);
424 for (
size_t i = 1; i < charLen; i++) {
425 codePoint = (codePoint << 6) |
426 (
static_cast<unsigned char>(str[i]) & 0x3FU);
431 static IDSParseStatus ConsumeIdeographicDescriptionSequence(
432 const char* str,
size_t len,
size_t depthLeft,
size_t maxCodePoints,
433 size_t* consumed,
size_t* codePoints) {
435 return IDSParseStatus::Incomplete;
437 if (depthLeft == 0 || *codePoints >= maxCodePoints) {
438 return IDSParseStatus::Invalid;
440 const size_t charLen = NextCharLengthNoException(str);
442 return IDSParseStatus::Invalid;
445 return IDSParseStatus::Incomplete;
449 const uint32_t codePoint = CodePointNoException(str, charLen);
450 const size_t arity = IdeographicDescriptionOperatorArity(codePoint);
453 return IDSParseStatus::Complete;
456 size_t offset = charLen;
457 for (
size_t i = 0; i < arity; i++) {
459 return IDSParseStatus::Incomplete;
461 size_t operandLength = 0;
462 const IDSParseStatus operandStatus = ConsumeIdeographicDescriptionSequence(
463 str + offset, len - offset, depthLeft - 1, maxCodePoints,
464 &operandLength, codePoints);
465 if (operandStatus != IDSParseStatus::Complete) {
466 return operandStatus;
468 offset += operandLength;
471 return IDSParseStatus::Complete;
Definition: Exception.hpp:77
UTF8 std::string utilities.
Definition: UTF8Util.hpp:39
static bool IsLineEndingOrFileEnding(const char ch)
Returns true if the character is a line ending or end of file.
Definition: UTF8Util.hpp:270
static size_t PrevCharLength(const char *str)
Returns the length in byte for the previous UTF8 character.
Definition: UTF8Util.hpp:82
static std::string FromSubstr(const char *str, size_t length)
Copies a substring with given length to a new string.
Definition: UTF8Util.hpp:277
static void ReplaceAll(std::string &str, const char *from, const char *to)
Replaces all patterns in a std::string in place.
Definition: UTF8Util.hpp:326
static size_t NextCharLengthNoException(const char *str)
Returns the length in byte for the next UTF8 character.
Definition: UTF8Util.hpp:50
static bool NotShorterThan(const char *str, size_t byteLength)
Returns true if the given std::string is longer or as long as the given length.
Definition: UTF8Util.hpp:288
static std::string Join(const std::vector< std::string > &strings)
Joins a std::string vector in to a std::string.
Definition: UTF8Util.hpp:356
static std::string TruncateUTF8(const char *str, size_t maxByteLength)
Truncates a std::string with a maximal length in byte.
Definition: UTF8Util.hpp:303
static size_t Length(const char *str)
Returns the UTF8 length of a null-terminated string.
Definition: UTF8Util.hpp:231
static const char * FindNextInline(const char *str, const char ch)
Finds a character in the same line.
Definition: UTF8Util.hpp:260
static size_t NextCharLength(const char *str)
Returns the length in byte for the next UTF8 character.
Definition: UTF8Util.hpp:71
static std::string Join(const std::vector< std::string > &strings, const std::string &separator)
Joins a std::string vector in to a std::string with a separator.
Definition: UTF8Util.hpp:339
static const char * PrevChar(const char *str)
Move the char* pointer before the previous UTF8 character.
Definition: UTF8Util.hpp:111
static const char * NextChar(const char *str)
Returns the char* pointer over the next UTF8 character.
Definition: UTF8Util.hpp:104