|
@@ -1,88 +1,45 @@
|
|
|
#include "core/utils/ArrayString.hpp"
|
|
|
|
|
|
+#include <limits.h>
|
|
|
+#include <stdlib.h>
|
|
|
+#include <string.h>
|
|
|
+#include <uchar.h>
|
|
|
+
|
|
|
+#include "core/data/Array.hpp"
|
|
|
#include "core/math/Math.hpp"
|
|
|
#include "core/utils/Error.hpp"
|
|
|
+#include "core/utils/Utility.hpp"
|
|
|
|
|
|
using CharString = Core::CharString;
|
|
|
using Char32String = Core::Char32String;
|
|
|
using Error = Core::Error;
|
|
|
namespace ErrorCode = Core::ErrorCode;
|
|
|
|
|
|
-template<typename T>
|
|
|
-constexpr int stringLength(const T* c) {
|
|
|
- const T* i = c + 1;
|
|
|
+constexpr int stringLength(const c32* c) {
|
|
|
+ const c32* i = c + 1;
|
|
|
while(*(c++) != '\0') {}
|
|
|
return static_cast<int>(c - i);
|
|
|
}
|
|
|
|
|
|
-static c32 read(const char*& s) {
|
|
|
- if(*s == '\0') {
|
|
|
- return 0;
|
|
|
- }
|
|
|
- return static_cast<c32>(*(s++));
|
|
|
-}
|
|
|
-
|
|
|
static Error readUnicode(c32& u, const char*& s) {
|
|
|
- u = read(s);
|
|
|
- if((u & 0x80) == 0) {
|
|
|
- return ErrorCode::NONE;
|
|
|
- }
|
|
|
- if((u & 0xE0) == 0xC0) {
|
|
|
- c32 u2 = read(s);
|
|
|
- if(u2 == 0) {
|
|
|
- return ErrorCode::INVALID_CHAR;
|
|
|
- }
|
|
|
- u = ((u & 0x1F) << 6) | (u2 & 0x3F);
|
|
|
- return ErrorCode::NONE;
|
|
|
- } else if((u & 0xF0) == 0xE0) {
|
|
|
- c32 u2 = read(s);
|
|
|
- c32 u3 = read(s);
|
|
|
- if(u2 == 0 || u3 == 0) {
|
|
|
- return ErrorCode::INVALID_CHAR;
|
|
|
- }
|
|
|
- u = ((u & 0xF) << 12) | ((u2 & 0x3F) << 6) | (u3 & 0x3F);
|
|
|
- return ErrorCode::NONE;
|
|
|
- } else if((u & 0xF8) == 0xF0) {
|
|
|
- c32 u2 = read(s);
|
|
|
- c32 u3 = read(s);
|
|
|
- c32 u4 = read(s);
|
|
|
- if(u2 == 0 || u3 == 0 || u4 == 0) {
|
|
|
- return ErrorCode::INVALID_CHAR;
|
|
|
- }
|
|
|
- u = ((u & 0x07) << 18) | ((u2 & 0x3F) << 12) | ((u3 & 0x3F) << 6) |
|
|
|
- (u4 & 0x3F);
|
|
|
- return ErrorCode::NONE;
|
|
|
- }
|
|
|
- return ErrorCode::INVALID_CHAR;
|
|
|
-}
|
|
|
-
|
|
|
-template<unsigned int L>
|
|
|
-static void unicodeToChar(c32 c, char (&buffer)[L]) {
|
|
|
- static_assert(L >= 5, "to small char buffer");
|
|
|
- buffer[0] = '\0';
|
|
|
- if(c < (1 << 7)) {
|
|
|
- buffer[0] = static_cast<char>(((c >> 0) & 0x7F) | 0x0);
|
|
|
- buffer[1] = '\0';
|
|
|
- } else if(c < (1 << 11)) {
|
|
|
- buffer[0] = static_cast<char>(((c >> 6) & 0x1F) | 0xC0);
|
|
|
- buffer[1] = static_cast<char>(((c >> 0) & 0x3F) | 0x80);
|
|
|
- buffer[2] = '\0';
|
|
|
- } else if(c < (1 << 16)) {
|
|
|
- buffer[0] = static_cast<char>(((c >> 12) & 0x0F) | 0xE0);
|
|
|
- buffer[1] = static_cast<char>(((c >> 6) & 0x3F) | 0x80);
|
|
|
- buffer[2] = static_cast<char>(((c >> 0) & 0x3F) | 0x80);
|
|
|
- buffer[3] = '\0';
|
|
|
- } else if(c < (1 << 21)) {
|
|
|
- buffer[0] = static_cast<char>(((c >> 18) & 0x07) | 0xF0);
|
|
|
- buffer[1] = static_cast<char>(((c >> 12) & 0x3F) | 0x80);
|
|
|
- buffer[2] = static_cast<char>(((c >> 6) & 0x3F) | 0x80);
|
|
|
- buffer[3] = static_cast<char>(((c >> 0) & 0x3F) | 0x80);
|
|
|
- buffer[4] = '\0';
|
|
|
+ size_t limit = MB_CUR_MAX;
|
|
|
+ size_t n = mbrtoc32(&u, s, limit, nullptr);
|
|
|
+ if(n > limit) {
|
|
|
+ return ErrorCode::INVALID_CHAR;
|
|
|
}
|
|
|
+ s += n;
|
|
|
+ return ErrorCode::NONE;
|
|
|
}
|
|
|
|
|
|
-static Error printChar(c32 u, u32 shift, u32 a, u32 o) {
|
|
|
- return Core::putChar(static_cast<int>(((u >> shift) & a) | o));
|
|
|
+using C32Buffer = Core::Array<char, MB_LEN_MAX + 1>;
|
|
|
+
|
|
|
+static Error convertC32(C32Buffer& buffer, c32 c) {
|
|
|
+ size_t n = c32rtomb(buffer.begin(), c, nullptr);
|
|
|
+ if(n >= static_cast<size_t>(buffer.getLength())) {
|
|
|
+ return ErrorCode::INVALID_CHAR;
|
|
|
+ }
|
|
|
+ buffer[static_cast<i64>(n)] = '\0';
|
|
|
+ return ErrorCode::NONE;
|
|
|
}
|
|
|
|
|
|
CharString::CharString(char* buffer, i32 bufferSize)
|
|
@@ -96,24 +53,11 @@ Error CharString::copyFrom(const CharString& s) {
|
|
|
}
|
|
|
|
|
|
bool CharString::operator==(const char* s) const {
|
|
|
- const char* p = data;
|
|
|
- while(*s == *p && *s != '\0') {
|
|
|
- s++;
|
|
|
- p++;
|
|
|
- }
|
|
|
- return *s == *p;
|
|
|
+ return strcmp(data, s) == 0;
|
|
|
}
|
|
|
|
|
|
bool CharString::operator==(const CharString& other) const {
|
|
|
- if(length != other.getLength()) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- for(int i = 0; i < length; i++) {
|
|
|
- if(data[i] != other[i]) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
- return true;
|
|
|
+ return length == other.length && strcmp(data, other.data) == 0;
|
|
|
}
|
|
|
|
|
|
bool CharString::operator!=(const char* s) const {
|
|
@@ -158,14 +102,14 @@ Error CharString::append(wchar_t c) {
|
|
|
}
|
|
|
|
|
|
Error CharString::append(c32 c) {
|
|
|
- char buffer[5];
|
|
|
- unicodeToChar(c, buffer);
|
|
|
- return append(static_cast<const char*>(buffer));
|
|
|
+ C32Buffer buffer;
|
|
|
+ CORE_RETURN_ERROR(convertC32(buffer, c));
|
|
|
+ return append(static_cast<const char*>(buffer.begin()));
|
|
|
}
|
|
|
|
|
|
Error CharString::append(const char* s) {
|
|
|
// stringLength as s could be some part of data
|
|
|
- for(int i = stringLength(s); i > 0; i--) {
|
|
|
+ for(size_t i = strlen(s); i > 0; i--) {
|
|
|
CORE_RETURN_ERROR(append(*(s++)));
|
|
|
}
|
|
|
return ErrorCode::NONE;
|
|
@@ -217,8 +161,7 @@ Error CharString::print() const {
|
|
|
|
|
|
Error CharString::printLine() const {
|
|
|
CORE_RETURN_ERROR(print());
|
|
|
- CORE_RETURN_ERROR(Core::putChar('\n'));
|
|
|
- return ErrorCode::NONE;
|
|
|
+ return Core::putChar('\n');
|
|
|
}
|
|
|
|
|
|
bool CharString::startsWidth(const CharString& other, int from) const {
|
|
@@ -430,22 +373,9 @@ void Char32String::clear() {
|
|
|
|
|
|
Error Char32String::print() const {
|
|
|
for(int i = 0; i < length; i++) {
|
|
|
- c32 c = data[i];
|
|
|
- if(c < (1 << 7)) {
|
|
|
- CORE_RETURN_ERROR(printChar(c, 0, 0x7F, 0x0));
|
|
|
- } else if(c < (1 << 11)) {
|
|
|
- CORE_RETURN_ERROR(printChar(c, 6, 0x1F, 0xC0));
|
|
|
- CORE_RETURN_ERROR(printChar(c, 0, 0x3F, 0x80));
|
|
|
- } else if(c < (1 << 16)) {
|
|
|
- CORE_RETURN_ERROR(printChar(c, 12, 0x0F, 0xE0));
|
|
|
- CORE_RETURN_ERROR(printChar(c, 6, 0x3F, 0x80));
|
|
|
- CORE_RETURN_ERROR(printChar(c, 0, 0x3F, 0x80));
|
|
|
- } else if(c < (1 << 21)) {
|
|
|
- CORE_RETURN_ERROR(printChar(c, 18, 0x07, 0xF0));
|
|
|
- CORE_RETURN_ERROR(printChar(c, 12, 0x3F, 0x80));
|
|
|
- CORE_RETURN_ERROR(printChar(c, 6, 0x3F, 0x80));
|
|
|
- CORE_RETURN_ERROR(printChar(c, 0, 0x3F, 0x80));
|
|
|
- }
|
|
|
+ C32Buffer buffer;
|
|
|
+ CORE_RETURN_ERROR(convertC32(buffer, data[i]));
|
|
|
+ CORE_RETURN_ERROR(putChars(buffer.begin()));
|
|
|
}
|
|
|
return ErrorCode::NONE;
|
|
|
}
|