#include "geometryCacheFile.h"
#include "geometryCacheBlockBase.h"
#include "geometryCacheBlockStringData.h"
#include "geometryCacheBlockIntData.h"
#include "geometryCacheBlockDVAData.h"
#include "geometryCacheBlockFVAData.h"
#include <maya/flib.h>
#include <maya/MString.h>
#include <maya/MGlobal.h>
#include <fstream>
#if defined (__APPLE__)
#include <stdlib.h>
#else
#include <malloc.h>
#endif
geometryCacheFile::geometryCacheFile(
const MString& fileName,
MIffFile* iffFile )
:cacheFileName( fileName )
{
readStatus = false;
iffFilePtr = iffFile;
}
geometryCacheFile::~geometryCacheFile()
{
while( blockList.size() )
{
geometryCacheBlockBase * block = blockList.back();
delete block;
blockList.pop_back();
}
}
const MString& geometryCacheFile::fileName()
{
return cacheFileName;
}
const bool& geometryCacheFile::isRead()
{
return readStatus;
}
bool geometryCacheFile::readCacheFiles()
{
status = iffFilePtr->open( cacheFileName );
if( !status ) return false;
if( iffFilePtr->isActive() ) {
readStatus = readHeaderGroup( status );
if( !readStatus ) return false;
do {
readStatus = readChannelGroup( status );
if( !readStatus ) return false;
} while ( status == MS::kSuccess );
} else
return false;
return true;
}
bool geometryCacheFile::convertToAscii()
{
int loc = cacheFileName.rindex('.');
outputFileName += ".txt";
std::ofstream oFile( outputFileName.
asChar() );
if( !oFile.bad() )
{
cacheBlockIterator blockIt;
for( blockIt = blockList.begin();
blockIt != blockList.end();
blockIt++ )
{
geometryCacheBlockBase* block = *blockIt;
block->outputToAscii( oFile );
}
} else
return false;
cacheFileName +
"\" to file \"" +
outputFileName +
"\"" );
return true;
}
bool geometryCacheFile::readHeaderGroup(
MStatus& status )
{
status = iffFilePtr->beginReadGroup( tmpTag, cachTag );
if( status ) {
if( cachTag ==
MIffTag(
'C',
'A',
'C',
'H') ) {
storeCacheBlock( "CACH" );
readStatus = readHeaderVersion();
if( !readStatus ) return false;
readStatus = readHeaderTimeRange();
if( !readStatus ) return false;
storeCacheBlock( "/CACH" );
}
}
iffFilePtr->endReadGroup();
return true;
}
bool geometryCacheFile::readHeaderVersion()
{
unsigned int byteCount;
status = iffFilePtr->beginGet( tmpTag, (unsigned *)&byteCount );
if( !status ) return false;
char *tmpName = (char*)alloca(sizeof(char)* (byteCount+1));
if( tmpName && tmpTag ==
MIffTag(
'V',
'R',
'S',
'N') ) {
iffFilePtr->get( tmpName, byteCount, &status);
if( !status ) return false;
storeCacheBlock( "VRSN", tmpName );
status = iffFilePtr->endGet();
if( !status ) return false;
}
return true;
}
bool geometryCacheFile::readHeaderTimeRange()
{
unsigned int byteCount;
const int *startTime = (int *)iffFilePtr->getChunk( tmpTag, (unsigned int *)&byteCount );
if( startTime == NULL ||
!(tmpTag ==
MIffTag (
'S',
'T',
'I',
'M')) ||
byteCount != sizeof(int) )
return false;
storeCacheBlock( "STIM", FLswapword(*startTime) );
const int *endTime = (int *)iffFilePtr->getChunk( tmpTag, (unsigned int *)&byteCount );
if( endTime == NULL ||
!(tmpTag ==
MIffTag(
'E',
'T',
'I',
'M')) ||
byteCount != sizeof(int) )
return false;
storeCacheBlock( "ETIM", FLswapword(*endTime) );
return true;
}
bool geometryCacheFile::readChannelGroup(
MStatus& groupStatus )
{
unsigned int byteCount;
groupStatus = iffFilePtr->beginReadGroup(tmpTag, mychTag);
if( groupStatus == MS::kSuccess ) {
if( mychTag ==
MIffTag(
'M',
'Y',
'C',
'H')) {
storeCacheBlock( "MYCH" );
MStatus stat = iffFilePtr->beginGet(tmpTag, (
unsigned *)&byteCount);
if (!stat) return false;
if( tmpTag ==
MIffTag(
'T',
'I',
'M',
'E') )
{
readStatus = readChannelTime();
if ( !readStatus ) return false;
stat = iffFilePtr->endGet();
if (!stat) return false;
}
MStatus channelStatus = MS::kSuccess;
do {
readStatus = readChannel( channelStatus );
if( !readStatus ) return false;
} while ( channelStatus == MS::kSuccess );
storeCacheBlock( "/MYCH" );
}
}
iffFilePtr->endReadGroup();
return readStatus;
}
bool geometryCacheFile::readChannelTime()
{
unsigned int byteCount;
const int *tmpNum = (int*) iffFilePtr->getChunk( tmpTag, (unsigned *)&byteCount );
if( tmpNum &&
tmpTag ==
MIffTag(
'T',
'I',
'M',
'E') &&
byteCount == sizeof(int)) {
storeCacheBlock( "TIME", FLswapword(*tmpNum) );
}
return true;
}
bool geometryCacheFile::readChannel(
MStatus& channelStatus )
{
readStatus = readChannelName( channelStatus );
if( !readStatus ) return false;
if( !channelStatus ) return true;
readStatus = readChannelData();
if( !readStatus ) return false;
return true;
}
bool geometryCacheFile::readChannelName(
MStatus& channelStatus )
{
unsigned int byteCount;
channelStatus = iffFilePtr->beginGet( chnmTag, (unsigned *)&byteCount );
if( channelStatus == MS::kSuccess ) {
char *tmpName = (char*)alloca(sizeof(char)* (byteCount+1));
if( tmpName && chnmTag ==
MIffTag(
'C',
'H',
'N',
'M') ) {
iffFilePtr->get( tmpName, byteCount, &lStatus);
if( !lStatus ) return false;
storeCacheBlock( "CHNM", channelName );
} else return false;
}
iffFilePtr->endGet();
return true;
}
bool geometryCacheFile::readChannelData()
{
unsigned int byteCount;
uint size;
const int *tmpNum = (int*) iffFilePtr->getChunk(tmpTag, (unsigned *)&byteCount);
if( tmpNum &&
tmpTag ==
MIffTag(
'S',
'I',
'Z',
'E') &&
byteCount == sizeof(int))
{
size = FLswapword(*tmpNum);
storeCacheBlock( "SIZE", size );
} else return false;
if( size ) {
const void *tmpVec = (double*) iffFilePtr->getChunk(tmpTag, (unsigned *)&byteCount);
if( tmpVec &&
tmpTag ==
MIffTag(
'D',
'V',
'C',
'A') &&
size * sizeof(double)*3 == byteCount )
{
double *tmpVecDbl = (double*) tmpVec;
double *dataArray = new double[size*3];
for(unsigned int i = 0; i < size*3; i++) {
FLswapdouble(tmpVecDbl[i], &(dataArray[i]));
}
storeCacheBlock( "DVCA", dataArray, size );
delete [] dataArray;
} else if( tmpVec &&
tmpTag ==
MIffTag(
'F',
'V',
'C',
'A') &&
size * sizeof(float)*3 == byteCount ) {
float *tmpVecFlt = (float*) tmpVec;
float *dataArray = new float[size*3];
for(unsigned int i = 0; i < size*3; i++) {
FLswapfloat(tmpVecFlt[i], &(dataArray[i]));
}
storeCacheBlock( "FVCA", dataArray, size );
delete [] dataArray;
} else {
return false;
}
}
return true;
}
void geometryCacheFile::storeCacheBlock(
const MString& tag )
{
blockList.push_back( new geometryCacheBlockBase( tag ) );
}
void geometryCacheFile::storeCacheBlock(
const MString& tag,
const int& value )
{
blockList.push_back( new geometryCacheBlockIntData( tag, value ) );
}
void geometryCacheFile::storeCacheBlock(
const MString& tag,
const MString& value )
{
blockList.push_back( new geometryCacheBlockStringData( tag, value ) );
}
void geometryCacheFile::storeCacheBlock(
const MString& tag,
const double* value,
const unsigned int& size )
{
blockList.push_back( new geometryCacheBlockDVAData( tag, value, size ) );
}
void geometryCacheFile::storeCacheBlock(
const MString& tag,
const float* value,
const unsigned int& size )
{
blockList.push_back( new geometryCacheBlockFVAData( tag, value, size ) );
}