|
|
1.1 root 1: // database.cpp : Defines the behaviors for the CDataBase class.
2: //
3: // This is a part of the Microsoft Foundation Classes C++ library.
4: // Copyright (C) 1992 Microsoft Corporation
5: // All rights reserved.
6: //
7: // This source code is only intended as a supplement to the
8: // Microsoft Foundation Classes Reference and Microsoft
9: // QuickHelp documentation provided with the library.
10: // See these sources for detailed information regarding the
11: // Microsoft Foundation Classes product.
12:
13: #include "database.h"
14: #include <string.h>
15:
16: #ifdef _DEBUG
17: #undef THIS_FILE
18: static char BASED_CODE THIS_FILE[] = __FILE__;
19: #endif
20:
21: const char szUntitled[] = "Untitled";
22:
23: //////////////////////////////////////////////////////////////////////////
24: // CDataBase
25: //
26:
27: //////////////////////////////////////////////////
28: // CDataBase::New
29: // Initializes the database.
30: //
31: BOOL CDataBase::New()
32: {
33: ASSERT_VALID( this );
34:
35: // Clean up any old data.
36: Terminate();
37:
38: m_pDataList = new CPersonList;
39:
40: return ( m_pDataList != NULL );
41: }
42:
43: //////////////////////////////////////////////////
44: // CDataBase::Terminate
45: // Cleans up the database.
46: //
47: void CDataBase::Terminate()
48: {
49: ASSERT_VALID( this );
50:
51: if ( m_pDataList != NULL )
52: m_pDataList->DeleteAll();
53:
54: delete m_pDataList;
55: delete m_pFindList;
56:
57: m_pDataList = NULL;
58: m_pFindList = NULL;
59:
60: m_szFileName = szUntitled;
61: m_szFileTitle = szUntitled;
62: }
63:
64: //////////////////////////////////////////////////
65: // CDataBase::AddPerson
66: // Inserts a person in the appropriate position (alphabetically by last
67: // name) in the database.
68: //
69: void CDataBase::AddPerson( CPerson* pNewPerson )
70: {
71: ASSERT_VALID( this );
72: ASSERT_VALID( pNewPerson );
73: ASSERT( pNewPerson != NULL );
74: ASSERT( m_pDataList != NULL );
75:
76: POSITION pos = m_pDataList->GetHeadPosition();
77: while ( pos != NULL &&
78: _stricmp( ((CPerson*)m_pDataList->GetAt(pos))->GetLastName(),
79: pNewPerson->GetLastName() ) <= 0 )
80: m_pDataList->GetNext( pos );
81:
82: if ( pos == NULL )
83: m_pDataList->AddTail( pNewPerson );
84: else
85: m_pDataList->InsertBefore( pos, pNewPerson );
86:
87: m_pDataList->SetDirty( TRUE );
88: }
89:
90: //////////////////////////////////////////////////
91: // CDataBase::GetPerson
92: // Look up someone by index.
93: //
94: CPerson* CDataBase::GetPerson( int nIndex )
95: {
96: ASSERT_VALID( this );
97: ASSERT( m_pDataList != NULL );
98:
99: if ( m_pFindList != NULL )
100: return (CPerson*)m_pFindList->GetAt( m_pFindList->FindIndex( nIndex ) );
101: else
102: return (CPerson*)m_pDataList->GetAt( m_pDataList->FindIndex( nIndex ) );
103: }
104:
105: //////////////////////////////////////////////////
106: // CDatabase::DeletePerson
107: // Removes record of person from database.
108: //
109: void CDataBase::DeletePerson( int nIndex )
110: {
111: ASSERT_VALID( this );
112: ASSERT( m_pDataList != NULL );
113:
114: POSITION el = m_pDataList->FindIndex( nIndex );
115: delete m_pDataList->GetAt( el );
116: m_pDataList->RemoveAt( el );
117: m_pDataList->SetDirty( TRUE );
118: }
119:
120: //////////////////////////////////////////////////
121: // CDatabase::ReplacePerson
122: // Replaces an object in the list with the new object.
123: //
124: void CDataBase::ReplacePerson( CPerson* pOldPerson, const CPerson& rNewPerson )
125: {
126: ASSERT_VALID( this );
127:
128: ASSERT( pOldPerson != NULL );
129: ASSERT( m_pDataList != NULL );
130:
131: // Using the overloaded operator= for CPerson
132: *pOldPerson = rNewPerson;
133: m_pDataList->SetDirty( TRUE );
134: }
135:
136: //////////////////////////////////////////////////
137: // CDataBase::DoFind
138: // Does a FindPerson call, or clears the find data.
139: //
140: BOOL CDataBase::DoFind( const char* pszLastName /* = NULL */ )
141: {
142: ASSERT_VALID( this );
143: ASSERT( m_pDataList != NULL );
144:
145: if ( pszLastName == NULL )
146: {
147: delete m_pFindList;
148: m_pFindList = NULL;
149: return FALSE;
150: }
151:
152: // The interface should not allow a second find to occur while
153: // we already have one.
154: ASSERT( m_pFindList == NULL );
155: return ( ( m_pFindList = m_pDataList->FindPerson( pszLastName ) ) != NULL );
156: }
157:
158: //////////////////////////////////////////////////
159: // CDataBase::DoOpen
160: // Reads a database from the given filename.
161: //
162: BOOL CDataBase::DoOpen( const char* pszFileName )
163: {
164: ASSERT_VALID( this );
165: ASSERT( pszFileName != NULL );
166:
167: CFile file( pszFileName, CFile::modeRead );
168:
169: // read the object data from file
170: CPersonList* pNewDataBase = ReadDataBase( &file );
171:
172: file.Close();
173:
174: // get rid of current data base if new one is OK
175: if ( pNewDataBase != NULL )
176: {
177: Terminate();
178: m_pDataList = pNewDataBase;
179: m_pDataList->SetDirty( FALSE );
180:
181: m_szFileName = pszFileName;
182: return TRUE;
183: }
184: else
185: return FALSE;
186: }
187:
188: //////////////////////////////////////////////////
189: // CDataBase::DoSave
190: // Saves the database to the given file.
191: //
192: BOOL CDataBase::DoSave( const char* pszFileName /* = NULL */ )
193: {
194: ASSERT_VALID( this );
195:
196: // if we were given a name store it in the object.
197: if ( pszFileName != NULL )
198: m_szFileName = pszFileName;
199:
200: CFileStatus status;
201: int nAccess = CFile::modeWrite;
202:
203: // GetStatus will return TRUE if file exists, or FALSE if it doesn't.
204: if ( !CFile::GetStatus( m_szFileName, status ) )
205: nAccess |= CFile::modeCreate;
206:
207: CFile file( m_szFileName, nAccess );
208:
209: // write the data base to a file
210: // mark it clean if write is successful
211: if ( WriteDataBase( &file ) )
212: {
213: m_pDataList->SetDirty( FALSE );
214: file.Close();
215: return TRUE;
216: }
217: else
218: {
219: file.Close();
220: return FALSE;
221: }
222: }
223:
224: //////////////////////////////////////////////////
225: // CDataBase::ReadDataBase
226: // Serializes in the database.
227: //
228: CPersonList* CDataBase::ReadDataBase( CFile* pFile )
229: {
230: ASSERT_VALID( this );
231: CPersonList* pNewDataBase = NULL;
232:
233: // Create a archive from pFile for reading.
234: CArchive archive( pFile, CArchive::load );
235:
236: // Deserialize the new data base from the archive, or catch the
237: // exception.
238: TRY
239: {
240: archive >> pNewDataBase;
241: }
242: CATCH( CArchiveException, e )
243: {
244: #ifdef _DEBUG
245: e->Dump( afxDump );
246: #endif
247: archive.Close();
248:
249: // If we got part of the database, then delete it.
250: if ( pNewDataBase != NULL )
251: {
252: pNewDataBase->DeleteAll();
253: delete pNewDataBase;
254: }
255:
256: // We caught this exception, but we throw it again so our caller can
257: // also catch it.
258: THROW_LAST();
259: }
260: END_CATCH
261:
262: // Exit here if no errors or exceptions.
263: archive.Close();
264: return pNewDataBase;
265: }
266:
267: //////////////////////////////////////////////////
268: // CDataBase::WriteDataBase
269: // Serializes out the data into the given file.
270: //
271: BOOL CDataBase::WriteDataBase( CFile* pFile )
272: {
273: ASSERT_VALID( this );
274: ASSERT( m_pDataList != NULL );
275:
276: // Create a archive from theFile for writing
277: CArchive archive( pFile, CArchive::store );
278:
279: // Archive out, or catch the exception.
280: TRY
281: {
282: archive << m_pDataList;
283: }
284: CATCH( CArchiveException, e )
285: {
286: #ifdef _DEBUG
287: e->Dump( afxDump );
288: #endif
289: archive.Close();
290:
291: // Throw this exception again for the benefit of our caller.
292: THROW_LAST();
293: }
294: END_CATCH
295:
296: // Exit here if no errors or exceptions.
297: archive.Close();
298: return TRUE;
299: }
300:
301: #ifdef _DEBUG
302: void CDataBase::AssertValid() const
303: {
304: if ( m_pDataList != NULL )
305: {
306: ASSERT_VALID( m_pDataList );
307: if ( m_pFindList != NULL )
308: ASSERT_VALID( m_pFindList );
309: }
310: else
311: ASSERT( m_pFindList == NULL );
312: }
313: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.