mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-07 09:25:33 +00:00
179 lines
3.7 KiB
C++
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));
|
|
}
|