⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sqlapi.cpp

📁 通用的数据库中间库
💻 CPP
📖 第 1 页 / 共 5 页
字号:
			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 + -