475 lines
8.9 KiB
C++
475 lines
8.9 KiB
C++
#include "stdafx.h"
|
|
#include "SMTMemoFile.h"
|
|
#include <math.h>
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
// CSMTMemoFile
|
|
IMPLEMENT_DYNAMIC(CSMTMemoFile, CMemoFile)
|
|
|
|
CSMTMemoFile::CSMTMemoFile()
|
|
{
|
|
}
|
|
|
|
CSMTMemoFile::~CSMTMemoFile()
|
|
{
|
|
Close();
|
|
}
|
|
|
|
BOOL CSMTMemoFile::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_SMTHead.block_size > 0,TG_DBF_ERROR_MEMO_BLOCK_SIZE);
|
|
|
|
m_bOpen = TRUE;
|
|
// }
|
|
// CATCH(CFileException, e)
|
|
// {
|
|
// e->ReportError();
|
|
// e->Delete();
|
|
// Close();
|
|
// }
|
|
// END_CATCH
|
|
return TRUE;
|
|
}
|
|
|
|
void CSMTMemoFile::Close()
|
|
{
|
|
if(m_bOpen)
|
|
CMemoFile::Close();
|
|
}
|
|
|
|
UINT CSMTMemoFile::GetMemoFileType()
|
|
{
|
|
return MEMO_TYPE_SIX;
|
|
}
|
|
|
|
BOOL CSMTMemoFile::ReadHeader()
|
|
{
|
|
if (!m_hFile)
|
|
return FALSE;
|
|
|
|
TRY
|
|
{
|
|
Seek(0, CFile::begin);
|
|
|
|
if(Read(&m_SMTHead, sizeof(SMT_HEAD)) != sizeof(SMT_HEAD))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
CATCH(CFileException, e)
|
|
{
|
|
e->ReportError();
|
|
e->Delete();
|
|
|
|
} END_CATCH
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL CSMTMemoFile::WriteHeader()
|
|
{
|
|
if (!m_hFile)
|
|
return FALSE;
|
|
|
|
TRY
|
|
{
|
|
Seek(0, CFile::begin);
|
|
|
|
Write(&m_SMTHead, sizeof(SMT_HEAD));
|
|
|
|
return TRUE;
|
|
}
|
|
CATCH(CFileException, e)
|
|
{
|
|
e->ReportError();
|
|
e->Delete();
|
|
|
|
} END_CATCH
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL CSMTMemoFile::ReadMemoRecord(DBF_ULONG lOffsetRec, DBF_LONG& nLen, CTDbfString& strMemo)
|
|
{
|
|
if (lOffsetRec < 0)
|
|
return FALSE;
|
|
|
|
strMemo = "";
|
|
|
|
if(!IsOpen())
|
|
return FALSE;
|
|
|
|
// TRY
|
|
// {
|
|
Seek(lOffsetRec * m_SMTHead.block_size,CFile::begin);
|
|
|
|
DBF_CHECK_ERROR(nLen > 0,TG_DBF_ERROR_MEMO_FIELD_READ);
|
|
|
|
char* buffer = new char[nLen+1]/*strMemo.GetBuffer(nLen + 1)*/;
|
|
|
|
DBF_CHECK_ERROR(
|
|
Read(buffer, nLen) == (UINT)nLen,
|
|
TG_DBF_ERROR_MEMO_FIELD_READ);
|
|
|
|
buffer[nLen] = '\0';
|
|
// strMemo.ReleaseBuffer(nLen + 1);
|
|
strMemo = buffer;
|
|
delete [] buffer;
|
|
buffer = NULL;
|
|
|
|
// }
|
|
// CATCH(CFileException, e)
|
|
// {
|
|
// e->ReportError();
|
|
// e->Delete();
|
|
//
|
|
// TGThrowDBFException(TG_DBF_ERROR_MEMO_FIELD_READ);
|
|
//
|
|
// } END_CATCH
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CSMTMemoFile::ReadMemoRecord(DBF_ULONG lOffsetRec, DBF_LONG& nLen, unsigned char** pMemoData)
|
|
{
|
|
if (lOffsetRec < 0)
|
|
return FALSE;
|
|
*pMemoData = NULL;
|
|
|
|
if(!IsOpen())
|
|
return FALSE;
|
|
|
|
// TRY
|
|
// {
|
|
Seek(lOffsetRec * m_SMTHead.block_size,CFile::begin);
|
|
|
|
DBF_CHECK_ERROR(nLen > 0,TG_DBF_ERROR_MEMO_FIELD_READ);
|
|
|
|
*pMemoData = new unsigned char[nLen];
|
|
|
|
DBF_CHECK_ERROR(
|
|
Read(*pMemoData, nLen) == (UINT)nLen,
|
|
TG_DBF_ERROR_MEMO_FIELD_READ);
|
|
|
|
// }
|
|
// CATCH(CFileException, e)
|
|
// {
|
|
// e->ReportError();
|
|
// e->Delete();
|
|
//
|
|
// TGThrowDBFException(TG_DBF_ERROR_MEMO_FIELD_READ);
|
|
//
|
|
// } END_CATCH
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CSMTMemoFile::WriteMemoRecord(DBF_ULONG& lOffsetRec, DBF_LONG& nLenMemo, CTDbfString& strMemo)
|
|
{
|
|
|
|
|
|
if(!IsOpen())
|
|
return FALSE;
|
|
|
|
// TRY
|
|
// {
|
|
if(lOffsetRec > 0)
|
|
{
|
|
DBF_UINT nBlockCnt = (DBF_UINT) ceil(((double)(nLenMemo))/((double)m_SMTHead.block_size));
|
|
|
|
if(strMemo.IsEmpty())
|
|
{
|
|
DeleteMemoRecord(lOffsetRec, nBlockCnt);
|
|
lOffsetRec = 0;
|
|
}
|
|
else
|
|
{
|
|
DBF_UINT nNeedBlockCnt = (DBF_UINT) ceil(((double)(strMemo.GetLength()))/((double)m_SMTHead.block_size));
|
|
|
|
if(nBlockCnt != nNeedBlockCnt)
|
|
{
|
|
DeleteMemoRecord(lOffsetRec, nBlockCnt);
|
|
lOffsetRec = 0;
|
|
|
|
if(!UndeleteMemoRecord(lOffsetRec, strMemo))
|
|
lOffsetRec = AddMemoRecord(strMemo);
|
|
}
|
|
else
|
|
UpdateMemoRecord(lOffsetRec, strMemo);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(!UndeleteMemoRecord(lOffsetRec, strMemo))
|
|
lOffsetRec = AddMemoRecord(strMemo);
|
|
}
|
|
// }
|
|
// CATCH(CFileException, e)
|
|
// {
|
|
// e->ReportError();
|
|
// e->Delete();
|
|
//
|
|
// TGThrowDBFException(TG_DBF_ERROR_MEMO_FIELD_WRITE);
|
|
//
|
|
// } END_CATCH
|
|
return TRUE;
|
|
}
|
|
|
|
#ifdef _DEBUG
|
|
void CSMTMemoFile::AssertValid() const
|
|
{
|
|
CMemoFile::AssertValid();
|
|
}
|
|
|
|
void CSMTMemoFile::Dump(CDumpContext& dc) const
|
|
{
|
|
|
|
|
|
CMemoFile::Dump(dc);
|
|
|
|
dc << "m_SMTHead.next_block = " << m_SMTHead.next_block;
|
|
dc << "m_SMTHead.block_size = " << m_SMTHead.block_size;
|
|
dc << "m_SMTHead.description = " << m_SMTHead.description;
|
|
|
|
dc << "\n";
|
|
}
|
|
#endif //_DEBUG
|
|
|
|
DBF_LONG CSMTMemoFile::AddMemoRecord(CTDbfString& strMemo)
|
|
{
|
|
DBF_ULONG lOffsetRec = 0;
|
|
|
|
TRY
|
|
{
|
|
DBF_LONG nLenMemo = strMemo.GetLength();
|
|
|
|
lOffsetRec = (DBF_ULONG) ceil((double)GetLength() / (double)m_SMTHead.block_size);
|
|
|
|
Seek(lOffsetRec * m_SMTHead.block_size,CFile::begin);
|
|
|
|
Write(strMemo.toLPCSTR(), strMemo.GetLength());
|
|
|
|
ReadHeader();
|
|
|
|
m_SMTHead.next_block = (DBF_ULONG) ceil((double)GetLength() / (double)m_SMTHead.block_size);
|
|
|
|
WriteHeader();
|
|
}
|
|
CATCH(CFileException, e)
|
|
{
|
|
e->ReportError();
|
|
e->Delete();
|
|
|
|
} END_CATCH
|
|
|
|
return lOffsetRec;
|
|
}
|
|
|
|
void CSMTMemoFile::UpdateMemoRecord(DBF_ULONG lOffsetRec, CTDbfString& strMemo)
|
|
{
|
|
|
|
TRY
|
|
{
|
|
|
|
Seek(lOffsetRec * m_SMTHead.block_size,CFile::begin);
|
|
|
|
Write(strMemo.toLPCSTR(), strMemo.GetLength());
|
|
|
|
}
|
|
CATCH(CFileException, e)
|
|
{
|
|
e->ReportError();
|
|
e->Delete();
|
|
|
|
} END_CATCH
|
|
|
|
}
|
|
|
|
void CSMTMemoFile::DeleteMemoRecord(DBF_ULONG lDelRec, DBF_UINT nDelBlockCnt)
|
|
{
|
|
|
|
TRY
|
|
{
|
|
ReadHeader();
|
|
|
|
int rec_size = sizeof(DBF_UINT) + sizeof(DBF_ULONG);
|
|
|
|
int max_rec_cnt = sizeof(m_SMTHead.free_rec_ptr)/rec_size;
|
|
|
|
for(int i = 0; i < m_SMTHead.free_rec_count; i++)
|
|
{
|
|
DBF_UINT nCurFreeBlockCnt = 0;
|
|
DBF_ULONG lCurFreeRec = 0;
|
|
|
|
|
|
memcpy(&nCurFreeBlockCnt, m_SMTHead.free_rec_ptr + i * rec_size, sizeof(nCurFreeBlockCnt));
|
|
|
|
memcpy(&lCurFreeRec, m_SMTHead.free_rec_ptr + i * rec_size + sizeof(nCurFreeBlockCnt), sizeof(lCurFreeRec));
|
|
|
|
|
|
if(lDelRec + nDelBlockCnt == lCurFreeRec)
|
|
{
|
|
lCurFreeRec = lDelRec;
|
|
nCurFreeBlockCnt += nDelBlockCnt;
|
|
|
|
memcpy(m_SMTHead.free_rec_ptr + i * rec_size, &nCurFreeBlockCnt, sizeof(nCurFreeBlockCnt));
|
|
|
|
memcpy(m_SMTHead.free_rec_ptr + i * rec_size + sizeof(nCurFreeBlockCnt), &lCurFreeRec, sizeof(lCurFreeRec));
|
|
|
|
WriteHeader();
|
|
|
|
return;
|
|
}
|
|
else if(lDelRec < lCurFreeRec)
|
|
{
|
|
if(i < max_rec_cnt)
|
|
{
|
|
DBF_CHAR* buf = new DBF_CHAR[(m_SMTHead.free_rec_count - i) * rec_size];
|
|
|
|
memcpy(buf, m_SMTHead.free_rec_ptr + i * rec_size, (m_SMTHead.free_rec_count - i) * rec_size);
|
|
memcpy(m_SMTHead.free_rec_ptr + (i + 1) * rec_size, buf, (m_SMTHead.free_rec_count - i) * rec_size);
|
|
|
|
m_SMTHead.free_rec_count++;
|
|
|
|
delete[] buf;
|
|
}
|
|
|
|
memcpy(m_SMTHead.free_rec_ptr + i * rec_size, &nDelBlockCnt, sizeof(nDelBlockCnt));
|
|
|
|
memcpy(m_SMTHead.free_rec_ptr + i * rec_size + sizeof(nDelBlockCnt), &lDelRec, sizeof(lDelRec));
|
|
|
|
WriteHeader();
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
if(m_SMTHead.free_rec_count < max_rec_cnt)
|
|
{
|
|
int i = m_SMTHead.free_rec_count;
|
|
|
|
memcpy(m_SMTHead.free_rec_ptr + i * rec_size, &nDelBlockCnt, sizeof(nDelBlockCnt));
|
|
|
|
memcpy(m_SMTHead.free_rec_ptr + i * rec_size + sizeof(nDelBlockCnt), &lDelRec, sizeof(lDelRec));
|
|
|
|
m_SMTHead.free_rec_count++;
|
|
|
|
WriteHeader();
|
|
}
|
|
}
|
|
CATCH(CFileException, e)
|
|
{
|
|
e->ReportError();
|
|
e->Delete();
|
|
|
|
} END_CATCH
|
|
|
|
}
|
|
|
|
BOOL CSMTMemoFile::UndeleteMemoRecord(DBF_ULONG& lOffsetRec, CTDbfString& strMemo)
|
|
{
|
|
|
|
TRY
|
|
{
|
|
ReadHeader();
|
|
|
|
DBF_LONG lLenMemo = strMemo.GetLength();
|
|
|
|
DBF_UINT nNeedBlockCnt = (DBF_UINT) ceil((double)lLenMemo / (double)m_SMTHead.block_size);
|
|
|
|
int rec_size = sizeof(DBF_UINT) + sizeof(DBF_ULONG);
|
|
|
|
int max_rec_cnt = sizeof(m_SMTHead.free_rec_ptr)/rec_size;
|
|
|
|
for(int i = 0; i < m_SMTHead.free_rec_count; i++)
|
|
{
|
|
DBF_UINT nCurFreeBlockCnt = 0;
|
|
DBF_ULONG lCurFreeRec = 0;
|
|
|
|
memcpy(&nCurFreeBlockCnt, m_SMTHead.free_rec_ptr + i * rec_size, sizeof(nCurFreeBlockCnt));
|
|
|
|
memcpy(&lCurFreeRec, m_SMTHead.free_rec_ptr + i * rec_size + sizeof(nCurFreeBlockCnt), sizeof(lCurFreeRec));
|
|
|
|
if(nCurFreeBlockCnt > nNeedBlockCnt)
|
|
{
|
|
lOffsetRec = (lCurFreeRec + nCurFreeBlockCnt - nNeedBlockCnt);
|
|
|
|
Seek(lOffsetRec * m_SMTHead.block_size,CFile::begin);
|
|
|
|
Write(strMemo.toLPCSTR(), strMemo.GetLength());
|
|
|
|
nCurFreeBlockCnt -= nNeedBlockCnt;
|
|
|
|
memcpy(m_SMTHead.free_rec_ptr + i * rec_size, &nCurFreeBlockCnt, sizeof(nCurFreeBlockCnt));
|
|
|
|
WriteHeader();
|
|
|
|
return TRUE;
|
|
}
|
|
else if(nCurFreeBlockCnt == nNeedBlockCnt)
|
|
{
|
|
lOffsetRec = lCurFreeRec;
|
|
|
|
Seek(lOffsetRec * m_SMTHead.block_size,CFile::begin);
|
|
|
|
Write(strMemo.toLPCSTR(), strMemo.GetLength());
|
|
|
|
if(i == m_SMTHead.free_rec_count - 1)
|
|
{
|
|
lCurFreeRec = 0;
|
|
nCurFreeBlockCnt = 0;
|
|
|
|
memcpy(m_SMTHead.free_rec_ptr + i * rec_size, &nCurFreeBlockCnt, sizeof(nCurFreeBlockCnt));
|
|
|
|
memcpy(m_SMTHead.free_rec_ptr + i * rec_size + sizeof(nCurFreeBlockCnt), &lCurFreeRec, sizeof(lCurFreeRec));
|
|
}
|
|
else
|
|
{
|
|
DBF_CHAR* buf = new DBF_CHAR[(m_SMTHead.free_rec_count - i - 1) * rec_size];
|
|
|
|
memcpy(buf, m_SMTHead.free_rec_ptr + (i + 1) * rec_size, (m_SMTHead.free_rec_count - i - 1) * rec_size);
|
|
memcpy(m_SMTHead.free_rec_ptr + i * rec_size, buf, (m_SMTHead.free_rec_count - i - 1) * rec_size);
|
|
|
|
delete[] buf;
|
|
}
|
|
|
|
m_SMTHead.free_rec_count--;
|
|
|
|
WriteHeader();
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
CATCH(CFileException, e)
|
|
{
|
|
e->ReportError();
|
|
e->Delete();
|
|
|
|
} END_CATCH
|
|
|
|
return FALSE;
|
|
}
|