2025-04-27 07:49:33 -04:00

296 lines
5.5 KiB
C++

#include "stdafx.h"
#include <string.h>
#include <assert.h>
#include "SimplStr.h"
// A simple string class
// This one is designed for minimal footprint, lack of virtual functions
// and UTF8/Unicode support
short strcasecmp(const char *a, const char *b)
{
for( ; ((*a > 96 ? *a - 32 : *a) == (*b > 96 ? *b - 32 : *b)) && *a; a++, b++)
{}
return (*a > 96 ? *a - 32 : *a) - (*b > 96 ? *b - 32 : *b);
}
CSimpleString::CSimpleString()
{
myData = 0;
myLength = 0;
myActualLength = 16; // Not true when myData == 0, but an optimization
myUTFPos = 0;
}
CSimpleUTFString::CSimpleUTFString()
{
myData = 0;
myLength = 0;
myActualLength = 16; // Not true when myData == 0, but an optimization
}
CSimpleString::~CSimpleString()
{
if(myData)
delete [] myData;
}
CSimpleUTFString::~CSimpleUTFString()
{
if(myData)
delete [] myData;
}
HRESULT CSimpleString::Grow(unsigned newSize)
{
HRESULT rc = S_OK;
if(!myData || newSize > myActualLength)
{
while(myActualLength < newSize)
myActualLength *= 2;
char *newData = new char[myActualLength];
if ( newData )
{
assert(newData != 0);
if(myData != 0 && myLength > 0)
{
assert(newData != 0);
assert(myData != 0);
assert(myLength > 0);
assert(myLength < 0x01000000); // Sanity checking
memmove(newData, myData, myLength);
delete [] myData;
}
myData = newData;
}
else
{
rc = E_OUTOFMEMORY;
}
}
return rc;
}
HRESULT CSimpleUTFString::Grow(unsigned newSize)
{
HRESULT rc = S_OK;
if(!myData || newSize > myActualLength)
{
while(myActualLength < newSize)
myActualLength *= 2;
unsigned short *newData = new unsigned short[myActualLength];
if ( newData )
{
assert(newData != 0);
if(myData != 0 && myLength > 0)
{
assert(newData != 0);
assert(myData != 0);
assert(myLength > 0);
assert(myLength < 0x01000000); // Sanity checking
memmove(newData, myData, myLength * 2);
delete [] myData;
}
myData = newData;
}
else
{
rc = E_OUTOFMEMORY;
}
}
return rc;
}
HRESULT CSimpleString::Copy(CSimpleString *val)
{
HRESULT rc = Grow(val->myLength);
if ( !FAILED( rc ) )
{
myLength = val->myLength;
memmove(myData, val->myData, myLength);
}
return rc;
}
HRESULT CSimpleUTFString::Copy(unsigned short *unicodeChars, unsigned long length)
{
HRESULT rc = Grow(length);
if ( !FAILED( rc ) )
{
myLength = length;
memmove(myData, unicodeChars, length * sizeof(unsigned short));
}
return rc;
}
HRESULT CSimpleUTFString::Copy(CSimpleUTFString *val)
{
HRESULT rc = Grow(val->myLength);
if ( !FAILED(rc) )
{
myLength = val->myLength;
memmove(myData, val->myData, myLength * 2);
}
return rc;
}
HRESULT CSimpleString::Cat(unsigned char theChar)
{
HRESULT rc = Grow(myLength + 1);
if ( !FAILED(rc) )
{
myData[myLength++] = theChar;
}
return rc;
}
HRESULT CSimpleUTFString::Cat(unsigned short theChar)
{
HRESULT rc = Grow(myLength + 1);
if ( !FAILED(rc) )
{
myData[myLength++] = theChar;
}
return rc;
}
HRESULT CSimpleUTFString::Cat(char * theChars)
{
HRESULT rc = S_OK;
while(*theChars)
{
rc = Grow(myLength + 1);
if ( FAILED(rc) )
{
return rc;
}
myData[myLength++] = *theChars;
theChars++;
}
return rc;
}
HRESULT CSimpleUTFString::Cat(unsigned char theChar)
{
HRESULT rc = S_OK;
// So that it will inline better
if(!(theChar & 0x80) || myUTFPos == 0)
{
rc = Grow(myLength + 1);
if ( FAILED(rc) )
{
return rc;
}
}
if(theChar & 0x80)
{
if(myUTFPos == 0)
{
if(theChar & 0x20) // 1st byte of three byte sequence
{
myData[myLength] = (theChar & 0x0f) << 12;
myUTFPos = 2;
}
else // 1st byte of a two byte sequence
{
myData[myLength] = (theChar & 0x1f) << 6;
myUTFPos = 1;
}
}
else if(myUTFPos == 1) // 2nd byte of a two byte sequence
{
myData[myLength++] |= (theChar & 0x3f);
myUTFPos = 0;
}
else if(myUTFPos == 2)
{
myData[myLength] |= (theChar & 0x3f) << 6;
myUTFPos = 3;
}
else
{
myData[myLength++] |= (theChar & 0x3f);
myUTFPos = 0;
}
}
else
{
myData[myLength++] = theChar;
}
return rc;
}
// The caller must call delete [] on the return value
char * CSimpleString::toString(void)
{
char *newData = new char[myLength + 1];
if ( newData )
{
memmove(newData, myData, myLength);
newData[myLength] = 0;
}
return newData;
}
char * CSimpleUTFString::toString(void)
{
char *newData = new char[myLength + 2];
if ( newData )
{
unsigned long i;
for(i = 0; i < myLength; i++)
newData[i] = (char) myData[i];
newData[myLength] = 0;
newData[myLength + 1] = 0;
}
return newData;
}
HRESULT CSimpleUTFString::Extract(char *into)
{
unsigned long i;
for(i = 0; i < myLength; i++)
into[i] = (char) myData[i];
into[myLength] = 0;
return S_OK;
}
long CSimpleString::Cmp(char *compareString, BOOL caseSensitive)
{
if ( FAILED( Grow(myLength + 1) ) )
{
return -1;
}
myData[myLength] = 0;
if(caseSensitive)
return strcmp(compareString, myData);
else
return strcasecmp(compareString, myData);
}
long CSimpleUTFString::Cmp(char *compareString, BOOL caseSensitive)
{
char *val = toString();
short result = -1;
if ( val )
{
if(caseSensitive)
result = strcmp(compareString, val);
else
result = strcasecmp(compareString, val);
delete [] val;
}
return result;
}