Support UTF8 to UTF16 LE
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
#include "ANSUtilities.h"
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include <iostream>
|
||||
#include <CkFileAccess.h>
|
||||
#include <CkAuthGoogle.h>
|
||||
@@ -949,5 +952,55 @@ namespace ANSCENTER
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string ANSUtilities::DecodeJsonUnicodeToUTF16LE(const std::string& escapedStr) {
|
||||
std::string result;
|
||||
result.reserve(escapedStr.size() * 2);
|
||||
size_t i = 0;
|
||||
while (i < escapedStr.size()) {
|
||||
if (i + 5 < escapedStr.size() && escapedStr[i] == '\\' && escapedStr[i + 1] == 'u') {
|
||||
char hex[5] = { escapedStr[i + 2], escapedStr[i + 3], escapedStr[i + 4], escapedStr[i + 5], 0 };
|
||||
uint16_t codepoint = (uint16_t)strtoul(hex, nullptr, 16);
|
||||
result += static_cast<char>(codepoint & 0xFF);
|
||||
result += static_cast<char>((codepoint >> 8) & 0xFF);
|
||||
i += 6;
|
||||
} else {
|
||||
result += escapedStr[i];
|
||||
result += '\0';
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string ANSUtilities::ConvertUTF16LEToUTF8(const char* utf16leBytes, int byteLen) {
|
||||
#ifdef _WIN32
|
||||
if (!utf16leBytes || byteLen <= 0) return "";
|
||||
int wideLen = byteLen / (int)sizeof(wchar_t);
|
||||
const wchar_t* wideStr = reinterpret_cast<const wchar_t*>(utf16leBytes);
|
||||
// First call: get required UTF-8 buffer size
|
||||
int utf8Len = WideCharToMultiByte(CP_UTF8, 0, wideStr, wideLen, nullptr, 0, nullptr, nullptr);
|
||||
if (utf8Len <= 0) return "";
|
||||
std::string utf8Str(utf8Len, 0);
|
||||
WideCharToMultiByte(CP_UTF8, 0, wideStr, wideLen, &utf8Str[0], utf8Len, nullptr, nullptr);
|
||||
return utf8Str;
|
||||
#else
|
||||
return std::string(utf16leBytes, byteLen);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string ANSUtilities::ConvertUTF8ToUTF16LE(const std::string& utf8Str) {
|
||||
#ifdef _WIN32
|
||||
if (utf8Str.empty()) return "";
|
||||
int wideLen = MultiByteToWideChar(CP_UTF8, 0, utf8Str.c_str(), (int)utf8Str.size(), nullptr, 0);
|
||||
if (wideLen <= 0) return "";
|
||||
std::wstring wideStr(wideLen, 0);
|
||||
MultiByteToWideChar(CP_UTF8, 0, utf8Str.c_str(), (int)utf8Str.size(), &wideStr[0], wideLen);
|
||||
const char* rawBytes = reinterpret_cast<const char*>(wideStr.data());
|
||||
return std::string(rawBytes, wideLen * sizeof(wchar_t));
|
||||
#else
|
||||
return utf8Str;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -89,6 +89,19 @@ namespace ANSCENTER {
|
||||
|
||||
// Restart PC
|
||||
[[nodiscard]] static bool RestartPC();
|
||||
|
||||
// Convert a UTF-8 encoded string to UTF-16LE byte string.
|
||||
// Useful for LabVIEW which can display UTF-16LE Unicode text on Windows.
|
||||
static std::string ConvertUTF8ToUTF16LE(const std::string& utf8Str);
|
||||
|
||||
// Decode JSON Unicode escape sequences (\uXXXX) to UTF-16LE byte string.
|
||||
// Input: ASCII string with \uXXXX escapes (e.g., "\\u6c5f\\u6771 599")
|
||||
// Output: UTF-16LE byte string for LabVIEW display.
|
||||
static std::string DecodeJsonUnicodeToUTF16LE(const std::string& escapedStr);
|
||||
|
||||
// Convert a UTF-16LE byte string to UTF-8.
|
||||
// Useful for receiving Unicode text from LabVIEW and converting to UTF-8 for internal processing.
|
||||
static std::string ConvertUTF16LEToUTF8(const char* utf16leBytes, int byteLen);
|
||||
};
|
||||
// Connection bundle for pool
|
||||
struct S3Connection {
|
||||
@@ -230,6 +243,10 @@ extern "C" ANSULT_API int SendEmail(const char* smtpServer, int port,
|
||||
|
||||
extern "C" ANSULT_API int RebootSystem();
|
||||
|
||||
// Unicode conversion utilities for LabVIEW
|
||||
extern "C" ANSULT_API int ANSConvertUTF8ToUTF16LE(const char* utf8Str, LStrHandle result);
|
||||
extern "C" ANSULT_API int ANSDecodeJsonUnicodeToUTF16LE(const char* escapedStr, LStrHandle result);
|
||||
extern "C" ANSULT_API int ANSConvertUTF16LEToUTF8(const unsigned char* utf16leBytes, int byteLen, LStrHandle result);
|
||||
|
||||
// AWS S3 class
|
||||
|
||||
|
||||
@@ -798,6 +798,104 @@ extern "C" ANSULT_API int RebootSystem() {
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" ANSULT_API int ANSConvertUTF8ToUTF16LE(const char* utf8Str, LStrHandle result) {
|
||||
try {
|
||||
if (!utf8Str || !result) return -1;
|
||||
int len = (int)strlen(utf8Str);
|
||||
if (len == 0) return 0;
|
||||
bool hasUnicodeEscapes = false;
|
||||
bool hasNonAscii = false;
|
||||
for (int i = 0; i < len; i++) {
|
||||
if ((unsigned char)utf8Str[i] >= 0x80) hasNonAscii = true;
|
||||
if (i + 1 < len && utf8Str[i] == '\\' && utf8Str[i + 1] == 'u') hasUnicodeEscapes = true;
|
||||
}
|
||||
if (!hasNonAscii && !hasUnicodeEscapes) {
|
||||
MgErr error = DSSetHandleSize(result, sizeof(int32) + len * sizeof(uChar));
|
||||
if (error != noErr) return -2;
|
||||
(*result)->cnt = len;
|
||||
memcpy((*result)->str, utf8Str, len);
|
||||
return 1;
|
||||
}
|
||||
if (hasUnicodeEscapes) {
|
||||
std::string utf16le;
|
||||
utf16le.reserve(len * 2);
|
||||
for (int i = 0; i < len; ) {
|
||||
if (i + 5 < len && utf8Str[i] == '\\' && utf8Str[i + 1] == 'u') {
|
||||
char hex[5] = { utf8Str[i + 2], utf8Str[i + 3], utf8Str[i + 4], utf8Str[i + 5], 0 };
|
||||
uint16_t cp = (uint16_t)strtoul(hex, nullptr, 16);
|
||||
utf16le += static_cast<char>(cp & 0xFF);
|
||||
utf16le += static_cast<char>((cp >> 8) & 0xFF);
|
||||
i += 6;
|
||||
} else {
|
||||
utf16le += utf8Str[i];
|
||||
utf16le += '\0';
|
||||
i++;
|
||||
}
|
||||
}
|
||||
int size = (int)utf16le.size();
|
||||
MgErr error = DSSetHandleSize(result, sizeof(int32) + size * sizeof(uChar));
|
||||
if (error != noErr) return -2;
|
||||
(*result)->cnt = size;
|
||||
memcpy((*result)->str, utf16le.data(), size);
|
||||
return 1;
|
||||
}
|
||||
std::string converted = ANSCENTER::ANSUtilities::ConvertUTF8ToUTF16LE(utf8Str);
|
||||
if (converted.empty()) return 0;
|
||||
int size = static_cast<int>(converted.size());
|
||||
MgErr error = DSSetHandleSize(result, sizeof(int32) + size * sizeof(uChar));
|
||||
if (error != noErr) return -2;
|
||||
(*result)->cnt = size;
|
||||
memcpy((*result)->str, converted.data(), size);
|
||||
return 1;
|
||||
}
|
||||
catch (...) { return -1; }
|
||||
}
|
||||
|
||||
extern "C" ANSULT_API int ANSConvertUTF16LEToUTF8(const unsigned char* utf16leBytes, int byteLen, LStrHandle result) {
|
||||
try {
|
||||
if (!utf16leBytes || byteLen <= 0 || !result) return -1;
|
||||
bool isUtf16le = (byteLen >= 2 && byteLen % 2 == 0);
|
||||
if (isUtf16le) {
|
||||
bool isAscii = true;
|
||||
for (int i = 1; i < byteLen; i += 2) {
|
||||
if (utf16leBytes[i] != 0x00) { isAscii = false; break; }
|
||||
}
|
||||
if (isAscii) {
|
||||
int asciiLen = byteLen / 2;
|
||||
MgErr error = DSSetHandleSize(result, sizeof(int32) + asciiLen * sizeof(uChar));
|
||||
if (error != noErr) return -2;
|
||||
(*result)->cnt = asciiLen;
|
||||
for (int i = 0; i < asciiLen; i++) (*result)->str[i] = utf16leBytes[i * 2];
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
std::string converted = ANSCENTER::ANSUtilities::ConvertUTF16LEToUTF8(
|
||||
reinterpret_cast<const char*>(utf16leBytes), byteLen);
|
||||
if (converted.empty()) return 0;
|
||||
int size = static_cast<int>(converted.size());
|
||||
MgErr error = DSSetHandleSize(result, sizeof(int32) + size * sizeof(uChar));
|
||||
if (error != noErr) return -2;
|
||||
(*result)->cnt = size;
|
||||
memcpy((*result)->str, converted.data(), size);
|
||||
return 1;
|
||||
}
|
||||
catch (...) { return -1; }
|
||||
}
|
||||
|
||||
extern "C" ANSULT_API int ANSDecodeJsonUnicodeToUTF16LE(const char* escapedStr, LStrHandle result) {
|
||||
try {
|
||||
if (!escapedStr || !result) return -1;
|
||||
std::string decoded = ANSCENTER::ANSUtilities::DecodeJsonUnicodeToUTF16LE(escapedStr);
|
||||
if (decoded.empty()) return 0;
|
||||
int size = static_cast<int>(decoded.size());
|
||||
MgErr error = DSSetHandleSize(result, sizeof(int32) + size * sizeof(uChar));
|
||||
if (error != noErr) return -2;
|
||||
(*result)->cnt = size;
|
||||
memcpy((*result)->str, decoded.data(), size);
|
||||
return 1;
|
||||
}
|
||||
catch (...) { return -1; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user