Files
core/PdfReader/Src/StringExt.cpp
Ilya.Kirillov eb965c1d6d Добавлен новый проект PdfReader для кроссплатформенного чтения Pdf.
git-svn-id: svn://fileserver/activex/AVS/Sources/TeamlabOffice/trunk/ServerComponents@62480 954022d7-b5bf-4e40-9824-e11837661b57
2016-05-21 00:01:53 +03:00

758 lines
18 KiB
C++
Raw Blame History

#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include "MemoryUtils.h"
#include "StringExt.h"
namespace PdfReader
{
union StringExtFormatArg
{
int iValue;
unsigned int uiValue;
long lValue;
unsigned long ulValue;
double fValue;
char cValue;
char *sValue;
StringExt *seValue;
};
enum StringExtFormatType
{
fmtIntDecimal,
fmtIntHex,
fmtIntOctal,
fmtIntBinary,
fmtUIntDecimal,
fmtUIntHex,
fmtUIntOctal,
fmtUIntBinary,
fmtLongDecimal,
fmtLongHex,
fmtLongOctal,
fmtLongBinary,
fmtULongDecimal,
fmtULongHex,
fmtULongOctal,
fmtULongBinary,
fmtDouble,
fmtDoubleTrim,
fmtChar,
fmtString,
fmtStringExt,
fmtSpace
};
static char *c_arrsFormatStrings[] =
{
"d", "x", "o", "b", "ud", "ux", "uo", "ub",
"ld", "lx", "lo", "lb", "uld", "ulx", "ulo", "ulb",
"f", "g",
"c",
"s",
"t",
"w",
NULL
};
//------------------------------------------------------------------------
static inline int Size(int nLen)
{
int nDelta;
for (nDelta = 8; nDelta < nLen && nDelta < 0x100000; nDelta <<= 1);
// ((nLen + 1) + (delta - 1)) & ~(delta - 1)
return (nLen + nDelta) & ~(nDelta - 1);
}
inline void StringExt::Resize(int nLength)
{
char *sTemp = NULL;
if (!m_sData)
m_sData = new char[Size(nLength)];
else if (Size(nLength) != Size(m_nLength))
{
sTemp = new char[Size(nLength)];
if (nLength < m_nLength)
{
memcpy(sTemp, m_sData, nLength);
sTemp[nLength] = '\0';
}
else
memcpy(sTemp, m_sData, m_nLength + 1);
delete[] m_sData;
m_sData = sTemp;
}
}
StringExt::StringExt()
{
m_sData = NULL;
Resize(m_nLength = 0);
m_sData[0] = '\0';
}
StringExt::StringExt(std::wstring& wsString)
{
int nLen = wsString.length();
m_sData = NULL;
Resize(m_nLength = nLen);
for (int nPos = 0; nPos < nLen; nPos++)
{
m_sData[nPos] = (unsigned char)wsString.at(nPos);
}
}
StringExt::StringExt(const wchar_t* _wsString)
{
std::wstring wsString(_wsString);
int nLen = wsString.length();
m_sData = NULL;
Resize(m_nLength = nLen);
for (int nPos = 0; nPos < nLen; nPos++)
{
m_sData[nPos] = (unsigned char)wsString.at(nPos);
}
}
StringExt::StringExt(const char *sSrc)
{
int nLen = strlen(sSrc);
m_sData = NULL;
Resize(m_nLength = nLen);
memcpy(m_sData, sSrc, nLen + 1);
}
StringExt::StringExt(const char *sSrc, int nLength)
{
m_sData = NULL;
Resize(m_nLength = nLength);
memcpy(m_sData, sSrc, m_nLength * sizeof(char));
m_sData[m_nLength] = '\0';
}
StringExt::StringExt(StringExt *seSrc, int nIndex, int nLength)
{
m_sData = NULL;
Resize(m_nLength = nLength);
memcpy(m_sData, seSrc->GetBuffer() + nIndex, m_nLength);
m_sData[m_nLength] = '\0';
}
StringExt::StringExt(StringExt *seSrc)
{
m_sData = NULL;
Resize(m_nLength = seSrc->GetLength());
memcpy(m_sData, seSrc->GetBuffer(), m_nLength + 1);
}
StringExt::StringExt(StringExt *seString1, StringExt *seString2)
{
int nLen1 = seString1->GetLength();
int nLen2 = seString2->GetLength();
m_sData = NULL;
Resize(m_nLength = nLen1 + nLen2);
memcpy(m_sData, seString1->GetBuffer(), nLen1);
memcpy(m_sData + nLen1, seString2->GetBuffer(), nLen2 + 1);
}
StringExt *StringExt::FromInt(int nValue)
{
char sBuffer[24];
char *pData = NULL;
int nLen;
FormatInt(nValue, sBuffer, sizeof(sBuffer), false, 0, 10, &pData, &nLen);
return new StringExt(pData, nLen);
}
StringExt *StringExt::Format(char *sFormat, ...)
{
va_list sArgList;
StringExt *seResult = new StringExt();
va_start(sArgList, sFormat);
seResult->AppendFormatV(sFormat, sArgList);
va_end(sArgList);
return seResult;
}
StringExt *StringExt::FormatV(char *sFormat, va_list sArgList)
{
StringExt *seResult = new StringExt();
seResult->AppendFormatV(sFormat, sArgList);
return seResult;
}
StringExt::~StringExt()
{
delete[] m_sData;
}
StringExt *StringExt::Clear()
{
m_sData[m_nLength = 0] = '\0';
Resize(0);
return this;
}
StringExt *StringExt::Append(char nChar)
{
Resize(m_nLength + 1);
m_sData[m_nLength++] = nChar;
m_sData[m_nLength] = '\0';
return this;
}
StringExt *StringExt::Append(StringExt *seString)
{
int nLen = seString->GetLength();
Resize(m_nLength + nLen);
memcpy(m_sData + m_nLength, seString->GetBuffer(), nLen + 1);
m_nLength += nLen;
return this;
}
StringExt *StringExt::Append(const char *sString)
{
int nLen = strlen(sString);
Resize(m_nLength + nLen);
memcpy(m_sData + m_nLength, sString, nLen + 1);
m_nLength += nLen;
return this;
}
StringExt *StringExt::Append(const char *sString, int nLength)
{
Resize(m_nLength + nLength);
memcpy(m_sData + m_nLength, sString, nLength);
m_nLength += nLength;
m_sData[m_nLength] = '\0';
return this;
}
StringExt *StringExt::AppendFormat(char *sFormat, ...)
{
va_list sArgList;
va_start(sArgList, sFormat);
AppendFormatV(sFormat, sArgList);
va_end(sArgList);
return this;
}
StringExt *StringExt::AppendFormatV(char *sFormat, va_list sArgList)
{
StringExtFormatArg uArg;
int nIndex, nWidth, nPrecision;
bool bReverseAlign, bZeroFill;
StringExtFormatType eFormatType;
char sBuffer[65];
int nLen;
char *pCur, *pTemp, *sTemp;
int nArgsLen = 0;
int nArgsSize = 8;
StringExtFormatArg *arrArgs = (StringExtFormatArg *)MemUtilsMallocArray(nArgsSize, sizeof(StringExtFormatArg));
pCur = sFormat;
while (*pCur)
{
if (*pCur == '{')
{
++pCur;
if (*pCur == '{')
{
++pCur;
Append('{');
}
else
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (!(*pCur >= '0' && *pCur <= '9'))
break;
nIndex = *pCur - '0';
for (++pCur; *pCur >= '0' && *pCur <= '9'; ++pCur)
nIndex = 10 * nIndex + (*pCur - '0');
if (*pCur != ':')
break;
++pCur;
if (*pCur == '-')
{
bReverseAlign = true;
++pCur;
}
else
bReverseAlign = false;
nWidth = 0;
bZeroFill = *pCur == '0';
for (; *pCur >= '0' && *pCur <= '9'; ++pCur)
nWidth = 10 * nWidth + (*pCur - '0');
if (*pCur == '.')
{
++pCur;
nPrecision = 0;
for (; *pCur >= '0' && *pCur <= '9'; ++pCur)
{
nPrecision = 10 * nPrecision + (*pCur - '0');
}
}
else
{
nPrecision = 0;
}
for (eFormatType = (StringExtFormatType)0;
c_arrsFormatStrings[eFormatType];
eFormatType = (StringExtFormatType)(eFormatType + 1))
{
if (!strncmp(pCur, c_arrsFormatStrings[eFormatType], strlen(c_arrsFormatStrings[eFormatType])))
{
break;
}
}
if (!c_arrsFormatStrings[eFormatType])
{
break;
}
pCur += strlen(c_arrsFormatStrings[eFormatType]);
if (*pCur != '}')
{
break;
}
++pCur;
// fetch the argument
if (nIndex > nArgsLen)
{
break;
}
if (nIndex == nArgsLen)
{
if (nArgsLen == nArgsSize)
{
nArgsSize *= 2;
arrArgs = (StringExtFormatArg *)MemUtilsReallocArray(arrArgs, nArgsSize, sizeof(StringExtFormatArg));
}
switch (eFormatType)
{
case fmtIntDecimal:
case fmtIntHex:
case fmtIntOctal:
case fmtIntBinary:
case fmtSpace:
arrArgs[nArgsLen].iValue = va_arg(sArgList, int);
break;
case fmtUIntDecimal:
case fmtUIntHex:
case fmtUIntOctal:
case fmtUIntBinary:
arrArgs[nArgsLen].uiValue = va_arg(sArgList, unsigned int);
break;
case fmtLongDecimal:
case fmtLongHex:
case fmtLongOctal:
case fmtLongBinary:
arrArgs[nArgsLen].lValue = va_arg(sArgList, long);
break;
case fmtULongDecimal:
case fmtULongHex:
case fmtULongOctal:
case fmtULongBinary:
arrArgs[nArgsLen].ulValue = va_arg(sArgList, unsigned long);
break;
case fmtDouble:
case fmtDoubleTrim:
arrArgs[nArgsLen].fValue = va_arg(sArgList, double);
break;
case fmtChar:
arrArgs[nArgsLen].cValue = (char)va_arg(sArgList, int);
break;
case fmtString:
arrArgs[nArgsLen].sValue = va_arg(sArgList, char *);
break;
case fmtStringExt:
arrArgs[nArgsLen].seValue = va_arg(sArgList, StringExt *);
break;
}
++nArgsLen;
}
uArg = arrArgs[nIndex];
switch (eFormatType)
{
case fmtIntDecimal:
FormatInt(uArg.iValue, sBuffer, sizeof(sBuffer), bZeroFill, nWidth, 10, &sTemp, &nLen);
break;
case fmtIntHex:
FormatInt(uArg.iValue, sBuffer, sizeof(sBuffer), bZeroFill, nWidth, 16, &sTemp, &nLen);
break;
case fmtIntOctal:
FormatInt(uArg.iValue, sBuffer, sizeof(sBuffer), bZeroFill, nWidth, 8, &sTemp, &nLen);
break;
case fmtIntBinary:
FormatInt(uArg.iValue, sBuffer, sizeof(sBuffer), bZeroFill, nWidth, 2, &sTemp, &nLen);
break;
case fmtUIntDecimal:
FormatUInt(uArg.uiValue, sBuffer, sizeof(sBuffer), bZeroFill, nWidth, 10, &sTemp, &nLen);
break;
case fmtUIntHex:
FormatUInt(uArg.uiValue, sBuffer, sizeof(sBuffer), bZeroFill, nWidth, 16, &sTemp, &nLen);
break;
case fmtUIntOctal:
FormatUInt(uArg.uiValue, sBuffer, sizeof(sBuffer), bZeroFill, nWidth, 8, &sTemp, &nLen);
break;
case fmtUIntBinary:
FormatUInt(uArg.uiValue, sBuffer, sizeof(sBuffer), bZeroFill, nWidth, 2, &sTemp, &nLen);
break;
case fmtLongDecimal:
FormatInt(uArg.lValue, sBuffer, sizeof(sBuffer), bZeroFill, nWidth, 10, &sTemp, &nLen);
break;
case fmtLongHex:
FormatInt(uArg.lValue, sBuffer, sizeof(sBuffer), bZeroFill, nWidth, 16, &sTemp, &nLen);
break;
case fmtLongOctal:
FormatInt(uArg.lValue, sBuffer, sizeof(sBuffer), bZeroFill, nWidth, 8, &sTemp, &nLen);
break;
case fmtLongBinary:
FormatInt(uArg.lValue, sBuffer, sizeof(sBuffer), bZeroFill, nWidth, 2, &sTemp, &nLen);
break;
case fmtULongDecimal:
FormatUInt(uArg.ulValue, sBuffer, sizeof(sBuffer), bZeroFill, nWidth, 10, &sTemp, &nLen);
break;
case fmtULongHex:
FormatUInt(uArg.ulValue, sBuffer, sizeof(sBuffer), bZeroFill, nWidth, 16, &sTemp, &nLen);
break;
case fmtULongOctal:
FormatUInt(uArg.ulValue, sBuffer, sizeof(sBuffer), bZeroFill, nWidth, 8, &sTemp, &nLen);
break;
case fmtULongBinary:
FormatUInt(uArg.ulValue, sBuffer, sizeof(sBuffer), bZeroFill, nWidth, 2, &sTemp, &nLen);
break;
case fmtDouble:
FormatDouble(uArg.fValue, sBuffer, sizeof(sBuffer), nPrecision, false, &sTemp, &nLen);
break;
case fmtDoubleTrim:
FormatDouble(uArg.fValue, sBuffer, sizeof(sBuffer), nPrecision, true, &sTemp, &nLen);
break;
case fmtChar:
sBuffer[0] = uArg.cValue;
sTemp = sBuffer;
nLen = 1;
bReverseAlign = !bReverseAlign;
break;
case fmtString:
sTemp = uArg.sValue;
nLen = strlen(sTemp);
bReverseAlign = !bReverseAlign;
break;
case fmtStringExt:
sTemp = uArg.seValue->GetBuffer();
nLen = uArg.seValue->GetLength();
bReverseAlign = !bReverseAlign;
break;
case fmtSpace:
sTemp = sBuffer;
nLen = 0;
nWidth = uArg.iValue;
break;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (!bReverseAlign && nLen < nWidth)
{
for (int nCounter = nLen; nCounter < nWidth; ++nCounter)
Append(' ');
}
Append(sTemp, nLen);
if (bReverseAlign && nLen < nWidth)
{
for (int nCounter = nLen; nCounter < nWidth; ++nCounter)
Append(' ');
}
}
}
else if (*pCur == '}')
{
++pCur;
if (*pCur == '}')
++pCur;
Append('}');
}
else
{
for (pTemp = pCur + 1; *pTemp && *pTemp != '{' && *pTemp != '}'; ++pTemp);
Append(pCur, pTemp - pCur);
pCur = pTemp;
}
}
MemUtilsFree(arrArgs);
return this;
}
void StringExt::FormatInt(long nValue, char *sBuffer, int nBufferSize, bool bZeroFill, int nWidth, int nBase, char **ppData, int *pnLen)
{
static char c_sValues[17] = "0123456789abcdef";
bool bNegative = false;
int nStart;
int nCur = nBufferSize;
if ((bNegative = nValue < 0))
{
nValue = -nValue;
}
nStart = bNegative ? 1 : 0;
if (nValue == 0)
{
sBuffer[--nCur] = '0';
}
else
{
while (nCur > nStart && nValue)
{
sBuffer[--nCur] = c_sValues[nValue % nBase];
nValue /= nBase;
}
}
if (bZeroFill)
{
for (int nCounter = nBufferSize - nCur; nCur > nStart && nCounter < nWidth - nStart; ++nCounter)
{
sBuffer[--nCur] = '0';
}
}
if (bNegative)
{
sBuffer[--nCur] = '-';
}
*ppData = sBuffer + nCur;
*pnLen = nBufferSize - nCur;
}
void StringExt::FormatUInt(unsigned long nValue, char *sBuffer, int nBufferSize, bool bZeroFill, int nWidth, int nBase, char **ppData, int *pnLen)
{
static char c_sValues[17] = "0123456789abcdef";
int nCur = nBufferSize;
if (nValue == 0)
{
sBuffer[--nCur] = '0';
}
else
{
while (nCur > 0 && nValue)
{
sBuffer[--nCur] = c_sValues[nValue % nBase];
nValue /= nBase;
}
}
if (bZeroFill)
{
for (int nCounter = nBufferSize - nCur; nCur > 0 && nCounter < nWidth; ++nCounter)
{
sBuffer[--nCur] = '0';
}
}
*ppData = sBuffer + nCur;
*pnLen = nBufferSize - nCur;
}
void StringExt::FormatDouble(double dValue, char *sBuffer, int nBufferSize, int nPrecision, bool bTrim, char **ppData, int *pnLen)
{
bool bNegative = false, bStarted = false;
double dTemp = 0;
int nInt;
if ((bNegative = dValue < 0))
dValue = -dValue;
dValue = floor(dValue * pow((double)10, nPrecision) + 0.5);
int nCur = nBufferSize;
bStarted = !bTrim;
for (int nCounter = 0; nCounter < nPrecision && nCur > 1; ++nCounter)
{
dTemp = floor(0.1 * (dValue + 0.5));
nInt = (int)floor(dValue - 10 * dTemp + 0.5);
if (bStarted || nInt != 0)
{
sBuffer[--nCur] = '0' + nInt;
bStarted = true;
}
dValue = dTemp;
}
if (nCur > 1 && bStarted)
sBuffer[--nCur] = '.';
if (nCur > 1)
{
do {
dTemp = floor(0.1 * (dValue + 0.5));
nInt = (int)floor(dValue - 10 * dTemp + 0.5);
sBuffer[--nCur] = '0' + nInt;
dValue = dTemp;
} while (nCur > 1 && dValue);
}
if (bNegative)
sBuffer[--nCur] = '-';
*ppData = sBuffer + nCur;
*pnLen = nBufferSize - nCur;
}
StringExt *StringExt::Insert(int nIndex, char nChar)
{
Resize(m_nLength + 1);
for (int nJ = m_nLength + 1; nJ > nIndex; --nJ)
m_sData[nJ] = m_sData[nJ - 1];
m_sData[nIndex] = nChar;
++m_nLength;
return this;
}
StringExt *StringExt::Insert(int nIndex, StringExt *seString)
{
int nLen = seString->GetLength();
Resize(m_nLength + nLen);
for (int nJ = m_nLength; nJ >= nIndex; --nJ)
m_sData[nJ + nLen] = m_sData[nJ];
memcpy(m_sData + nIndex, seString->GetBuffer(), nLen);
m_nLength += nLen;
return this;
}
StringExt *StringExt::Insert(int nIndex, const char *sString)
{
int nLen = strlen(sString);
Resize(m_nLength + nLen);
for (int nJ = m_nLength; nJ >= nIndex; --nJ)
m_sData[nJ + nLen] = m_sData[nJ];
memcpy(m_sData + nIndex, sString, nLen);
m_nLength += nLen;
return this;
}
StringExt *StringExt::Insert(int nIndex, const char *sString, int nLength)
{
Resize(m_nLength + nLength);
for (int nJ = m_nLength; nJ >= nIndex; --nJ)
m_sData[nJ + nLength] = m_sData[nJ];
memcpy(m_sData + nIndex, sString, nLength);
m_nLength += nLength;
return this;
}
StringExt *StringExt::Delete(int nIndex, int nCount)
{
if (nCount > 0)
{
if (nIndex + nCount > m_nLength)
nCount = m_nLength - nIndex;
for (int nJ = nIndex; nJ <= m_nLength - nCount; ++nJ)
{
m_sData[nJ] = m_sData[nJ + nCount];
}
Resize(m_nLength -= nCount);
}
return this;
}
StringExt *StringExt::MakeUpper()
{
for (int nIndex = 0; nIndex < m_nLength; ++nIndex)
{
if (islower(m_sData[nIndex]))
m_sData[nIndex] = toupper(m_sData[nIndex]);
}
return this;
}
StringExt *StringExt::MakeLower()
{
for (int nIndex = 0; nIndex < m_nLength; ++nIndex)
{
if (isupper(m_sData[nIndex]))
m_sData[nIndex] = tolower(m_sData[nIndex]);
}
return this;
}
int StringExt::Compare(StringExt *seOther)
{
int nIndex = 0;
char *pThis, *pOther;
int nThisLen = m_nLength;
int nOtherLen = seOther->m_nLength;
for (nIndex = 0, pThis = m_sData, pOther = seOther->m_sData; nIndex < nThisLen && nIndex < nOtherLen; ++nIndex, ++pThis, ++pOther)
{
int nRes = *pThis - *pOther;
if (0 != nRes)
return nRes;
}
return nThisLen - nOtherLen;
}
int StringExt::CompareN(StringExt *seOther, int nCount)
{
int nIndex;
char *pThis, *pOther;
int nThisLen = m_nLength;
int nOtherLen = seOther->m_nLength;
for (nIndex = 0, pThis = m_sData, pOther = seOther->m_sData; nIndex < nThisLen && nIndex < nOtherLen && nIndex < nCount; ++nIndex, ++pThis, ++pOther)
{
int nRes = *pThis - *pOther;
if (0 != nRes)
return nRes;
}
if (nIndex == nCount)
return 0;
return nThisLen - nOtherLen;
}
int StringExt::Compare(const char *sOther)
{
int nIndex;
const char *pThis, *pOther;
int nThisLen = m_nLength;
for (nIndex = 0, pThis = m_sData, pOther = sOther; nIndex < nThisLen && *pOther; ++nIndex, ++pThis, ++pOther)
{
int nRes = *pThis - *pOther;
if (0 != nRes)
return nRes;
}
if (nIndex < nThisLen)
return 1;
if (*pOther)
return -1;
return 0;
}
int StringExt::CompareN(const char *sOther, int nCount)
{
int nIndex;
const char *pThis, *pOther;
int nThisLen = m_nLength;
for (nIndex = 0, pThis = m_sData, pOther = sOther; nIndex < nThisLen && *pOther && nIndex < nCount; ++nIndex, ++pThis, ++pOther)
{
int nRes = *pThis - *pOther;
if (0 != nRes)
return nRes;
}
if (nIndex == nCount)
return 0;
if (nIndex < nThisLen)
return 1;
if (*pOther)
return -1;
return 0;
}
}