2025-11-28 00:35:46 +09:00

359 lines
8.3 KiB
C++

#include "stdafx.h"
#include "CRow.h"
// Allocating a buffer to use for storage of the row
// This proxy will be the temporary storage area for values as they are
// passed from file to the consumer and back.
void CRow::AllocProxyBuffer(ATLCOLUMNINFO * prgColInfo, DBORDINAL cNumCols)
{
DBLENGTH uSize = 0;
for (DBORDINAL i = 0; i < cNumCols; i++)
{
switch(prgColInfo[i].wType)
{
case DBTYPE_I4:
uSize += 4;
break;
case DBTYPE_STR:
uSize += prgColInfo[i].ulColumnSize;
break;
#ifdef _DEBUG
default:
// the types in the column info structures should always be correct but
// this is just a precaution
_ASSERTE(0);
return;
#endif
}
}
m_pbProxyData = new BYTE[uSize];
m_cbProxyData = uSize;
memset(m_pbProxyData,0,uSize);
}
// GetProxyData will convert the data in the file into the native data
// specified in the .INI file.
void CRow::GetProxyData(ATLCOLUMNINFO * pColInfo, DBORDINAL cCols)
{
// if (m_bRetrieved)
// return; // already have the data for the row
char* pPos = m_pbStartLoc;
char szColumnString[MAX_COLUMNSIZE];
// pPos will be incremented as data is fetched and can be passed into
// subsequent calls
//TODO: optimize by passing in the proxybuffer into FetchColumnString for string fields
for (DBORDINAL i = 0; i < cCols; i++)
{
// if (!(pColInfo[i].dwFlags &= DBCOLUMNFLAGS_ISBOOKMARK))
if (!(pColInfo[i].dwFlags & DBCOLUMNFLAGS_ISBOOKMARK))
{
int nResult = FetchColumnString(szColumnString, &pPos);
if (nResult == BAD_RECORD_FORMAT)
return; // TODO: handle bad file info
StoreInProxy(i, szColumnString, pColInfo);
}
else
StoreInProxy(i, NULL, pColInfo);
}
m_bRetrieved = true;
}
int CRow::FetchColumnString(char * pszColData, char ** ppPos)
{
// TODO: need to parse out white space before and after column data
if (*ppPos > m_pbStartLoc + m_cbRowSize - 1)
return BAD_RECORD_FORMAT;
while ((*ppPos <= (m_pbStartLoc + m_cbRowSize - 1)) && **ppPos != ',')
{
*pszColData++ = **ppPos;
(*ppPos)++;
}
if (**ppPos == ',')
(*ppPos)++;
*pszColData = '\0';
return 0;
}
void CRow::StoreInProxy(DBORDINAL iCol, char * szColumnString, ATLCOLUMNINFO * pColInfo)
{
// TODO: Probably need to do something here with bookmarks
// pColInfo is ordered by ordinal so we can do a simple array look-up
// currently only supports DBTYPE_I4
void * pvBuffer = m_pbProxyData + pColInfo[iCol].cbOffset;
switch(pColInfo[iCol].wType)
{
case DBTYPE_I4:
if (pColInfo[iCol].dwFlags & DBCOLUMNFLAGS_ISBOOKMARK)
*((long *)pvBuffer) = m_bmk;
else
*((long *)pvBuffer) = atoi(szColumnString);
break;
case DBTYPE_STR:
_tcscpy_s((char*) pvBuffer, m_cbProxyData - pColInfo[iCol].cbOffset, szColumnString);
break;
#ifdef _DEBUG
default:
// Should never get here if we have all of the types supported and we
// validate the types at the time of reading the schema
_ASSERTE(0);
break;
#endif
}
}
int CRow::CalculateRowData(ATLCOLUMNINFO * prgColInfo, DBORDINAL cNumCols, bool bAddEOL)
{
size_t nBytesNeeded = 0;
for (ULONG i = 0; i < cNumCols; i++)
{
void * pvBuffer = m_pbProxyData + prgColInfo[i].cbOffset;
switch(prgColInfo[i].wType)
{
case DBTYPE_I4:
if (!(prgColInfo[i].dwFlags & DBCOLUMNFLAGS_ISBOOKMARK))
{
//convert to string
char szTemp[MAX_COLUMNSIZE];
_itoa_s(*((long*)pvBuffer), szTemp, _countof(szTemp), 10);
nBytesNeeded += _tcslen(szTemp);
}
else
continue;
break;
case DBTYPE_STR:
nBytesNeeded += _tcslen((char*)pvBuffer);
if(_tcslen((char*)pvBuffer)> prgColInfo[i].ulColumnSize)
return -1;
break;
#ifdef _DEBUG
default:
// the types in the column info structures should always be correct but
// this is just a precaution
_ASSERTE(0);
return -1;
#endif
}
nBytesNeeded++; // add one byte for the comma
}
nBytesNeeded--; // subtract the count which was added for the comma
if (bAddEOL)
nBytesNeeded += 2;
return (int)(nBytesNeeded - m_cbRowSize) < 0 ? 0 : (int)(nBytesNeeded - m_cbRowSize);
}
int CRow::CalculateRowDataToDelete(ATLCOLUMNINFO * prgColInfo, DBORDINAL cNumCols, bool bAddEOL)
{
DBLENGTH nBytesNeeded = 0;
for (DBORDINAL i = 0; i < cNumCols; i++)
{
void * pvBuffer = m_pbProxyData + prgColInfo[i].cbOffset;
switch(prgColInfo[i].wType)
{
case DBTYPE_I4:
if (!(prgColInfo[i].dwFlags & DBCOLUMNFLAGS_ISBOOKMARK))
{
//convert to string
char szTemp[MAX_COLUMNSIZE];
_itoa_s(*((long*)pvBuffer), szTemp, _countof(szTemp), 10);
nBytesNeeded += _tcslen(szTemp);
}
else
continue;
break;
case DBTYPE_STR:
nBytesNeeded += _tcslen((char*)pvBuffer);
if(_tcslen((char*)pvBuffer)> prgColInfo[i].ulColumnSize)
return -1;
break;
#ifdef _DEBUG
default:
// the types in the column info structures should always be correct but
// this is just a precaution
_ASSERTE(0);
return -1;
#endif
}
nBytesNeeded++; // add one byte for the comma
}
nBytesNeeded--; // subtract the count which was added for the comma
if (bAddEOL)
nBytesNeeded += 2;
return (int)(m_cbRowSize - nBytesNeeded);
}
int CRow::Update(ATLCOLUMNINFO * prgColInfo, DBORDINAL cCols)
{
// CDBFile will update the row size
BYTE * pbCurrentPos = (BYTE *)m_pbStartLoc;
// copy data from proxy to the file
for (DBORDINAL i = 0; i < cCols; i++)
{
void * pvBuffer = m_pbProxyData + prgColInfo[i].cbOffset;
switch(prgColInfo[i].wType)
{
case DBTYPE_I4:
if (prgColInfo[i].dwFlags & DBCOLUMNFLAGS_ISBOOKMARK)
continue;
else
{
//convert to string
char szTemp[MAX_COLUMNSIZE];
_itoa_s(*((long*)pvBuffer), szTemp, _countof(szTemp), 10);
//copy from buffer to file
for (int n = 0; szTemp[n] != '\0'; n++)
*pbCurrentPos++ = szTemp[n];
}
break;
case DBTYPE_STR:
{
char* pszTemp;
pszTemp = (char *)pvBuffer;
for (DBLENGTH n = 0; *pszTemp != '\0'; n++)
*pbCurrentPos++ = *pszTemp++;
}
break;
#ifdef _DEBUG
default:
// the types in the column info structures should always be correct but
// this is just a precaution
_ASSERTE(0);
return 0;
#endif
}
if (i != cCols -1) // not the last column
*pbCurrentPos++ = ',';
}
/* // fill remainder of bytes with spaces
// This can occur because we don't allocate a new row if the updated row will be
// smaller
if ((pbCurrentPos - (BYTE *)m_pbStartLoc) < m_cbRowSize)
{
int n = m_cbRowSize - (pbCurrentPos - (BYTE *)m_pbStartLoc);
for (;n != 0; n--)
*pbCurrentPos++= ' ';
}*/
m_cbRowSize = (int) (pbCurrentPos - (BYTE *)m_pbStartLoc);
// add seperator
// *pbCurrentPos++ = '\r';
// *pbCurrentPos = '\n';
return 0;
}
bool CRow::HasEOL(BYTE * pbEOF)
{
char * pbEOR = m_pbStartLoc + m_cbRowSize;
if (pbEOR <= (char *)pbEOF && pbEOR[0] == '\r' && pbEOR[1] == '\n')
return true;
else
return false;
}
void CRow::AddEOL()
{
//assumes the space has already been allocated to do this
char * pbEOR = m_pbStartLoc + m_cbRowSize;
*pbEOR++ = '\r';
*pbEOR = '\n';
}
int CRow::CreateDefaultRow(ATLCOLUMNINFO *prgColInfo, DBORDINAL cNumCols, bool bAddEOL)
{
USES_CONVERSION;
DBLENGTH nBytesNeeded = 0;
for (DBORDINAL i = 0; i < cNumCols; i++)
{
void * pvBuffer = m_pbProxyData + prgColInfo[i].cbOffset;
switch(prgColInfo[i].wType)
{
case DBTYPE_I4:
if (!(prgColInfo[i].dwFlags & DBCOLUMNFLAGS_ISBOOKMARK))
{
//Store default '0' in the Proxy Buffer
StoreInProxy(i, "0", prgColInfo);
nBytesNeeded ++;
}
else // Do not store if it is a bookmark
continue;
break;
case DBTYPE_STR:
// Store the name of the field
if (_tcslen(OLE2A(prgColInfo[i].pwszName)) > 0 && _tcslen(OLE2A(prgColInfo[i].pwszName)) < prgColInfo[i].ulColumnSize)
{
StoreInProxy(i, OLE2A(prgColInfo[i].pwszName), prgColInfo);
nBytesNeeded += _tcslen(OLE2A(prgColInfo[i].pwszName));
}
else
{
// Store a '?'
StoreInProxy(i,"?", prgColInfo);
nBytesNeeded ++;
}
break;
#ifdef _DEBUG
default:
// the types in the column info structures should always be correct but
// this is just a precaution
_ASSERTE(0);
return -1;
#endif
}
nBytesNeeded++; // add one byte for the comma
}
nBytesNeeded--; // subtract the count which was added for the comma
if (bAddEOL)
nBytesNeeded += 2;
return (int)(nBytesNeeded - m_cbRowSize) < 0 ? 0 : (int)(nBytesNeeded - m_cbRowSize);
}