/* Name: xstring Copyright: Copyright (C) 2003-2017 SIL International. Documentation: Description: Create Date: 27 Aug 2012 Modified Date: 27 Aug 2012 Authors: mcdurdin Related Files: Dependencies: Bugs: Todo: Notes: History: 27 Aug 2012 - mcdurdin - I3439 - V9.0 - Refactor xstring support in C++ code */ #include "pch.h" /* * int xstrlen( LPBYTE 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. */ PWSTR incxstr(PWSTR 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; } p+=2; switch(*(p-1)) { case CODE_ANY: return p+1; case CODE_NOTANY: return p+1; case CODE_INDEX: return p+2; case CODE_USE: return p+1; case CODE_DEADKEY: return p+1; case CODE_EXTENDED: p += 2; while(*p && *p != UC_SENTINEL_EXTENDEDEND) p++; return p+1; case CODE_CLEARCONTEXT: return p+1; case CODE_CALL: return p+1; case CODE_CONTEXTEX: return p+1; case CODE_IFOPT: return p+3; case CODE_IFSYSTEMSTORE: return p+3; case CODE_SETOPT: return p+2; case CODE_SETSYSTEMSTORE: return p+2; case CODE_RESETOPT: return p+1; case CODE_SAVEOPT: return p+1; default: return p; } } PWSTR decxstr(PWSTR p, PWSTR pStart) { if (p <= pStart) { // At start of string so return NULL // incxstr returns pointer to NULL at end of str so // be aware of this difference. 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) return p; // Don't allow test before pStart if(*p >= 0xDC00 && *p <= 0xDFFF && *(p-1) >= 0xD800 && *(p-1) <= 0xDBFF) { return p-1; } else if(*(p-1) == UC_SENTINEL) return p-1; else if(p > pStart + 1 && *(p-2) == UC_SENTINEL) { switch(*(p-1)) { case CODE_ANY: case CODE_NOTANY: case CODE_USE: case CODE_DEADKEY: case CODE_CLEARCONTEXT: case CODE_CALL: case CODE_CONTEXTEX: case CODE_RESETOPT: case CODE_SAVEOPT: return p-2; } } else if(p > pStart + 2 && *(p-3) == UC_SENTINEL) { switch(*(p-2)) { case CODE_INDEX: case CODE_SETOPT: case CODE_SETSYSTEMSTORE: return p-3; } } else if(p > pStart + 3 && *(p-4) == UC_SENTINEL) { switch(*(p-3)) { case CODE_IFOPT: case CODE_IFSYSTEMSTORE: // I3432 return p-4; } } return p; } int xstrlen_ignoreifopt(PWSTR 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 xstrlen(PWSTR p) { int i; for(i = 0; *p; i++, p=incxstr(p)); return i; } int xstrpos(PWSTR p1, PWSTR p) { int i; for(i = 0; p < p1; p = incxstr(p), i++); return i; } /*PWSTR xstrchr(PWSTR buf, int x) { int clow, chigh; if(x < 0x10000) { chigh = x; clow = -1; } else { chigh = Uni_UTF32ToSurrogate1(x); clow = Uni_UTF32ToSurrogate2(x); } for(; *buf; buf = incxstr(buf)) if(*buf == chigh && (*(buf+1) == clow || clow == -1)) return buf; return NULL; }*/ PWSTR xstrchr(PWSTR buf, PWSTR chr) { for(PWSTR q = incxstr(buf); *buf; buf = q, q = incxstr(buf)) if(!wcsncmp(buf, chr, (intptr_t)(q-buf))) return buf; return NULL; } int xchrcmp(PWSTR ch1, PWSTR ch2) { PWSTR nch1 = incxstr(ch1); if(nch1 == ch1) return *ch2 - *ch1; /* comparing *ch2 to nul */ return wcsncmp(ch1, ch2, (intptr_t)(nch1-ch1)); }