home *** CD-ROM | disk | FTP | other *** search
- // -------------------------------------------------------------------------
- // Copyright @ 1997 TCK Software, Incorporated
- // All Rights Reserved
- // -------------------------------------------------------------------------
- #ifndef __RECDB_H__
- #define __RECDB_H__
-
- #include <string.h>
-
- // Parameterized Record DB class
- // This class represents a file of the typed records
- // Note: the records used must provide the following functions
- // BOOL IsDeleted()
- // void PreWrite() // called just before writing
- // void PreRead() // called just after reading
-
- template<class TYPE>
- class CRecDB
- {
- private:
- int m_recCnt; // How many records
- CString m_fileName; // filename
- CFile m_file; // The disk file (contains the recs)
- BOOL m_bIsOpen; // is the file currently open
-
- public:
- CRecDB() { m_recCnt=0; m_bIsOpen=FALSE; } // Constructor
- ~CRecDB() {}; // Destructor
-
- int GetCount() { return m_recCnt; }
- const CString& FileName() { return m_fileName; }
- BOOL IsOpen() { return m_bIsOpen; }
-
- void FileName(LPCTSTR x){ m_fileName = x; }
-
- BOOL Open(); // Opens the file, counts the recs
- BOOL OpenOrCreate(); // Opens/Creates the file, counts the recs
- BOOL Close(); // Closes the file
- BOOL GetRec(int xRecId, TYPE& xRec); // retrieves the specified rec
- BOOL AddRec(int& xRecId, TYPE& xRec); // adds a record to the file
- BOOL UpdateRec(int xRecId, TYPE& xRec); // updates the specified rec
- BOOL Pack(); // removes deleted records
-
- static void Replace(LPTSTR xP, int xLen, _TCHAR xFrom, _TCHAR xTo);
- };
-
- // -------------------------------------------------------------------------
- // Opens the flat file database full of records
- // -------------------------------------------------------------------------
- template<class TYPE>
- inline BOOL CRecDB<TYPE>::Open()
- {
- CFileStatus status;
- CFileException e;
- long recSize = sizeof(TYPE);
-
- if(m_bIsOpen)
- {
- m_bIsOpen = FALSE;
- m_file.Close();
- }
-
- if(m_fileName.IsEmpty())
- return FALSE;
-
- // First check the status of the file
- if (!CFile::GetStatus(m_fileName, status))
- {
- // File does not exist
- return FALSE;
- }
-
- if(status.m_attribute & CFile::directory) // File is a directory
- return FALSE;
-
- // Make sure file size is a multiple of our rec size
- if ((status.m_size % recSize) != 0)
- {
- return FALSE; // File is not of these records
- }
-
- // Now attempt to open the file
- if (!m_file.Open( m_fileName, CFile::typeBinary |
- CFile::modeReadWrite | CFile::shareExclusive, &e ))
- {
- return FALSE;
- }
-
- // Count how many records are in the file
- m_recCnt = status.m_size / recSize;
- m_bIsOpen = TRUE;
-
- return TRUE;
- }
-
- // -------------------------------------------------------------------------
- // Opens the flat file database full of records
- // -------------------------------------------------------------------------
- template<class TYPE>
- inline BOOL CRecDB<TYPE>::OpenOrCreate()
- {
- CFileStatus status;
- CFileException e;
- long recSize = sizeof(TYPE);
-
- if(m_bIsOpen)
- {
- m_bIsOpen = FALSE;
- m_file.Close();
- }
-
- if(m_fileName.IsEmpty())
- return FALSE;
-
- // First check the status of the file
- if (!CFile::GetStatus(m_fileName, status))
- {
- // File does not exist - Try to Create It
- if (!m_file.Open( m_fileName, CFile::typeBinary | CFile::modeCreate |
- CFile::modeReadWrite | CFile::shareExclusive, &e ))
- {
- return FALSE;
- }
- m_recCnt = 0;
- m_bIsOpen = TRUE;
- return TRUE;
- }
-
- if(status.m_attribute & CFile::directory) // File is a directory
- return FALSE;
-
- // Make sure file size is a multiple of our rec size
- if ((status.m_size % recSize) != 0)
- {
- return FALSE; // File is not of these records
- }
-
- // Now attempt to open the file
- if (!m_file.Open( m_fileName, CFile::typeBinary |
- CFile::modeReadWrite | CFile::shareExclusive, &e ))
- {
- return FALSE;
- }
-
- // Count how many records are in the file
- m_recCnt = status.m_size / recSize;
- m_bIsOpen = TRUE;
-
- return TRUE;
- }
-
-
- // -------------------------------------------------------------------------
- // Closes the flat file database
- // -------------------------------------------------------------------------
- template<class TYPE>
- inline BOOL CRecDB<TYPE>::Close()
- {
- if(!m_bIsOpen)
- return TRUE;
-
- m_bIsOpen = FALSE;
- m_file.Close();
-
- return TRUE;
- }
-
-
- // -------------------------------------------------------------------------
- // Retrieves the record located at the specified index
- // -------------------------------------------------------------------------
- template<class TYPE>
- inline BOOL CRecDB<TYPE>::GetRec(int xRecId, TYPE& xRec)
- {
- // Check if record id is out of range
- if(xRecId < 0 || xRecId >= m_recCnt)
- return FALSE;
-
- long offset = xRecId * sizeof(xRec);
-
- m_file.Seek(offset, CFile::begin);
-
- // Read the rec from this DB file
- try
- {
- if(m_file.Read(&xRec, sizeof(xRec)) != sizeof(xRec))
- return FALSE;
- }
- catch (CFileException e)
- {
- return FALSE;
- }
-
- // Call the classes OnRead() - to format for memory use
- xRec.OnRead();
- return TRUE;
- }
-
-
- // -------------------------------------------------------------------------
- // Writes a record to the end of the file
- // -------------------------------------------------------------------------
- template<class TYPE>
- inline BOOL CRecDB<TYPE>::AddRec(int& xRecId, TYPE& xRec)
- {
- TYPE tmpRec(xRec); // make a copy of the record
-
- m_file.SeekToEnd();
- long offset = m_file.GetPosition();
-
- // Calculate record ID
- xRecId = offset / sizeof(xRec);
-
- // Call the classes OnWrite() - to format for disk file
- tmpRec.OnWrite();
-
- // Add the rec to this DB file
- try
- {
- m_file.Write(&tmpRec, sizeof(tmpRec));
- }
- catch (CFileException e)
- {
- return FALSE;
- }
-
- m_recCnt++; // Increment the record count
-
- ASSERT(m_recCnt == xRecId + 1);
-
- return TRUE;
- }
-
- // -------------------------------------------------------------------------
- // Overwrites (Updates) the record at the specified index
- // -------------------------------------------------------------------------
- template<class TYPE>
- inline BOOL CRecDB<TYPE>::UpdateRec(int xRecId, TYPE& xRec)
- {
- long offset = xRecId * sizeof(xRec);
- TYPE tmpRec(xRec); // make a copy of the record
-
- // Call the classes OnWrite() - to format for disk file
- tmpRec.OnWrite();
-
- // Get the correct file position
- m_file.Seek(offset, CFile::begin);
-
- // Overwrite the old rec
- try
- {
- m_file.Write(&tmpRec, sizeof(tmpRec));
- }
- catch (CFileException e)
- {
- return FALSE;
- }
-
- return TRUE;
- }
-
- // -------------------------------------------------------------------------
- // Remove all Deleted Records
- // -------------------------------------------------------------------------
- template<class TYPE>
- inline BOOL CRecDB<TYPE>::Pack()
- {
- // _TCHAR szTmpPath[MAX_PATH];
- _TCHAR szTmpFile[MAX_PATH];
- CString s1, sOrigPath;
- CFile tmpFile;
- CFileException e;
- TYPE rec;
- int rc, idx;
-
- if(!IsOpen())
- return FALSE;
-
- // Open a new temporary file
- s1 = m_file.GetFilePath(); // returns path and filename
- idx = s1.ReverseFind('\\');
- if(idx < 1)
- return FALSE;
-
- sOrigPath = s1.Left(idx+1); // extract the path only
-
- // rc = GetTempPath(szTmpPath, MAX_PATH);
- // if(rc == 0 || rc > MAX_PATH) return FALSE;
- GetTempFileName(sOrigPath, _T("tmp"), 0, szTmpFile);
-
- rc = tmpFile.Open(szTmpFile,
- CFile::modeWrite | CFile::shareExclusive | CFile::modeCreate,
- &e);
-
- // Read each record, writing to the new file
- m_file.SeekToBegin();
-
- while(1)
- {
- try
- {
- if (m_file.Read(&rec, sizeof(rec)) != sizeof(rec))
- break; // weve hit the end of the file
- }
- catch (CFileException* e)
- {
- e->ReportError();
- e->Delete();
- return FALSE;
- }
-
- if(rec.IsDeleted()) continue; // remove deleted ones
-
- try
- {
- tmpFile.Write(&rec, sizeof(rec));
- }
- catch (CFileException* e)
- {
- e->ReportError();
- e->Delete();
- return FALSE;
- }
- }
-
- // Delete the old DB file
- Close();
- tmpFile.Close();
- try
- {
- m_file.Remove(m_fileName);
- }
- catch(CFileException* e)
- {
- e->ReportError();
- e->Delete();
- return FALSE;
- }
-
- // Rename the temp file to the DB file name
- try
- {
- CFile::Rename(szTmpFile, m_fileName);
- }
- catch(CFileException* e)
- {
- e->ReportError();
- e->Delete();
- return FALSE;
- }
-
- // Re open the renamed file
- if(!Open()) return FALSE;
-
- return TRUE;
- }
-
-
- // -------------------------------------------------------------------------
- // This function replaces all of one char in a string with another
- // -------------------------------------------------------------------------
- inline void RecDB_Replace(LPTSTR xP, int xLen, _TCHAR xFrom, _TCHAR xTo)
- {
- for(int i=0; i < xLen; i++)
- if (xP[i] == xFrom)
- xP[i] = xTo;
- }
-
- #endif