359 lines
8.3 KiB
C++
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);
|
|
} |