Files
core/PdfReader/Src/StringExt.cpp
Alexander.Trofimov 01a3fd5efc to utf8
2016-06-23 16:47:17 +03:00

763 lines
18 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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
{
// Разбираем форматированную строку
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;
default:
sTemp = sBuffer;
nLen = 0;
nWidth = uArg.iValue;
break;
}
// Добавляем аргумент в нужном формате, с нужным прилеганием
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;
}
}