Files
simgear/simgear/scene/sky/clouds3d/SkyArchive.cpp
T

1201 lines
41 KiB
C++

//------------------------------------------------------------------------------
// File : SkyArchive.cpp
//------------------------------------------------------------------------------
// SkyWorks : Copyright 2002 Mark J. Harris and
// The University of North Carolina at Chapel Hill
//------------------------------------------------------------------------------
// Permission to use, copy, modify, distribute and sell this software and its
// documentation for any purpose is hereby granted without fee, provided that
// the above copyright notice appear in all copies and that both that copyright
// notice and this permission notice appear in supporting documentation.
// Binaries may be compiled with this software without any royalties or
// restrictions.
//
// The author(s) and The University of North Carolina at Chapel Hill make no
// representations about the suitability of this software for any purpose.
// It is provided "as is" without express or
// implied warranty.
/**
* @file SkyArchive.cpp
*
* Implementation of class SkyArchive.
*/
#include "SkyArchive.hpp"
#include <assert.h>
struct SkyArchiveEntry
{
SkyArchiveEntry() : type(0), pData(NULL), iDataSize(0) {}
unsigned char type;
void* pData;
unsigned int iDataSize;
};
struct SkyArchiveFileEntry
{
SkyArchiveFileEntry() : type(0), iDataSize(0) {}
unsigned char type;
char pName[32];
unsigned int iDataSize;
};
//------------------------------------------------------------------------------
// Function : SkyArchive::SkyArchive
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::SkyArchive()
* @brief Default constructor. Creates an empty, unnamed archive. |
*/
SkyArchive::SkyArchive()
: _pName(NULL)
{
}
//------------------------------------------------------------------------------
// Function : SkyArchive::SkyArchive
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::SkyArchive(const char* pName)
* @brief Constructor. Creates an empty, named archive.
*/
SkyArchive::SkyArchive(const char* pName)
{
_pName = new char[::strlen(pName)+1];
::strcpy( _pName, pName);
}
//.---------------------------------------------------------------------------.
//| Function : SkyArchive::SkyArchive |
//| Description:
//.---------------------------------------------------------------------------.
//------------------------------------------------------------------------------
// Function : SkyArchive::SkyArchive
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::SkyArchive(const SkyArchive& src)
* @brief Copy constructor. Deep-copies the contents of one archive to another.
*/
SkyArchive::SkyArchive(const SkyArchive& src)
{
_pName = new char[::strlen(src._pName)+1];
::strcpy( _pName, src._pName);
_CopyDataTable( src._dataTable);
}
//------------------------------------------------------------------------------
// Function : SkyArchive::~SkyArchive
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::~SkyArchive()
* @brief Destructor.
*/
SkyArchive::~SkyArchive()
{
MakeEmpty();
SAFE_DELETE_ARRAY(_pName);
}
//.---------------------------------------------------------------------------.
//| Function : SkyArchive::operator= |
//| Description: |
//.---------------------------------------------------------------------------.
//------------------------------------------------------------------------------
// Function : SkyArchive::operator=
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::operator=( const SkyArchive& src)
* @brief @todo Deep-copies the contents of one archive to another.
*/
SkyArchive& SkyArchive::operator=( const SkyArchive& src)
{
if (this != &src)
{
MakeEmpty();
SAFE_DELETE_ARRAY(_pName);
_pName = new char[::strlen(src._pName)+1];
::strcpy( _pName, src.GetName());
_CopyDataTable( src._dataTable);
}
return *this;
}
//=============================================================================
// Adding Content to SkyArchive
//=============================================================================
//------------------------------------------------------------------------------
// Function : SkyArchive::AddData
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::AddData(const char* pName,
SkyArchiveTypeCode eType,
const void* pData,
unsigned int iNumBytes,
unsigned int iNumItems)
* @brief Adds a new data field to the archive.
*
* Makes a copy of the data, stores it in a SkyArchiveEntry, and adds it to the
* database. All specialized functions for the base types are implemented using
* this function.
*
* PARAMETERS
* @param name Field name. This is used as the key for the database entry.
* @param type Data type of the field.
* @param pData Pointer to the data to be added to the archive.
* @param iNumBytes Size of each individual item in the data
* @param iNumItems Number of items to copy
*/
SKYRESULT SkyArchive::AddData(const char* pName,
SkyArchiveTypeCode eType,
const void* pData,
unsigned int iNumBytes,
unsigned int iNumItems /* = 1 */)
{
// fill out a new archive entry with the supplied data
SkyArchiveEntry* pNewEntry = new SkyArchiveEntry;
pNewEntry->type = eType;
pNewEntry->iDataSize = iNumBytes * iNumItems;
if (eType != ARCHIVE_TYPE)
{
pNewEntry->pData = new unsigned char[pNewEntry->iDataSize];
::memcpy(pNewEntry->pData, pData, pNewEntry->iDataSize);
}
else
{
pNewEntry->pData = (void*)pData;
}
char* pInternalName = new char[::strlen(pName)+1];
::strcpy( pInternalName, pName);
_dataTable.insert(std::make_pair(pInternalName, pNewEntry));
return SKYRESULT_OK;
}
//-----------------------------------------------------------------------------
// SkyArchive :: AddBool( const char* pName, bool aBool)
// SkyArchive :: AddInt8( const char* pName, Int8 anInt8)
// SkyArchive :: AddInt16( const char* pName, Int16 anInt16)
// SkyArchive :: AddInt32( const char* pName, Int32 anInt32)
// ...
//-----------------------------------------------------------------------------
//
// Specialized functions for the most common base types
//
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Function : SkyArchive::AddBool
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::AddBool(const char* pName, bool aBool)
* @brief Adds a named bool to the archive.
*/
SKYRESULT SkyArchive::AddBool(const char* pName, bool aBool)
{
return AddData( pName, BOOL_TYPE, &aBool, sizeof(bool));
}
//------------------------------------------------------------------------------
// Function : SkyArchive::AddInt8
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::AddInt8(const char* pName, char anInt8)
* @brief Adds a named 8-bit integer to the archive.
*/
SKYRESULT SkyArchive::AddInt8(const char* pName, char anInt8)
{
return AddData( pName, INT8_TYPE, &anInt8, sizeof(char));
}
//------------------------------------------------------------------------------
// Function : SkyArchive::AddInt16
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::AddInt16(const char* pName, short anInt16)
* @brief Adds a named 16-bit integer to the archive.
*/
SKYRESULT SkyArchive::AddInt16(const char* pName, short anInt16)
{
return AddData( pName, INT16_TYPE, &anInt16, sizeof(short));
}
//------------------------------------------------------------------------------
// Function : SkyArchive::AddInt32
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::AddInt32(const char* pName, int anInt32)
* @brief Adds a named 32-bit integer to the archive.
*/
SKYRESULT SkyArchive::AddInt32(const char* pName, int anInt32)
{
return AddData( pName, INT32_TYPE, &anInt32, sizeof(int));
}
//------------------------------------------------------------------------------
// Function : SkyArchive::AddUInt8
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::AddUInt8(const char* pName, unsigned char anUInt8)
* @brief Adds a named unsigned 8-bit integer to the archive.
*/
SKYRESULT SkyArchive::AddUInt8(const char* pName, unsigned char anUInt8)
{
return AddData( pName, UINT8_TYPE, &anUInt8, sizeof(unsigned char));
}
//------------------------------------------------------------------------------
// Function : SkyArchive::AddUInt16
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::AddUInt16(const char* pName, unsigned short anUInt16)
* @brief Adds a named unsigned 16-bit integer to the archive.
*/
SKYRESULT SkyArchive::AddUInt16(const char* pName, unsigned short anUInt16)
{
return AddData( pName, UINT16_TYPE, &anUInt16, sizeof(unsigned short));
}
//------------------------------------------------------------------------------
// Function : SkyArchive::AddUInt32
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::AddUInt32(const char* pName, unsigned int anUInt32)
* @brief Adds a named unsigned 32-bit integer to the archive.
*/
SKYRESULT SkyArchive::AddUInt32(const char* pName, unsigned int anUInt32)
{
return AddData( pName, UINT32_TYPE, &anUInt32, sizeof(unsigned int));
}
//------------------------------------------------------------------------------
// Function : SkyArchive::AddFloat32
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::AddFloat32(const char* pName, float aFloat32)
* @brief Adds a named 32-bit real number to the archive.
*/
SKYRESULT SkyArchive::AddFloat32(const char* pName, float aFloat32)
{
return AddData( pName, FLOAT32_TYPE, &aFloat32, sizeof(float));
}
//------------------------------------------------------------------------------
// Function : SkyArchive::AddFloat64
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::AddFloat64(const char* pName, double aFloat64)
* @brief Adds a named 64-bit real number to the archive.
*/
SKYRESULT SkyArchive::AddFloat64(const char* pName, double aFloat64)
{
return AddData( pName, FLOAT64_TYPE, &aFloat64, sizeof(double));
}
//------------------------------------------------------------------------------
// Function : SkyArchive::AddString
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::AddString(const char* pName, const char* pString)
* @brief Adds a named string to the archive.
*/
SKYRESULT SkyArchive::AddString(const char* pName, const char* pString)
{
return AddData( pName, STRING_TYPE, pString, ::strlen(pString)+1);
}
//------------------------------------------------------------------------------
// Function : SkyArchive::AddArchive
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::AddArchive(const SkyArchive& anArchive)
* @brief Adds a subarchive to this archive.
*
* This method allows hierarchical data structures to be stored in an archive.
*/
SKYRESULT SkyArchive::AddArchive(const SkyArchive& anArchive)
{
SkyArchive* pCopy = new SkyArchive(anArchive);
return AddData( pCopy->GetName(), ARCHIVE_TYPE, pCopy, sizeof(SkyArchive));
}
//-----------------------------------------------------------------------------
// Adding Vector types
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Function : SkyArchive::AddVec2f
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::AddVec2f(const char* pName, const Vec2f& aVec2f)
* @brief Adds a 2-component 32-bit real number vector to the archive.
*/
SKYRESULT SkyArchive::AddVec2f(const char* pName, const Vec2f& aVec2f)
{
return AddData( pName, VEC2F_TYPE, &aVec2f, sizeof(Vec2f));
}
//------------------------------------------------------------------------------
// Function : SkyArchive::AddVec3f
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::AddVec3f(const char* pName, const Vec3f& aVec3f)
* @brief Adds a 3-component 32-bit real number vector to the archive.
*/
SKYRESULT SkyArchive::AddVec3f(const char* pName, const Vec3f& aVec3f)
{
return AddData( pName, VEC3F_TYPE, &aVec3f, sizeof(Vec3f));
}
//------------------------------------------------------------------------------
// Function : SkyArchive::AddVec4f
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::AddVec4f(const char* pName, const Vec4f& aVec4f)
* @brief Adds a 4-component 32-bit real number vector to the archive.
*/
SKYRESULT SkyArchive::AddVec4f(const char* pName, const Vec4f& aVec4f)
{
return AddData( pName, VEC4F_TYPE, &aVec4f, sizeof(Vec4f));
}
//=============================================================================
// Retrieving Content from SkyArchive
//=============================================================================
//------------------------------------------------------------------------------
// Function : SkyArchive::FindData
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::FindData(const char* pName,
SkyArchiveTypeCode eType,
void** const pData,
unsigned int* pNumBytes,
unsigned int index) const
* @brief Retrieves datafield from _dataTable.
*
* PARAMETERS
* @param name The field name. used as the key for the multimap entry.
* @param type Data type of the field.
* @param pData Pointer to the returned data.
* @param pNumBytes Returns the size of the field entry returned.
* @param index Which item of the given \a name to locate.
*/
SKYRESULT SkyArchive::FindData(const char* pName,
SkyArchiveTypeCode eType,
void** const pData,
unsigned int* pNumBytes,
unsigned int index /* = 0 */) const
{
const SkyArchiveEntry* pEntry = _FindEntry(pName, index, eType);
if (pEntry)
{
if (pData)
{
*pData = new unsigned char[pEntry->iDataSize];
::memcpy( ((void*)*pData), pEntry->pData, pEntry->iDataSize);
}
if (pNumBytes)
{
*pNumBytes = pEntry->iDataSize;
}
return SKYRESULT_OK;
}
return SKYRESULT_FAIL;
}
//-----------------------------------------------------------------------------
// SkyArchive :: FindBool( const char* pName, bool* aBool)
// SkyArchive :: FindInt8( const char* pName, Int8* anInt8)
// SkyArchive :: FindInt16( const char* pName, Int16* anInt16)
// SkyArchive :: FindInt32( const char* pName, Int32* anInt32)
// ...
//-----------------------------------------------------------------------------
//
// specialized function for the most common base types
//
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Function : SkyArchive::FindBool
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::FindBool(const char* pName, bool* pBool, unsigned int index) const
* @brief Finds a named bool in the archive.
*/
SKYRESULT SkyArchive::FindBool(const char* pName, bool* pBool, unsigned int index) const
{
const SkyArchiveEntry* pEntry = _FindEntry(pName, index, BOOL_TYPE);
if (pEntry)
{
bool* pData = (bool*)(pEntry->pData);
*pBool = *pData;
return SKYRESULT_OK;
}
return SKYRESULT_FAIL;
}
//------------------------------------------------------------------------------
// Function : SkyArchive::FindInt8
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::FindInt8(const char* pName, char* pInt8, unsigned int index) const
* @brief Finds a named 8-bit integer in the archive.
*/
SKYRESULT SkyArchive::FindInt8(const char* pName, char* pInt8, unsigned int index) const
{
const SkyArchiveEntry* pEntry = _FindEntry(pName, index, INT8_TYPE);
if (pEntry)
{
char* pData = (char*)(pEntry->pData);
*pInt8 = *pData;
return SKYRESULT_OK;
}
return SKYRESULT_FAIL;
}
//------------------------------------------------------------------------------
// Function : SkyArchive::FindInt16
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::FindInt16(const char* pName, short* pInt16, unsigned int index) const
* @brief Finds a named 16-bit integer in the archive.
*/
SKYRESULT SkyArchive::FindInt16(const char* pName, short* pInt16, unsigned int index) const
{
const SkyArchiveEntry* pEntry = _FindEntry(pName, index, INT16_TYPE);
if (pEntry)
{
short* pData = (short*)(pEntry->pData);
*pInt16 = *pData;
return SKYRESULT_OK;
}
return SKYRESULT_FAIL;
}
//------------------------------------------------------------------------------
// Function : SkyArchive::FindInt32
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::FindInt32(const char* pName, int* pInt32, unsigned int index) const
* @brief Finds a named 32-bit integer in the archive.
*/
SKYRESULT SkyArchive::FindInt32(const char* pName, int* pInt32, unsigned int index) const
{
const SkyArchiveEntry* pEntry = _FindEntry(pName, index, INT32_TYPE);
if (pEntry)
{
int* pData = (int*)(pEntry->pData);
*pInt32 = *pData;
return SKYRESULT_OK;
}
return SKYRESULT_FAIL;
}
//------------------------------------------------------------------------------
// Function : SkyArchive::FindUInt8
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::FindUInt8(const char* pName, unsigned char* pUInt8, unsigned int index) const
* @brief Finds a named unsigned 8-bit integer in the archive.
*/
SKYRESULT SkyArchive::FindUInt8(const char* pName, unsigned char* pUInt8, unsigned int index) const
{
const SkyArchiveEntry* pEntry = _FindEntry(pName, index, UINT8_TYPE);
if (pEntry)
{
unsigned char* pData = (unsigned char*)(pEntry->pData);
*pUInt8 = *pData;
return SKYRESULT_OK;
}
return SKYRESULT_FAIL;
}
//------------------------------------------------------------------------------
// Function : SkyArchive::FindUInt16
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::FindUInt16(const char* pName, unsigned short* pUInt16, unsigned int index) const
* @brief Finds a named unsigned 16-bit integer in the archive.
*/
SKYRESULT SkyArchive::FindUInt16(const char* pName, unsigned short* pUInt16, unsigned int index) const
{
const SkyArchiveEntry* pEntry = _FindEntry(pName, index, UINT16_TYPE);
if (pEntry)
{
unsigned short* pData = (unsigned short*)(pEntry->pData);
*pUInt16 = *pData;
return SKYRESULT_OK;
}
return SKYRESULT_FAIL;
}
//------------------------------------------------------------------------------
// Function : SkyArchive::FindUInt32
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::FindUInt32(const char* pName, unsigned int* pUInt32, unsigned int index) const
* @brief Finds a named unsigned 32-bit integer in the archive.
*/
SKYRESULT SkyArchive::FindUInt32(const char* pName, unsigned int* pUInt32, unsigned int index) const
{
const SkyArchiveEntry* pEntry = _FindEntry(pName, index, UINT32_TYPE);
if (pEntry)
{
unsigned int* pData = (unsigned int*)(pEntry->pData);
*pUInt32 = *pData;
return SKYRESULT_OK;
}
return SKYRESULT_FAIL;
}
//------------------------------------------------------------------------------
// Function : SkyArchive::FindFloat32
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::FindFloat32(const char* pName, float* pFloat32, unsigned int index) const
* @brief Finds a named 32-bit real number in the archive.
*/
SKYRESULT SkyArchive::FindFloat32(const char* pName, float* pFloat32, unsigned int index) const
{
const SkyArchiveEntry* pEntry = _FindEntry(pName, index, FLOAT32_TYPE);
if (pEntry)
{
float* pData = (float*)(pEntry->pData);
*pFloat32 = *pData;
return SKYRESULT_OK;
}
return SKYRESULT_FAIL;
}
//------------------------------------------------------------------------------
// Function : SkyArchive::FindFloat64
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::FindFloat64(const char* pName, double* pFloat64, unsigned int index) const
* @brief Finds a named 64-bit real number in the archive.
*/
SKYRESULT SkyArchive::FindFloat64(const char* pName, double* pFloat64, unsigned int index) const
{
const SkyArchiveEntry* pEntry = _FindEntry(pName, index, FLOAT64_TYPE);
if (pEntry)
{
double* pData = (double*)(pEntry->pData);
*pFloat64 = *pData;
return SKYRESULT_OK;
}
return SKYRESULT_FAIL;
}
//------------------------------------------------------------------------------
// Function : SkyArchive::FindString
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::FindString(const char* pName, char** const pString, unsigned int index) const
* @brief Finds a named string in the archive.
*/
SKYRESULT SkyArchive::FindString(const char* pName, char** const pString, unsigned int index) const
{
const SkyArchiveEntry* pEntry = _FindEntry(pName, index, STRING_TYPE);
if (pEntry)
{
char* pData = (char*)(pEntry->pData);
*pString = new char[pEntry->iDataSize];
::strcpy((char*)*pString, pData);
return SKYRESULT_OK;
}
return SKYRESULT_FAIL;
}
//------------------------------------------------------------------------------
// Function : SkyArchive::FindArchive
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::FindArchive(const char* pName, SkyArchive* pArchive, unsigned int index) const
* @brief Finds a named sub-archive in the archive.
*/
SKYRESULT SkyArchive::FindArchive(const char* pName, SkyArchive* pArchive, unsigned int index) const
{
const SkyArchiveEntry* pEntry = _FindEntry(pName, index, ARCHIVE_TYPE);
if (pEntry)
{
SkyArchive* pData = (SkyArchive*)(pEntry->pData);
*pArchive = *pData;
return SKYRESULT_OK;
}
return SKYRESULT_FAIL;
}
//------------------------------------------------------------------------------
// Function : SkyArchive::FindVec2f
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::FindVec2f(const char* pName, Vec2f* pVec2f, unsigned int index) const
* @brief Finds a 2-component 32-bit real number vector in the archive.
*/
SKYRESULT SkyArchive::FindVec2f(const char* pName, Vec2f* pVec2f, unsigned int index) const
{
const SkyArchiveEntry* pEntry = _FindEntry(pName, index, VEC2F_TYPE);
if (pEntry)
{
Vec2f* pData = (Vec2f*)(pEntry->pData);
*pVec2f = *pData;
return SKYRESULT_OK;
}
return SKYRESULT_FAIL;
}
//------------------------------------------------------------------------------
// Function : SkyArchive::FindVec3f
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::FindVec3f(const char* pName, Vec3f* pVec3f, unsigned int index) const
* @brief Finds a 3-component 32-bit real number vector in the archive.
*/
SKYRESULT SkyArchive::FindVec3f(const char* pName, Vec3f* pVec3f, unsigned int index) const
{
const SkyArchiveEntry* pEntry = _FindEntry(pName, index, VEC3F_TYPE);
if (pEntry)
{
Vec3f* pData = (Vec3f*)(pEntry->pData);
*pVec3f = *pData;
return SKYRESULT_OK;
}
return SKYRESULT_FAIL;
}
//------------------------------------------------------------------------------
// Function : SkyArchive::FindVec4f
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::FindVec4f(const char* pName, Vec4f* pVec4f, unsigned int index) const
* @brief Finds a 4-component 32-bit real number vector in the archive.
*/
SKYRESULT SkyArchive::FindVec4f(const char* pName, Vec4f* pVec4f, unsigned int index) const
{
const SkyArchiveEntry* pEntry = _FindEntry(pName, index, VEC4F_TYPE);
if (pEntry)
{
Vec4f* pData = (Vec4f*)(pEntry->pData);
*pVec4f = *pData;
return SKYRESULT_OK;
}
return SKYRESULT_FAIL;
}
//------------------------------------------------------------------------------
// Function : SkyArchive::AccessArchive
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::AccessArchive(const char* pName, SkyArchive** pArchive, unsigned int index) const
* @brief Accesses a named sub-archive in an archive directly.
*
* Note: The data are not copied!
*/
SKYRESULT SkyArchive::AccessArchive(const char* pName, SkyArchive** pArchive, unsigned int index) const
{
const SkyArchiveEntry* pEntry = _FindEntry(pName, index, ARCHIVE_TYPE);
if (pEntry)
{
SkyArchive* pData = (SkyArchive*)(pEntry->pData);
*pArchive = pData;
return SKYRESULT_OK;
}
return SKYRESULT_FAIL;
}
//------------------------------------------------------------------------------
// Function : SkyArchive::GetInfo
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::GetInfo(const char* pName, SkyArchiveTypeCode eType, unsigned int* pNumFound) const
* @brief Computes the number of fields that contain the given name and type.
*
* PARAMETERS
* @param pName Field name to search for.
* @param eType Field type to search for.
* @param pNumFound Returns the number of fields that contain given name and type.
*/
SKYRESULT SkyArchive::GetInfo(const char* pName,
SkyArchiveTypeCode eType,
unsigned int* pNumFound) const
{
//
// Find the range of entries in the mmap with the key matching pName
//
std::pair<SkyMMapConstIter, SkyMMapConstIter> b = _dataTable.equal_range((char*)pName);
unsigned int count = 0;
for ( SkyMMapConstIter i = b.first; i != b.second; ++i )
{
//
// The entry's type must match...
//
const SkyArchiveEntry* pEntry = (*i).second;
if (pEntry->type == eType || ANY_TYPE == eType)
{
// only increment the count when the type matches
++count;
}
}
if (pNumFound)
{
*pNumFound = count;
}
if (0 == count)
return SKYRESULT_FAIL;
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkyArchive::GetInfo
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::GetInfo(unsigned int iNameIndex, char** pNameFound, SkyArchiveTypeCode* pTypeCode, unsigned int* pNumFound)
* @brief Returns information about the key at the specified index.
*
* PARAMETERS
* @param nameIndex Key index to look up.
* @param pNameFound Key name is returned here.
* @param pTypeCode Key type is returned here.
* @param pNumFound Number of fields held under key name is returned here.
*/
SKYRESULT SkyArchive::GetInfo(unsigned int iNameIndex,
char** pNameFound,
SkyArchiveTypeCode* pTypeCode,
unsigned int* pNumFound)
{
assert( pNameFound != NULL);
if (!pNameFound)
return SKYRESULT_FAIL;
unsigned int iCurrentKeyIndex = 0;
SkyMMapConstIter iter;
const char* pLastKey = "";
for (iter = _dataTable.begin(); iter != _dataTable.end(); iter++)
{
const char* pKey = (*iter).first;
if (::strcmp( pLastKey, pKey))
{
if (iCurrentKeyIndex == iNameIndex)
{
*pNameFound = new char[::strlen(pKey) + 1];
::strcpy(*pNameFound, pKey);
if (pTypeCode)
{
const SkyArchiveEntry* pEntry = (*iter).second;
*pTypeCode = (SkyArchiveTypeCode)pEntry->type;
}
if (pNumFound)
{
return GetInfo( *pNameFound, *pTypeCode, pNumFound);
}
return SKYRESULT_OK;
}
pLastKey = pKey;
++iCurrentKeyIndex;
}
}
return SKYRESULT_FAIL;
}
//------------------------------------------------------------------------------
// Function : SkyArchive::GetNumUniqueNames
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::GetNumUniqueNames() const
* @brief Computes the number of unique key names in _dataTable.
*/
unsigned int SkyArchive::GetNumUniqueNames() const
{
// duh!
if (IsEmpty())
return 0;
unsigned int iNumKeys = 0;
SkyMMapConstIter iter;
const char* pLastKey = "";
for (iter = _dataTable.begin(); iter != _dataTable.end(); iter++)
{
const char* pKey = (*iter).first;
if (::strcmp( pLastKey, pKey))
{
++iNumKeys;
pLastKey = pKey;
}
}
return iNumKeys;
}
//=============================================================================
// Removing Contents of SkyArchive
//=============================================================================
//------------------------------------------------------------------------------
// Function : SkyArchive::MakeEmpty
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::MakeEmpty()
* @brief Remove all the contents of the database.
*/
SKYRESULT SkyArchive::MakeEmpty()
{
SkyMMapIter iter;
for (iter = _dataTable.begin(); iter != _dataTable.end(); iter++)
{
SkyArchiveEntry* pEntry = (*iter).second;
char* pName = (*iter).first;
SAFE_DELETE_ARRAY(pName);
if (ARCHIVE_TYPE == pEntry->type)
{
SkyArchive* pArchive = (SkyArchive*)(pEntry->pData);
SAFE_DELETE(pArchive);
}
else
{
SAFE_DELETE_ARRAY(pEntry->pData);
}
SAFE_DELETE(pEntry);
}
_dataTable.clear();
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkyArchive::IsEmpty
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::IsEmpty() const
* @brief returns true if the archive is empty, false if it contains any data.
*/
bool SkyArchive::IsEmpty() const
{
return (0 == _dataTable.size());
}
//------------------------------------------------------------------------------
// Function : SkyArchive::Load
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::Load(const char* pFileName)
* @brief Load the contents of a SkyArchive from file storage.
*/
bool SkyArchive::Load(const char* pFileName)
{
if (!pFileName) {
FAIL_RETURN_MSG(SKYRESULT_FAIL, "Error: SkyArchive::Load(): file name is NULL.");
}
FILE* pSrcFile = NULL;
if (NULL == (pSrcFile = fopen(pFileName, "rb"))) // file opened successfully
{
SkyTrace("Error: SkyArchive::Load(): failed to open file for reading.");
return false;
}
SKYRESULT retVal = _Load(pSrcFile);
fclose(pSrcFile);
FAIL_RETURN(retVal);
return true;
}
//------------------------------------------------------------------------------
// Function : SkyArchive::Commit
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::Save(const char* pFilename) const
* @brief Commit Contents of SkyArchive to file storage.
*/
SKYRESULT SkyArchive::Save(const char* pFileName) const
{
if (!pFileName)
FAIL_RETURN_MSG(SKYRESULT_FAIL, "Error: SkyArchive::Save(): file name is NULL.");
FILE* pDestFile = NULL;
if (NULL == (pDestFile = fopen(pFileName, "wb"))) // file opened successfully
FAIL_RETURN_MSG(SKYRESULT_FAIL, "Error: SkyArchive::Save(): failed to open file for writing.");
SKYRESULT retVal = _Save(pDestFile);
fflush(pDestFile);
fclose(pDestFile);
FAIL_RETURN(retVal);
return SKYRESULT_OK;
}
//=============================================================================
// Private helper functions
//=============================================================================
//------------------------------------------------------------------------------
// Function : SkyArchive::_FindEntry
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::_FindEntry(const char* pName, unsigned int index, SkyArchiveTypeCode eType) const
* @brief Locates and returns the SkyArchiveEntry with the specified name, index, and type.
*
* PARAMETERS
* @param pName Entry name to locate (this is used as the database key)
* @param index Entry index to locate (in case of multiple entries)
* @param type Entry must have this type (@see SkyArchiveTypeCode)
*
* Returns a pointer to the entry or NULL if no matching entry could be located.
*/
const SkyArchiveEntry* SkyArchive::_FindEntry(const char* pName,
unsigned int index,
SkyArchiveTypeCode eType) const
{
//
// Find the range of entries in the mmap with the key matching /name/
//
std::pair< SkyMMapConstIter, SkyMMapConstIter > b = _dataTable.equal_range((char*)pName);
unsigned int count = 0;
for (SkyMMapConstIter i = b.first; (i != b.second) && (count <= index); ++i)
{
//
// The entry's type and index must match...
//
const SkyArchiveEntry* pEntry = (*i).second;
if (pEntry->type == eType)
{
if (count == index)
{
return pEntry;
}
// only increment the count when the type matches
++count;
}
}
return NULL;
}
//.---------------------------------------------------------------------------.
//| Function : SkyArchive::_CopyDataTable |
//| Description: |
//.---------------------------------------------------------------------------.
void SkyArchive::_CopyDataTable( const SkyArchiveMMap& src)
{
SkyMMapConstIter iter;
for (iter = src.begin(); iter != src.end(); iter++)
{
const SkyArchiveEntry* pSrcEntry = (*iter).second;
const char* pSrcName = (*iter).first;
if (ARCHIVE_TYPE == pSrcEntry->type)
{
SkyArchive* pSrcArchive = (SkyArchive*)pSrcEntry->pData;
AddArchive(*pSrcArchive);
}
else
{
SkyArchiveEntry* pNewEntry = new SkyArchiveEntry;
pNewEntry->type = pSrcEntry->type;
pNewEntry->iDataSize = pSrcEntry->iDataSize;
pNewEntry->pData = new unsigned char[pNewEntry->iDataSize];
::memcpy( pNewEntry->pData, pSrcEntry->pData, pNewEntry->iDataSize);
char* pName = new char[::strlen(pSrcName)+1];
::strcpy( pName, pSrcName );
_dataTable.insert(std::make_pair(pName, pNewEntry));
}
}
}
//------------------------------------------------------------------------------
// Function : SkyArchive::_Save
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::_Save(FILE* pDestFile) const
* @brief Saves data to a file (possibly recursively in the case of subarchives).
*/
SKYRESULT SkyArchive::_Save(FILE* pDestFile) const
{
// fill out a record for this archive & write it
SkyArchiveFileEntry me;
me.type = ARCHIVE_TYPE;
::strncpy( me.pName, _pName, 32);
me.iDataSize = _dataTable.size();
size_t iNumItemsWritten = fwrite((const void*)&me, sizeof(SkyArchiveFileEntry), 1, pDestFile);
if (1 > iNumItemsWritten)
FAIL_RETURN_MSG(SKYRESULT_FAIL, "Error: SkyArchive::_Save(): failed to write Archive header.");
SkyMMapConstIter iter;
for (iter = _dataTable.begin(); iter != _dataTable.end(); iter++)
{
// fill out a record for each item in _dataTable & write it
const SkyArchiveEntry* pEntry = (*iter).second;
switch(pEntry->type)
{
case ARCHIVE_TYPE:
{
((SkyArchive*)(pEntry->pData))->_Save(pDestFile);
break;
}
default:
{
SkyArchiveFileEntry item;
item.type = pEntry->type;
::strncpy( item.pName, (*iter).first, 32);
item.iDataSize = pEntry->iDataSize;
iNumItemsWritten = fwrite((const void*)&item, sizeof(SkyArchiveFileEntry), 1, pDestFile);
if (1 > iNumItemsWritten)
FAIL_RETURN_MSG(SKYRESULT_FAIL, "Error: SkyArchive::_Save(): failed to write Archive Entry header.");
iNumItemsWritten = fwrite((const void*)pEntry->pData, pEntry->iDataSize, 1, pDestFile);
if (1 > iNumItemsWritten)
FAIL_RETURN_MSG(SKYRESULT_FAIL, "Error: SkyArchive::_Save(): failed to write Archive Entry data.");
break;
}
}
}
return SKYRESULT_OK;
}
//------------------------------------------------------------------------------
// Function : SkyArchive::_Load
// Description :
//------------------------------------------------------------------------------
/**
* @fn SkyArchive::_Load( FILE* pSrcFile)
* @brief Loads data from a file (possibly recursively in the case of subarchives).
*/
SKYRESULT SkyArchive::_Load( FILE* pSrcFile)
{
// first make sure the file is open and readable.
// load the first record
SkyArchiveFileEntry thisItem;
size_t iNumItemsRead = fread((void*)&thisItem, sizeof(SkyArchiveFileEntry), 1, pSrcFile);
if (1 > iNumItemsRead)
FAIL_RETURN_MSG(SKYRESULT_FAIL, "Error: SkyArchive::_Load(): failed to read Archive header.");
_pName = new char[::strlen(thisItem.pName)+1];
::strcpy( _pName, thisItem.pName);
for (unsigned int iNumItems = 0; iNumItems < thisItem.iDataSize; ++iNumItems)
{
SkyArchiveFileEntry embeddedItem;
long iFileLoc = ftell(pSrcFile); // store location before the read
iNumItemsRead = fread((void*)&embeddedItem, sizeof(SkyArchiveFileEntry), 1, pSrcFile);
if (1 > iNumItemsRead)
FAIL_RETURN_MSG(SKYRESULT_FAIL, "Error: SkyArchive::_Load(): failed to read embedded archive item.");
switch( embeddedItem.type)
{
case ARCHIVE_TYPE:
{
if (0 != fseek(pSrcFile, iFileLoc, SEEK_SET))
FAIL_RETURN_MSG(SKYRESULT_FAIL, "Error: SkyArchive::_Load(): failed to set the file position.");
SkyArchive newArchive;
newArchive._Load(pSrcFile); // recursively load the subarchive
AddArchive(newArchive); // add the loaded archive to the database in memory.
}
break;
default:
{
void* pData = new unsigned char[embeddedItem.iDataSize];
iNumItemsRead = fread((void*)pData, embeddedItem.iDataSize, 1, pSrcFile);
if (1 > iNumItemsRead)
FAIL_RETURN_MSG(SKYRESULT_FAIL, "Error: SkyArchive::_Load(): failed to read item data.");
AddData( embeddedItem.pName,
(SkyArchiveTypeCode)embeddedItem.type,
pData,
embeddedItem.iDataSize);
delete[] pData;
break;
}
}
}
return SKYRESULT_OK;
}