Fix AMD and OpenVINO

This commit is contained in:
2026-04-08 13:45:52 +10:00
parent a4a8caaa86
commit 69787b0ff0
15 changed files with 1209 additions and 132 deletions

View File

@@ -514,6 +514,177 @@ extern "C" ANSFR_API int InsertUser(ANSCENTER::ANSFacialRecognition** H
return -1;
}
}
// Helper: repair mixed-encoding LabVIEW LStrHandle to clean UTF-16LE.
// LabVIEW text controls may produce a mix of UTF-16LE pairs, embedded UTF-8
// multi-byte sequences, and lone space bytes (0x20 without 0x00 high byte).
// This normalizes everything to proper UTF-16LE pairs.
// Input: BOM-stripped raw bytes. Output: clean UTF-16LE vector.
static std::vector<unsigned char> RepairLabVIEWUTF16LE_Local(const unsigned char* data, int len) {
std::vector<unsigned char> repaired;
if (!data || len <= 0) return repaired;
repaired.reserve(len + 32);
auto emitU16 = [&](uint16_t cp) {
repaired.push_back(static_cast<unsigned char>(cp & 0xFF));
repaired.push_back(static_cast<unsigned char>((cp >> 8) & 0xFF));
};
for (int i = 0; i < len; ) {
unsigned char b = data[i];
// 1. Detect embedded UTF-8 multi-byte sequences
// 2-byte UTF-8: C2-DF followed by 80-BF
if (b >= 0xC2 && b <= 0xDF && i + 1 < len) {
unsigned char b1 = data[i + 1];
if ((b1 & 0xC0) == 0x80) {
uint32_t cp = ((b & 0x1F) << 6) | (b1 & 0x3F);
emitU16(static_cast<uint16_t>(cp));
i += 2; continue;
}
}
// 3-byte UTF-8: E0-EF followed by 80-BF 80-BF
if (b >= 0xE0 && b <= 0xEF && i + 2 < len) {
unsigned char b1 = data[i + 1], b2 = data[i + 2];
if ((b1 & 0xC0) == 0x80 && (b2 & 0xC0) == 0x80) {
uint32_t cp = ((b & 0x0F) << 12) | ((b1 & 0x3F) << 6) | (b2 & 0x3F);
if (cp >= 0x0800 && (cp < 0xD800 || cp > 0xDFFF)) {
emitU16(static_cast<uint16_t>(cp));
i += 3; continue;
}
}
}
// 4-byte UTF-8: F0-F4 followed by 80-BF 80-BF 80-BF
if (b >= 0xF0 && b <= 0xF4 && i + 3 < len) {
unsigned char b1 = data[i + 1], b2 = data[i + 2], b3 = data[i + 3];
if ((b1 & 0xC0) == 0x80 && (b2 & 0xC0) == 0x80 && (b3 & 0xC0) == 0x80) {
uint32_t cp = ((b & 0x07) << 18) | ((b1 & 0x3F) << 12)
| ((b2 & 0x3F) << 6) | (b3 & 0x3F);
if (cp >= 0x10000 && cp <= 0x10FFFF) {
cp -= 0x10000;
emitU16(static_cast<uint16_t>(0xD800 + (cp >> 10)));
emitU16(static_cast<uint16_t>(0xDC00 + (cp & 0x3FF)));
i += 4; continue;
}
}
}
// 2. Normal UTF-16LE pair (low byte + 0x00 high byte)
if (i + 1 < len && data[i + 1] == 0x00) {
repaired.push_back(data[i]); repaired.push_back(0x00); i += 2;
}
// 3. Lone space byte — LabVIEW dropped the 0x00 high byte
else if (b == 0x20 && (i + 1 >= len || data[i + 1] != 0x00)) {
repaired.push_back(0x20); repaired.push_back(0x00); i += 1;
}
// 4. Non-ASCII UTF-16LE pair
else if (i + 1 < len) {
repaired.push_back(data[i]); repaired.push_back(data[i + 1]); i += 2;
}
// 5. Trailing odd byte — skip
else { i++; }
}
return repaired;
}
// Helper: convert LStrHandle (mixed UTF-8/UTF-16LE or system codepage) to UTF-8 string
static std::string LStrHandleToUTF8(LStrHandle handle) {
if (!handle) return "";
int byteLen = (*handle)->cnt;
if (byteLen <= 0) return "";
const unsigned char* data = reinterpret_cast<const unsigned char*>((*handle)->str);
// Check for BOM or 0x00 bytes → UTF-16LE (possibly mixed with UTF-8)
bool isUtf16le = false;
if (byteLen >= 2 && data[0] == 0xFF && data[1] == 0xFE) isUtf16le = true;
if (!isUtf16le) {
for (int i = 0; i < byteLen; i++) {
if (data[i] == 0x00) { isUtf16le = true; break; }
}
}
if (isUtf16le) {
const unsigned char* convData = data;
int convLen = byteLen;
if (convLen >= 2 && convData[0] == 0xFF && convData[1] == 0xFE) { convData += 2; convLen -= 2; }
if (convLen <= 0) return "";
// Repair mixed encoding (UTF-8 islands, lone spaces) → clean UTF-16LE
auto repaired = RepairLabVIEWUTF16LE_Local(convData, convLen);
#ifdef _WIN32
int wideLen = static_cast<int>(repaired.size()) / 2;
const wchar_t* wideStr = reinterpret_cast<const wchar_t*>(repaired.data());
int utf8Len = WideCharToMultiByte(CP_UTF8, 0, wideStr, wideLen, nullptr, 0, nullptr, nullptr);
if (utf8Len > 0) {
std::string utf8(utf8Len, 0);
WideCharToMultiByte(CP_UTF8, 0, wideStr, wideLen, &utf8[0], utf8Len, nullptr, nullptr);
return utf8;
}
#endif
return std::string(reinterpret_cast<const char*>(repaired.data()), repaired.size());
} else {
// No 0x00 bytes — try UTF-8 first, fall back to system codepage.
// IsValidUTF8: check if bytes form valid UTF-8 with at least one multi-byte sequence.
auto IsValidUTF8 = [](const unsigned char* d, int l) -> bool {
bool hasMulti = false;
for (int j = 0; j < l; ) {
unsigned char c = d[j];
if (c <= 0x7F) { j++; }
else if (c >= 0xC2 && c <= 0xDF) {
if (j + 1 >= l || (d[j + 1] & 0xC0) != 0x80) return false;
hasMulti = true; j += 2;
} else if (c >= 0xE0 && c <= 0xEF) {
if (j + 2 >= l || (d[j + 1] & 0xC0) != 0x80 || (d[j + 2] & 0xC0) != 0x80) return false;
hasMulti = true; j += 3;
} else if (c >= 0xF0 && c <= 0xF4) {
if (j + 3 >= l || (d[j + 1] & 0xC0) != 0x80 || (d[j + 2] & 0xC0) != 0x80 || (d[j + 3] & 0xC0) != 0x80) return false;
hasMulti = true; j += 4;
} else { return false; }
}
return hasMulti;
};
if (IsValidUTF8(data, byteLen)) {
return std::string(reinterpret_cast<const char*>(data), byteLen);
}
#ifdef _WIN32
int wideLen = MultiByteToWideChar(CP_ACP, 0, reinterpret_cast<const char*>(data), byteLen, nullptr, 0);
if (wideLen > 0) {
std::wstring wideStr(wideLen, 0);
MultiByteToWideChar(CP_ACP, 0, reinterpret_cast<const char*>(data), byteLen, &wideStr[0], wideLen);
int utf8Len = WideCharToMultiByte(CP_UTF8, 0, wideStr.c_str(), wideLen, nullptr, 0, nullptr, nullptr);
if (utf8Len > 0) {
std::string utf8(utf8Len, 0);
WideCharToMultiByte(CP_UTF8, 0, wideStr.c_str(), wideLen, &utf8[0], utf8Len, nullptr, nullptr);
return utf8;
}
}
#endif
return std::string(reinterpret_cast<const char*>(data), byteLen);
}
}
extern "C" ANSFR_API int InsertUser_LV(ANSCENTER::ANSFacialRecognition** Handle, const char* userCode, LStrHandle userName) {
try {
if (!Handle || !*Handle || !userCode || !userName) return -1;
std::string utf8Name = LStrHandleToUTF8(userName);
if (utf8Name.empty()) return -1;
return (*Handle)->InsertUser(userCode, utf8Name);
}
catch (const std::exception& e) { return -1; }
}
extern "C" ANSFR_API int UpdateUser_LV(ANSCENTER::ANSFacialRecognition** Handle, int userId, const char* userCode, LStrHandle userName) {
try {
if (!Handle || !*Handle || !userCode || !userName) return -1;
std::string utf8Name = LStrHandleToUTF8(userName);
if (utf8Name.empty()) return -1;
return (*Handle)->UpdateUser(userId, userCode, utf8Name);
}
catch (const std::exception& e) { return -1; }
}
extern "C" ANSFR_API int UpdateUser(ANSCENTER::ANSFacialRecognition** Handle, int userId, const char* userCode, const char* userName) {
try {
if (!Handle || !*Handle || !userCode || !userName) return -1;