home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 23 / IOPROG_23.ISO / SOFT / VFORM.ZIP / Samples / vfTest / Recdb.h < prev    next >
Encoding:
C/C++ Source or Header  |  1998-10-10  |  8.8 KB  |  369 lines

  1. // -------------------------------------------------------------------------
  2. // Copyright @ 1997 TCK Software, Incorporated
  3. // All Rights Reserved
  4. // -------------------------------------------------------------------------
  5. #ifndef __RECDB_H__
  6. #define __RECDB_H__
  7.  
  8. #include <string.h>
  9.  
  10. // Parameterized Record DB class
  11. // This class represents a file of the typed records
  12. // Note: the records used must provide the following functions
  13. //            BOOL IsDeleted()
  14. //            void PreWrite()            // called just before writing
  15. //            void PreRead()            // called just after reading
  16.  
  17. template<class TYPE>
  18. class CRecDB
  19. {
  20. private:
  21.     int                m_recCnt;            // How many records
  22.     CString            m_fileName;            // filename
  23.     CFile            m_file;                // The disk file (contains the recs)
  24.     BOOL            m_bIsOpen;            // is the file currently open
  25.  
  26. public:
  27.     CRecDB()  { m_recCnt=0; m_bIsOpen=FALSE; }        // Constructor
  28.     ~CRecDB() {};                                    // Destructor
  29.  
  30.     int        GetCount()            { return m_recCnt; }
  31.     const CString&    FileName()    { return m_fileName; }
  32.     BOOL    IsOpen()            { return m_bIsOpen; }
  33.  
  34.     void    FileName(LPCTSTR x){ m_fileName = x; }
  35.  
  36.     BOOL    Open();                    // Opens the file, counts the recs
  37.     BOOL    OpenOrCreate();            // Opens/Creates the file, counts the recs
  38.     BOOL    Close();                // Closes the file
  39.     BOOL    GetRec(int xRecId, TYPE& xRec);        // retrieves the specified rec
  40.     BOOL    AddRec(int& xRecId, TYPE& xRec);    // adds a record to the file
  41.     BOOL    UpdateRec(int xRecId, TYPE& xRec);    // updates the specified rec
  42.     BOOL    Pack();                            // removes deleted records
  43.  
  44.     static void Replace(LPTSTR xP, int xLen, _TCHAR xFrom, _TCHAR xTo);
  45. };
  46.  
  47. // -------------------------------------------------------------------------
  48. //    Opens the flat file database full of records
  49. // -------------------------------------------------------------------------
  50. template<class TYPE>
  51. inline BOOL CRecDB<TYPE>::Open()
  52. {
  53.     CFileStatus status;
  54.     CFileException e;
  55.     long recSize = sizeof(TYPE);
  56.  
  57.     if(m_bIsOpen)
  58.     {
  59.         m_bIsOpen = FALSE;
  60.         m_file.Close();
  61.     }
  62.  
  63.     if(m_fileName.IsEmpty())
  64.         return FALSE;
  65.  
  66.     // First check the status of the file
  67.     if (!CFile::GetStatus(m_fileName, status))
  68.     {
  69.         // File does not exist
  70.         return FALSE;
  71.     }
  72.  
  73.     if(status.m_attribute & CFile::directory)    // File is a directory
  74.         return FALSE;
  75.  
  76.     // Make sure file size is a multiple of our rec size
  77.     if ((status.m_size % recSize) != 0)
  78.     {
  79.         return FALSE;                            // File is not of these records
  80.     }
  81.  
  82.     // Now attempt to open the file
  83.     if (!m_file.Open( m_fileName, CFile::typeBinary | 
  84.         CFile::modeReadWrite | CFile::shareExclusive, &e ))
  85.     {
  86.         return FALSE;
  87.     }
  88.  
  89.     // Count how many records are in the file
  90.     m_recCnt = status.m_size / recSize;
  91.     m_bIsOpen = TRUE;
  92.  
  93.     return TRUE;
  94. }
  95.  
  96. // -------------------------------------------------------------------------
  97. //    Opens the flat file database full of records
  98. // -------------------------------------------------------------------------
  99. template<class TYPE>
  100. inline BOOL CRecDB<TYPE>::OpenOrCreate()
  101. {
  102.     CFileStatus status;
  103.     CFileException e;
  104.     long recSize = sizeof(TYPE);
  105.  
  106.     if(m_bIsOpen)
  107.     {
  108.         m_bIsOpen = FALSE;
  109.         m_file.Close();
  110.     }
  111.  
  112.     if(m_fileName.IsEmpty())
  113.         return FALSE;
  114.  
  115.     // First check the status of the file
  116.     if (!CFile::GetStatus(m_fileName, status))
  117.     {
  118.         // File does not exist - Try to Create It
  119.         if (!m_file.Open( m_fileName, CFile::typeBinary | CFile::modeCreate |
  120.             CFile::modeReadWrite | CFile::shareExclusive, &e ))
  121.         {
  122.             return FALSE;
  123.         }
  124.         m_recCnt = 0;
  125.         m_bIsOpen = TRUE;
  126.         return TRUE;
  127.     }
  128.  
  129.     if(status.m_attribute & CFile::directory)    // File is a directory
  130.         return FALSE;
  131.  
  132.     // Make sure file size is a multiple of our rec size
  133.     if ((status.m_size % recSize) != 0)
  134.     {
  135.         return FALSE;                            // File is not of these records
  136.     }
  137.  
  138.     // Now attempt to open the file
  139.     if (!m_file.Open( m_fileName, CFile::typeBinary | 
  140.         CFile::modeReadWrite | CFile::shareExclusive, &e ))
  141.     {
  142.         return FALSE;
  143.     }
  144.  
  145.     // Count how many records are in the file
  146.     m_recCnt = status.m_size / recSize;
  147.     m_bIsOpen = TRUE;
  148.  
  149.     return TRUE;
  150. }
  151.  
  152.  
  153. // -------------------------------------------------------------------------
  154. //    Closes the flat file database
  155. // -------------------------------------------------------------------------
  156. template<class TYPE>
  157. inline BOOL CRecDB<TYPE>::Close()
  158. {
  159.     if(!m_bIsOpen)
  160.         return TRUE;
  161.  
  162.     m_bIsOpen = FALSE;
  163.     m_file.Close();
  164.  
  165.     return TRUE;
  166. }
  167.  
  168.  
  169. // -------------------------------------------------------------------------
  170. //    Retrieves the record located at the specified index
  171. // -------------------------------------------------------------------------
  172. template<class TYPE>
  173. inline BOOL CRecDB<TYPE>::GetRec(int xRecId, TYPE& xRec)
  174. {
  175.     // Check if record id is out of range
  176.     if(xRecId < 0 || xRecId >= m_recCnt)
  177.         return FALSE;
  178.  
  179.     long offset = xRecId * sizeof(xRec);
  180.  
  181.     m_file.Seek(offset, CFile::begin);
  182.  
  183.     // Read the rec from this DB file
  184.     try
  185.     {
  186.         if(m_file.Read(&xRec, sizeof(xRec)) != sizeof(xRec))
  187.             return FALSE;
  188.     }
  189.     catch (CFileException e)
  190.     {
  191.         return FALSE;
  192.     }
  193.  
  194.     // Call the classes OnRead() - to format for memory use
  195.     xRec.OnRead();
  196.     return TRUE;
  197. }
  198.  
  199.  
  200. // -------------------------------------------------------------------------
  201. //    Writes a record to the end of the file
  202. // -------------------------------------------------------------------------
  203. template<class TYPE>
  204. inline BOOL CRecDB<TYPE>::AddRec(int& xRecId, TYPE& xRec)
  205. {
  206.     TYPE tmpRec(xRec);                            // make a copy of the record
  207.  
  208.     m_file.SeekToEnd();
  209.     long offset = m_file.GetPosition();
  210.  
  211.     // Calculate record ID
  212.     xRecId = offset / sizeof(xRec);
  213.  
  214.     // Call the classes OnWrite() - to format for disk file
  215.     tmpRec.OnWrite();                
  216.  
  217.     // Add the rec to this DB file
  218.     try
  219.     {
  220.         m_file.Write(&tmpRec, sizeof(tmpRec));
  221.     }
  222.     catch (CFileException e)
  223.     {
  224.         return FALSE;
  225.     }
  226.  
  227.     m_recCnt++;                // Increment the record count
  228.  
  229.     ASSERT(m_recCnt == xRecId + 1);
  230.  
  231.     return TRUE;
  232. }
  233.  
  234. // -------------------------------------------------------------------------
  235. //    Overwrites (Updates) the record at the specified index
  236. // -------------------------------------------------------------------------
  237. template<class TYPE>
  238. inline BOOL CRecDB<TYPE>::UpdateRec(int xRecId, TYPE& xRec)
  239. {
  240.     long offset = xRecId * sizeof(xRec);
  241.     TYPE tmpRec(xRec);                        // make a copy of the record
  242.  
  243.     // Call the classes OnWrite() - to format for disk file
  244.     tmpRec.OnWrite();                
  245.  
  246.     // Get the correct file position
  247.     m_file.Seek(offset, CFile::begin);
  248.  
  249.     // Overwrite the old rec
  250.     try
  251.     {
  252.         m_file.Write(&tmpRec, sizeof(tmpRec));
  253.     }
  254.     catch (CFileException e)
  255.     {
  256.         return FALSE;
  257.     }
  258.  
  259.     return TRUE;
  260. }
  261.  
  262. // -------------------------------------------------------------------------
  263. //    Remove all Deleted Records
  264. // -------------------------------------------------------------------------
  265. template<class TYPE>
  266. inline BOOL CRecDB<TYPE>::Pack()
  267. {
  268.     // _TCHAR szTmpPath[MAX_PATH];
  269.     _TCHAR szTmpFile[MAX_PATH];
  270.     CString s1, sOrigPath;
  271.     CFile    tmpFile;
  272.     CFileException e;
  273.     TYPE    rec;
  274.     int        rc, idx;
  275.  
  276.     if(!IsOpen())
  277.         return FALSE;
  278.  
  279.     // Open a new temporary file
  280.     s1 = m_file.GetFilePath();        // returns path and filename
  281.     idx = s1.ReverseFind('\\');
  282.     if(idx < 1)
  283.         return FALSE;
  284.  
  285.     sOrigPath = s1.Left(idx+1);                // extract the path only
  286.  
  287.     // rc = GetTempPath(szTmpPath, MAX_PATH);
  288.     // if(rc == 0 || rc > MAX_PATH)    return FALSE;
  289.     GetTempFileName(sOrigPath, _T("tmp"), 0, szTmpFile);
  290.  
  291.     rc = tmpFile.Open(szTmpFile,
  292.         CFile::modeWrite | CFile::shareExclusive | CFile::modeCreate,
  293.         &e);
  294.  
  295.     // Read each record, writing to the new file
  296.     m_file.SeekToBegin();
  297.  
  298.     while(1)
  299.     {
  300.         try
  301.         {
  302.             if (m_file.Read(&rec, sizeof(rec)) != sizeof(rec))
  303.                 break;        // weve hit the end of the file
  304.         }
  305.         catch (CFileException* e)
  306.         {
  307.             e->ReportError();
  308.             e->Delete();
  309.             return FALSE;
  310.         }
  311.  
  312.         if(rec.IsDeleted()) continue;    // remove deleted ones
  313.  
  314.         try
  315.         {
  316.             tmpFile.Write(&rec, sizeof(rec));
  317.         }
  318.         catch (CFileException* e)
  319.         {
  320.             e->ReportError();
  321.             e->Delete();
  322.             return FALSE;
  323.         }
  324.     }
  325.     
  326.     // Delete the old DB file
  327.     Close();
  328.     tmpFile.Close();
  329.     try
  330.     {
  331.         m_file.Remove(m_fileName);
  332.     }
  333.     catch(CFileException* e) 
  334.     {
  335.         e->ReportError();
  336.         e->Delete();
  337.         return FALSE;
  338.     }
  339.  
  340.     // Rename the temp file to the DB file name
  341.     try
  342.     {
  343.         CFile::Rename(szTmpFile, m_fileName);
  344.     }
  345.     catch(CFileException* e)
  346.     {
  347.         e->ReportError();
  348.         e->Delete();
  349.         return FALSE;
  350.     }
  351.  
  352.     // Re open the renamed file
  353.     if(!Open())    return FALSE;
  354.  
  355.     return TRUE;
  356. }
  357.  
  358.  
  359. // -------------------------------------------------------------------------
  360. // This function replaces all of one char in a string with another
  361. // -------------------------------------------------------------------------
  362. inline void RecDB_Replace(LPTSTR xP, int xLen, _TCHAR xFrom, _TCHAR xTo)
  363. {
  364.     for(int i=0; i < xLen; i++)
  365.         if (xP[i] == xFrom)
  366.             xP[i] = xTo;
  367. }
  368.  
  369. #endif