📄 sqlapi.cpp
字号:
int nLen = SafeStrlen(lpsz);
if (nLen != 0)
{
AllocBuffer(nLen);
memcpy(m_pchData, lpsz, nLen*sizeof(SAChar));
}
}
/////////////////////////////////////////////////////////////////////////////
// Special conversion constructors
#ifdef SA_UNICODE
SAString::SAString(const char *lpsz)
{
Init();
int nSrcLen = lpsz != NULL ? strlen(lpsz) : 0;
if (nSrcLen != 0)
{
AllocBuffer(nSrcLen);
ReleaseBuffer(SAMultiByteToWideChar(m_pchData, lpsz, nSrcLen));
}
}
SAString::SAString(const char *lpch, int nLength)
{
Init();
if (nLength != 0)
{
AllocBuffer(nLength);
ReleaseBuffer(SAMultiByteToWideChar(m_pchData, lpch, nLength));
}
}
#else // !SA_UNICODE
SAString::SAString(const wchar_t *lpsz)
{
Init();
int nSrcLen = lpsz != NULL ? wcslen(lpsz) : 0;
if (nSrcLen != 0)
{
AllocBuffer(nSrcLen*2);
ReleaseBuffer(SAWideCharToMultiByte(m_pchData, lpsz, nSrcLen));
}
}
SAString::SAString(const wchar_t *lpch, int nLength)
{
Init();
if (nLength != 0)
{
AllocBuffer(nLength*2);
ReleaseBuffer(SAWideCharToMultiByte(m_pchData, lpch, nLength));
}
}
#endif //!SA_UNICODE
SAString::SAString(const SAChar *lpch, int nLength)
{
Init();
if (nLength != 0)
{
assert(lpch);
AllocBuffer(nLength);
memcpy(m_pchData, lpch, nLength*sizeof(SAChar));
}
}
SAString::SAString(const unsigned char *psz)
{
Init();
*this = (const char*)psz;
}
//////////////////////////////////////////////////////////////////////////////
// More sophisticated construction
SAString::SAString(SAChar ch, int nLength)
{
Init();
if (nLength >= 1)
{
AllocBuffer(nLength);
#ifdef SA_UNICODE
for (int i = 0; i < nLength; ++i)
m_pchData[i] = ch;
#else
memset(m_pchData, ch, nLength);
#endif
}
}
SAString::~SAString()
{
if (GetData() != _saDataNil)
{
// free any attached data
if (--GetData()->nRefs <= 0)
FreeData(GetData());
}
}
void SAString::Empty()
{
if (GetData()->nDataLength == 0)
return;
if (GetData()->nRefs >= 0)
Release();
else
*this = _saPchNil;
assert(GetData()->nDataLength == 0);
assert(GetData()->nRefs < 0 || GetData()->nAllocLength == 0);
}
bool SAString::IsEmpty() const
{
return GetData()->nDataLength == 0;
}
int SAString::GetLength() const
{
return GetData()->nDataLength;
}
SAString::operator const SAChar *() const
{
return m_pchData;
}
//////////////////////////////////////////////////////////////////////////////
// Assignment operators
// All assign a new value to the string
// (a) first see if the buffer is big enough
// (b) if enough room, copy on top of old buffer, set size and type
// (c) otherwise free old string data, and create a new one
//
// All routines return the new string (but as a 'const SAString&' so that
// assigning it again will cause a copy, eg: s1 = s2 = "hi there".
//
#ifdef SA_UNICODE
void SAString::AssignBinaryCopy(int nSrcLenInBytes, const void *pSrcData)
{
int nBinaryDataLengthDiff = nSrcLenInBytes % sizeof(SAChar);
// allocate at least so many characters that all binary data could be stored (round up if necessary)
int nSrcLenInChars = nSrcLenInBytes / sizeof(SAChar) + (nBinaryDataLengthDiff? 1 : 0);
AllocBeforeWrite(nSrcLenInChars);
memcpy(m_pchData, pSrcData, nSrcLenInBytes);
GetData()->nDataLength = nSrcLenInChars;
m_pchData[nSrcLenInChars] = '\0';
// if nSrcLenInBytes is not a multiply of sizeof(SAChar)
// we have to save the difference
GetData()->nBinaryDataLengthDiff = nBinaryDataLengthDiff;
}
#endif // SA_UNICODE
void SAString::AssignCopy(int nSrcLen, const SAChar *lpszSrcData)
{
AllocBeforeWrite(nSrcLen);
memcpy(m_pchData, lpszSrcData, nSrcLen*sizeof(SAChar));
GetData()->nDataLength = nSrcLen;
m_pchData[nSrcLen] = '\0';
}
const SAString &SAString::operator=(const SAString &stringSrc)
{
if (m_pchData != stringSrc.m_pchData)
{
if ((GetData()->nRefs < 0 && GetData() != _saDataNil) ||
stringSrc.GetData()->nRefs < 0)
{
// actual copy necessary since one of the strings is locked
#ifdef SA_UNICODE
// Under Unicode we should be aware that stringSrc
// can be binary string with length not being multiply of sizeof(SAChar),
// so we should copy bytes, not characters
AssignBinaryCopy(stringSrc.GetBinaryLength(), (const void*)stringSrc);
#else // !SA_UNICODE
AssignCopy(stringSrc.GetData()->nDataLength, stringSrc.m_pchData);
#endif // !SA_UNICODE
}
else
{
// can just copy references around
Release();
assert(stringSrc.GetData() != _saDataNil);
m_pchData = stringSrc.m_pchData;
++GetData()->nRefs;
}
}
return *this;
}
const SAString &SAString::operator =(const SAChar *lpsz)
{
AssignCopy(SafeStrlen(lpsz), lpsz);
return *this;
}
/////////////////////////////////////////////////////////////////////////////
// Special conversion assignment
#ifdef SA_UNICODE
const SAString &SAString::operator=(const char *lpsz)
{
int nSrcLen = lpsz? strlen(lpsz) : 0;
AllocBeforeWrite(nSrcLen);
ReleaseBuffer(SAMultiByteToWideChar(m_pchData, lpsz, nSrcLen));
return *this;
}
#else //!SA_UNICODE
const SAString &SAString::operator=(const wchar_t *lpsz)
{
int nSrcLen = lpsz? wcslen(lpsz) : 0;
AllocBeforeWrite(nSrcLen*2);
ReleaseBuffer(SAWideCharToMultiByte(m_pchData, lpsz, nSrcLen));
return *this;
}
#endif //!SA_UNICODE
const SAString &SAString::operator=(SAChar ch)
{
AssignCopy(1, &ch);
return *this;
}
#ifdef SA_UNICODE
const SAString &SAString::operator=(char ch)
{
*this = (SAChar)ch;
return *this;
}
#endif
const SAString &SAString::operator=(const unsigned char *psz)
{
*this = (const char *)psz;
return *this;
}
//////////////////////////////////////////////////////////////////////////////
// concatenation
// NOTE: "operator+" is done as friend functions for simplicity
// There are three variants:
// SAString + SAString
// and for ? = SAChar, const SAChar*
// SAString + ?
// ? + CString
#ifdef SA_UNICODE
void SAString::ConcatBinaryCopy(int nSrc1LenInBytes, const void *pSrc1Data,
int nSrc2LenInBytes, const void *pSrc2Data)
{
// -- master concatenation routine (binary)
// Concatenate two sources
// -- assume that 'this' is a new SAString object
int nNewLenInBytes = nSrc1LenInBytes + nSrc2LenInBytes;
if (nNewLenInBytes != 0)
{
int nBinaryDataLengthDiff = nNewLenInBytes % sizeof(SAChar);
// allocate at least so many characters that all binary data could be stored (round up if necessary)
int nNewLenInChars = nNewLenInBytes / sizeof(SAChar) + (nBinaryDataLengthDiff? 1 : 0);
AllocBuffer(nNewLenInChars);
// if nNewLengthInBytes is not a multiply of sizeof(SAChar)
// we have to save the difference
GetData()->nBinaryDataLengthDiff = nBinaryDataLengthDiff;
memcpy((unsigned char*)m_pchData, pSrc1Data, nSrc1LenInBytes);
memcpy((unsigned char*)m_pchData+nSrc1LenInBytes, pSrc2Data, nSrc2LenInBytes);
}
}
#endif // SA_UNICODE
void SAString::ConcatCopy(int nSrc1Len, const SAChar *lpszSrc1Data,
int nSrc2Len, const SAChar *lpszSrc2Data)
{
// -- master concatenation routine
// Concatenate two sources
// -- assume that 'this' is a new SAString object
int nNewLen = nSrc1Len + nSrc2Len;
if (nNewLen != 0)
{
AllocBuffer(nNewLen);
memcpy(m_pchData, lpszSrc1Data, nSrc1Len*sizeof(SAChar));
memcpy(m_pchData+nSrc1Len, lpszSrc2Data, nSrc2Len*sizeof(SAChar));
}
}
SAString operator+(const SAString &string1, const SAString &string2)
{
#ifdef SA_UNICODE
// Under Unicode we should be aware that *this or string (or both)
// can be binary string with length not being multiply of sizeof(SAChar),
// so we should concatinate bytes, not characters
SAString s;
s.ConcatBinaryCopy(string1.GetBinaryLength(), (const void*)string1,
string2.GetBinaryLength(), (const void*)string2);
return s;
#else // !SA_UNICODE
SAString s;
s.ConcatCopy(string1.GetData()->nDataLength, string1.m_pchData,
string2.GetData()->nDataLength, string2.m_pchData);
return s;
#endif // !SA_UNICODE
}
SAString operator+(const SAString &string, const SAChar *lpsz)
{
SAString s;
s.ConcatCopy(string.GetData()->nDataLength, string.m_pchData,
SAString::SafeStrlen(lpsz), lpsz);
return s;
}
SAString operator+(const SAChar *lpsz, const SAString &string)
{
SAString s;
s.ConcatCopy(SAString::SafeStrlen(lpsz), lpsz, string.GetData()->nDataLength,
string.m_pchData);
return s;
}
SAString operator+(const SAString &string1, SAChar ch)
{
SAString s;
s.ConcatCopy(string1.GetData()->nDataLength, string1.m_pchData, 1, &ch);
return s;
}
SAString operator+(SAChar ch, const SAString &string)
{
SAString s;
s.ConcatCopy(1, &ch, string.GetData()->nDataLength, string.m_pchData);
return s;
}
#ifdef SA_UNICODE
SAString operator+(const SAString &string, char ch)
{
return string + (SAChar)ch;
}
SAString operator+(char ch, const SAString &string)
{
return (SAChar)ch + string;
}
#endif
/////////////////////////////////////////////////////////////////////////////
// SAString formatting
#define FORCE_ANSI 0x10000
#define FORCE_UNICODE 0x20000
#define FORCE_INT64 0x40000
void SAString::FormatV(const SAChar *lpszFormat, va_list argList)
{
assert(lpszFormat);
va_list argListSave = argList;
// make a guess at the maximum length of the resulting string
int nMaxLen = 0;
for (const SAChar *lpsz = lpszFormat; *lpsz != '\0'; lpsz = sa_csinc(lpsz))
{
// handle '%' character, but watch out for '%%'
if (*lpsz != '%' || *(lpsz = sa_csinc(lpsz)) == '%')
{
nMaxLen += sa_clen(lpsz);
continue;
}
int nItemLen = 0;
// handle '%' character with format
int nWidth = 0;
for (; *lpsz != '\0'; lpsz = sa_csinc(lpsz))
{
// check for valid flags
if (*lpsz == '#')
nMaxLen += 2; // for '0x'
else if (*lpsz == '*')
nWidth = va_arg(argList, int);
else if (*lpsz == '-' || *lpsz == '+' || *lpsz == '0' ||
*lpsz == ' ')
;
else // hit non-flag character
break;
}
// get width and skip it
if (nWidth == 0)
{
// width indicated by
nWidth = sa_toi(lpsz);
for (; *lpsz != '\0' && sa_isdigit(*lpsz); lpsz = sa_csinc(lpsz))
;
}
assert(nWidth >= 0);
int nPrecision = 0;
if (*lpsz == '.')
{
// skip past '.' separator (width.precision)
lpsz = sa_csinc(lpsz);
// get precision and skip it
if (*lpsz == '*')
{
nPrecision = va_arg(argList, int);
lpsz = sa_csinc(lpsz);
}
else
{
nPrecision = sa_toi(lpsz);
for (; *lpsz != '\0' && sa_isdigit(*lpsz); lpsz = sa_csinc(lpsz))
;
}
assert(nPrecision >= 0);
}
// should be on type modifier or specifier
int nModifier = 0;
if (sa_strncmp(lpsz, _SA("I64"), 3) == 0)
{
lpsz += 3;
nModifier = FORCE_INT64;
#if !defined(_X86_) && !defined(_ALPHA_)
// __int64 is only available on X86 and ALPHA platforms
assert(false);
#endif
}
else
{
switch (*lpsz)
{
// modifiers that affect size
case 'h':
nModifier = FORCE_ANSI;
lpsz = sa_csinc(lpsz);
break;
case 'l':
nModifier = FORCE_UNICODE;
lpsz = sa_csinc(lpsz);
break;
// modifiers that do not affect size
case 'F':
case 'N':
case 'L':
lpsz = sa_csinc(lpsz);
break;
}
}
// now should be on specifier
switch (*lpsz | nModifier)
{
// single characters
case 'c':
case 'C':
nItemLen = 2;
// int is OK
// need a cast here since va_arg only
// takes fully promoted types
(void)va_arg(argList, int/*SAChar*/);
break;
case 'c'|FORCE_ANSI:
case 'C'|FORCE_ANSI:
nItemLen = 2;
// int is OK
// need a cast here since va_arg only
// takes fully promoted types
(void)va_arg(argList, int/*char*/);
break;
case 'c'|FORCE_UNICODE:
case 'C'|FORCE_UNICODE:
nItemLen = 2;
// int is OK
// need a cast here since va_arg only
// takes fully promoted types
(void)va_arg(argList, int/*wchar_t*/);
break;
// strings
case 's':
{
const SAChar *pstrNextArg = va_arg(argList, const SAChar*);
if (pstrNextArg == NULL)
nItemLen = 6; // "(null)"
else
{
nItemLen = sa_strlen(pstrNextArg);
nItemLen = sa_max(1, nItemLen);
}
}
break;
case 'S':
{
#ifndef SA_UNICODE
wchar_t *pstrNextArg = va_arg(argList, wchar_t*);
if (pstrNextArg == NULL)
nItemLen = 6; // "(null)"
else
{
nItemLen = wcslen(pstrNextArg);
nItemLen = sa_max(1, nItemLen);
}
#else
const char *pstrNextArg = va_arg(argList, const char*);
if (pstrNextArg == NULL)
nItemLen = 6; // "(null)"
else
{
nItemLen = strlen(pstrNextArg);
nItemLen = sa_max(1, nItemLen);
}
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -