OpenSceneGraph/src/osgPlugins/txp/trpage_writebuf.cpp
Robert Osfield 720551d549 From Michael Platings, Converted std::fstream/ifstream/ofstream to osgDB::fstream/ifstream/ofstream and
fopen to osgDB::fopen to facilitate support for wide character filenames using UT8 encoding.
2008-11-07 15:08:08 +00:00

461 lines
9.6 KiB
C++

/* ************************
Copyright Terrain Experts Inc.
Terrain Experts Inc (TERREX) reserves all rights to this source code
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.
4400 East Broadway #314
Tucson, AZ 85711
info@terrex.com
Tel: (520) 323-7990
************************
*/
#include <osgDB/FileUtils>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/* trpage_writebuf.cpp
This source file contains the implementation of trpgMemWriteBuffer.
That is a subclass of trpgWriteBuffer, which implements an interface
definition for an object which can accept data to be written.
The Mem version is used to write (for example) a tile's worth of data.
That data can then be written to a file (or sent over the network).
You should not need to change this implementation. Simply sublcass
trpgWriteBuffer and implement all of the required methods. The
resulting class can then be used in all the places a trpgWriteBuffer
is required.
*/
#include <trpage_io.h>
#include <trpage_swap.h>
/* **********************
Memory Write Buffer functions
**********************
*/
// Constructor
trpgMemWriteBuffer::trpgMemWriteBuffer(trpgEndian in_ness)
{
ness = in_ness;
cpuNess = trpg_cpu_byte_order();
data = NULL;
curLen = totLen = 0;
}
// Destructor
trpgMemWriteBuffer::~trpgMemWriteBuffer()
{
if (data)
delete [] data;
data = NULL;
}
/* Length()
Return the length of the given buffer.
*/
int trpgMemWriteBuffer::length() const
{
return curLen;
}
/* getData()
Return a pointer to the memory buffer.
*/
const char *trpgMemWriteBuffer::getData() const
{
return data;
}
/* Length()
Set the maximum buffer length.
*/
void trpgMemWriteBuffer::setLength(unsigned int len)
{
if ((int)len > totLen) {
char *old_data = data;
int oldLen = totLen;
totLen = 2*len;
data = new char[totLen];
if (old_data) {
memcpy(data,old_data,oldLen);
delete [] old_data;
}
}
}
/* append()
Append the given data to our buffer.
*/
void trpgMemWriteBuffer::append(unsigned int len,const char *val)
{
if (len == 0) return;
setLength(curLen+len);
memcpy(&data[curLen],val,len);
curLen += len;
}
/* set()
Set a specific portion of the buffer to a given value.
*/
void trpgMemWriteBuffer::set(unsigned int pos,unsigned int len,const char *val)
{
if (len == 0) return;
if (pos+len > (unsigned int)curLen) return;
memcpy(&data[pos],val,len);
}
/* --- replacement virtual functions --- */
/* Reset()
Drop whatever's being stored.
*/
void trpgMemWriteBuffer::Reset()
{
curLen = 0;
}
// Add(Int32)
void trpgMemWriteBuffer::Add(int32 val)
{
if (ness != cpuNess)
val = trpg_byteswap_int(val);
append(sizeof(int32),(const char *)&val);
}
// Add(int64)
void trpgMemWriteBuffer::Add(int64 val)
{
if (ness != cpuNess)
val = trpg_byteswap_llong(val);
append(sizeof(int64),(const char *)&val);
}
// Add(string)
// [len] [value...]
void trpgMemWriteBuffer::Add(const char *val)
{
int32 len = (val ? strlen(val) : 0),vlen = len;
if (ness != cpuNess)
vlen = trpg_byteswap_int(vlen);
append(sizeof(int32),(const char *)&vlen);
append(len,val);
}
// Add(std::string)
void trpgMemWriteBuffer::Add(std::string &val)
{
Add(val.c_str());
}
// Add(float32)
void trpgMemWriteBuffer::Add(float32 val)
{
char cval[4];
if (ness != cpuNess)
trpg_byteswap_float_to_4bytes(val,cval);
else
memcpy(cval,&val,4);
append(sizeof(float32),cval);
}
// Add(float64)
void trpgMemWriteBuffer::Add(float64 val)
{
char cval[8];
if (ness != cpuNess)
trpg_byteswap_double_to_8bytes(val,cval);
else
memcpy(cval,&val,8);
append(sizeof(float64),cval);
}
// Add(int8)
void trpgMemWriteBuffer::Add(uint8 val)
{
// No byte swapping needed
append(sizeof(uint8),(const char *)&val);
}
//#if (bool != int32)
// Add(bool)
void trpgMemWriteBuffer::Add(bool val)
{
uint8 ival;
ival = (val ? 1 : 0);
Add(ival);
}
//#endif
#if (trpgDiskRef != int64)
// Add(trpgDiskRef)
void trpgMemWriteBuffer::Add(trpgDiskRef val)
{
if (ness != cpuNess)
val = trpg_byteswap_llong(val);
append(sizeof(trpgDiskRef),(const char *)&val);
}
#endif
// Add(trpgToken)
void trpgMemWriteBuffer::Add(trpgToken val)
{
if (ness != cpuNess)
val = trpg_byteswap_short(val);
append(sizeof(trpgToken),(const char *)&val);
}
// Add(tx2iPoint)
void trpgWriteBuffer::Add(const trpg2iPoint &val)
{
Add((int32)val.x);
Add((int32)val.y);
}
// Add(tx2dPoint)
void trpgWriteBuffer::Add(const trpg2dPoint &val)
{
Add((float64)val.x);
Add((float64)val.y);
}
// Add(trpg3dPoint)
void trpgWriteBuffer::Add(const trpg3dPoint &val)
{
Add((float64)val.x);
Add((float64)val.y);
Add((float64)val.z);
}
// Add(trpgColor)
void trpgWriteBuffer::Add(const trpgColor &val)
{
Add(val.red);
Add(val.green);
Add(val.blue);
}
// Add(std::string)
void trpgWriteBuffer::Add(const std::string &val)
{
Add(val.c_str());
}
/* Push()
Starts defining a new object.
Need to keep track of where length goes.
*/
void trpgMemWriteBuffer::Begin(trpgToken tok)
{
Add(tok);
lengths.push_back(curLen);
Add((int32)0);
}
/* Push()
Pushes a level on the stack. For defining children.
*/
void trpgMemWriteBuffer::Push()
{
Add((trpgToken)TRPG_PUSH);
}
/* Pop()
Pops a level off the "stack".
*/
void trpgMemWriteBuffer::Pop()
{
Add((trpgToken)TRPG_POP);
}
/* Will take out a pop from the end of the buffer, if there is one */
bool trpgMemWriteBuffer::UnPop()
{
//Check to see if there is a pop token ant the end
trpgToken tk;
memcpy(&tk, &data[curLen - sizeof(trpgToken)], sizeof(trpgToken));
if(tk == TRPG_POP)
{
curLen -= sizeof(trpgToken);
return true;
}
else
return false;
}
/* Will take out a push from the end of the buffer, if there is one */
bool trpgMemWriteBuffer::UnPush()
{
//Check to see if there is a push token ant the end
trpgToken tk;
memcpy(&tk, &data[curLen - sizeof(trpgToken)], sizeof(trpgToken));
if(tk == TRPG_PUSH)
{
curLen -= sizeof(trpgToken);
return true;
}
else
return false;
}
/* End()
Finished defining an object.
Write the length out where appropriate.
*/
void trpgMemWriteBuffer::End()
{
if (lengths.size() == 0)
// Note: say something clever here
return;
int id = lengths.size()-1;
int32 len = curLen - lengths[id];
int32 rlen = len-sizeof(int32);
if (ness != cpuNess)
rlen = trpg_byteswap_int(rlen);
set(curLen - len,sizeof(int32),(const char *)&rlen);
lengths.resize(id);
}
/* Appendable File
This class is used as a simple appendable file. It's used
for dumping tile and texture (or most anything) into.
*/
trpgwAppFile::trpgwAppFile(trpgEndian inNess,const char *fileName,bool reuse)
{
Init(inNess,fileName,reuse);
}
void trpgwAppFile::Init(trpgEndian inNess,const char *fileName,bool reuse)
{
valid = false;
ness = inNess;
cpuNess = trpg_cpu_byte_order();
if (reuse==false) {
if (!(fp = osgDB::fopen(fileName,"wb")))
return;
lengthSoFar = 0;
valid = true;
} else {
if (!(fp = osgDB::fopen(fileName,"ab")))
return;
// ftell is still zero, dammit. Arg.
fseek(fp,0,SEEK_END);
lengthSoFar = ftell(fp);
valid = true;
}
}
trpgwAppFile::~trpgwAppFile()
{
if (fp)
fclose(fp);
valid = false;
}
// Return the amount of data written so far (in total)
int trpgwAppFile::GetLengthWritten()
{
return lengthSoFar;
}
// Append the given buffer to our appendable file
bool trpgwAppFile::Append(const trpgMemWriteBuffer *buf1,const trpgMemWriteBuffer *buf2)
{
if (!isValid()) return false;
// Get the total length
int totLen = buf1->length() + (buf2 ? buf2->length() : 0);
// Write the length out
if (fwrite(&totLen,sizeof(int32),1,fp) != 1) {
valid = false;
return false;
}
// Write the data out
const char *data = buf1->getData();
unsigned int len = buf1->length();
if (fwrite(data,sizeof(char),len,fp) != len) {
valid = false;
return false;
}
if (buf2) {
data = buf2->getData();
len = buf2->length();
if (fwrite(data,sizeof(char),len,fp) != len) {
valid = false;
return false;
}
}
lengthSoFar += totLen;
return true;
}
// Append the given raw data to our appendable file
bool trpgwAppFile::Append(const char *data,int size)
{
if (!isValid()) return false;
if (!data)
return false;
// Write the length out
if (fwrite(&size,sizeof(int32),1,fp) != 1) {
valid = false;
return false;
}
// Write the data out
if (fwrite(data,sizeof(char),size,fp) != (size_t)size) {
valid = false;
return false;
}
lengthSoFar += size;
return true;
}
// Flushes the current tile file
bool trpgwAppFile::Flush()
{
// Flush the File *
if (fp)
fflush(fp);
return true;
}
// Return the current file position
int64 trpgwAppFile::Pos() const
{
if (!isValid())
return 0;
// Note: This means an appendable file is capped at 2GB
long pos = ftell(fp);
return pos;
}
// Validity check
bool trpgwAppFile::isValid() const
{
return valid;
}