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
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
19 * @file SkyArchive.cpp
21 * Implementation of class SkyArchive.
25 #include "SkyArchive.hpp"
27 // FIXME: Remove this section whenever plib has it's own endian conversion
28 // funcrtions for 64-bit data types.
29 #ifndef ulEndianLittleDouble
30 // This hack doesn't actually do anything, but it's pressence
31 // marks the places that need endiannes attention.
32 inline double ulEndianLittleDouble(double x) {
39 struct SkyArchiveEntry
41 SkyArchiveEntry() : type(0), pData(NULL), iDataSize(0) {}
44 unsigned int iDataSize;
47 struct SkyArchiveFileEntry
49 SkyArchiveFileEntry() : type(0), iDataSize(0) {}
52 unsigned int iDataSize;
56 //------------------------------------------------------------------------------
57 // Function : SkyArchive::SkyArchive
59 //------------------------------------------------------------------------------
61 * @fn SkyArchive::SkyArchive()
62 * @brief Default constructor. Creates an empty, unnamed archive. |
64 SkyArchive::SkyArchive()
70 //------------------------------------------------------------------------------
71 // Function : SkyArchive::SkyArchive
73 //------------------------------------------------------------------------------
75 * @fn SkyArchive::SkyArchive(const char* pName)
76 * @brief Constructor. Creates an empty, named archive.
78 SkyArchive::SkyArchive(const char* pName)
80 _pName = new char[::strlen(pName)+1];
81 ::strcpy( _pName, pName);
85 //.---------------------------------------------------------------------------.
86 //| Function : SkyArchive::SkyArchive |
88 //.---------------------------------------------------------------------------.
90 //------------------------------------------------------------------------------
91 // Function : SkyArchive::SkyArchive
93 //------------------------------------------------------------------------------
95 * @fn SkyArchive::SkyArchive(const SkyArchive& src)
96 * @brief Copy constructor. Deep-copies the contents of one archive to another.
98 SkyArchive::SkyArchive(const SkyArchive& src)
100 _pName = new char[::strlen(src._pName)+1];
101 ::strcpy( _pName, src._pName);
103 _CopyDataTable( src._dataTable);
106 //------------------------------------------------------------------------------
107 // Function : SkyArchive::~SkyArchive
109 //------------------------------------------------------------------------------
111 * @fn SkyArchive::~SkyArchive()
114 SkyArchive::~SkyArchive()
117 SAFE_DELETE_ARRAY(_pName);
121 //.---------------------------------------------------------------------------.
122 //| Function : SkyArchive::operator= |
124 //.---------------------------------------------------------------------------.
126 //------------------------------------------------------------------------------
127 // Function : SkyArchive::operator=
129 //------------------------------------------------------------------------------
131 * @fn SkyArchive::operator=( const SkyArchive& src)
132 * @brief @todo Deep-copies the contents of one archive to another.
134 SkyArchive& SkyArchive::operator=( const SkyArchive& src)
139 SAFE_DELETE_ARRAY(_pName);
140 _pName = new char[::strlen(src._pName)+1];
141 ::strcpy( _pName, src.GetName());
143 _CopyDataTable( src._dataTable);
150 //=============================================================================
151 // Adding Content to SkyArchive
152 //=============================================================================
154 //------------------------------------------------------------------------------
155 // Function : SkyArchive::AddData
157 //------------------------------------------------------------------------------
159 * @fn SkyArchive::AddData(const char* pName,
160 SkyArchiveTypeCode eType,
162 unsigned int iNumBytes,
163 unsigned int iNumItems)
164 * @brief Adds a new data field to the archive.
166 * Makes a copy of the data, stores it in a SkyArchiveEntry, and adds it to the
167 * database. All specialized functions for the base types are implemented using
171 * @param name Field name. This is used as the key for the database entry.
172 * @param type Data type of the field.
173 * @param pData Pointer to the data to be added to the archive.
174 * @param iNumBytes Size of each individual item in the data
175 * @param iNumItems Number of items to copy
177 SKYRESULT SkyArchive::AddData(const char* pName,
178 SkyArchiveTypeCode eType,
180 unsigned int iNumBytes,
181 unsigned int iNumItems /* = 1 */)
183 // fill out a new archive entry with the supplied data
184 SkyArchiveEntry* pNewEntry = new SkyArchiveEntry;
185 pNewEntry->type = eType;
186 pNewEntry->iDataSize = iNumBytes * iNumItems;
188 if (eType != ARCHIVE_TYPE)
190 pNewEntry->pData = new unsigned char[pNewEntry->iDataSize];
191 ::memcpy(pNewEntry->pData, pData, pNewEntry->iDataSize);
195 pNewEntry->pData = (void*)pData;
198 char* pInternalName = new char[::strlen(pName)+1];
199 ::strcpy( pInternalName, pName);
200 _dataTable.insert(std::make_pair(pInternalName, pNewEntry));
206 //-----------------------------------------------------------------------------
207 // SkyArchive :: AddBool( const char* pName, bool aBool)
208 // SkyArchive :: AddInt8( const char* pName, Int8 anInt8)
209 // SkyArchive :: AddInt16( const char* pName, Int16 anInt16)
210 // SkyArchive :: AddInt32( const char* pName, Int32 anInt32)
212 //-----------------------------------------------------------------------------
214 // Specialized functions for the most common base types
216 //-----------------------------------------------------------------------------
219 //------------------------------------------------------------------------------
220 // Function : SkyArchive::AddBool
222 //------------------------------------------------------------------------------
224 * @fn SkyArchive::AddBool(const char* pName, bool aBool)
225 * @brief Adds a named bool to the archive.
227 SKYRESULT SkyArchive::AddBool(const char* pName, bool aBool)
229 return AddData( pName, BOOL_TYPE, &aBool, sizeof(bool));
232 //------------------------------------------------------------------------------
233 // Function : SkyArchive::AddInt8
235 //------------------------------------------------------------------------------
237 * @fn SkyArchive::AddInt8(const char* pName, char anInt8)
238 * @brief Adds a named 8-bit integer to the archive.
240 SKYRESULT SkyArchive::AddInt8(const char* pName, char anInt8)
242 return AddData( pName, INT8_TYPE, &anInt8, sizeof(char));
245 //------------------------------------------------------------------------------
246 // Function : SkyArchive::AddInt16
248 //------------------------------------------------------------------------------
250 * @fn SkyArchive::AddInt16(const char* pName, short anInt16)
251 * @brief Adds a named 16-bit integer to the archive.
253 SKYRESULT SkyArchive::AddInt16(const char* pName, short anInt16)
255 return AddData( pName, INT16_TYPE, &anInt16, sizeof(short));
258 //------------------------------------------------------------------------------
259 // Function : SkyArchive::AddInt32
261 //------------------------------------------------------------------------------
263 * @fn SkyArchive::AddInt32(const char* pName, int anInt32)
264 * @brief Adds a named 32-bit integer to the archive.
266 SKYRESULT SkyArchive::AddInt32(const char* pName, int anInt32)
268 return AddData( pName, INT32_TYPE, &anInt32, sizeof(int));
271 //------------------------------------------------------------------------------
272 // Function : SkyArchive::AddUInt8
274 //------------------------------------------------------------------------------
276 * @fn SkyArchive::AddUInt8(const char* pName, unsigned char anUInt8)
277 * @brief Adds a named unsigned 8-bit integer to the archive.
279 SKYRESULT SkyArchive::AddUInt8(const char* pName, unsigned char anUInt8)
281 return AddData( pName, UINT8_TYPE, &anUInt8, sizeof(unsigned char));
284 //------------------------------------------------------------------------------
285 // Function : SkyArchive::AddUInt16
287 //------------------------------------------------------------------------------
289 * @fn SkyArchive::AddUInt16(const char* pName, unsigned short anUInt16)
290 * @brief Adds a named unsigned 16-bit integer to the archive.
292 SKYRESULT SkyArchive::AddUInt16(const char* pName, unsigned short anUInt16)
294 return AddData( pName, UINT16_TYPE, &anUInt16, sizeof(unsigned short));
297 //------------------------------------------------------------------------------
298 // Function : SkyArchive::AddUInt32
300 //------------------------------------------------------------------------------
302 * @fn SkyArchive::AddUInt32(const char* pName, unsigned int anUInt32)
303 * @brief Adds a named unsigned 32-bit integer to the archive.
305 SKYRESULT SkyArchive::AddUInt32(const char* pName, unsigned int anUInt32)
307 return AddData( pName, UINT32_TYPE, &anUInt32, sizeof(unsigned int));
310 //------------------------------------------------------------------------------
311 // Function : SkyArchive::AddFloat32
313 //------------------------------------------------------------------------------
315 * @fn SkyArchive::AddFloat32(const char* pName, float aFloat32)
316 * @brief Adds a named 32-bit real number to the archive.
318 SKYRESULT SkyArchive::AddFloat32(const char* pName, float aFloat32)
320 return AddData( pName, FLOAT32_TYPE, &aFloat32, sizeof(float));
323 //------------------------------------------------------------------------------
324 // Function : SkyArchive::AddFloat64
326 //------------------------------------------------------------------------------
328 * @fn SkyArchive::AddFloat64(const char* pName, double aFloat64)
329 * @brief Adds a named 64-bit real number to the archive.
331 SKYRESULT SkyArchive::AddFloat64(const char* pName, double aFloat64)
333 return AddData( pName, FLOAT64_TYPE, &aFloat64, sizeof(double));
336 //------------------------------------------------------------------------------
337 // Function : SkyArchive::AddString
339 //------------------------------------------------------------------------------
341 * @fn SkyArchive::AddString(const char* pName, const char* pString)
342 * @brief Adds a named string to the archive.
344 SKYRESULT SkyArchive::AddString(const char* pName, const char* pString)
346 return AddData( pName, STRING_TYPE, pString, ::strlen(pString)+1);
349 //------------------------------------------------------------------------------
350 // Function : SkyArchive::AddArchive
352 //------------------------------------------------------------------------------
354 * @fn SkyArchive::AddArchive(const SkyArchive& anArchive)
355 * @brief Adds a subarchive to this archive.
357 * This method allows hierarchical data structures to be stored in an archive.
359 SKYRESULT SkyArchive::AddArchive(const SkyArchive& anArchive)
361 SkyArchive* pCopy = new SkyArchive(anArchive);
362 return AddData( pCopy->GetName(), ARCHIVE_TYPE, pCopy, sizeof(SkyArchive));
365 //-----------------------------------------------------------------------------
366 // Adding Vector types
367 //-----------------------------------------------------------------------------
369 //------------------------------------------------------------------------------
370 // Function : SkyArchive::AddVec2f
372 //------------------------------------------------------------------------------
374 * @fn SkyArchive::AddVec2f(const char* pName, const Vec2f& aVec2f)
375 * @brief Adds a 2-component 32-bit real number vector to the archive.
377 SKYRESULT SkyArchive::AddVec2f(const char* pName, const Vec2f& aVec2f)
379 return AddData( pName, VEC2F_TYPE, &aVec2f, sizeof(Vec2f));
382 //------------------------------------------------------------------------------
383 // Function : SkyArchive::AddVec3f
385 //------------------------------------------------------------------------------
387 * @fn SkyArchive::AddVec3f(const char* pName, const Vec3f& aVec3f)
388 * @brief Adds a 3-component 32-bit real number vector to the archive.
390 SKYRESULT SkyArchive::AddVec3f(const char* pName, const Vec3f& aVec3f)
392 return AddData( pName, VEC3F_TYPE, &aVec3f, sizeof(Vec3f));
395 //------------------------------------------------------------------------------
396 // Function : SkyArchive::AddVec4f
398 //------------------------------------------------------------------------------
400 * @fn SkyArchive::AddVec4f(const char* pName, const Vec4f& aVec4f)
401 * @brief Adds a 4-component 32-bit real number vector to the archive.
403 SKYRESULT SkyArchive::AddVec4f(const char* pName, const Vec4f& aVec4f)
405 return AddData( pName, VEC4F_TYPE, &aVec4f, sizeof(Vec4f));
408 //=============================================================================
409 // Retrieving Content from SkyArchive
410 //=============================================================================
412 //------------------------------------------------------------------------------
413 // Function : SkyArchive::FindData
415 //------------------------------------------------------------------------------
417 * @fn SkyArchive::FindData(const char* pName,
418 SkyArchiveTypeCode eType,
420 unsigned int* pNumBytes,
421 unsigned int index) const
422 * @brief Retrieves datafield from _dataTable.
425 * @param name The field name. used as the key for the multimap entry.
426 * @param type Data type of the field.
427 * @param pData Pointer to the returned data.
428 * @param pNumBytes Returns the size of the field entry returned.
429 * @param index Which item of the given \a name to locate.
431 SKYRESULT SkyArchive::FindData(const char* pName,
432 SkyArchiveTypeCode eType,
434 unsigned int* pNumBytes,
435 unsigned int index /* = 0 */) const
437 const SkyArchiveEntry* pEntry = _FindEntry(pName, index, eType);
442 *pData = new unsigned char[pEntry->iDataSize];
443 ::memcpy( ((void*)*pData), pEntry->pData, pEntry->iDataSize);
448 *pNumBytes = pEntry->iDataSize;
453 return SKYRESULT_FAIL;
457 //-----------------------------------------------------------------------------
458 // SkyArchive :: FindBool( const char* pName, bool* aBool)
459 // SkyArchive :: FindInt8( const char* pName, Int8* anInt8)
460 // SkyArchive :: FindInt16( const char* pName, Int16* anInt16)
461 // SkyArchive :: FindInt32( const char* pName, Int32* anInt32)
463 //-----------------------------------------------------------------------------
465 // specialized function for the most common base types
467 //-----------------------------------------------------------------------------
469 //------------------------------------------------------------------------------
470 // Function : SkyArchive::FindBool
472 //------------------------------------------------------------------------------
474 * @fn SkyArchive::FindBool(const char* pName, bool* pBool, unsigned int index) const
475 * @brief Finds a named bool in the archive.
477 SKYRESULT SkyArchive::FindBool(const char* pName, bool* pBool, unsigned int index) const
479 const SkyArchiveEntry* pEntry = _FindEntry(pName, index, BOOL_TYPE);
482 bool* pData = (bool*)(pEntry->pData);
486 return SKYRESULT_FAIL;
489 //------------------------------------------------------------------------------
490 // Function : SkyArchive::FindInt8
492 //------------------------------------------------------------------------------
494 * @fn SkyArchive::FindInt8(const char* pName, char* pInt8, unsigned int index) const
495 * @brief Finds a named 8-bit integer in the archive.
497 SKYRESULT SkyArchive::FindInt8(const char* pName, char* pInt8, unsigned int index) const
499 const SkyArchiveEntry* pEntry = _FindEntry(pName, index, INT8_TYPE);
502 char* pData = (char*)(pEntry->pData);
506 return SKYRESULT_FAIL;
509 //------------------------------------------------------------------------------
510 // Function : SkyArchive::FindInt16
512 //------------------------------------------------------------------------------
514 * @fn SkyArchive::FindInt16(const char* pName, short* pInt16, unsigned int index) const
515 * @brief Finds a named 16-bit integer in the archive.
517 SKYRESULT SkyArchive::FindInt16(const char* pName, short* pInt16, unsigned int index) const
519 const SkyArchiveEntry* pEntry = _FindEntry(pName, index, INT16_TYPE);
522 unsigned short* pData = (unsigned short*)(pEntry->pData);
523 *pInt16 = ulEndianLittle16(*pData);
526 return SKYRESULT_FAIL;
529 //------------------------------------------------------------------------------
530 // Function : SkyArchive::FindInt32
532 //------------------------------------------------------------------------------
534 * @fn SkyArchive::FindInt32(const char* pName, int* pInt32, unsigned int index) const
535 * @brief Finds a named 32-bit integer in the archive.
537 SKYRESULT SkyArchive::FindInt32(const char* pName, int* pInt32, unsigned int index) const
539 const SkyArchiveEntry* pEntry = _FindEntry(pName, index, INT32_TYPE);
542 unsigned int* pData = (unsigned int*)(pEntry->pData);
543 *pInt32 = ulEndianLittle32(*pData);
546 return SKYRESULT_FAIL;
549 //------------------------------------------------------------------------------
550 // Function : SkyArchive::FindUInt8
552 //------------------------------------------------------------------------------
554 * @fn SkyArchive::FindUInt8(const char* pName, unsigned char* pUInt8, unsigned int index) const
555 * @brief Finds a named unsigned 8-bit integer in the archive.
557 SKYRESULT SkyArchive::FindUInt8(const char* pName, unsigned char* pUInt8, unsigned int index) const
559 const SkyArchiveEntry* pEntry = _FindEntry(pName, index, UINT8_TYPE);
562 unsigned char* pData = (unsigned char*)(pEntry->pData);
566 return SKYRESULT_FAIL;
569 //------------------------------------------------------------------------------
570 // Function : SkyArchive::FindUInt16
572 //------------------------------------------------------------------------------
574 * @fn SkyArchive::FindUInt16(const char* pName, unsigned short* pUInt16, unsigned int index) const
575 * @brief Finds a named unsigned 16-bit integer in the archive.
577 SKYRESULT SkyArchive::FindUInt16(const char* pName, unsigned short* pUInt16, unsigned int index) const
579 const SkyArchiveEntry* pEntry = _FindEntry(pName, index, UINT16_TYPE);
582 unsigned short* pData = (unsigned short*)(pEntry->pData);
583 *pUInt16 = ulEndianLittle16(*pData);
586 return SKYRESULT_FAIL;
589 //------------------------------------------------------------------------------
590 // Function : SkyArchive::FindUInt32
592 //------------------------------------------------------------------------------
594 * @fn SkyArchive::FindUInt32(const char* pName, unsigned int* pUInt32, unsigned int index) const
595 * @brief Finds a named unsigned 32-bit integer in the archive.
597 SKYRESULT SkyArchive::FindUInt32(const char* pName, unsigned int* pUInt32, unsigned int index) const
599 const SkyArchiveEntry* pEntry = _FindEntry(pName, index, UINT32_TYPE);
602 unsigned int* pData = (unsigned int*)(pEntry->pData);
603 *pUInt32 = ulEndianLittle32(*pData);
606 return SKYRESULT_FAIL;
609 //------------------------------------------------------------------------------
610 // Function : SkyArchive::FindFloat32
612 //------------------------------------------------------------------------------
614 * @fn SkyArchive::FindFloat32(const char* pName, float* pFloat32, unsigned int index) const
615 * @brief Finds a named 32-bit real number in the archive.
617 SKYRESULT SkyArchive::FindFloat32(const char* pName, float* pFloat32, unsigned int index) const
619 const SkyArchiveEntry* pEntry = _FindEntry(pName, index, FLOAT32_TYPE);
622 float* pData = (float*)(pEntry->pData);
623 *pFloat32 = ulEndianLittleFloat(*pData);
626 return SKYRESULT_FAIL;
629 //------------------------------------------------------------------------------
630 // Function : SkyArchive::FindFloat64
632 //------------------------------------------------------------------------------
634 * @fn SkyArchive::FindFloat64(const char* pName, double* pFloat64, unsigned int index) const
635 * @brief Finds a named 64-bit real number in the archive.
637 SKYRESULT SkyArchive::FindFloat64(const char* pName, double* pFloat64, unsigned int index) const
639 const SkyArchiveEntry* pEntry = _FindEntry(pName, index, FLOAT64_TYPE);
642 double* pData = (double*)(pEntry->pData);
643 *pFloat64 = ulEndianLittleDouble(*pData);
646 return SKYRESULT_FAIL;
649 //------------------------------------------------------------------------------
650 // Function : SkyArchive::FindString
652 //------------------------------------------------------------------------------
654 * @fn SkyArchive::FindString(const char* pName, char** const pString, unsigned int index) const
655 * @brief Finds a named string in the archive.
657 SKYRESULT SkyArchive::FindString(const char* pName, char** const pString, unsigned int index) const
659 const SkyArchiveEntry* pEntry = _FindEntry(pName, index, STRING_TYPE);
662 char* pData = (char*)(pEntry->pData);
663 *pString = new char[pEntry->iDataSize];
664 ::strcpy((char*)*pString, pData);
667 return SKYRESULT_FAIL;
670 //------------------------------------------------------------------------------
671 // Function : SkyArchive::FindArchive
673 //------------------------------------------------------------------------------
675 * @fn SkyArchive::FindArchive(const char* pName, SkyArchive* pArchive, unsigned int index) const
676 * @brief Finds a named sub-archive in the archive.
678 SKYRESULT SkyArchive::FindArchive(const char* pName, SkyArchive* pArchive, unsigned int index) const
680 const SkyArchiveEntry* pEntry = _FindEntry(pName, index, ARCHIVE_TYPE);
683 SkyArchive* pData = (SkyArchive*)(pEntry->pData);
687 return SKYRESULT_FAIL;
690 //------------------------------------------------------------------------------
691 // Function : SkyArchive::FindVec2f
693 //------------------------------------------------------------------------------
695 * @fn SkyArchive::FindVec2f(const char* pName, Vec2f* pVec2f, unsigned int index) const
696 * @brief Finds a 2-component 32-bit real number vector in the archive.
698 SKYRESULT SkyArchive::FindVec2f(const char* pName, Vec2f* pVec2f, unsigned int index) const
700 const SkyArchiveEntry* pEntry = _FindEntry(pName, index, VEC2F_TYPE);
703 Vec2f* pData = (Vec2f*)(pEntry->pData);
707 return SKYRESULT_FAIL;
710 //------------------------------------------------------------------------------
711 // Function : SkyArchive::FindVec3f
713 //------------------------------------------------------------------------------
715 * @fn SkyArchive::FindVec3f(const char* pName, Vec3f* pVec3f, unsigned int index) const
716 * @brief Finds a 3-component 32-bit real number vector in the archive.
718 SKYRESULT SkyArchive::FindVec3f(const char* pName, Vec3f* pVec3f, unsigned int index) const
720 const SkyArchiveEntry* pEntry = _FindEntry(pName, index, VEC3F_TYPE);
723 Vec3f* pData = (Vec3f*)(pEntry->pData);
727 return SKYRESULT_FAIL;
730 //------------------------------------------------------------------------------
731 // Function : SkyArchive::FindVec4f
733 //------------------------------------------------------------------------------
735 * @fn SkyArchive::FindVec4f(const char* pName, Vec4f* pVec4f, unsigned int index) const
736 * @brief Finds a 4-component 32-bit real number vector in the archive.
738 SKYRESULT SkyArchive::FindVec4f(const char* pName, Vec4f* pVec4f, unsigned int index) const
740 const SkyArchiveEntry* pEntry = _FindEntry(pName, index, VEC4F_TYPE);
743 Vec4f* pData = (Vec4f*)(pEntry->pData);
747 return SKYRESULT_FAIL;
750 //------------------------------------------------------------------------------
751 // Function : SkyArchive::AccessArchive
753 //------------------------------------------------------------------------------
755 * @fn SkyArchive::AccessArchive(const char* pName, SkyArchive** pArchive, unsigned int index) const
756 * @brief Accesses a named sub-archive in an archive directly.
758 * Note: The data are not copied!
760 SKYRESULT SkyArchive::AccessArchive(const char* pName, SkyArchive** pArchive, unsigned int index) const
762 const SkyArchiveEntry* pEntry = _FindEntry(pName, index, ARCHIVE_TYPE);
765 SkyArchive* pData = (SkyArchive*)(pEntry->pData);
769 return SKYRESULT_FAIL;
773 //------------------------------------------------------------------------------
774 // Function : SkyArchive::GetInfo
776 //------------------------------------------------------------------------------
778 * @fn SkyArchive::GetInfo(const char* pName, SkyArchiveTypeCode eType, unsigned int* pNumFound) const
779 * @brief Computes the number of fields that contain the given name and type.
782 * @param pName Field name to search for.
783 * @param eType Field type to search for.
784 * @param pNumFound Returns the number of fields that contain given name and type.
786 SKYRESULT SkyArchive::GetInfo(const char* pName,
787 SkyArchiveTypeCode eType,
788 unsigned int* pNumFound) const
791 // Find the range of entries in the mmap with the key matching pName
793 std::pair<SkyMMapConstIter, SkyMMapConstIter> b = _dataTable.equal_range((char*)pName);
795 unsigned int count = 0;
796 for ( SkyMMapConstIter i = b.first; i != b.second; ++i )
799 // The entry's type must match...
801 const SkyArchiveEntry* pEntry = (*i).second;
802 if (pEntry->type == eType || ANY_TYPE == eType)
804 // only increment the count when the type matches
815 return SKYRESULT_FAIL;
821 //------------------------------------------------------------------------------
822 // Function : SkyArchive::GetInfo
824 //------------------------------------------------------------------------------
826 * @fn SkyArchive::GetInfo(unsigned int iNameIndex, char** pNameFound, SkyArchiveTypeCode* pTypeCode, unsigned int* pNumFound)
827 * @brief Returns information about the key at the specified index.
830 * @param nameIndex Key index to look up.
831 * @param pNameFound Key name is returned here.
832 * @param pTypeCode Key type is returned here.
833 * @param pNumFound Number of fields held under key name is returned here.
835 SKYRESULT SkyArchive::GetInfo(unsigned int iNameIndex,
837 SkyArchiveTypeCode* pTypeCode,
838 unsigned int* pNumFound)
840 assert( pNameFound != NULL);
843 return SKYRESULT_FAIL;
845 unsigned int iCurrentKeyIndex = 0;
846 SkyMMapConstIter iter;
847 const char* pLastKey = "";
849 for (iter = _dataTable.begin(); iter != _dataTable.end(); iter++)
851 const char* pKey = (*iter).first;
852 if (::strcmp( pLastKey, pKey))
854 if (iCurrentKeyIndex == iNameIndex)
856 *pNameFound = new char[::strlen(pKey) + 1];
857 ::strcpy(*pNameFound, pKey);
861 const SkyArchiveEntry* pEntry = (*iter).second;
862 *pTypeCode = (SkyArchiveTypeCode)pEntry->type;
867 return GetInfo( *pNameFound, *pTypeCode, pNumFound);
876 return SKYRESULT_FAIL;
880 //------------------------------------------------------------------------------
881 // Function : SkyArchive::GetNumUniqueNames
883 //------------------------------------------------------------------------------
885 * @fn SkyArchive::GetNumUniqueNames() const
886 * @brief Computes the number of unique key names in _dataTable.
888 unsigned int SkyArchive::GetNumUniqueNames() const
894 unsigned int iNumKeys = 0;
895 SkyMMapConstIter iter;
896 const char* pLastKey = "";
898 for (iter = _dataTable.begin(); iter != _dataTable.end(); iter++)
900 const char* pKey = (*iter).first;
901 if (::strcmp( pLastKey, pKey))
911 //=============================================================================
912 // Removing Contents of SkyArchive
913 //=============================================================================
915 //------------------------------------------------------------------------------
916 // Function : SkyArchive::MakeEmpty
918 //------------------------------------------------------------------------------
920 * @fn SkyArchive::MakeEmpty()
921 * @brief Remove all the contents of the database.
923 SKYRESULT SkyArchive::MakeEmpty()
927 for (iter = _dataTable.begin(); iter != _dataTable.end(); iter++)
929 SkyArchiveEntry* pEntry = (*iter).second;
930 char* pName = (*iter).first;
931 SAFE_DELETE_ARRAY(pName);
933 if (ARCHIVE_TYPE == pEntry->type)
935 SkyArchive* pArchive = (SkyArchive*)(pEntry->pData);
936 SAFE_DELETE(pArchive);
940 SAFE_DELETE_ARRAY(pEntry->pData);
950 //------------------------------------------------------------------------------
951 // Function : SkyArchive::IsEmpty
953 //------------------------------------------------------------------------------
955 * @fn SkyArchive::IsEmpty() const
956 * @brief returns true if the archive is empty, false if it contains any data.
958 bool SkyArchive::IsEmpty() const
960 return (0 == _dataTable.size());
964 //------------------------------------------------------------------------------
965 // Function : SkyArchive::Load
967 //------------------------------------------------------------------------------
969 * @fn SkyArchive::Load(const char* pFileName)
970 * @brief Load the contents of a SkyArchive from file storage.
972 SKYRESULT SkyArchive::Load(const char* pFileName)
975 FAIL_RETURN_MSG(SKYRESULT_FAIL, "Error: SkyArchive::Load(): file name is NULL.");
977 FILE* pSrcFile = NULL;
980 sprintf(buf,"SkyArchive::Load(%s)",pFileName);
982 if (NULL == (pSrcFile = fopen(pFileName, "rb"))) // file opened successfully
984 SkyTrace("Error: SkyArchive::Load(): failed to open file for reading.");
985 return SKYRESULT_FAIL;
988 SKYRESULT retVal = _Load(pSrcFile);
995 //------------------------------------------------------------------------------
996 // Function : SkyArchive::Commit
998 //------------------------------------------------------------------------------
1000 * @fn SkyArchive::Save(const char* pFilename) const
1001 * @brief Commit Contents of SkyArchive to file storage.
1003 SKYRESULT SkyArchive::Save(const char* pFileName) const
1006 FAIL_RETURN_MSG(SKYRESULT_FAIL, "Error: SkyArchive::Save(): file name is NULL.");
1008 FILE* pDestFile = NULL;
1010 if (NULL == (pDestFile = fopen(pFileName, "wb"))) // file opened successfully
1011 FAIL_RETURN_MSG(SKYRESULT_FAIL, "Error: SkyArchive::Save(): failed to open file for writing.");
1013 SKYRESULT retVal = _Save(pDestFile);
1017 FAIL_RETURN(retVal);
1018 return SKYRESULT_OK;
1022 //=============================================================================
1023 // Private helper functions
1024 //=============================================================================
1026 //------------------------------------------------------------------------------
1027 // Function : SkyArchive::_FindEntry
1029 //------------------------------------------------------------------------------
1031 * @fn SkyArchive::_FindEntry(const char* pName, unsigned int index, SkyArchiveTypeCode eType) const
1032 * @brief Locates and returns the SkyArchiveEntry with the specified name, index, and type.
1035 * @param pName Entry name to locate (this is used as the database key)
1036 * @param index Entry index to locate (in case of multiple entries)
1037 * @param type Entry must have this type (@see SkyArchiveTypeCode)
1039 * Returns a pointer to the entry or NULL if no matching entry could be located.
1041 const SkyArchiveEntry* SkyArchive::_FindEntry(const char* pName,
1043 SkyArchiveTypeCode eType) const
1046 // Find the range of entries in the mmap with the key matching /name/
1048 std::pair< SkyMMapConstIter, SkyMMapConstIter > b = _dataTable.equal_range((char*)pName);
1050 unsigned int count = 0;
1051 for (SkyMMapConstIter i = b.first; (i != b.second) && (count <= index); ++i)
1054 // The entry's type and index must match...
1056 const SkyArchiveEntry* pEntry = (*i).second;
1057 if (pEntry->type == eType)
1064 // only increment the count when the type matches
1072 //.---------------------------------------------------------------------------.
1073 //| Function : SkyArchive::_CopyDataTable |
1075 //.---------------------------------------------------------------------------.
1076 void SkyArchive::_CopyDataTable( const SkyArchiveMMap& src)
1078 SkyMMapConstIter iter;
1080 for (iter = src.begin(); iter != src.end(); iter++)
1082 const SkyArchiveEntry* pSrcEntry = (*iter).second;
1083 const char* pSrcName = (*iter).first;
1085 if (ARCHIVE_TYPE == pSrcEntry->type)
1087 SkyArchive* pSrcArchive = (SkyArchive*)pSrcEntry->pData;
1088 AddArchive(*pSrcArchive);
1092 SkyArchiveEntry* pNewEntry = new SkyArchiveEntry;
1093 pNewEntry->type = pSrcEntry->type;
1094 pNewEntry->iDataSize = pSrcEntry->iDataSize;
1095 pNewEntry->pData = new unsigned char[pNewEntry->iDataSize];
1096 ::memcpy( pNewEntry->pData, pSrcEntry->pData, pNewEntry->iDataSize);
1098 char* pName = new char[::strlen(pSrcName)+1];
1099 ::strcpy( pName, pSrcName );
1100 _dataTable.insert(std::make_pair(pName, pNewEntry));
1105 //------------------------------------------------------------------------------
1106 // Function : SkyArchive::_Save
1108 //------------------------------------------------------------------------------
1110 * @fn SkyArchive::_Save(FILE* pDestFile) const
1111 * @brief Saves data to a file (possibly recursively in the case of subarchives).
1113 SKYRESULT SkyArchive::_Save(FILE* pDestFile) const
1115 // fill out a record for this archive & write it
1116 SkyArchiveFileEntry me;
1117 me.type = ARCHIVE_TYPE;
1118 ::strncpy( me.pName, _pName, 32);
1119 me.iDataSize = _dataTable.size();
1121 size_t iNumItemsWritten = fwrite((const void*)&me, sizeof(SkyArchiveFileEntry), 1, pDestFile);
1123 if (1 > iNumItemsWritten)
1124 FAIL_RETURN_MSG(SKYRESULT_FAIL, "Error: SkyArchive::_Save(): failed to write Archive header.");
1126 SkyMMapConstIter iter;
1127 for (iter = _dataTable.begin(); iter != _dataTable.end(); iter++)
1129 // fill out a record for each item in _dataTable & write it
1130 const SkyArchiveEntry* pEntry = (*iter).second;
1131 switch(pEntry->type)
1135 ((SkyArchive*)(pEntry->pData))->_Save(pDestFile);
1141 SkyArchiveFileEntry item;
1142 item.type = pEntry->type;
1143 ::strncpy( item.pName, (*iter).first, 32);
1144 item.iDataSize = pEntry->iDataSize;
1146 iNumItemsWritten = fwrite((const void*)&item, sizeof(SkyArchiveFileEntry), 1, pDestFile);
1147 if (1 > iNumItemsWritten)
1148 FAIL_RETURN_MSG(SKYRESULT_FAIL, "Error: SkyArchive::_Save(): failed to write Archive Entry header.");
1149 iNumItemsWritten = fwrite((const void*)pEntry->pData, pEntry->iDataSize, 1, pDestFile);
1150 if (1 > iNumItemsWritten)
1151 FAIL_RETURN_MSG(SKYRESULT_FAIL, "Error: SkyArchive::_Save(): failed to write Archive Entry data.");
1156 return SKYRESULT_OK;
1160 //------------------------------------------------------------------------------
1161 // Function : SkyArchive::_Load
1163 //------------------------------------------------------------------------------
1165 * @fn SkyArchive::_Load( FILE* pSrcFile)
1166 * @brief Loads data from a file (possibly recursively in the case of subarchives).
1168 SKYRESULT SkyArchive::_Load( FILE* pSrcFile)
1170 // first make sure the file is open and readable.
1172 // load the first record
1173 SkyArchiveFileEntry thisItem;
1174 size_t iNumItemsRead = fread((void*)&thisItem, sizeof(SkyArchiveFileEntry), 1, pSrcFile);
1176 FAIL_RETURN_MSG(SKYRESULT_FAIL, "Error: SkyArchive::_Load(): failed to read Archive header.");
1178 unsigned int ui = thisItem.iDataSize;
1179 thisItem.iDataSize = ulEndianLittle32(ui);
1181 _pName = new char[::strlen(thisItem.pName)+1];
1182 ::strcpy( _pName, thisItem.pName);
1184 for (unsigned int iNumItems = 0; iNumItems < thisItem.iDataSize; ++iNumItems)
1186 SkyArchiveFileEntry embeddedItem;
1187 long iFileLoc = ftell(pSrcFile); // store location before the read
1188 iNumItemsRead = fread((void*)&embeddedItem, sizeof(SkyArchiveFileEntry), 1, pSrcFile);
1189 if (1 > iNumItemsRead)
1190 FAIL_RETURN_MSG(SKYRESULT_FAIL, "Error: SkyArchive::_Load(): failed to read embedded archive item.");
1192 unsigned int ui = embeddedItem.iDataSize;
1193 embeddedItem.iDataSize = ulEndianLittle32(ui);
1196 switch( embeddedItem.type)
1200 if (0 != fseek(pSrcFile, iFileLoc, SEEK_SET))
1201 FAIL_RETURN_MSG(SKYRESULT_FAIL, "Error: SkyArchive::_Load(): failed to set the file position.");
1202 SkyArchive newArchive;
1203 newArchive._Load(pSrcFile); // recursively load the subarchive
1204 AddArchive(newArchive); // add the loaded archive to the database in memory.
1209 void* pData = new unsigned char[embeddedItem.iDataSize];
1210 iNumItemsRead = fread((void*)pData, embeddedItem.iDataSize, 1, pSrcFile);
1211 if (1 > iNumItemsRead)
1212 FAIL_RETURN_MSG(SKYRESULT_FAIL, "Error: SkyArchive::_Load(): failed to read item data.");
1213 AddData( embeddedItem.pName,
1214 (SkyArchiveTypeCode)embeddedItem.type,
1216 embeddedItem.iDataSize);
1222 return SKYRESULT_OK;