spiegel-keyman/common/windows/cpp/src/xstring.cpp

179 lines
3.7 KiB
C++

/*
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));
}