385 lines
6.4 KiB
C++
385 lines
6.4 KiB
C++
#include "stdafx.h"
|
|
#include "MemoFile.h"
|
|
#include <math.h>
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
// CMemoFile
|
|
IMPLEMENT_DYNAMIC(CMemoFile, CObject)
|
|
|
|
CMemoFile::CMemoFile()
|
|
{
|
|
m_bOpen = FALSE;
|
|
|
|
m_pDBTHead = NULL;
|
|
}
|
|
|
|
CMemoFile::~CMemoFile()
|
|
{
|
|
Close();
|
|
}
|
|
|
|
BOOL CMemoFile::Open(LPCTSTR lpszName, UINT nOpenFlag)
|
|
{
|
|
if (!lpszName)
|
|
return FALSE;
|
|
|
|
nOpenFlag = nOpenFlag | CFile::typeBinary;
|
|
|
|
// Re-open is invalid
|
|
if (IsOpen())
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// TRY
|
|
// {
|
|
|
|
DBF_CHECK_ERROR(
|
|
CFile::Open(lpszName, nOpenFlag), TG_DBF_ERROR_MEMO_OPEN);
|
|
|
|
DBF_CHECK_ERROR(
|
|
ReadHeader(),TG_DBF_ERROR_MEMO_HEAD_READ);
|
|
|
|
DBF_CHECK_ERROR(m_nBlockSize > 0,TG_DBF_ERROR_MEMO_BLOCK_SIZE);
|
|
|
|
m_bOpen = TRUE;
|
|
// }
|
|
// CATCH(CFileException, e)
|
|
// {
|
|
// e->ReportError();
|
|
// e->Delete();
|
|
// Close();
|
|
// }
|
|
// END_CATCH
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CMemoFile::IsOpen() const
|
|
{
|
|
|
|
return m_bOpen;
|
|
}
|
|
|
|
void CMemoFile::Close()
|
|
{
|
|
if(m_bOpen)
|
|
CFile::Close();
|
|
|
|
m_bOpen = FALSE;
|
|
|
|
if(m_pDBTHead != NULL)
|
|
delete m_pDBTHead;
|
|
m_pDBTHead = NULL;
|
|
}
|
|
|
|
UINT CMemoFile::GetMemoFileType()
|
|
{
|
|
return MEMO_TYPE_DBASE;
|
|
}
|
|
|
|
BOOL CMemoFile::ReadHeader()
|
|
{
|
|
if (!m_hFile)
|
|
return FALSE;
|
|
TRY
|
|
{
|
|
Seek(0, CFile::begin);
|
|
|
|
if(m_pDBTHead == NULL)
|
|
m_pDBTHead = new DBT_HEAD;
|
|
|
|
if(Read(m_pDBTHead, sizeof(DBT_HEAD)) != sizeof(DBT_HEAD))
|
|
return FALSE;
|
|
|
|
m_nBlockSize = m_pDBTHead->block_size;
|
|
|
|
if(m_nBlockSize <= 0)
|
|
m_nBlockSize = 512;
|
|
|
|
return TRUE;
|
|
}
|
|
CATCH(CFileException, e)
|
|
{
|
|
e->ReportError();
|
|
e->Delete();
|
|
|
|
} END_CATCH
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL CMemoFile::WriteHeader()
|
|
{
|
|
if (!m_hFile)
|
|
return FALSE;
|
|
TRY
|
|
{
|
|
Seek(0, CFile::begin);
|
|
|
|
Write(m_pDBTHead, sizeof(DBT_HEAD));
|
|
|
|
return TRUE;
|
|
}
|
|
CATCH(CFileException, e)
|
|
{
|
|
e->ReportError();
|
|
e->Delete();
|
|
|
|
} END_CATCH
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL CMemoFile::ReadMemoRecord(DBF_ULONG lOffsetRec, DBF_LONG& nLen, CTDbfString& strMemo)
|
|
{
|
|
if (lOffsetRec < 0)
|
|
return FALSE;
|
|
strMemo = "";
|
|
|
|
if(!IsOpen())
|
|
return FALSE;
|
|
|
|
// TRY
|
|
// {
|
|
DBF_UCHAR* pBuffer;
|
|
DBF_CHAR chCurChar = 0x0;
|
|
DBF_UINT nBlockCount = 1;
|
|
DBF_LONG nLenMemo = 0;
|
|
DBF_LONG lMaxLen;
|
|
|
|
Seek(lOffsetRec * m_nBlockSize,CFile::begin);
|
|
|
|
pBuffer = new DBF_UCHAR[m_nBlockSize];
|
|
lMaxLen = (DBF_LONG)(GetLength() - GetPosition());
|
|
|
|
while(chCurChar != REC_EOF && nLenMemo < lMaxLen)
|
|
{
|
|
if(Read(&chCurChar, sizeof(chCurChar)) != sizeof(DBF_UCHAR))
|
|
{
|
|
delete[] pBuffer;
|
|
TGThrowDBFException(TG_DBF_ERROR_MEMO_FIELD_READ);
|
|
}
|
|
else
|
|
{
|
|
if(chCurChar == REC_EOF)
|
|
pBuffer[nLenMemo] = '\0';
|
|
else
|
|
pBuffer[nLenMemo] = chCurChar;
|
|
nLenMemo++;
|
|
if(nLenMemo >= nBlockCount * m_nBlockSize)
|
|
{
|
|
DBF_UCHAR* pBuff;
|
|
nBlockCount++;
|
|
pBuff = new DBF_UCHAR[nBlockCount * m_nBlockSize];
|
|
memcpy(pBuff,pBuffer,(nBlockCount - 1) * m_nBlockSize);
|
|
delete[] pBuffer;
|
|
pBuffer = pBuff;
|
|
}
|
|
}
|
|
}
|
|
char *_buf = new char[nLenMemo];
|
|
memcpy(_buf/*strMemo.GetBuffer(nLenMemo)*/,pBuffer,nLenMemo);
|
|
// strMemo.ReleaseBuffer(nLenMemo);
|
|
strMemo = _buf;
|
|
delete[] _buf;
|
|
delete[] pBuffer;
|
|
_buf = NULL;
|
|
nLen = nLenMemo;
|
|
|
|
// }
|
|
// CATCH(CFileException, e)
|
|
// {
|
|
// e->ReportError();
|
|
// e->Delete();
|
|
//
|
|
// TGThrowDBFException(TG_DBF_ERROR_MEMO_FIELD_READ);
|
|
//
|
|
// } END_CATCH
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CMemoFile::ReadMemoRecord(DBF_ULONG lOffsetRec, DBF_LONG& nLen, unsigned char** pMemoData)
|
|
{
|
|
if (lOffsetRec < 0)
|
|
return FALSE;
|
|
*pMemoData = NULL;
|
|
|
|
if(!IsOpen())
|
|
return FALSE;
|
|
|
|
// TRY
|
|
// {
|
|
DBF_CHAR chCurChar = 0x0;
|
|
DBF_UINT nBlockCount = 1;
|
|
DBF_LONG nLenMemo = 0;
|
|
DBF_LONG lMaxLen;
|
|
|
|
Seek(lOffsetRec * m_nBlockSize,CFile::begin);
|
|
|
|
*pMemoData = new DBF_UCHAR[m_nBlockSize];
|
|
lMaxLen = (DBF_LONG)(GetLength() - GetPosition());
|
|
|
|
while(chCurChar != REC_EOF && nLenMemo < lMaxLen)
|
|
{
|
|
if(Read(&chCurChar, sizeof(chCurChar)) != sizeof(DBF_UCHAR))
|
|
{
|
|
delete[] *pMemoData;
|
|
*pMemoData = NULL;
|
|
TGThrowDBFException(TG_DBF_ERROR_MEMO_FIELD_READ);
|
|
}
|
|
else
|
|
{
|
|
if(chCurChar == REC_EOF)
|
|
(*pMemoData)[nLenMemo] = '\0';
|
|
else
|
|
(*pMemoData)[nLenMemo] = chCurChar;
|
|
nLenMemo++;
|
|
if(nLenMemo >= nBlockCount * m_nBlockSize)
|
|
{
|
|
DBF_UCHAR* pBuff;
|
|
nBlockCount++;
|
|
pBuff = new DBF_UCHAR[nBlockCount * m_nBlockSize];
|
|
memcpy(pBuff,*pMemoData,(nBlockCount - 1) * m_nBlockSize);
|
|
delete[] *pMemoData;
|
|
*pMemoData = pBuff;
|
|
}
|
|
}
|
|
}
|
|
nLen = nLenMemo;
|
|
|
|
// }
|
|
// CATCH(CFileException, e)
|
|
// {
|
|
// e->ReportError();
|
|
// e->Delete();
|
|
//
|
|
// TGThrowDBFException(TG_DBF_ERROR_MEMO_FIELD_READ);
|
|
//
|
|
// } END_CATCH
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CMemoFile::WriteMemoRecord(DBF_ULONG& lOffsetRec, DBF_LONG& nLen, CTDbfString& strMemo)
|
|
{
|
|
|
|
|
|
if(!IsOpen())
|
|
return FALSE;
|
|
|
|
// TRY
|
|
// {
|
|
DBF_LONG nLenMemo = 0;
|
|
|
|
if(strMemo.IsEmpty())
|
|
lOffsetRec = 0;
|
|
|
|
else if(lOffsetRec > 0)
|
|
{
|
|
CTDbfString strCurMemoData;
|
|
|
|
ReadMemoRecord(lOffsetRec, nLenMemo, strCurMemoData);
|
|
Seek(lOffsetRec * m_nBlockSize + sizeof(DBF_LONG),CFile::begin);
|
|
|
|
nLenMemo = (DBF_LONG) ceil(((double)(nLenMemo + sizeof(DBF_CHAR)))/((double)m_nBlockSize)) * m_nBlockSize - sizeof(DBF_CHAR);
|
|
|
|
if(nLenMemo < (int)strMemo.GetLength())
|
|
|
|
lOffsetRec = AddMemoRecord(strMemo);
|
|
else
|
|
UpdateMemoRecord(lOffsetRec, strMemo);
|
|
}
|
|
else
|
|
lOffsetRec = AddMemoRecord(strMemo);
|
|
// }
|
|
// CATCH(CFileException, e)
|
|
// {
|
|
// e->ReportError();
|
|
// e->Delete();
|
|
//
|
|
// TGThrowDBFException(TG_DBF_ERROR_MEMO_FIELD_WRITE);
|
|
//
|
|
// } END_CATCH
|
|
return TRUE;
|
|
}
|
|
|
|
#ifdef _DEBUG
|
|
void CMemoFile::AssertValid() const
|
|
{
|
|
CObject::AssertValid();
|
|
}
|
|
|
|
void CMemoFile::Dump(CDumpContext& dc) const
|
|
{
|
|
|
|
|
|
CObject::Dump(dc);
|
|
|
|
dc << "m_bOpen = " << m_bOpen;
|
|
|
|
dc << "\n";
|
|
}
|
|
#endif //_DEBUG
|
|
|
|
DBF_LONG CMemoFile::AddMemoRecord(CTDbfString& strMemo)
|
|
{
|
|
DBF_ULONG lOffsetRec = 0;
|
|
|
|
TRY
|
|
{
|
|
DBF_LONG nLenMemo = strMemo.GetLength();
|
|
|
|
ReadHeader();
|
|
|
|
lOffsetRec = m_pDBTHead->next_block;
|
|
m_pDBTHead->next_block += (DBF_LONG) ceil((double)(nLenMemo + sizeof(DBF_CHAR)) / (double)m_nBlockSize);
|
|
|
|
Seek(lOffsetRec * m_nBlockSize,CFile::begin);
|
|
|
|
Write(strMemo.toLPCSTR(), strMemo.GetLength());
|
|
|
|
DBF_CHAR eof = REC_EOF;
|
|
|
|
Write(&eof, sizeof(eof));
|
|
|
|
WriteHeader();
|
|
}
|
|
CATCH(CFileException, e)
|
|
{
|
|
e->ReportError();
|
|
e->Delete();
|
|
|
|
} END_CATCH
|
|
|
|
return lOffsetRec;
|
|
}
|
|
|
|
void CMemoFile::UpdateMemoRecord(DBF_ULONG lOffsetRec, CTDbfString& strMemo)
|
|
{
|
|
|
|
TRY
|
|
{
|
|
DBF_LONG nLenMemo = strMemo.GetLength();
|
|
|
|
Seek(lOffsetRec * m_nBlockSize,CFile::begin);
|
|
|
|
Write(strMemo.toLPCSTR(), strMemo.GetLength());
|
|
|
|
DBF_CHAR eof = REC_EOF;
|
|
|
|
Write(&eof, sizeof(eof));
|
|
}
|
|
CATCH(CFileException, e)
|
|
{
|
|
e->ReportError();
|
|
e->Delete();
|
|
|
|
} END_CATCH
|
|
|
|
}
|
|
|