TXP plugin update from Boris Bralo.

This commit is contained in:
Robert Osfield
2002-03-09 10:51:09 +00:00
parent 689eca77d7
commit ab5603e3d4
27 changed files with 7786 additions and 4872 deletions

View File

@@ -1,34 +1,32 @@
/* ************************
Copyright Terrain Experts Inc.
Terrain Experts Inc (TERREX) reserves all rights to this source code
unless otherwise specified in writing by the Chief Operating Officer
of TERREX.
unless otherwise specified in writing by the President of TERREX.
This copyright may be updated in the future, in which case that version
supercedes this one.
-------------------
Terrex Experts Inc.
84 West Santa Clara St., Suite 380
San Jose, CA 95113
4400 East Broadway #314
Tucson, AZ 85711
info@terrex.com
Tel: (408) 293-9977
Tel: (520) 323-7990
************************
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
/* trpage_readbuf.cpp
Methods for the trpgReadBuffer and trpgMemReadBuffer classes.
trpgReadBuffer is a virtual base class with a few utility functions.
It's used as generic interface for reading data out of.
trpgMemReadBuffer is a subclass of that which implements methods for
reading out of a chunk of memory. Data is read off of disk and then
dumped into a read buffer for parsing.
If you wanted to read directly from disk, for example, you could
implement a trpgDiskReadBuffer as a subclass of trpgReadBuffer.
*/
Methods for the trpgReadBuffer and trpgMemReadBuffer classes.
trpgReadBuffer is a virtual base class with a few utility functions.
It's used as generic interface for reading data out of.
trpgMemReadBuffer is a subclass of that which implements methods for
reading out of a chunk of memory. Data is read off of disk and then
dumped into a read buffer for parsing.
If you wanted to read directly from disk, for example, you could
implement a trpgDiskReadBuffer as a subclass of trpgReadBuffer.
*/
#include "trpage_io.h"
#include "trpage_swap.h"
@@ -41,243 +39,243 @@
// Basic get functions
bool trpgReadBuffer::Get(int32 &ret)
{
int32 val;
int32 val;
if (!GetData((char *)&val,sizeof(int32))) return false;
if (ness != cpuNess)
ret = trpg_byteswap_int(val);
else
ret = val;
if (!GetData((char *)&val,sizeof(int32))) return false;
if (ness != cpuNess)
ret = trpg_byteswap_int(val);
else
ret = val;
return true;
return true;
}
bool trpgReadBuffer::Get(int64 &ret)
{
int64 val;
int64 val;
if (!GetData((char *)&val,sizeof(int64))) return false;
if (ness != cpuNess)
ret = trpg_byteswap_llong(val);
else
ret = val;
if (!GetData((char *)&val,sizeof(int64))) return false;
if (ness != cpuNess)
ret = trpg_byteswap_long(val);
else
ret = val;
return true;
return true;
}
bool trpgReadBuffer::Get(char *ret,int retLen)
{
int32 len;
int32 len;
// Get the length first
if (!Get(len)) return false;
// Get the length first
if (!Get(len)) return false;
// Read what we can
int rlen = MIN(len,retLen-1);
if (!GetData(ret,rlen)) return false;
ret[rlen] = 0;
// Read what we can
int rlen = MIN(len,retLen-1);
if (!GetData(ret,rlen)) return false;
ret[rlen] = 0;
// Skip the rest
if (!Skip(rlen-len)) return false;
// Skip the rest
if (!Skip(rlen-len)) return false;
return true;
return true;
}
bool trpgReadBuffer::Get(float32 &ret)
{
char cval[4];
char cval[4];
if (!GetData(cval,sizeof(float32))) return false;
try {
if (ness == cpuNess)
memcpy(&ret,cval,4);
else
ret = trpg_byteswap_4bytes_to_float(cval);
}
catch (...) {
}
if (!GetData(cval,sizeof(float32))) return false;
try {
if (ness == cpuNess)
memcpy(&ret,cval,4);
else
ret = trpg_byteswap_4bytes_to_float(cval);
}
catch (...) {
}
return true;
return true;
}
bool trpgReadBuffer::Get(float64 &ret)
{
char cval[8];
char cval[8];
if (!GetData(cval,sizeof(float64))) return false;
try {
if (ness == cpuNess)
memcpy(&ret,cval,8);
else
ret = trpg_byteswap_8bytes_to_double(cval);
}
catch (...) {
}
if (!GetData(cval,sizeof(float64))) return false;
try {
if (ness == cpuNess)
memcpy(&ret,cval,8);
else
ret = trpg_byteswap_8bytes_to_double(cval);
}
catch (...) {
}
return true;
return true;
}
bool trpgReadBuffer::Get(uint8 &ret)
{
uint8 val;
uint8 val;
if (!GetData((char *)&val,sizeof(uint8))) return false;
// No byte swapping needed
ret = val;
if (!GetData((char *)&val,sizeof(uint8))) return false;
// No byte swapping needed
ret = val;
return true;
return true;
}
#if (bool != int32)
bool trpgReadBuffer::Get(bool &ret)
{
uint8 val;
uint8 val;
if (!GetData((char *)&val,sizeof(uint8))) return false;
// No byte swapping needed
ret = (val == 0) ? false : true;
if (!GetData((char *)&val,sizeof(uint8))) return false;
// No byte swapping needed
ret = (val == 0) ? false : true;
return true;
return true;
}
#endif
#if (trpgDiskRef != int64)
bool trpgReadBuffer::Get(trpgDiskRef &ret)
{
trpgDiskRef val;
trpgDiskRef val;
if (!GetData((char *)&val,sizeof(trpgDiskRef))) return false;
if (ness == cpuNess)
ret = val;
else
ret = trpg_byteswap_llong(val);
if (!GetData((char *)&val,sizeof(trpgDiskRef))) return false;
if (ness == cpuNess)
ret = val;
else
ret = trpg_byteswap_llong(val);
return true;
return true;
}
#endif
bool trpgReadBuffer::Get(trpgToken &ret)
{
trpgToken val;
trpgToken val;
if (!GetData((char *)&val,sizeof(trpgToken))) return false;
if (ness == cpuNess)
ret = val;
else
ret = trpg_byteswap_short(val);
if (!GetData((char *)&val,sizeof(trpgToken))) return false;
if (ness == cpuNess)
ret = val;
else
ret = trpg_byteswap_short(val);
return true;
return true;
}
// Array Get functions
bool trpgReadBuffer::GetArray(int len,float32 **arr)
{
if (!GetDataRef((char **)arr,sizeof(float32)*len))
return false;
// Byteswap in place if necessary
if (ness != cpuNess) {
char *ptr;
int pos;
for (pos=0,ptr = (char *)*arr;pos<len;pos++,ptr+=4)
trpg_swap_four(ptr,ptr);
}
if (!GetDataRef((char **)arr,sizeof(float32)*len))
return false;
// Byteswap in place if necessary
if (ness != cpuNess) {
char *ptr;
int pos;
for (pos=0,ptr = (char *)*arr;pos<len;pos++,ptr+=4)
trpg_swap_four(ptr,ptr);
}
return true;
return true;
}
bool trpgReadBuffer::GetArray(int len,float64 **arr)
{
if (!GetDataRef((char **)arr,sizeof(float64)*len))
return false;
// Byteswap in place if necessary
if (ness != cpuNess) {
char *ptr;
int pos;
for (pos=0,ptr = (char *)*arr;pos<len;pos++,ptr+=8)
trpg_swap_eight(ptr,ptr);
}
return true;
if (!GetDataRef((char **)arr,sizeof(float64)*len))
return false;
// Byteswap in place if necessary
if (ness != cpuNess) {
char *ptr;
int pos;
for (pos=0,ptr = (char *)*arr;pos<len;pos++,ptr+=8)
trpg_swap_eight(ptr,ptr);
}
return true;
}
bool trpgReadBuffer::GetArray(int len,int32 **arr)
{
if (!GetDataRef((char **)arr,sizeof(int32)*len))
return false;
// Byteswap in place if necessary
if (ness != cpuNess) {
char *ptr;
int pos;
for (pos=0,ptr = (char *)*arr;pos<len;pos++,ptr+=4)
trpg_swap_four(ptr,ptr);
}
return true;
if (!GetDataRef((char **)arr,sizeof(int32)*len))
return false;
// Byteswap in place if necessary
if (ness != cpuNess) {
char *ptr;
int pos;
for (pos=0,ptr = (char *)*arr;pos<len;pos++,ptr+=4)
trpg_swap_four(ptr,ptr);
}
return true;
}
bool trpgReadBuffer::GetArray(int len,trpgColor **arr)
{
if (!GetDataRef((char **)arr,sizeof(trpgColor)*len))
return false;
// Byteswap in place if necessary
if (ness != cpuNess) {
char *ptr;
int pos;
for (pos=0,ptr = (char *)*arr;pos<len;pos++,ptr+=8)
trpg_swap_four(ptr,ptr);
}
return true;
if (!GetDataRef((char **)arr,sizeof(trpgColor)*len))
return false;
// Byteswap in place if necessary
if (ness != cpuNess) {
char *ptr;
int pos;
for (pos=0,ptr = (char *)*arr;pos<len;pos++,ptr+=8)
trpg_swap_four(ptr,ptr);
}
return true;
}
bool trpgReadBuffer::GetArray(int len,char **arr)
{
return GetDataRef((char **)arr,sizeof(char)*len);
return GetDataRef((char **)arr,sizeof(char)*len);
}
// Utility Get functions - Just call the others
bool trpgReadBuffer::Get(trpg2iPoint &pt)
{
if (!Get(pt.x) || !Get(pt.y))
return false;
return true;
if (!Get(pt.x) || !Get(pt.y))
return false;
return true;
}
bool trpgReadBuffer::Get(trpg2dPoint &pt)
{
if (!Get(pt.x) || !Get(pt.y))
return false;
return true;
if (!Get(pt.x) || !Get(pt.y))
return false;
return true;
}
bool trpgReadBuffer::Get(trpg3dPoint &pt)
{
if (!Get(pt.x) || !Get(pt.y) || !Get(pt.z))
return false;
return true;
if (!Get(pt.x) || !Get(pt.y) || !Get(pt.z))
return false;
return true;
}
bool trpgReadBuffer::Get(trpgColor &color)
{
if (!Get(color.red) || !Get(color.green) || !Get(color.blue))
return false;
return true;
if (!Get(color.red) || !Get(color.green) || !Get(color.blue))
return false;
return true;
}
// Get both a token and it's length, since that's fairly common
bool trpgReadBuffer::GetToken(trpgToken &tok,int32 &len)
{
if (!Get(tok) || !Get(len))
return false;
if (!Get(tok) || !Get(len))
return false;
return true;
return true;
}
/* Limit Handling functions
These impose arbitrary lenght limits on the read buffer.
This keeps us from reading pased a token group and parsing
random data within an archive.
*/
These impose arbitrary lenght limits on the read buffer.
This keeps us from reading pased a token group and parsing
random data within an archive.
*/
// Push Limit
// Add another limit to the top of the stack
void trpgReadBuffer::PushLimit(int limit)
{
limits.push_back(limit);
limits.push_back(limit);
}
// Pop Limit
// Remove the current limit from the stack
void trpgReadBuffer::PopLimit()
{
int len = limits.size();
int len = limits.size();
if (len > 0)
limits.resize(len-1);
if (len > 0)
limits.resize(len-1);
}
// Skip To Limit
@@ -285,34 +283,34 @@ void trpgReadBuffer::PopLimit()
// This happens when we bag the rest of the current token
bool trpgReadBuffer::SkipToLimit()
{
int len=0;
int len=0;
if (limits.size() != 0)
len = limits[limits.size()-1];
if (limits.size() != 0)
len = limits[limits.size()-1];
if (len > 0)
return Skip(len);
if (len > 0)
return Skip(len);
return true;
return true;
}
// Test Limit
// See if the next read is going to blow the limits
bool trpgReadBuffer::TestLimit(int len)
{
for (unsigned int i=0;i<limits.size();i++)
if (len > limits[i])
return false;
for (int i=0;i<limits.size();i++)
if (len > limits[i])
return false;
return true;
return true;
}
// Update Limits
// We just read a few bytes. Update the limits
void trpgReadBuffer::UpdateLimits(int len)
{
for (unsigned int i=0;i<limits.size();i++)
limits[i] -= len;
for (int i=0;i<limits.size();i++)
limits[i] -= len;
}
/* *************************
@@ -321,110 +319,299 @@ void trpgReadBuffer::UpdateLimits(int len)
*/
trpgMemReadBuffer::trpgMemReadBuffer(trpgEndian in_ness)
{
data = NULL;
len = totLen = pos = 0;
ness = in_ness;
cpuNess = trpg_cpu_byte_order();
data = NULL;
len = totLen = pos = 0;
ness = in_ness;
cpuNess = trpg_cpu_byte_order();
}
trpgMemReadBuffer::~trpgMemReadBuffer()
{
if (data)
delete data;
if (data)
delete [] data;
}
// Empty check
bool trpgMemReadBuffer::isEmpty()
{
if (!data) return true;
if (!data) return true;
if (pos >= len)
return true;
if (pos >= len)
return true;
// Also test the limits
for (unsigned int i=0;i<limits.size();i++)
if (limits[i] == 0) return true;
// Also test the limits
for (int i=0;i<limits.size();i++)
if (limits[i] == 0) return true;
return false;
return false;
}
// Set Length
// Allocate the given space
void trpgMemReadBuffer::SetLength(int newLen)
{
if (newLen > totLen) {
if (data)
delete data;
data = new char[newLen];
totLen = newLen;
}
len = newLen;
pos = 0;
if (newLen > totLen) {
if (data)
delete [] data;
data = new char[newLen];
totLen = newLen;
}
len = newLen;
pos = 0;
}
// Get Data Ptr
// Return a pointer to our data so it can be written to
char *trpgMemReadBuffer::GetDataPtr()
{
return data;
return data;
}
// Get Data
// Protected method for actually retrieving a piece of data
bool trpgMemReadBuffer::GetData(char *ret,int rlen)
{
if (rlen < 0)
return false;
if (rlen < 0)
return false;
// Test against limits imposed from without
if (!TestLimit(rlen)) throw 1;
// Test against limits imposed from without
if (!TestLimit(rlen)) throw 1;
// See if we've actually got the data
if (pos+rlen > len) throw 1;
// See if we've actually got the data
if (pos+rlen > len) throw 1;
// Copy into the return buffer
memcpy(ret,&data[pos],rlen);
// Copy into the return buffer
memcpy(ret,&data[pos],rlen);
// Update any limits we might have
UpdateLimits(rlen);
// Update any limits we might have
UpdateLimits(rlen);
pos += rlen;
pos += rlen;
return true;
return true;
}
// Get Reference to Data
// Protected method that retrieves a reference to the given amoutn of data
bool trpgMemReadBuffer::GetDataRef(char **ret,int rlen)
{
if (rlen < 0) return false;
if (rlen < 0) return false;
// Test against limits
if (!TestLimit(rlen)) throw 1;
if (pos + rlen > len) throw 1;
// Test against limits
if (!TestLimit(rlen)) throw 1;
if (pos + rlen > len) throw 1;
// Set up reference
*ret = &data[pos];
// Set up reference
*ret = &data[pos];
UpdateLimits(rlen);
pos += rlen;
UpdateLimits(rlen);
pos += rlen;
return true;
return true;
}
// Skip
// Same as read except we're not, uh, reading
bool trpgMemReadBuffer::Skip(int rlen)
{
if (rlen < 0)
return false;
if (rlen < 0)
return false;
// Test against limits
if (!TestLimit(rlen)) return false;
if (pos + rlen > len) return false;
// Test against limits
if (!TestLimit(rlen)) return false;
if (pos + rlen > len) return false;
UpdateLimits(rlen);
UpdateLimits(rlen);
pos += rlen;
pos += rlen;
return true;
return true;
}
/* Appendable File read class
*/
trpgrAppFile::trpgrAppFile(trpgEndian inNess,const char *fileName)
{
valid = false;
ness = inNess;
cpuNess = trpg_cpu_byte_order();
if (!(fp = fopen(fileName,"rb")))
return;
valid = true;
}
trpgrAppFile::~trpgrAppFile()
{
if (fp)
fclose(fp);
valid = false;
}
// Read a section of data from the given file
// and dump it into the given buffer
bool trpgrAppFile::Read(trpgMemReadBuffer *buf,int32 offset)
{
if (!valid) return false;
// Seek to the right location
if (fseek(fp,offset,SEEK_SET))
return false;
// Read a length
int32 len;
if (fread(&len,sizeof(int32),1,fp) != 1) {
valid = false;
return false;
}
// Byteswap if necessary
if (ness != cpuNess)
trpg_byteswap_int(len);
if (len < 0) {
valid = false;
return false;
}
buf->SetLength(len);
char *data = buf->GetDataPtr();
if (!data) {
valid = false;
return false;
}
if (fread(data,sizeof(char),len,fp) != len) {
valid = false;
return false;
}
return true;
}
/* Read a section of data from the given file
and dump it into the given memory. Sanity
check the length against the size of the memory
passed into dataSize.
*/
bool trpgrAppFile::Read(char *data,int32 offset,int32 dataSize)
{
if (!valid) return false;
// Seek to the right place
int result;
if ((result = fseek(fp,offset,SEEK_SET))) {
valid = false;
return false;
}
// Read the length
int32 len;
if (fread(&len,sizeof(int32),1,fp) != 1) {
valid = false;
return false;
}
// Byteswap if necessary
if (ness != cpuNess)
trpg_byteswap_int(len);
if (len < 0) {
valid = false;
return false;
}
// It's all right to read less than the whol data block
if (dataSize > len)
return false;
// Read the raw data
// Note: What about byte swapping?
if (fread(data,sizeof(char),dataSize,fp) != dataSize) {
valid = false;
return false;
}
return true;
}
/* App File Cache
This class manages a group of appendable files with
the same base name and extension. It will keep a certain
number of them open to facilitate caching.
*/
trpgrAppFileCache::trpgrAppFileCache(const char *inPre,const char *inExt,int noFiles)
{
strcpy(baseName,inPre);
strcpy(ext,inExt);
files.resize(noFiles);
timeCount = 0;
}
trpgrAppFileCache::~trpgrAppFileCache()
{
for (unsigned int i=0;i<files.size();i++) {
if (files[i].afile) {
delete files[i].afile;
files[i].afile = NULL;
}
}
}
/*
*/
trpgrAppFile *trpgrAppFileCache::GetFile(trpgEndian ness,int id)
{
// Look for it already here
int foundID = -1;
unsigned int i;
for (i=0;i<files.size();i++) {
if (files[i].id == id) {
foundID = i;
}
}
// Found it in cache, just return
if (foundID != -1) {
OpenFile &of = files[foundID];
of.lastUsed = timeCount;
return of.afile;
}
// Didn't find it. Need to reclaim one
// Look for the oldest used
int oldTime=-1,oldID=-1;
for (i=0;i<files.size();i++) {
OpenFile &of = files[i];
if (!of.afile || (of.lastUsed < oldTime)) {
oldID = i;
oldTime = of.lastUsed;
if (!of.afile)
break;
}
}
// Reclaim this one
OpenFile &of = files[oldID];
if (of.afile) delete of.afile;
char fileName[1024];
sprintf(fileName,"%s_%d.%s",baseName,id,ext);
of.afile = new trpgrAppFile(ness,fileName);
of.id = id;
of.lastUsed = timeCount;
timeCount++;
return of.afile;
}
// Constructor for OpenFile class
trpgrAppFileCache::OpenFile::OpenFile()
{
afile = NULL;
lastUsed = 0;
id = -1;
}