📄 sqlapi.cpp
字号:
break;
case 's'|FORCE_ANSI:
case 'S'|FORCE_ANSI:
{
const char *pstrNextArg = va_arg(argList, const char*);
if (pstrNextArg == NULL)
nItemLen = 6; // "(null)"
else
{
nItemLen = strlen(pstrNextArg);
nItemLen = sa_max(1, nItemLen);
}
}
break;
case 's'|FORCE_UNICODE:
case 'S'|FORCE_UNICODE:
{
wchar_t *pstrNextArg = va_arg(argList, wchar_t*);
if (pstrNextArg == NULL)
nItemLen = 6; // "(null)"
else
{
nItemLen = wcslen(pstrNextArg);
nItemLen = sa_max(1, nItemLen);
}
}
break;
}
// adjust nItemLen for strings
if (nItemLen != 0)
{
if (nPrecision != 0)
nItemLen = sa_min(nItemLen, nPrecision);
nItemLen = sa_max(nItemLen, nWidth);
}
else
{
switch (*lpsz)
{
// integers
case 'd':
case 'i':
case 'u':
case 'x':
case 'X':
case 'o':
if (nModifier & FORCE_INT64)
(void)va_arg(argList, int); // __int64 in original code
else
(void)va_arg(argList, int);
nItemLen = 32;
nItemLen = sa_max(nItemLen, nWidth+nPrecision);
break;
case 'e':
case 'g':
case 'G':
(void)va_arg(argList, double);
nItemLen = 128;
nItemLen = sa_max(nItemLen, nWidth+nPrecision);
break;
case 'f':
{
double f;
SAChar *pszTemp;
// 312 == strlen("-1+(309 zeroes).")
// 309 zeroes == max precision of a double
// 6 == adjustment in case precision is not specified,
// which means that the precision defaults to 6
pszTemp = (SAChar *)malloc(sa_max(nWidth, 312+nPrecision+6));
f = va_arg(argList, double);
sa_sprintf( pszTemp, _SA( "%*.*f" ), nWidth, nPrecision+6, f );
nItemLen = sa_strlen(pszTemp);
}
break;
case 'p':
(void)va_arg(argList, void*);
nItemLen = 32;
nItemLen = sa_max(nItemLen, nWidth+nPrecision);
break;
// no output
case 'n':
(void)va_arg(argList, int*);
break;
default:
assert(false); // unknown formatting option
}
}
// adjust nMaxLen for output nItemLen
nMaxLen += nItemLen;
}
// if the buffer is too small, or we have a width mis-match, just
// allocate a new buffer (slow but sure)
if (GetData()->nRefs > 1 || nMaxLen > GetData()->nAllocLength)
{
// we have to grow the buffer
Release();
AllocBuffer(nMaxLen);
}
if(!(sa_vsprintf(m_pchData, lpszFormat, argListSave) <= nMaxLen))
assert(false);
ReleaseBuffer();
va_end(argListSave);
}
// formatting (using wsprintf style formatting)
void SAString::Format(const SAChar *lpszFormat, ...)
{
assert(lpszFormat);
va_list argList;
va_start(argList, lpszFormat);
FormatV(lpszFormat, argList);
va_end(argList);
}
/*static */
int SAString::SafeStrlen(const SAChar *lpsz)
{
return (lpsz == NULL) ? 0 : sa_strlen(lpsz);
}
SAString SAString::Mid(int nFirst) const
{
return Mid(nFirst, GetData()->nDataLength - nFirst);
}
SAString SAString::Mid(int nFirst, int nCount) const
{
// optimize case of returning empty string
if(nFirst > GetLength())
return _saPchNil;
// out-of-bounds requests return sensible things
if (nFirst < 0)
nFirst = 0;
if (nCount < 0)
nCount = 0;
if (nFirst + nCount > GetLength())
nCount = GetLength() - nFirst;
if (nFirst > GetLength())
nCount = 0;
assert(nFirst >= 0);
assert(nFirst + nCount <= GetData()->nDataLength);
// optimize case of returning entire string
if (nFirst == 0 && nFirst + nCount == GetData()->nDataLength)
return *this;
SAString dest(m_pchData+nFirst, nCount);
return dest;
}
SAString SAString::Right(int nCount) const
{
if (nCount < 0)
nCount = 0;
if (nCount >= GetData()->nDataLength)
return *this;
SAString dest(m_pchData+GetData()->nDataLength-nCount, nCount);
return dest;
}
SAString SAString::Left(int nCount) const
{
if (nCount < 0)
nCount = 0;
if (nCount >= GetData()->nDataLength)
return *this;
SAString dest(m_pchData, nCount);
return dest;
}
//////////////////////////////////////////////////////////////////////////////
// Advanced manipulation
int SAString::Delete(int nIndex, int nCount /* = 1 */)
{
if (nIndex < 0)
nIndex = 0;
int nNewLength = GetData()->nDataLength;
if (nCount > 0 && nIndex < nNewLength)
{
CopyBeforeWrite();
int nBytesToCopy = nNewLength - (nIndex + nCount) + 1;
memcpy(m_pchData + nIndex,
m_pchData + nIndex + nCount, nBytesToCopy * sizeof(SAChar));
GetData()->nDataLength = nNewLength - nCount;
}
return nNewLength;
}
int SAString::Insert(int nIndex, SAChar ch)
{
CopyBeforeWrite();
if (nIndex < 0)
nIndex = 0;
int nNewLength = GetData()->nDataLength;
if (nIndex > nNewLength)
nIndex = nNewLength;
nNewLength++;
if (GetData()->nAllocLength < nNewLength)
{
SAStringData *pOldData = GetData();
SAChar *pstr = m_pchData;
AllocBuffer(nNewLength);
memcpy(m_pchData, pstr, (pOldData->nDataLength+1)*sizeof(SAChar));
SAString::Release(pOldData);
}
// move existing bytes down
memcpy(m_pchData + nIndex + 1,
m_pchData + nIndex, (nNewLength-nIndex)*sizeof(SAChar));
m_pchData[nIndex] = ch;
GetData()->nDataLength = nNewLength;
return nNewLength;
}
int SAString::Insert(int nIndex, const SAChar *pstr)
{
if (nIndex < 0)
nIndex = 0;
int nInsertLength = SafeStrlen(pstr);
int nNewLength = GetData()->nDataLength;
if (nInsertLength > 0)
{
CopyBeforeWrite();
if (nIndex > nNewLength)
nIndex = nNewLength;
nNewLength += nInsertLength;
if (GetData()->nAllocLength < nNewLength)
{
SAStringData *pOldData = GetData();
SAChar* pstr = m_pchData;
AllocBuffer(nNewLength);
memcpy(m_pchData, pstr, (pOldData->nDataLength+1)*sizeof(SAChar));
SAString::Release(pOldData);
}
// move existing bytes down
memcpy(m_pchData + nIndex + nInsertLength,
m_pchData + nIndex,
(nNewLength-nIndex-nInsertLength+1)*sizeof(SAChar));
memcpy(m_pchData + nIndex,
pstr, nInsertLength*sizeof(SAChar));
GetData()->nDataLength = nNewLength;
}
return nNewLength;
}
int SAString::Replace(const SAChar *lpszOld, const SAChar *lpszNew)
{
// can't have empty or NULL lpszOld
int nSourceLen = SafeStrlen(lpszOld);
if (nSourceLen == 0)
return 0;
int nReplacementLen = SafeStrlen(lpszNew);
// loop once to figure out the size of the result string
int nCount = 0;
SAChar *lpszStart = m_pchData;
SAChar *lpszEnd = m_pchData + GetData()->nDataLength;
SAChar *lpszTarget;
while (lpszStart < lpszEnd)
{
while ((lpszTarget = sa_strstr(lpszStart, lpszOld)) != NULL)
{
nCount++;
lpszStart = lpszTarget + nSourceLen;
}
lpszStart += sa_strlen(lpszStart) + 1;
}
// if any changes were made, make them
if (nCount > 0)
{
CopyBeforeWrite();
// if the buffer is too small, just
// allocate a new buffer (slow but sure)
int nOldLength = GetData()->nDataLength;
int nNewLength = nOldLength + (nReplacementLen-nSourceLen)*nCount;
if (GetData()->nAllocLength < nNewLength || GetData()->nRefs > 1)
{
SAStringData *pOldData = GetData();
SAChar *pstr = m_pchData;
AllocBuffer(nNewLength);
memcpy(m_pchData, pstr, pOldData->nDataLength*sizeof(SAChar));
SAString::Release(pOldData);
}
// else, we just do it in-place
lpszStart = m_pchData;
lpszEnd = m_pchData + GetData()->nDataLength;
// loop again to actually do the work
while (lpszStart < lpszEnd)
{
while ( (lpszTarget = sa_strstr(lpszStart, lpszOld)) != NULL)
{
int nBalance = nOldLength - (lpszTarget - m_pchData + nSourceLen);
memmove(lpszTarget + nReplacementLen, lpszTarget + nSourceLen,
nBalance * sizeof(SAChar));
memcpy(lpszTarget, lpszNew, nReplacementLen*sizeof(SAChar));
lpszStart = lpszTarget + nReplacementLen;
lpszStart[nBalance] = '\0';
nOldLength += (nReplacementLen - nSourceLen);
}
lpszStart += sa_strlen(lpszStart) + 1;
}
assert(m_pchData[nNewLength] == '\0');
GetData()->nDataLength = nNewLength;
}
return nCount;
}
void SAString::TrimRight(const SAChar *lpszTargetList)
{
// find beginning of trailing matches
// by starting at beginning (DBCS aware)
CopyBeforeWrite();
SAChar *lpsz = m_pchData;
SAChar *lpszLast = NULL;
while (*lpsz != '\0')
{
if (sa_strchr(lpszTargetList, *lpsz) != NULL)
{
if (lpszLast == NULL)
lpszLast = lpsz;
}
else
lpszLast = NULL;
++lpsz;
}
if (lpszLast != NULL)
{
// truncate at left-most matching character
*lpszLast = '\0';
GetData()->nDataLength = lpszLast - m_pchData;
}
}
void SAString::TrimRight(SAChar chTarget)
{
// find beginning of trailing matches
// by starting at beginning (DBCS aware)
CopyBeforeWrite();
SAChar *lpsz = m_pchData;
SAChar *lpszLast = NULL;
while (*lpsz != '\0')
{
if (*lpsz == chTarget)
{
if (lpszLast == NULL)
lpszLast = lpsz;
}
else
lpszLast = NULL;
++lpsz;
}
if (lpszLast != NULL)
{
// truncate at left-most matching character
*lpszLast = '\0';
GetData()->nDataLength = lpszLast - m_pchData;
}
}
void SAString::TrimRight()
{
// find beginning of trailing spaces by starting at beginning (DBCS aware)
CopyBeforeWrite();
SAChar *lpsz = m_pchData;
SAChar *lpszLast = NULL;
while (*lpsz != '\0')
{
if (sa_isspace(*lpsz))
{
if (lpszLast == NULL)
lpszLast = lpsz;
}
else
lpszLast = NULL;
++lpsz;
}
if (lpszLast != NULL)
{
// truncate at trailing space start
*lpszLast = '\0';
GetData()->nDataLength = lpszLast - m_pchData;
}
}
void SAString::TrimLeft(const SAChar *lpszTargets)
{
// if we're not trimming anything, we're not doing any work
if (SafeStrlen(lpszTargets) == 0)
return;
CopyBeforeWrite();
const SAChar *lpsz = m_pchData;
while (*lpsz != '\0')
{
if (sa_strchr(lpszTargets, *lpsz) == NULL)
break;
++lpsz;
}
if (lpsz != m_pchData)
{
// fix up data and length
int nDataLength = GetData()->nDataLength - (lpsz - m_pchData);
memmove(m_pchData, lpsz, (nDataLength+1)*sizeof(SAChar));
GetData()->nDataLength = nDataLength;
}
}
void SAString::TrimLeft(SAChar chTarget)
{
// find first non-matching character
CopyBeforeWrite();
const SAChar *lpsz = m_pchData;
while (chTarget == *lpsz)
++lpsz;
if (lpsz != m_pchData)
{
// fix up data and length
int nDataLength = GetData()->nDataLength - (lpsz - m_pchData);
memmove(m_pchData, lpsz, (nDataLength+1)*sizeof(SAChar));
GetData()->nDataLength = nDataLength;
}
}
void SAString::TrimLeft()
{
// find first non-space character
CopyBeforeWrite();
const SAChar *lpsz = m_pchData;
while (sa_isspace(*lpsz))
++lpsz;
if (lpsz != m_pchData)
{
// fix up data and length
int nDataLength = GetData()->nDataLength - (lpsz - m_pchData);
memmove(m_pchData, lpsz, (nDataLength+1)*sizeof(SAChar));
GetData()->nDataLength = nDataLength;
}
}
int SAString::Compare(const SAChar *lpsz) const
{
assert(lpsz);
return sa_strcmp(m_pchData, lpsz);
}
int SAString::CompareNoCase(const SAChar *lpsz) const
{
assert(lpsz);
// implement our own case-insensitive comparison
// by converting to lower case before comparison
const SAChar *psThis = m_pchData;
const SAChar *psOther = lpsz;
while(*psThis && *psOther)
{
int iThis = sa_tolower(*psThis);
int iOther = sa_tolower(*psOther);
if(iThis == iOther)
{
++psThis;
++psOther;
continue;
}
if(iThis > iOther)
return 1;
return -1;
}
if(*psThis && !*psOther)
return 1;
if(!*psThis && *psOther)
return -1;
assert(!*psThis && !*psOther);
return 0;
}
int SAString::Collate(const SAChar *lpsz) const
{
assert(lpsz);
return sa_strcoll(m_pchData, lpsz);
}
bool operator==(const SAString &s1, const SAString &s2)
{
return s1.Compare(s2) == 0;
}
bool operator==(const SAString &s1, const SAChar *s2)
{
return s1.Compare(s2) == 0;
}
bool operator==(const SAChar *s1, const SAString &s2)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -