/* Copyright: Copyright (C) 2003-2018 SIL International. Authors: mcdurdin */ #include #include #include #include #include "kmx_processevent.h" #include "utfcodec.hpp" using namespace km::core; using namespace kmx; const km_core_cp *km::core::kmx::u16chr(const km_core_cp *p, km_core_cp ch) { while (*p) { if (*p == ch) return p; p++; } return ch == 0 ? p : NULL; } const km_core_cp *km::core::kmx::u16cpy(km_core_cp *dst, const km_core_cp *src) { km_core_cp *o = dst; while (*src) { *dst++ = *src++; } *dst = 0; return o; } const km_core_cp *km::core::kmx::u16ncpy(km_core_cp *dst, const km_core_cp *src, size_t max) { km_core_cp *o = dst; while (*src && max > 0) { *dst++ = *src++; max--; } while(max > 0) { *dst++ = 0; max--; } return o; } size_t km::core::kmx::u16len(const km_core_cp *p) { int i = 0; while (*p) { p++; i++; } return i; } int km::core::kmx::u16cmp(const km_core_cp *p, const km_core_cp *q) { while (*p && *q) { if (*p != *q) return *p - *q; p++; q++; } return *p - *q; } int km::core::kmx::u16icmp(const km_core_cp *p, const km_core_cp *q) { while (*p && *q) { if (toupper(*p) != toupper(*q)) return *p - *q; p++; q++; } return *p - *q; } int km::core::kmx::u16ncmp(const km_core_cp *p, const km_core_cp *q, size_t count) { while (*p && *q && count) { if (*p != *q) return *p - *q; p++; q++; count--; } if (count) return *p - *q; return 0; } km_core_cp *km::core::kmx::u16tok(km_core_cp *p, km_core_cp ch, km_core_cp **ctx) { if (!p) { p = *ctx; if (!p) return NULL; } km_core_cp *q = p; while (*q && *q != ch) { q++; } if (*q) { *q = 0; q++; while (*q == ch) q++; *ctx = q; } else { *ctx = NULL; } return p; } km_core_cp *km::core::kmx::u16dup(km_core_cp *src) { km_core_cp *dup = new km_core_cp[u16len(src) + 1]; memcpy(dup, src, (u16len(src) + 1) * sizeof(km_core_cp)); return dup; } /* * int xstrlen( PKMX_BYTE p ); * * Parameters: p Pointer to string to get length of * * Returns: length of string * * Called by: various functions * * xstrlen calculates the length of a string, ignoring some special chars. */ PKMX_WCHAR km::core::kmx::incxstr(PKMX_WCHAR p) { if (*p == 0) return p; if (*p != UC_SENTINEL) { if (*p >= 0xD800 && *p <= 0xDBFF && *(p + 1) >= 0xDC00 && *(p + 1) <= 0xDFFF) return p + 2; return p + 1; } // UC_SENTINEL(FFFF) with UC_SENTINEL_EXTENDEDEND(0x10) == variable length if (*(p + 1) == CODE_EXTENDED) { p += 2; while (*p && *p != UC_SENTINEL_EXTENDEDEND) p++; if (*p == 0) return p; return p + 1; } if (*(p + 1) > CODE_LASTCODE || CODE__SIZE[*(p + 1)] == -1) { return p + 1; } int deltaptr = 2 + CODE__SIZE[*(p + 1)]; // check for \0 between UC_SENTINEL(FFFF) and next printable character for (int i = 0; i < deltaptr; i++) { if (*p == 0) return p; p++; } return p; } PKMX_WCHAR km::core::kmx::decxstr(PKMX_WCHAR p, PKMX_WCHAR pStart) { PKMX_WCHAR q; if(p <= pStart) { return NULL; } p--; if(*p == UC_SENTINEL_EXTENDEDEND) { int n = 0; while (p >= pStart && *p != UC_SENTINEL && n < 10) { p--; n++; } if(p < pStart) { // May be a malformed virtual key return pStart; } return p; } if (p == pStart) { // Don't allow test before pStart return p; } if(*p >= 0xDC00 && *p <= 0xDFFF && *(p-1) >= 0xD800 && *(p-1) <= 0xDBFF) { return p-1; } // Look for a UC_SENTINEL to jump to // note: If we are pointing to the middle of a UC_SENTINEL CODE_x, then we won't treat it as valid, // and will just go back a single wchar q = p; for (int i = 0; i < CODE__SIZE_MAX && q >= pStart; i++, q--) { // *q == UC_SENTINEL && *(q + 1) is within CODE__SIZE && next CODE_ right of UC_SENTINEL ( looked up in CODE__SIZE+1) has value i if (*q == UC_SENTINEL && *(q + 1) <= CODE_LASTCODE && CODE__SIZE[*(q + 1)] + 1 == i) return q; } return p; } int km::core::kmx::xstrlen_ignoreifopt(PKMX_WCHAR p) { int i; for(i = 0; *p; i++, p=incxstr(p)) { if(*p == UC_SENTINEL && (*(p+1) == CODE_IFOPT || *(p+1) == CODE_IFSYSTEMSTORE)) i--; // I3432 } return i; } int km::core::kmx::xstrlen(PKMX_WCHAR p) { int i; for(i = 0; *p; i++, p=incxstr(p)); return i; } int km::core::kmx::xstrpos(PKMX_WCHAR p1, PKMX_WCHAR p) { int i; for(i = 0; p < p1; p = incxstr(p), i++); return i; } PKMX_WCHAR km::core::kmx::xstrchr(PKMX_WCHAR buf, PKMX_WCHAR chr) { for(PKMX_WCHAR q = incxstr(buf); *buf; buf = q, q = incxstr(buf)) if(!u16ncmp(buf, chr, (intptr_t)(q-buf))) return buf; return NULL; } int km::core::kmx::xchrcmp(PKMX_WCHAR ch1, PKMX_WCHAR ch2) { PKMX_WCHAR nch1 = incxstr(ch1); if(nch1 == ch1) return *ch2 - *ch1; /* comparing *ch2 to nul */ return u16ncmp(ch1, ch2, (intptr_t)(nch1-ch1)); } PKMX_WCHAR km::core::kmx::strtowstr(PKMX_CHAR in) { PKMX_WCHAR result; auto s = convert(in); result = new char16_t[s.length() + 1]; s.copy(result, s.length()); result[s.length()] = 0; return result; } PKMX_CHAR km::core::kmx::wstrtostr(PKMX_WCHAR in) { PKMX_CHAR result; auto s = convert(in); result = new char[s.length() + 1]; s.copy(result, s.length()); result[s.length()] = 0; return result; }