📄 sqlapi.cpp
字号:
return s2.Compare(s1) == 0;
}
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)
{
return s2.Compare(s1) != 0;
}
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)
{
return s2.Compare(s1) > 0;
}
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)
{
return s2.Compare(s1) < 0;
}
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)
{
return s2.Compare(s1) >= 0;
}
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)
{
return s2.Compare(s1) <= 0;
}
//////////////////////////////////////////////////////////////////////////////
// Finding
int SAString::Find(SAChar ch) const
{
return Find(ch, 0);
}
int SAString::Find(SAChar ch, int nStart) const
{
int nLength = GetData()->nDataLength;
if (nStart >= nLength)
return -1;
// find first single character
const SAChar *lpsz = sa_strchr(m_pchData + nStart, ch);
// return -1 if not found and index otherwise
return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
}
int SAString::FindOneOf(const SAChar *lpszCharSet) const
{
assert(lpszCharSet);
const SAChar *lpsz = sa_strpbrk(m_pchData, lpszCharSet);
return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
}
int SAString::ReverseFind(SAChar ch) const
{
// find last single character
const SAChar *lpsz = sa_strrchr(m_pchData, ch);
// return -1 if not found, distance from beginning otherwise
return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
}
// find a sub-string (like strstr)
int SAString::Find(const SAChar *lpszSub) const
{
return Find(lpszSub, 0);
}
int SAString::Find(const SAChar *lpszSub, int nStart) const
{
assert(lpszSub);
int nLength = GetData()->nDataLength;
if (nStart > nLength)
return -1;
// find first matching substring
const SAChar *lpsz = sa_strstr(m_pchData + nStart, lpszSub);
// return -1 for not found, distance from beginning otherwise
return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
}
// Special constructor and buffer access routines to manipulate binary data
// constructor for binary data (no converion to SAChar)
SAString::SAString(const void *pBuffer, int nLengthInBytes)
{
#ifdef SA_UNICODE
Init();
if (nLengthInBytes != 0)
{
assert(pBuffer);
int nBinaryDataLengthDiff = nLengthInBytes % sizeof(SAChar);
// allocate at least so many characters that all binary data can be stored (round up if necessary)
int nLengthInChars = nLengthInBytes / sizeof(SAChar) + (nBinaryDataLengthDiff? 1 : 0);
AllocBuffer(nLengthInChars);
// if nLengthInBytes is not a multiply of sizeof(SAChar)
// we have to save the difference
GetData()->nBinaryDataLengthDiff = nBinaryDataLengthDiff;
memcpy(m_pchData, pBuffer, nLengthInBytes);
}
#else // !SA_UNICODE
// byte == character in non-Unicode build
Init();
if (nLengthInBytes != 0)
{
assert(pBuffer);
AllocBuffer(nLengthInBytes);
memcpy(m_pchData, pBuffer, nLengthInBytes);
}
#endif // !SA_UNICODE
}
// get binary data length (in bytes)
int SAString::GetBinaryLength() const
{
#ifdef SA_UNICODE
return GetLength()*sizeof(SAChar) - GetData()->nBinaryDataLengthDiff;
#else // !SA_UNICODE
// byte == character in non-Unicode build
return GetLength();
#endif // !SA_UNICODE
}
// return pointer to const binary data buffer
SAString::operator const void *() const
{
return (const void *)m_pchData;
}
// get pointer to modifiable binary data buffer at least as long as nMinBufLengthInBytes
void *SAString::GetBinaryBuffer(int nMinBufLengthInBytes)
{
#ifdef SA_UNICODE
// convert bytes count to characters count (round up if necessasry)
int nMinBufLengthInChars = nMinBufLengthInBytes / sizeof(SAChar) + (nMinBufLengthInBytes % sizeof(SAChar)? 1 : 0);
return GetBuffer(nMinBufLengthInChars);
#else // !SA_UNICODE
// byte == character in non-Unicode build
return GetBuffer(nMinBufLengthInBytes);
#endif // !SA_UNICODE
}
// release buffer, setting length to nNewLength (or to first nul if -1)
void SAString::ReleaseBinaryBuffer(int nNewLengthInBytes)
{
#ifdef SA_UNICODE
int nBinaryDataLengthDiff = nNewLengthInBytes % sizeof(SAChar);
// release at least so many characters that all binary data can be stored (round up if necessary)
int nNewLengthInChars = nNewLengthInBytes / sizeof(SAChar) + (nBinaryDataLengthDiff? 1 : 0);
ReleaseBuffer(nNewLengthInChars);
// if nNewLengthInBytes is not a multiply of sizeof(SAChar)
// we have to save the difference
GetData()->nBinaryDataLengthDiff = nBinaryDataLengthDiff;
#else // !SA_UNICODE
// byte == character in non-Unicode build
ReleaseBuffer(nNewLengthInBytes);
#endif // !SA_UNICODE
}
// Special conversion functions (multi byte <-> unicode)
#ifdef SA_UNICODE
static void ConvertToMultiByteChars(SAStringData *pData)
{
if(pData->pConvertedData) // already converted and cached
return;
// calculate multi-byte length
int mbLen = SAWideCharToMultiByte(
NULL, pData->data(), pData->nDataLength);
// alocate space for conversion
pData->pConvertedData = (SAStringConvertedData *)
new unsigned char[sizeof(SAStringConvertedData) + (mbLen+1)*sizeof(char)];
pData->pConvertedData->nDataLength = mbLen;
pData->pConvertedData->data()[mbLen] = '\0';
// now actually convert
SAWideCharToMultiByte(pData->pConvertedData->data(), pData->data(), pData->nDataLength);
}
const char *SAString::GetMultiByteChars() const
{
ConvertToMultiByteChars(GetData());
return GetData()->pConvertedData->data();
}
int SAString::GetMultiByteCharsLength() const
{
ConvertToMultiByteChars(GetData());
return GetData()->pConvertedData->nDataLength;
}
#else // !SA_UNICODE
static void ConvertToWideChars(SAStringData *pData)
{
if(pData->pConvertedData) // already converted and cached
return;
// alocate space for conversion
pData->pConvertedData = (SAStringConvertedData *)
new unsigned char[sizeof(SAStringConvertedData) + (pData->nDataLength+1)*sizeof(wchar_t)];
int wLen = SAMultiByteToWideChar(pData->pConvertedData->data(), pData->data(), pData->nDataLength);
pData->pConvertedData->nDataLength = wLen;
pData->pConvertedData->data()[wLen] = '\0';
}
const wchar_t *SAString::GetWideChars() const
{
ConvertToWideChars(GetData());
return GetData()->pConvertedData->data();
}
int SAString::GetWideCharsLength() const
{
ConvertToWideChars(GetData());
return GetData()->pConvertedData->nDataLength;
}
#endif // !SA_UNICODE
//////////////////////////////////////////////////////////////////////
// SADateTime Class
//////////////////////////////////////////////////////////////////////
/*static */
int SADateTime::m_saMonthDays[13] =
{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
// thanks to Microsoft for AFX_STATIC BOOL AFXAPI _AfxOleDateFromTm
/*static */
bool SADateTime::DateFromTm(unsigned short wYear, unsigned short wMonth, unsigned short wDay,
unsigned short wHour, unsigned short wMinute, unsigned short wSecond,
unsigned long nNanoSecond,
double &dtDest)
{
wYear += (unsigned short)1900;
// Validate year and month (ignore day of week and milliseconds)
if (wYear > 9999 || wMonth < 1 || wMonth > 12)
return false;
// Check for leap year and set the number of days in the month
bool bLeapYear = ((wYear & 3) == 0) &&
((wYear % 100) != 0 || (wYear % 400) == 0);
int nDaysInMonth =
m_saMonthDays[wMonth] - m_saMonthDays[wMonth-1] +
((bLeapYear && wDay == 29 && wMonth == 2) ? 1 : 0);
// Finish validating the date
if (wDay < 1 || wDay > nDaysInMonth ||
wHour > 23 || wMinute > 59 ||
wSecond > 59)
{
return false;
}
// Cache the date in days and time in fractional days
long nDate;
double dblTime;
//It is a valid date; make Jan 1, 1AD be 1
nDate = wYear*365L + wYear/4 - wYear/100 + wYear/400 +
m_saMonthDays[wMonth-1] + wDay;
// If leap year and it's before March, subtract 1:
if (wMonth <= 2 && bLeapYear)
--nDate;
// Offset so that 12/30/1899 is 0
nDate -= 693959L;
dblTime = (((long)wHour * 3600L) + // hrs in seconds
((long)wMinute * 60L) + // mins in seconds
((long)wSecond)) / 86400.;
// add nanoseconds
double dNanoSec = (double)nNanoSecond/(24.0*60.0*60.0*1e9);
dblTime += dNanoSec;
dtDest = (double) nDate + ((nDate >= 0) ? dblTime : -dblTime);
return true;
}
// AFX_STATIC BOOL AFXAPI _AfxTmFromOleDate(DATE dtSrc, struct tm& tmDest)
/*static */
bool SADateTime::TmFromDate(
double dtSrc,
struct tm &tmDest, unsigned long &nNanoSecond)
{
long MIN_DATE = (-657434L); // about year 100
long MAX_DATE = 2958465L; // about year 9999
// double HALF_SECOND = (1.0/172800.0);
// The legal range does not actually span year 0 to 9999.
if (dtSrc > MAX_DATE || dtSrc < MIN_DATE) // about year 100 to about 9999
return false;
long nDaysAbsolute; // Number of days since 1/1/0
long nSecsInDay; // Time in seconds since midnight
long nMinutesInDay; // Minutes in day
long n400Years; // Number of 400 year increments since 1/1/0
long n400Century; // Century within 400 year block (0,1,2 or 3)
long n4Years; // Number of 4 year increments since 1/1/0
long n4Day; // Day within 4 year block
// (0 is 1/1/yr1, 1460 is 12/31/yr4)
long n4Yr; // Year within 4 year block (0,1,2 or 3)
bool bLeap4 = true; // TRUE if 4 year block includes leap year
double dblDate = dtSrc; // tempory serial date
// MS Original Code:Round to the second
// MS Original Code:dblDate += ((dtSrc > 0.0) ? HALF_SECOND : -HALF_SECOND);
// SQLAPI++ Code:No rounding, we will maintain nanoseconds
nDaysAbsolute = (long)dblDate + 693959L; // Add days from 1/1/0 to 12/30/1899
dblDate = fabs(dblDate);
double dblTime = dblDate - floor(dblDate);
nSecsInDay = (long)(dblTime * 86400.);
// Calculate the day of week (sun=1, mon=2...)
// -1 because 1/1/0 is Sat. +1 because we want 1-based
tmDest.tm_wday = (int)((nDaysAbsolute - 1) % 7L) + 1;
// Leap years every 4 yrs except centuries not multiples of 400.
n400Years = (long)(nDaysAbsolute / 146097L);
// Set nDaysAbsolute to day within 400-year block
nDaysAbsolute %= 146097L;
// -1 because first century has extra day
n400Century = (long)((nDaysAbsolute - 1) / 36524L);
// Non-leap century
if (n400Century != 0)
{
// Set nDaysAbsolute to day within century
nDaysAbsolute = (nDaysAbsolute - 1) % 36524L;
// +1 because 1st 4 year increment has 1460 days
n4Years = (long)((nDaysAbsolute + 1) / 1461L);
if (n4Years != 0)
n4Day = (long)((nDaysAbsolute + 1) % 1461L);
else
{
bLeap4 = false;
n4Day = (long)nDaysAbsolute;
}
}
else
{
// Leap century - not special case!
n4Years = (long)(nDaysAbsolute / 1461L);
n4Day = (long)(nDaysAbsolute % 1461L);
}
if (bLeap4)
{
// -1 because first year has 366 days
n4Yr = (n4Day - 1) / 365;
if (n4Yr != 0)
n4Day = (n4Day - 1) % 365;
}
else
{
n4Yr = n4Day / 365;
n4Day %= 365;
}
// n4Day is now 0-based day of year. Save 1-based day of year, year number
tmDest.tm_yday = (int)n4Day + 1;
tmDest.tm_year = n400Years * 400 + n400Century * 100 + n4Years * 4 + n4Yr;
// Handle leap year: before, on, and after Feb. 29.
if (n4Yr == 0 && bLeap4)
{
// Leap Year
if (n4Day == 59)
{
/* Feb. 29 */
tmDest.tm_mon = 2;
tmDest.tm_mday = 29;
goto DoTime;
}
// Pretend it's not a leap year for month/day comp.
if (n4Day >= 60)
--n4Day;
}
// Make n4DaY a 1-based day of non-leap year and compute
// month/day for everything but Feb. 29.
++n4Day;
// Month number always >= n/32, so save some loop time */
for (tmDest.tm_mon = (n4Day >> 5) + 1;
n4Day > m_saMonthDays[tmDest.tm_mon]; tmDest.tm_mon++);
tmDest.tm_mday = (int)(n4Day - m_saMonthDays[tmDest.tm_mon-1]);
DoTime:
if (nSecsInDay == 0)
tmDest.tm_hour = tmDest.tm_min = tmDest.tm_sec = 0;
else
{
tmDest.tm_sec = (int)nSecsInDay % 60L;
nMinutesInDay = nSecsInDay / 60L;
tmDest.tm_min = (int)nMinutesInDay % 60;
tmDest.tm_hour = (int)nMinutesInDay / 60;
}
double dNanoSecs = dblTime - ((double)nSecsInDay/86400.0);
assert(dNanoSecs >= 0);
dNanoSecs *= 24.0 * 60.0 * 60.0 * 1e9;
assert(dNanoSecs < 1e9);
nNanoSecond = (unsigned long)dNanoSecs;
assert(nNanoSecond <= 999999999);
tmDest.tm_year -= 1900; // year is based on 1900
tmDest.tm_mon -= 1; // month of year is 0-based
tmDest.tm_wday -= 1; // day of week is 0-based
tmDest.tm_yday -= 1; // day of year is 0-based
return true;
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
void SADateTime::Init_Tm()
{
memset(&m_tm, 0, sizeof(m_tm));
m_nFraction = 0;
}
SADateTime::SADateTime()
{
Init_Tm();
}
SADateTime::SADateTime(const SADateTime &other)
{
m_tm = other.m_tm;
m_nFraction = other.m_nFraction;
}
SADateTime::SADateTime(const struct tm &tmValue)
{
m_tm = tmValue;
m_nFraction = 0;
}
SADateTime::operator struct tm &()
{
return m_tm;
}
SADateTime::operator struct tm() const
{
return m_tm;
}
SADateTime::SADateTime(double dt)
{
if(!TmFromDate(dt, m_tm, m_nFraction))
Init_Tm();
}
SADateTime::operator double() const
{
double dt;
if(DateFromTm(
(unsigned short)m_tm.tm_year, (unsigned short)(m_tm.tm_mon + 1), (unsigned short)m_tm.tm_mday,
(unsigned short)m_tm.tm_hour, (unsigned short)m_tm.tm_min, (unsigned short)m_tm.tm_sec,
m_nFraction,
dt))
return dt;
return (double)0;
}
SADateTime::SADateTime(int nYear, int nMonth, int nDay, int nHour, int nMinute, int nSecond)
{
m_tm.tm_year = nYear - 1900;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -