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