]> git.mxchange.org Git - simgear.git/blob - simgear/scene/sky/clouds3d/SkyArchive.cpp
Tweak lib name.
[simgear.git] / simgear / scene / sky / clouds3d / SkyArchive.cpp
1 //------------------------------------------------------------------------------
2 // File : SkyArchive.cpp
3 //------------------------------------------------------------------------------
4 // SkyWorks : Copyright 2002 Mark J. Harris and
5 //                                              The University of North Carolina at Chapel Hill
6 //------------------------------------------------------------------------------
7 // Permission to use, copy, modify, distribute and sell this software and its 
8 // documentation for any purpose is hereby granted without fee, provided that 
9 // the above copyright notice appear in all copies and that both that copyright 
10 // notice and this permission notice appear in supporting documentation. 
11 // Binaries may be compiled with this software without any royalties or 
12 // restrictions. 
13 //
14 // The author(s) and The University of North Carolina at Chapel Hill make no 
15 // representations about the suitability of this software for any purpose. 
16 // It is provided "as is" without express or 
17 // implied warranty.
18 /**
19  * @file SkyArchive.cpp
20  * 
21  * Implementation of class SkyArchive.
22  */
23 #include "SkyArchive.hpp"
24
25 #include <assert.h>
26
27 struct SkyArchiveEntry
28 {
29   SkyArchiveEntry() : type(0), pData(NULL), iDataSize(0) {}
30   unsigned char type;
31   void*         pData;
32   unsigned int  iDataSize;
33 };
34
35 struct SkyArchiveFileEntry
36 {
37   SkyArchiveFileEntry() : type(0), iDataSize(0) {}
38   unsigned char type;
39   char          pName[32];
40   unsigned int  iDataSize;
41 };
42
43
44 //------------------------------------------------------------------------------
45 // Function               : SkyArchive::SkyArchive
46 // Description      : 
47 //------------------------------------------------------------------------------
48 /**
49  * @fn SkyArchive::SkyArchive()
50  * @brief Default constructor.  Creates an empty, unnamed archive.                                             |
51  */ 
52 SkyArchive::SkyArchive()
53 : _pName(NULL)
54 {
55 }
56
57
58 //------------------------------------------------------------------------------
59 // Function               : SkyArchive::SkyArchive
60 // Description      : 
61 //------------------------------------------------------------------------------
62 /**
63  * @fn SkyArchive::SkyArchive(const char* pName)
64  * @brief Constructor.  Creates an empty, named archive. 
65  */ 
66 SkyArchive::SkyArchive(const char* pName)
67 {
68   _pName = new char[::strlen(pName)+1];
69   ::strcpy( _pName, pName);  
70 }
71
72
73 //.---------------------------------------------------------------------------.
74 //|   Function   : SkyArchive::SkyArchive                                 |
75 //|   Description: 
76 //.---------------------------------------------------------------------------.
77
78 //------------------------------------------------------------------------------
79 // Function               : SkyArchive::SkyArchive
80 // Description      : 
81 //------------------------------------------------------------------------------
82 /**
83  * @fn SkyArchive::SkyArchive(const SkyArchive& src)
84  * @brief Copy constructor.  Deep-copies the contents of one archive to another.
85  */ 
86 SkyArchive::SkyArchive(const SkyArchive& src)
87 {  
88   _pName = new char[::strlen(src._pName)+1];
89   ::strcpy( _pName, src._pName);
90   
91   _CopyDataTable( src._dataTable);
92 }
93
94 //------------------------------------------------------------------------------
95 // Function               : SkyArchive::~SkyArchive
96 // Description      : 
97 //------------------------------------------------------------------------------
98 /**
99  * @fn SkyArchive::~SkyArchive()
100  * @brief Destructor.
101  */ 
102 SkyArchive::~SkyArchive()
103 {
104   MakeEmpty();
105   SAFE_DELETE_ARRAY(_pName);
106 }
107
108
109 //.---------------------------------------------------------------------------.
110 //|   Function   : SkyArchive::operator=                                    |
111 //|   Description: |
112 //.---------------------------------------------------------------------------.
113
114 //------------------------------------------------------------------------------
115 // Function               : SkyArchive::operator=
116 // Description      : 
117 //------------------------------------------------------------------------------
118 /**
119  * @fn SkyArchive::operator=( const SkyArchive& src)
120  * @brief @todo Deep-copies the contents of one archive to another.
121  */ 
122 SkyArchive& SkyArchive::operator=( const SkyArchive& src)
123 {
124   if (this != &src)
125   {
126     MakeEmpty();
127     SAFE_DELETE_ARRAY(_pName);
128     _pName = new char[::strlen(src._pName)+1];
129     ::strcpy( _pName, src.GetName());
130     
131     _CopyDataTable( src._dataTable);
132   }
133   return *this;
134 }
135
136
137
138 //=============================================================================
139 //  Adding Content to SkyArchive
140 //=============================================================================
141
142 //------------------------------------------------------------------------------
143 // Function               : SkyArchive::AddData
144 // Description      : 
145 //------------------------------------------------------------------------------
146 /**
147 * @fn SkyArchive::AddData(const char*         pName, 
148 SkyArchiveTypeCode  eType, 
149 const void*         pData, 
150 unsigned int        iNumBytes, 
151 unsigned int        iNumItems)
152 * @brief Adds a new data field to the archive.
153
154 * Makes a copy of the data, stores it in a SkyArchiveEntry, and adds it to the
155 * database.  All specialized functions for the base types are implemented using 
156 * this function.
157
158 * PARAMETERS
159 * @param name Field name.  This is used as the key for the database entry.
160 * @param type Data type of the field.
161 * @param pData Pointer to the data to be added to the archive.
162 * @param iNumBytes Size of each individual item in the data
163 * @param iNumItems Number of items to copy                                  
164 */
165 SKYRESULT SkyArchive::AddData(const char*         pName, 
166                               SkyArchiveTypeCode  eType, 
167                               const void*         pData, 
168                               unsigned int        iNumBytes, 
169                               unsigned int        iNumItems /* = 1 */)
170 {
171   // fill out a new archive entry with the supplied data
172   SkyArchiveEntry* pNewEntry  = new SkyArchiveEntry;
173   pNewEntry->type             = eType;
174   pNewEntry->iDataSize        = iNumBytes * iNumItems;
175   
176   if (eType != ARCHIVE_TYPE)
177   {
178     pNewEntry->pData = new unsigned char[pNewEntry->iDataSize];
179     ::memcpy(pNewEntry->pData, pData, pNewEntry->iDataSize);
180   }
181   else
182   {
183     pNewEntry->pData = (void*)pData;
184   }
185   
186   char* pInternalName = new char[::strlen(pName)+1];
187   ::strcpy( pInternalName, pName);
188   _dataTable.insert(std::make_pair(pInternalName, pNewEntry));
189   
190   return SKYRESULT_OK;
191 }
192
193
194 //-----------------------------------------------------------------------------
195 //  SkyArchive :: AddBool( const char* pName, bool aBool)
196 //  SkyArchive :: AddInt8( const char* pName, Int8 anInt8)
197 //  SkyArchive :: AddInt16( const char* pName, Int16 anInt16)
198 //  SkyArchive :: AddInt32( const char* pName, Int32 anInt32)
199 //  ...
200 //-----------------------------------------------------------------------------
201 //
202 //  Specialized functions for the most common base types
203 //  
204 //-----------------------------------------------------------------------------
205
206
207 //------------------------------------------------------------------------------
208 // Function               : SkyArchive::AddBool
209 // Description      : 
210 //------------------------------------------------------------------------------
211 /**
212  * @fn SkyArchive::AddBool(const char* pName, bool aBool)
213  * @brief Adds a named bool to the archive.
214  */ 
215 SKYRESULT SkyArchive::AddBool(const char* pName, bool aBool)
216 {
217   return AddData( pName, BOOL_TYPE, &aBool, sizeof(bool));
218 }
219
220 //------------------------------------------------------------------------------
221 // Function               : SkyArchive::AddInt8
222 // Description      : 
223 //------------------------------------------------------------------------------
224 /**
225  * @fn SkyArchive::AddInt8(const char* pName, char anInt8)
226  * @brief Adds a named 8-bit integer to the archive.
227  */ 
228 SKYRESULT SkyArchive::AddInt8(const char* pName, char anInt8)
229 {
230   return AddData( pName, INT8_TYPE, &anInt8, sizeof(char));
231 }
232
233 //------------------------------------------------------------------------------
234 // Function               : SkyArchive::AddInt16
235 // Description      : 
236 //------------------------------------------------------------------------------
237 /**
238  * @fn SkyArchive::AddInt16(const char* pName, short anInt16)
239  * @brief Adds a named 16-bit integer to the archive.
240  */ 
241 SKYRESULT SkyArchive::AddInt16(const char* pName, short anInt16)
242 {
243   return AddData( pName, INT16_TYPE, &anInt16, sizeof(short));
244 }
245
246 //------------------------------------------------------------------------------
247 // Function               : SkyArchive::AddInt32
248 // Description      : 
249 //------------------------------------------------------------------------------
250 /**
251  * @fn SkyArchive::AddInt32(const char* pName, int anInt32)
252  * @brief Adds a named 32-bit integer to the archive.
253  */ 
254 SKYRESULT SkyArchive::AddInt32(const char* pName, int anInt32)
255 {
256   return AddData( pName, INT32_TYPE, &anInt32, sizeof(int));
257 }
258
259 //------------------------------------------------------------------------------
260 // Function               : SkyArchive::AddUInt8
261 // Description      : 
262 //------------------------------------------------------------------------------
263 /**
264  * @fn SkyArchive::AddUInt8(const char* pName, unsigned char anUInt8)
265  * @brief Adds a named unsigned 8-bit integer to the archive.
266  */ 
267 SKYRESULT SkyArchive::AddUInt8(const char* pName, unsigned char anUInt8)
268 {
269   return AddData( pName, UINT8_TYPE, &anUInt8, sizeof(unsigned char));
270 }
271
272 //------------------------------------------------------------------------------
273 // Function               : SkyArchive::AddUInt16
274 // Description      : 
275 //------------------------------------------------------------------------------
276 /**
277  * @fn SkyArchive::AddUInt16(const char* pName, unsigned short anUInt16)
278  * @brief Adds a named unsigned 16-bit integer to the archive.
279  */ 
280 SKYRESULT SkyArchive::AddUInt16(const char* pName, unsigned short anUInt16)
281 {
282   return AddData( pName, UINT16_TYPE, &anUInt16, sizeof(unsigned short));
283 }
284
285 //------------------------------------------------------------------------------
286 // Function               : SkyArchive::AddUInt32
287 // Description      : 
288 //------------------------------------------------------------------------------
289 /**
290  * @fn SkyArchive::AddUInt32(const char* pName, unsigned int anUInt32)
291  * @brief Adds a named unsigned 32-bit integer to the archive.
292  */ 
293 SKYRESULT SkyArchive::AddUInt32(const char* pName, unsigned int anUInt32)
294 {
295   return AddData( pName, UINT32_TYPE, &anUInt32, sizeof(unsigned int));
296 }
297
298 //------------------------------------------------------------------------------
299 // Function               : SkyArchive::AddFloat32
300 // Description      : 
301 //------------------------------------------------------------------------------
302 /**
303  * @fn SkyArchive::AddFloat32(const char* pName, float aFloat32)
304  * @brief Adds a named 32-bit real number to the archive.
305  */ 
306 SKYRESULT SkyArchive::AddFloat32(const char* pName, float aFloat32)
307 {
308   return AddData( pName, FLOAT32_TYPE, &aFloat32, sizeof(float));
309 }
310
311 //------------------------------------------------------------------------------
312 // Function               : SkyArchive::AddFloat64
313 // Description      : 
314 //------------------------------------------------------------------------------
315 /**
316  * @fn SkyArchive::AddFloat64(const char* pName, double aFloat64)
317  * @brief Adds a named 64-bit real number to the archive.
318  */ 
319 SKYRESULT SkyArchive::AddFloat64(const char* pName, double aFloat64)
320 {
321   return AddData( pName, FLOAT64_TYPE, &aFloat64, sizeof(double));
322 }
323
324 //------------------------------------------------------------------------------
325 // Function               : SkyArchive::AddString
326 // Description      : 
327 //------------------------------------------------------------------------------
328 /**
329  * @fn SkyArchive::AddString(const char* pName, const char* pString)
330  * @brief Adds a named string to the archive.
331  */ 
332 SKYRESULT SkyArchive::AddString(const char* pName, const char* pString)
333 {
334   return AddData( pName, STRING_TYPE, pString, ::strlen(pString)+1);
335 }
336
337 //------------------------------------------------------------------------------
338 // Function               : SkyArchive::AddArchive
339 // Description      : 
340 //------------------------------------------------------------------------------
341 /**
342  * @fn SkyArchive::AddArchive(const SkyArchive& anArchive)
343  * @brief Adds a subarchive to this archive.
344  *
345  * This method allows hierarchical data structures to be stored in an archive.
346  */
347 SKYRESULT SkyArchive::AddArchive(const SkyArchive& anArchive)
348 {
349   SkyArchive* pCopy = new SkyArchive(anArchive);
350   return AddData( pCopy->GetName(), ARCHIVE_TYPE, pCopy, sizeof(SkyArchive));
351 }
352
353 //-----------------------------------------------------------------------------
354 //  Adding Vector types
355 //-----------------------------------------------------------------------------
356
357 //------------------------------------------------------------------------------
358 // Function               : SkyArchive::AddVec2f
359 // Description      : 
360 //------------------------------------------------------------------------------
361 /**
362  * @fn SkyArchive::AddVec2f(const char* pName, const Vec2f& aVec2f)
363  * @brief Adds a 2-component 32-bit real number vector to the archive.
364  */ 
365 SKYRESULT SkyArchive::AddVec2f(const char* pName, const Vec2f& aVec2f)
366 {
367   return AddData( pName, VEC2F_TYPE, &aVec2f, sizeof(Vec2f));
368 }
369
370 //------------------------------------------------------------------------------
371 // Function               : SkyArchive::AddVec3f
372 // Description      : 
373 //------------------------------------------------------------------------------
374 /**
375  * @fn SkyArchive::AddVec3f(const char* pName, const Vec3f& aVec3f)
376  * @brief Adds a 3-component 32-bit real number vector to the archive.
377  */ 
378 SKYRESULT SkyArchive::AddVec3f(const char* pName, const Vec3f& aVec3f)
379 {
380   return AddData( pName, VEC3F_TYPE, &aVec3f, sizeof(Vec3f));
381 }
382
383 //------------------------------------------------------------------------------
384 // Function               : SkyArchive::AddVec4f
385 // Description      : 
386 //------------------------------------------------------------------------------
387 /**
388  * @fn SkyArchive::AddVec4f(const char* pName, const Vec4f& aVec4f)
389  * @brief Adds a 4-component 32-bit real number vector to the archive.
390  */ 
391 SKYRESULT SkyArchive::AddVec4f(const char* pName, const Vec4f& aVec4f)
392 {
393   return AddData( pName, VEC4F_TYPE, &aVec4f, sizeof(Vec4f));
394 }
395
396 //=============================================================================
397 //  Retrieving Content from SkyArchive
398 //=============================================================================
399
400 //------------------------------------------------------------------------------
401 // Function               : SkyArchive::FindData
402 // Description      : 
403 //------------------------------------------------------------------------------
404 /**
405  * @fn SkyArchive::FindData(const char*        pName, 
406                                SkyArchiveTypeCode eType, 
407                                void** const       pData, 
408                                unsigned int*      pNumBytes, 
409                                unsigned int       index) const
410  * @brief Retrieves datafield from _dataTable.
411  * 
412  * PARAMETERS
413  * @param name The field name.  used as the key for the multimap entry.
414  * @param type Data type of the field.
415  * @param pData Pointer to the returned data.
416  * @param pNumBytes Returns the size of the field entry returned.
417  * @param index Which item of the given \a name to locate.
418  */ 
419 SKYRESULT SkyArchive::FindData(const char*        pName, 
420                                SkyArchiveTypeCode eType, 
421                                void** const       pData, 
422                                unsigned int*      pNumBytes, 
423                                unsigned int       index /* = 0 */) const
424 {
425   const SkyArchiveEntry* pEntry = _FindEntry(pName, index, eType);
426   if (pEntry)
427   {
428     if (pData)
429     {
430       *pData = new unsigned char[pEntry->iDataSize];
431       ::memcpy( ((void*)*pData), pEntry->pData, pEntry->iDataSize);
432     }
433     
434     if (pNumBytes)
435     {
436       *pNumBytes = pEntry->iDataSize;
437     }
438     
439     return SKYRESULT_OK;
440   }
441   return SKYRESULT_FAIL;
442 }
443
444
445 //-----------------------------------------------------------------------------
446 //  SkyArchive :: FindBool( const char* pName, bool* aBool)
447 //  SkyArchive :: FindInt8( const char* pName, Int8* anInt8)
448 //  SkyArchive :: FindInt16( const char* pName, Int16* anInt16)
449 //  SkyArchive :: FindInt32( const char* pName, Int32* anInt32)
450 //  ...
451 //-----------------------------------------------------------------------------
452 //
453 //  specialized function for the most common base types
454 //  
455 //-----------------------------------------------------------------------------
456
457 //------------------------------------------------------------------------------
458 // Function               : SkyArchive::FindBool
459 // Description      : 
460 //------------------------------------------------------------------------------
461 /**
462  * @fn SkyArchive::FindBool(const char* pName, bool* pBool, unsigned int index) const
463  * @brief Finds a named bool in the archive.
464  */ 
465 SKYRESULT SkyArchive::FindBool(const char* pName, bool* pBool, unsigned int index) const
466 {
467   const SkyArchiveEntry* pEntry = _FindEntry(pName, index, BOOL_TYPE);
468   if (pEntry)
469   {
470     bool* pData = (bool*)(pEntry->pData);
471     *pBool      = *pData;
472     return SKYRESULT_OK;
473   }
474   return SKYRESULT_FAIL;
475 }
476
477 //------------------------------------------------------------------------------
478 // Function               : SkyArchive::FindInt8
479 // Description      : 
480 //------------------------------------------------------------------------------
481 /**
482  * @fn SkyArchive::FindInt8(const char* pName, char* pInt8, unsigned int index) const
483  * @brief Finds a named 8-bit integer in the archive.
484  */ 
485 SKYRESULT SkyArchive::FindInt8(const char* pName, char* pInt8, unsigned int index) const
486 {
487   const SkyArchiveEntry* pEntry = _FindEntry(pName, index, INT8_TYPE);
488   if (pEntry)
489   {
490     char* pData = (char*)(pEntry->pData);
491     *pInt8      = *pData;
492     return SKYRESULT_OK;
493   }
494   return SKYRESULT_FAIL;
495 }
496
497 //------------------------------------------------------------------------------
498 // Function               : SkyArchive::FindInt16
499 // Description      : 
500 //------------------------------------------------------------------------------
501 /**
502  * @fn SkyArchive::FindInt16(const char* pName, short* pInt16, unsigned int index) const
503  * @brief Finds a named 16-bit integer in the archive.
504  */ 
505 SKYRESULT SkyArchive::FindInt16(const char* pName, short* pInt16, unsigned int index) const
506 {
507   const SkyArchiveEntry* pEntry = _FindEntry(pName, index, INT16_TYPE);
508   if (pEntry)
509   {
510     short* pData  = (short*)(pEntry->pData);
511     *pInt16       = *pData;
512     return SKYRESULT_OK;
513   }
514   return SKYRESULT_FAIL;
515 }
516
517 //------------------------------------------------------------------------------
518 // Function               : SkyArchive::FindInt32
519 // Description      : 
520 //------------------------------------------------------------------------------
521 /**
522  * @fn SkyArchive::FindInt32(const char* pName, int* pInt32, unsigned int index) const
523  * @brief Finds a named 32-bit integer in the archive.
524  */ 
525 SKYRESULT SkyArchive::FindInt32(const char* pName, int* pInt32, unsigned int index) const
526 {
527   const SkyArchiveEntry* pEntry = _FindEntry(pName, index, INT32_TYPE);
528   if (pEntry)
529   {
530     int* pData  = (int*)(pEntry->pData);
531     *pInt32     = *pData;
532     return SKYRESULT_OK;
533   }
534   return SKYRESULT_FAIL;
535 }
536
537 //------------------------------------------------------------------------------
538 // Function               : SkyArchive::FindUInt8
539 // Description      : 
540 //------------------------------------------------------------------------------
541 /**
542  * @fn SkyArchive::FindUInt8(const char* pName, unsigned char* pUInt8, unsigned int index) const
543  * @brief Finds a named unsigned 8-bit integer in the archive.
544  */ 
545 SKYRESULT SkyArchive::FindUInt8(const char* pName, unsigned char* pUInt8, unsigned int index) const
546 {
547   const SkyArchiveEntry* pEntry = _FindEntry(pName, index, UINT8_TYPE);
548   if (pEntry)
549   {
550     unsigned char* pData  = (unsigned char*)(pEntry->pData);
551     *pUInt8               = *pData;
552     return SKYRESULT_OK;
553   }
554   return SKYRESULT_FAIL;
555 }
556
557 //------------------------------------------------------------------------------
558 // Function               : SkyArchive::FindUInt16
559 // Description      : 
560 //------------------------------------------------------------------------------
561 /**
562  * @fn SkyArchive::FindUInt16(const char* pName, unsigned short* pUInt16, unsigned int index) const
563  * @brief Finds a named unsigned 16-bit integer in the archive.
564  */ 
565 SKYRESULT SkyArchive::FindUInt16(const char* pName, unsigned short* pUInt16, unsigned int index) const
566 {
567   const SkyArchiveEntry* pEntry = _FindEntry(pName, index, UINT16_TYPE);
568   if (pEntry)
569   {
570     unsigned short* pData = (unsigned short*)(pEntry->pData);
571     *pUInt16              = *pData;
572     return SKYRESULT_OK;
573   }
574   return SKYRESULT_FAIL;
575 }
576
577 //------------------------------------------------------------------------------
578 // Function               : SkyArchive::FindUInt32
579 // Description      : 
580 //------------------------------------------------------------------------------
581 /**
582  * @fn SkyArchive::FindUInt32(const char* pName, unsigned int* pUInt32, unsigned int index) const
583  * @brief Finds a named unsigned 32-bit integer in the archive.
584  */ 
585 SKYRESULT SkyArchive::FindUInt32(const char* pName, unsigned int* pUInt32, unsigned int index) const
586 {
587   const SkyArchiveEntry* pEntry = _FindEntry(pName, index, UINT32_TYPE);
588   if (pEntry)
589   {
590     unsigned int* pData = (unsigned int*)(pEntry->pData);
591     *pUInt32            = *pData;
592     return SKYRESULT_OK;
593   }
594   return SKYRESULT_FAIL;
595 }
596
597 //------------------------------------------------------------------------------
598 // Function               : SkyArchive::FindFloat32
599 // Description      : 
600 //------------------------------------------------------------------------------
601 /**
602  * @fn SkyArchive::FindFloat32(const char* pName, float* pFloat32, unsigned int index) const
603  * @brief Finds a named 32-bit real number in the archive.
604  */ 
605 SKYRESULT SkyArchive::FindFloat32(const char* pName, float* pFloat32, unsigned int index) const
606 {
607   const SkyArchiveEntry* pEntry = _FindEntry(pName, index, FLOAT32_TYPE);
608   if (pEntry)
609   {
610     float* pData  = (float*)(pEntry->pData);
611     *pFloat32     = *pData;
612     return SKYRESULT_OK;
613   }
614   return SKYRESULT_FAIL;
615 }
616
617 //------------------------------------------------------------------------------
618 // Function               : SkyArchive::FindFloat64
619 // Description      : 
620 //------------------------------------------------------------------------------
621 /**
622  * @fn SkyArchive::FindFloat64(const char* pName, double* pFloat64, unsigned int index) const
623  * @brief Finds a named 64-bit real number in the archive.
624  */ 
625 SKYRESULT SkyArchive::FindFloat64(const char* pName, double* pFloat64, unsigned int index) const
626 {
627   const SkyArchiveEntry* pEntry = _FindEntry(pName, index, FLOAT64_TYPE);
628   if (pEntry)
629   {
630     double* pData = (double*)(pEntry->pData);
631     *pFloat64     = *pData;
632     return SKYRESULT_OK;
633   }
634   return SKYRESULT_FAIL;
635 }
636
637 //------------------------------------------------------------------------------
638 // Function               : SkyArchive::FindString
639 // Description      : 
640 //------------------------------------------------------------------------------
641 /**
642  * @fn SkyArchive::FindString(const char* pName, char** const pString, unsigned int index) const
643  * @brief Finds a named string in the archive.
644  */ 
645 SKYRESULT SkyArchive::FindString(const char* pName, char** const pString, unsigned int index) const
646 {
647   const SkyArchiveEntry* pEntry = _FindEntry(pName, index, STRING_TYPE);
648   if (pEntry)
649   {
650     char* pData = (char*)(pEntry->pData);
651     *pString    = new char[pEntry->iDataSize];
652     ::strcpy((char*)*pString, pData);
653     return SKYRESULT_OK;
654   }
655   return SKYRESULT_FAIL;
656 }
657
658 //------------------------------------------------------------------------------
659 // Function               : SkyArchive::FindArchive
660 // Description      : 
661 //------------------------------------------------------------------------------
662 /**
663  * @fn SkyArchive::FindArchive(const char* pName, SkyArchive* pArchive, unsigned int index) const
664  * @brief Finds a named sub-archive in the archive.
665  */ 
666 SKYRESULT SkyArchive::FindArchive(const char* pName, SkyArchive* pArchive, unsigned int index) const
667 {
668   const SkyArchiveEntry* pEntry = _FindEntry(pName, index, ARCHIVE_TYPE);
669   if (pEntry)
670   {
671     SkyArchive* pData  = (SkyArchive*)(pEntry->pData);
672     *pArchive         = *pData;
673     return SKYRESULT_OK;
674   }
675   return SKYRESULT_FAIL;
676 }
677
678 //------------------------------------------------------------------------------
679 // Function               : SkyArchive::FindVec2f
680 // Description      : 
681 //------------------------------------------------------------------------------
682 /**
683  * @fn SkyArchive::FindVec2f(const char* pName, Vec2f* pVec2f, unsigned int index) const
684  * @brief Finds a 2-component 32-bit real number vector in the archive.
685  */ 
686 SKYRESULT SkyArchive::FindVec2f(const char* pName, Vec2f* pVec2f, unsigned int index) const
687 {
688   const SkyArchiveEntry* pEntry = _FindEntry(pName, index, VEC2F_TYPE);
689   if (pEntry)
690   {
691     Vec2f* pData  = (Vec2f*)(pEntry->pData);
692     *pVec2f       = *pData;
693     return SKYRESULT_OK;
694   }
695   return SKYRESULT_FAIL;
696 }
697
698 //------------------------------------------------------------------------------
699 // Function               : SkyArchive::FindVec3f
700 // Description      : 
701 //------------------------------------------------------------------------------
702 /**
703  * @fn SkyArchive::FindVec3f(const char* pName, Vec3f* pVec3f, unsigned int index) const
704  * @brief Finds a 3-component 32-bit real number vector in the archive.
705  */ 
706 SKYRESULT SkyArchive::FindVec3f(const char* pName, Vec3f* pVec3f, unsigned int index) const
707 {
708   const SkyArchiveEntry* pEntry = _FindEntry(pName, index, VEC3F_TYPE);
709   if (pEntry)
710   {
711     Vec3f* pData  = (Vec3f*)(pEntry->pData);
712     *pVec3f       = *pData;
713     return SKYRESULT_OK;
714   }
715   return SKYRESULT_FAIL;
716 }
717
718 //------------------------------------------------------------------------------
719 // Function               : SkyArchive::FindVec4f
720 // Description      : 
721 //------------------------------------------------------------------------------
722 /**
723  * @fn SkyArchive::FindVec4f(const char* pName, Vec4f* pVec4f, unsigned int index) const
724  * @brief Finds a 4-component 32-bit real number vector in the archive.
725  */ 
726 SKYRESULT SkyArchive::FindVec4f(const char* pName, Vec4f* pVec4f, unsigned int index) const
727 {
728   const SkyArchiveEntry* pEntry = _FindEntry(pName, index, VEC4F_TYPE);
729   if (pEntry)
730   {
731     Vec4f* pData  = (Vec4f*)(pEntry->pData);
732     *pVec4f       = *pData;
733     return SKYRESULT_OK;
734   }
735   return SKYRESULT_FAIL;
736 }
737
738 //------------------------------------------------------------------------------
739 // Function               : SkyArchive::AccessArchive
740 // Description      : 
741 //------------------------------------------------------------------------------
742 /**
743  * @fn SkyArchive::AccessArchive(const char* pName, SkyArchive** pArchive, unsigned int index) const
744  * @brief Accesses a named sub-archive in an archive directly.
745  * 
746  * Note: The data are not copied!
747  */ 
748 SKYRESULT SkyArchive::AccessArchive(const char* pName, SkyArchive** pArchive, unsigned int index) const
749 {
750   const SkyArchiveEntry* pEntry = _FindEntry(pName, index, ARCHIVE_TYPE);
751   if (pEntry)
752   {
753     SkyArchive* pData = (SkyArchive*)(pEntry->pData);
754     *pArchive        = pData;
755     return SKYRESULT_OK;
756   }
757   return SKYRESULT_FAIL;
758 }
759
760
761 //------------------------------------------------------------------------------
762 // Function               : SkyArchive::GetInfo
763 // Description      : 
764 //------------------------------------------------------------------------------
765 /**
766  * @fn SkyArchive::GetInfo(const char* pName, SkyArchiveTypeCode eType, unsigned int* pNumFound) const
767  * @brief Computes the number of fields that contain the given name and type.
768  * 
769  * PARAMETERS
770  * @param pName Field name to search for.
771  * @param eType Field type to search for.
772  * @param pNumFound Returns the number of fields that contain given name and type.
773  */ 
774 SKYRESULT SkyArchive::GetInfo(const char*         pName, 
775                               SkyArchiveTypeCode  eType, 
776                               unsigned int*       pNumFound) const
777 {
778   //
779   // Find the range of entries in the mmap with the key matching pName
780   //
781   std::pair<SkyMMapConstIter, SkyMMapConstIter> b = _dataTable.equal_range((char*)pName);
782   
783   unsigned int count = 0;
784   for ( SkyMMapConstIter i = b.first; i != b.second; ++i )
785   {
786     //
787     // The entry's type must match...
788     //
789     const SkyArchiveEntry* pEntry = (*i).second;
790     if (pEntry->type == eType || ANY_TYPE == eType)
791     {
792       // only increment the count when the type matches
793       ++count;
794     }
795   }
796   
797   if (pNumFound)
798   {
799     *pNumFound = count;
800   }
801   
802   if (0 == count)
803     return SKYRESULT_FAIL;
804   
805   return SKYRESULT_OK;
806 }
807
808
809 //------------------------------------------------------------------------------
810 // Function               : SkyArchive::GetInfo
811 // Description      : 
812 //------------------------------------------------------------------------------
813 /**
814  * @fn SkyArchive::GetInfo(unsigned int iNameIndex, char** pNameFound, SkyArchiveTypeCode* pTypeCode, unsigned int* pNumFound)
815  * @brief Returns information about the key at the specified index.
816  * 
817  * PARAMETERS
818  * @param nameIndex Key index to look up.
819  * @param pNameFound Key name is returned here.
820  * @param pTypeCode Key type is returned here.
821  * @param pNumFound Number of fields held under key name is returned here.
822  */ 
823 SKYRESULT SkyArchive::GetInfo(unsigned int        iNameIndex, 
824                               char**              pNameFound, 
825                               SkyArchiveTypeCode* pTypeCode,
826                               unsigned int*       pNumFound)
827
828   assert( pNameFound != NULL);
829   
830   if (!pNameFound)
831     return SKYRESULT_FAIL;
832
833   unsigned int      iCurrentKeyIndex = 0;
834   SkyMMapConstIter  iter;
835   const char*       pLastKey = "";
836   
837   for (iter = _dataTable.begin(); iter != _dataTable.end(); iter++)
838   {
839     const char* pKey = (*iter).first;
840     if (::strcmp( pLastKey, pKey))
841     {
842       if (iCurrentKeyIndex == iNameIndex)
843       {
844         *pNameFound = new char[::strlen(pKey) + 1];
845         ::strcpy(*pNameFound, pKey);
846         
847         if (pTypeCode)
848         {
849           const SkyArchiveEntry* pEntry = (*iter).second;
850           *pTypeCode = (SkyArchiveTypeCode)pEntry->type;
851         }
852         
853         if (pNumFound)
854         {
855           return GetInfo( *pNameFound, *pTypeCode, pNumFound);
856         }
857         return SKYRESULT_OK;
858       }
859       
860       pLastKey = pKey;
861       ++iCurrentKeyIndex;
862     }
863   }
864   return SKYRESULT_FAIL;
865 }
866
867
868 //------------------------------------------------------------------------------
869 // Function               : SkyArchive::GetNumUniqueNames
870 // Description      : 
871 //------------------------------------------------------------------------------
872 /**
873 * @fn SkyArchive::GetNumUniqueNames() const
874 * @brief Computes the number of unique key names in _dataTable.
875 */ 
876 unsigned int SkyArchive::GetNumUniqueNames() const
877 {
878   // duh!
879   if (IsEmpty())
880     return 0;
881   
882   unsigned int      iNumKeys = 0;
883   SkyMMapConstIter  iter;
884   const char*       pLastKey = "";
885   
886   for (iter = _dataTable.begin(); iter != _dataTable.end(); iter++)
887   {
888     const char* pKey = (*iter).first;
889     if (::strcmp( pLastKey, pKey))
890     {
891       ++iNumKeys;
892       pLastKey = pKey;
893     }
894   }
895   return iNumKeys;
896 }
897
898
899 //=============================================================================
900 //  Removing Contents of SkyArchive
901 //=============================================================================
902
903 //------------------------------------------------------------------------------
904 // Function               : SkyArchive::MakeEmpty
905 // Description      : 
906 //------------------------------------------------------------------------------
907 /**
908 * @fn SkyArchive::MakeEmpty()
909 * @brief Remove all the contents of the database. 
910 */ 
911 SKYRESULT SkyArchive::MakeEmpty()
912 {
913   SkyMMapIter iter;
914   
915   for (iter = _dataTable.begin(); iter != _dataTable.end(); iter++)
916   {
917     SkyArchiveEntry* pEntry = (*iter).second;
918     char* pName = (*iter).first;
919     SAFE_DELETE_ARRAY(pName);
920     
921     if (ARCHIVE_TYPE == pEntry->type)
922     {
923       SkyArchive* pArchive = (SkyArchive*)(pEntry->pData);
924       SAFE_DELETE(pArchive);
925     }
926     else
927     {
928       SAFE_DELETE_ARRAY(pEntry->pData);
929     }
930     SAFE_DELETE(pEntry);
931   }
932   
933   _dataTable.clear();
934   
935   return SKYRESULT_OK;
936 }
937
938 //------------------------------------------------------------------------------
939 // Function               : SkyArchive::IsEmpty
940 // Description      : 
941 //------------------------------------------------------------------------------
942 /**
943 * @fn SkyArchive::IsEmpty() const
944 * @brief returns true if the archive is empty, false if it contains any data.
945 */ 
946 bool SkyArchive::IsEmpty() const
947 {
948   return (0 == _dataTable.size());
949 }
950
951
952 //------------------------------------------------------------------------------
953 // Function               : SkyArchive::Load
954 // Description      : 
955 //------------------------------------------------------------------------------
956 /**
957  * @fn SkyArchive::Load(const char* pFileName)
958  * @brief Load the contents of a SkyArchive from file storage.
959  */ 
960 SKYRESULT SkyArchive::Load(const char* pFileName)
961 {
962   if (!pFileName)
963     FAIL_RETURN_MSG(SKYRESULT_FAIL, "Error: SkyArchive::Load(): file name is NULL.");
964   
965   FILE* pSrcFile = NULL;
966   
967   if (NULL == (pSrcFile = fopen(pFileName, "rb"))) // file opened successfully   
968   {
969     SkyTrace("Error: SkyArchive::Load(): failed to open file for reading.");
970     return SKYRESULT_FAIL;
971   }
972     
973   SKYRESULT retVal = _Load(pSrcFile);
974   fclose(pSrcFile);
975
976   FAIL_RETURN(retVal);
977   return SKYRESULT_OK;
978 }
979
980 //------------------------------------------------------------------------------
981 // Function               : SkyArchive::Commit
982 // Description      : 
983 //------------------------------------------------------------------------------
984 /**
985  * @fn SkyArchive::Save(const char* pFilename) const
986  * @brief Commit Contents of SkyArchive to file storage.                 
987  */ 
988 SKYRESULT SkyArchive::Save(const char* pFileName) const
989 {
990   if (!pFileName)
991     FAIL_RETURN_MSG(SKYRESULT_FAIL, "Error: SkyArchive::Save(): file name is NULL.");
992
993   FILE* pDestFile = NULL;
994   
995   if (NULL == (pDestFile = fopen(pFileName, "wb"))) // file opened successfully   
996     FAIL_RETURN_MSG(SKYRESULT_FAIL, "Error: SkyArchive::Save(): failed to open file for writing."); 
997   
998   SKYRESULT retVal = _Save(pDestFile);
999   fflush(pDestFile);
1000   fclose(pDestFile);
1001
1002   FAIL_RETURN(retVal);
1003   return SKYRESULT_OK;
1004 }
1005
1006
1007 //=============================================================================
1008 // Private helper functions
1009 //=============================================================================
1010
1011 //------------------------------------------------------------------------------
1012 // Function               : SkyArchive::_FindEntry
1013 // Description      : 
1014 //------------------------------------------------------------------------------
1015 /**
1016  * @fn SkyArchive::_FindEntry(const char* pName, unsigned int index, SkyArchiveTypeCode  eType) const
1017  * @brief Locates and returns the SkyArchiveEntry with the specified name, index, and type.                                                                
1018  * 
1019  * PARAMETERS
1020  * @param pName Entry name to locate (this is used as the database key)
1021  * @param index Entry index to locate (in case of multiple entries)
1022  * @param type Entry must have this type (@see SkyArchiveTypeCode)
1023  *
1024  * Returns a pointer to the entry or NULL if no matching entry could be located.
1025  */ 
1026 const SkyArchiveEntry* SkyArchive::_FindEntry(const char*         pName, 
1027                                               unsigned int        index, 
1028                                               SkyArchiveTypeCode  eType) const
1029 {
1030   //
1031   // Find the range of entries in the mmap with the key matching /name/
1032   //
1033   std::pair< SkyMMapConstIter, SkyMMapConstIter > b = _dataTable.equal_range((char*)pName);
1034   
1035   unsigned int count = 0;
1036   for (SkyMMapConstIter i = b.first; (i != b.second) && (count <= index); ++i)
1037   {
1038     //
1039     // The entry's type and index must match...
1040     //
1041     const SkyArchiveEntry* pEntry = (*i).second;
1042     if (pEntry->type == eType)
1043     {
1044       if (count == index)
1045       {
1046         return pEntry;
1047       }
1048       
1049       // only increment the count when the type matches
1050       ++count;
1051     }
1052   }
1053   return NULL;
1054 }
1055
1056
1057 //.---------------------------------------------------------------------------.
1058 //|   Function   : SkyArchive::_CopyDataTable                               |
1059 //|   Description:                                                            |
1060 //.---------------------------------------------------------------------------.
1061 void SkyArchive::_CopyDataTable( const SkyArchiveMMap& src)
1062 {
1063   SkyMMapConstIter iter;
1064   
1065   for (iter = src.begin(); iter != src.end(); iter++)
1066   {
1067     const SkyArchiveEntry* pSrcEntry  = (*iter).second;
1068     const char* pSrcName              = (*iter).first;
1069     
1070     if (ARCHIVE_TYPE == pSrcEntry->type)
1071     {
1072       SkyArchive* pSrcArchive = (SkyArchive*)pSrcEntry->pData;
1073       AddArchive(*pSrcArchive);
1074     }
1075     else
1076     {
1077       SkyArchiveEntry* pNewEntry    = new SkyArchiveEntry;
1078       pNewEntry->type               = pSrcEntry->type;
1079       pNewEntry->iDataSize          = pSrcEntry->iDataSize;
1080       pNewEntry->pData              = new unsigned char[pNewEntry->iDataSize];
1081       ::memcpy( pNewEntry->pData, pSrcEntry->pData, pNewEntry->iDataSize);
1082       
1083       char* pName = new char[::strlen(pSrcName)+1];
1084       ::strcpy( pName, pSrcName );
1085       _dataTable.insert(std::make_pair(pName, pNewEntry));
1086     }
1087   }
1088 }
1089
1090 //------------------------------------------------------------------------------
1091 // Function               : SkyArchive::_Save
1092 // Description      : 
1093 //------------------------------------------------------------------------------
1094 /**
1095  * @fn SkyArchive::_Save(FILE* pDestFile) const
1096  * @brief Saves data to a file (possibly recursively in the case of subarchives).
1097  */ 
1098 SKYRESULT SkyArchive::_Save(FILE* pDestFile) const
1099 {
1100   // fill out a record for this archive & write it
1101   SkyArchiveFileEntry me;
1102   me.type       = ARCHIVE_TYPE;
1103   ::strncpy( me.pName, _pName, 32);
1104   me.iDataSize  = _dataTable.size();
1105   
1106   size_t iNumItemsWritten = fwrite((const void*)&me, sizeof(SkyArchiveFileEntry), 1, pDestFile);
1107   
1108   if (1 > iNumItemsWritten)
1109     FAIL_RETURN_MSG(SKYRESULT_FAIL, "Error: SkyArchive::_Save(): failed to write Archive header.");
1110   
1111   SkyMMapConstIter iter;
1112   for (iter = _dataTable.begin(); iter != _dataTable.end(); iter++)
1113   {
1114     // fill out a record for each item in _dataTable & write it
1115     const SkyArchiveEntry* pEntry = (*iter).second;
1116     switch(pEntry->type)
1117     {
1118     case ARCHIVE_TYPE:
1119       {
1120         ((SkyArchive*)(pEntry->pData))->_Save(pDestFile);
1121         break;
1122       }
1123       
1124     default:
1125       {
1126         SkyArchiveFileEntry item;
1127         item.type       = pEntry->type;
1128         ::strncpy( item.pName, (*iter).first, 32);
1129         item.iDataSize  = pEntry->iDataSize;
1130         
1131         iNumItemsWritten = fwrite((const void*)&item, sizeof(SkyArchiveFileEntry), 1, pDestFile);
1132         if (1 > iNumItemsWritten)
1133           FAIL_RETURN_MSG(SKYRESULT_FAIL, "Error: SkyArchive::_Save(): failed to write Archive Entry header.");
1134         iNumItemsWritten = fwrite((const void*)pEntry->pData, pEntry->iDataSize, 1, pDestFile);
1135         if (1 > iNumItemsWritten)
1136           FAIL_RETURN_MSG(SKYRESULT_FAIL, "Error: SkyArchive::_Save(): failed to write Archive Entry data.");
1137         break;
1138       }
1139     }
1140   }
1141   return SKYRESULT_OK;
1142 }
1143
1144
1145 //------------------------------------------------------------------------------
1146 // Function               : SkyArchive::_Load
1147 // Description      : 
1148 //------------------------------------------------------------------------------
1149 /**
1150 * @fn SkyArchive::_Load( FILE* pSrcFile)
1151 * @brief Loads data from a file (possibly recursively in the case of subarchives).
1152 */ 
1153 SKYRESULT SkyArchive::_Load( FILE* pSrcFile)
1154 {
1155   // first make sure the file is open and readable.
1156   
1157   // load the first record
1158   SkyArchiveFileEntry thisItem;
1159   size_t iNumItemsRead = fread((void*)&thisItem, sizeof(SkyArchiveFileEntry), 1, pSrcFile);
1160   if (1 > iNumItemsRead)
1161     FAIL_RETURN_MSG(SKYRESULT_FAIL, "Error: SkyArchive::_Load(): failed to read Archive header.");
1162   
1163   _pName = new char[::strlen(thisItem.pName)+1];
1164   ::strcpy( _pName, thisItem.pName);
1165     
1166   for (unsigned int iNumItems = 0; iNumItems < thisItem.iDataSize; ++iNumItems)
1167   {
1168     SkyArchiveFileEntry embeddedItem;
1169     long iFileLoc = ftell(pSrcFile);  // store location before the read
1170     iNumItemsRead = fread((void*)&embeddedItem, sizeof(SkyArchiveFileEntry), 1, pSrcFile);
1171     if (1 > iNumItemsRead)
1172       FAIL_RETURN_MSG(SKYRESULT_FAIL, "Error: SkyArchive::_Load(): failed to read embedded archive item.");
1173    
1174     switch( embeddedItem.type)
1175     {
1176     case ARCHIVE_TYPE:
1177       {
1178         if (0 != fseek(pSrcFile, iFileLoc, SEEK_SET))
1179           FAIL_RETURN_MSG(SKYRESULT_FAIL, "Error: SkyArchive::_Load(): failed to set the file position.");
1180         SkyArchive newArchive;
1181         newArchive._Load(pSrcFile); // recursively load the subarchive
1182         AddArchive(newArchive);     // add the loaded archive to the database in memory.
1183       }
1184       break;
1185     default:
1186       {
1187         void* pData = new unsigned char[embeddedItem.iDataSize];
1188         iNumItemsRead = fread((void*)pData, embeddedItem.iDataSize, 1, pSrcFile);
1189         if (1 > iNumItemsRead)
1190           FAIL_RETURN_MSG(SKYRESULT_FAIL, "Error: SkyArchive::_Load(): failed to read item data.");
1191         AddData( embeddedItem.pName, 
1192                 (SkyArchiveTypeCode)embeddedItem.type, 
1193                 pData, 
1194                 embeddedItem.iDataSize);
1195         delete[] pData;
1196         break;
1197       }      
1198     }
1199   }
1200   return SKYRESULT_OK;
1201 }