diff options
Diffstat (limited to 'src/im_binfile.cpp')
-rw-r--r-- | src/im_binfile.cpp | 644 |
1 files changed, 644 insertions, 0 deletions
diff --git a/src/im_binfile.cpp b/src/im_binfile.cpp new file mode 100644 index 0000000..670623c --- /dev/null +++ b/src/im_binfile.cpp @@ -0,0 +1,644 @@ +/** \file + * \brief Binary File Access + * + * See Copyright Notice in im_lib.h + * $Id: im_binfile.cpp,v 1.1 2008/10/17 06:10:16 scuri Exp $ + */ + + +#include <stdlib.h> +#include <stdio.h> +#include <memory.h> +#include <assert.h> +#include <stdarg.h> + +#include "im_util.h" +#include "im_binfile.h" + + +/************************************************** + imBinMemoryFile +***************************************************/ + +class imBinMemoryFile: public imBinFileBase +{ +protected: + unsigned long CurrentSize, BufferSize; + unsigned char* Buffer, *CurPos; + int Error; + float Reallocate; + imBinMemoryFileName* file_name; + + unsigned long ReadBuf(void* pValues, unsigned long pSize); + unsigned long WriteBuf(void* pValues, unsigned long pSize); + +public: + void Open(const char* pFileName); + void New(const char* pFileName); + void Close() {} // Does nothing, the memory belongs to the user + + unsigned long FileSize(); + int HasError() const; + void SeekTo(unsigned long pOffset); + void SeekOffset(long pOffset); + void SeekFrom(long pOffset); + unsigned long Tell() const; + int EndOfFile() const; +}; + +static imBinFileBase* iBinMemoryFileNewFunc() +{ + return new imBinMemoryFile(); +} + +void imBinMemoryRelease(unsigned char *buffer) +{ + free(buffer); +} + +void imBinMemoryFile::Open(const char* pFileName) +{ + this->file_name = (imBinMemoryFileName*)pFileName; + + InitByteOrder(imBinCPUByteOrder()); + this->IsNew = 0; + + assert(this->file_name->size); + + this->Buffer = this->file_name->buffer; + this->BufferSize = this->file_name->size; + this->Reallocate = this->file_name->reallocate; + this->CurrentSize = this->BufferSize; + this->CurPos = this->Buffer; + this->Error = 0; +} + +void imBinMemoryFile::New(const char* pFileName) +{ + this->file_name = (imBinMemoryFileName*)pFileName; + + InitByteOrder(imBinCPUByteOrder()); + this->IsNew = 1; + + assert(this->file_name->size); + + this->Buffer = this->file_name->buffer; + this->BufferSize = this->file_name->size; + this->Reallocate = this->file_name->reallocate; + this->CurrentSize = 0; + + if (!this->Buffer) + { + this->Buffer = (unsigned char*)malloc(this->BufferSize); + this->file_name->buffer = this->Buffer; + } + + this->CurPos = this->Buffer; + this->Error = 0; +} + +unsigned long imBinMemoryFile::ReadBuf(void* pValues, unsigned long pSize) +{ + assert(this->Buffer); + + unsigned long lOffset = this->CurPos - this->Buffer; + + this->Error = 0; + if (lOffset + pSize > this->CurrentSize) + { + this->Error = 1; + pSize = this->CurrentSize - lOffset; + } + + if (pSize) + { + memcpy(pValues, this->CurPos, pSize); + this->CurPos += pSize; + } + + return pSize; +} + +unsigned long imBinMemoryFile::WriteBuf(void* pValues, unsigned long pSize) +{ + assert(this->Buffer); + + unsigned long lOffset = this->CurPos - this->Buffer; + + this->Error = 0; + if (lOffset + pSize > this->BufferSize) + { + if (this->Reallocate != 0.0) + { + unsigned long nSize = this->BufferSize; + while (lOffset + pSize > nSize) + nSize += (unsigned long)(this->Reallocate*(float)this->BufferSize); + + this->Buffer = (unsigned char*)realloc(this->Buffer, nSize); + + if (this->Buffer) + { + this->BufferSize = nSize; + this->file_name->buffer = this->Buffer; + this->file_name->size = this->BufferSize; + } + else + { + this->Buffer = this->file_name->buffer; + this->Error = 1; + pSize = this->BufferSize - lOffset; + } + + this->CurPos = this->Buffer + lOffset; + } + else + { + this->Error = 1; + pSize = this->BufferSize - lOffset; + } + } + + memcpy(this->CurPos, pValues, pSize); + + if (lOffset + pSize > this->CurrentSize) + this->CurrentSize = lOffset + pSize; + + this->CurPos += pSize; + + return pSize; +} + +unsigned long imBinMemoryFile::FileSize() +{ + assert(this->Buffer); + return this->CurrentSize; +} + +int imBinMemoryFile::HasError() const +{ + if (!this->Buffer) return 1; + return this->Error; +} + +void imBinMemoryFile::SeekTo(unsigned long pOffset) +{ + assert(this->Buffer); + + this->Error = 0; + if (pOffset > this->BufferSize) + { + this->Error = 1; + return; + } + + this->CurPos = this->Buffer + pOffset; + + /* update size if we seek after EOF */ + if (pOffset > this->CurrentSize) + this->CurrentSize = pOffset; +} + +void imBinMemoryFile::SeekFrom(long pOffset) +{ + assert(this->Buffer); + + /* remember that offset is usually a negative value in this case */ + + this->Error = 0; + if (this->CurrentSize + pOffset > this->BufferSize || + (long)this->CurrentSize + pOffset < 0) + { + this->Error = 1; + return; + } + + this->CurPos = this->Buffer + this->CurrentSize + pOffset; + + /* update size if we seek after EOF */ + if (pOffset > 0) + this->CurrentSize = this->CurrentSize + pOffset; +} + +void imBinMemoryFile::SeekOffset(long pOffset) +{ + assert(this->Buffer); + long lOffset = this->CurPos - this->Buffer; + + this->Error = 0; + if (lOffset + pOffset < 0 || lOffset + pOffset > (long)this->BufferSize) + { + this->Error = 1; + return; + } + + this->CurPos += pOffset; + + /* update size if we seek after EOF */ + if (lOffset + pOffset > (long)this->CurrentSize) + this->CurrentSize = lOffset + pOffset; +} + +unsigned long imBinMemoryFile::Tell() const +{ + assert(this->Buffer); + unsigned long lOffset = this->CurPos - this->Buffer; + return lOffset; +} + +int imBinMemoryFile::EndOfFile() const +{ + assert(this->Buffer); + unsigned long lOffset = this->CurPos - this->Buffer; + return lOffset == this->CurrentSize? 1: 0; +} + +/************************************************** + imBinSubFile +**************************************************/ + +static imBinFileBase* iBinFileBaseHandle(const char* pFileName); + +class imBinSubFile: public imBinFileBase +{ +protected: + imBinFileBase* FileHandle; + unsigned long StartOffset; + + unsigned long ReadBuf(void* pValues, unsigned long pSize); + unsigned long WriteBuf(void* pValues, unsigned long pSize); + +public: + void Open(const char* pFileName); + void New(const char* pFileName); + void Close() {} // Does nothing, the file should be close by the parent file. + + unsigned long FileSize(); + int HasError() const; + void SeekTo(unsigned long pOffset); + void SeekOffset(long pOffset); + void SeekFrom(long pOffset); + unsigned long Tell() const; + int EndOfFile() const; +}; + +static imBinFileBase* iBinSubFileNewFunc() +{ + return new imBinSubFile(); +} + +void imBinSubFile::Open(const char* pFileName) +{ + this->FileHandle = iBinFileBaseHandle(pFileName); + this->FileByteOrder = this->FileByteOrder; + this->IsNew = 0; + + StartOffset = this->FileHandle->Tell(); +} + +void imBinSubFile::New(const char* pFileName) +{ + this->FileHandle = iBinFileBaseHandle(pFileName); + this->FileByteOrder = this->FileByteOrder; + this->IsNew = 1; + + StartOffset = this->FileHandle->Tell(); +} + +unsigned long imBinSubFile::FileSize() +{ + assert(this->FileHandle); + return this->FileHandle->FileSize(); +} + +unsigned long imBinSubFile::ReadBuf(void* pValues, unsigned long pSize) +{ + assert(this->FileHandle); + return this->FileHandle->ReadBuf(pValues, pSize); +} + +unsigned long imBinSubFile::WriteBuf(void* pValues, unsigned long pSize) +{ + assert(this->FileHandle); + return this->FileHandle->WriteBuf(pValues, pSize); +} + +int imBinSubFile::HasError() const +{ + assert(this->FileHandle); + return this->FileHandle->HasError(); +} + +void imBinSubFile::SeekTo(unsigned long pOffset) +{ + assert(this->FileHandle); + this->FileHandle->SeekTo(StartOffset + pOffset); +} + +void imBinSubFile::SeekOffset(long pOffset) +{ + assert(this->FileHandle); + this->FileHandle->SeekOffset(pOffset); +} + +void imBinSubFile::SeekFrom(long pOffset) +{ + assert(this->FileHandle); + this->FileHandle->SeekFrom(pOffset); +} + +unsigned long imBinSubFile::Tell() const +{ + assert(this->FileHandle); + return this->FileHandle->Tell() - StartOffset; +} + +int imBinSubFile::EndOfFile() const +{ + assert(this->FileHandle); + return this->FileHandle->EndOfFile(); +} + +/************************************************** + imBinStreamFile +**************************************************/ + +class imBinStreamFile: public imBinFileBase +{ +protected: + FILE* FileHandle; + + unsigned long ReadBuf(void* pValues, unsigned long pSize); + unsigned long WriteBuf(void* pValues, unsigned long pSize); + +public: + void Open(const char* pFileName); + void New(const char* pFileName); + void Close(); + + unsigned long FileSize(); + int HasError() const; + void SeekTo(unsigned long pOffset); + void SeekOffset(long pOffset); + void SeekFrom(long pOffset); + unsigned long Tell() const; + int EndOfFile() const; +}; + +static imBinFileBase* iBinStreamFileNewFunc() +{ + return new imBinStreamFile(); +} + +void imBinStreamFile::Open(const char* pFileName) +{ + this->FileHandle = fopen(pFileName, "rb"); + InitByteOrder(imBinCPUByteOrder()); + this->IsNew = 0; +} + +void imBinStreamFile::New(const char* pFileName) +{ + this->FileHandle = fopen(pFileName, "wb"); + InitByteOrder(imBinCPUByteOrder()); + this->IsNew = 1; +} + +void imBinStreamFile::Close() +{ + if (this->FileHandle) fclose(this->FileHandle); +} + +unsigned long imBinStreamFile::FileSize() +{ + assert(this->FileHandle); + unsigned long lCurrentPosition = ftell(this->FileHandle); + fseek(this->FileHandle, 0L, SEEK_END); + unsigned long lSize = ftell(this->FileHandle); + fseek(this->FileHandle, lCurrentPosition, SEEK_SET); + return lSize; +} + +unsigned long imBinStreamFile::ReadBuf(void* pValues, unsigned long pSize) +{ + assert(this->FileHandle); + return fread(pValues, 1, pSize, this->FileHandle); +} + +unsigned long imBinStreamFile::WriteBuf(void* pValues, unsigned long pSize) +{ + assert(this->FileHandle); + return fwrite(pValues, 1, pSize, this->FileHandle); +} + +int imBinStreamFile::HasError() const +{ + if (!this->FileHandle) return 1; + return ferror(this->FileHandle) == 0? 0: 1; +} + +void imBinStreamFile::SeekTo(unsigned long pOffset) +{ + assert(this->FileHandle); + fseek(this->FileHandle, pOffset, SEEK_SET); +} + +void imBinStreamFile::SeekOffset(long pOffset) +{ + assert(this->FileHandle); + fseek(this->FileHandle, pOffset, SEEK_CUR); +} + +void imBinStreamFile::SeekFrom(long pOffset) +{ + assert(this->FileHandle); + fseek(this->FileHandle, pOffset, SEEK_END); +} + +unsigned long imBinStreamFile::Tell() const +{ + assert(this->FileHandle); + return ftell(this->FileHandle); +} + +int imBinStreamFile::EndOfFile() const +{ + assert(this->FileHandle); + return feof(this->FileHandle) == 0? 0: 1; +} + +/************************************************** + NewFuncModules +**************************************************/ + +/* implemented in "im_sysfile*.cpp" */ +imBinFileBase* iBinSystemFileNewFunc(); +imBinFileBase* iBinSystemFileHandleNewFunc(); + +#define MAX_MODULES 10 + +static imBinFileNewFunc iBinFileModule[MAX_MODULES] = +{ + iBinSystemFileNewFunc, + iBinStreamFileNewFunc, + iBinMemoryFileNewFunc, + iBinSubFileNewFunc, + iBinSystemFileHandleNewFunc +}; +static int iBinFileModuleCount = 5; +static int iBinFileModuleCurrent = 0; // default module is the first + +int imBinFileSetCurrentModule(int pModule) +{ + int old_module = iBinFileModuleCurrent; + + if (pModule >= iBinFileModuleCount) + return -1; + + iBinFileModuleCurrent = pModule; + + return old_module; +} + +int imBinFileRegisterModule(imBinFileNewFunc pNewFunc) +{ + if (iBinFileModuleCount == MAX_MODULES) return -1; + int id = iBinFileModuleCount; + iBinFileModule[id] = pNewFunc; + iBinFileModuleCount++; + return id; +} + +/************************************************** + imBinFile +**************************************************/ + +struct _imBinFile +{ + imBinFileBase* binfile; +}; + +imBinFile* imBinFileOpen(const char* pFileName) +{ + assert(pFileName); + + assert(iBinFileModuleCurrent < iBinFileModuleCount); + assert(iBinFileModuleCurrent < MAX_MODULES); + + imBinFileNewFunc NewFunc = iBinFileModule[iBinFileModuleCurrent]; + imBinFileBase* binfile = NewFunc(); + + binfile->Open(pFileName); + if (binfile->HasError()) + { + delete binfile; + return NULL; + } + + imBinFile* bfile = new imBinFile; + bfile->binfile = binfile; + + return bfile; +} + +imBinFile* imBinFileNew(const char* pFileName) +{ + assert(pFileName); + + imBinFileNewFunc NewFunc = iBinFileModule[iBinFileModuleCurrent]; + imBinFileBase* binfile = NewFunc(); + + binfile->New(pFileName); + if (binfile->HasError()) + { + delete binfile; + return NULL; + } + + imBinFile* bfile = new imBinFile; + bfile->binfile = binfile; + + return bfile; +} + +void imBinFileClose(imBinFile* bfile) +{ + assert(bfile); + bfile->binfile->Close(); + delete bfile->binfile; + delete bfile; +} + +int imBinFileByteOrder(imBinFile* bfile, int pByteOrder) +{ + assert(bfile); + return bfile->binfile->InitByteOrder(pByteOrder); +} + +int imBinFileError(imBinFile* bfile) +{ + assert(bfile); + return bfile->binfile->HasError(); +} + +unsigned long imBinFileSize(imBinFile* bfile) +{ + assert(bfile); + return bfile->binfile->FileSize(); +} + +unsigned long imBinFileRead(imBinFile* bfile, void* pValues, unsigned long pCount, int pSizeOf) +{ + assert(bfile); + return bfile->binfile->Read(pValues, pCount, pSizeOf); +} + +unsigned long imBinFileWrite(imBinFile* bfile, void* pValues, unsigned long pCount, int pSizeOf) +{ + assert(bfile); + return bfile->binfile->Write(pValues, pCount, pSizeOf); +} + +void imBinFileSeekTo(imBinFile* bfile, unsigned long pOffset) +{ + assert(bfile); + bfile->binfile->SeekTo(pOffset); +} + +void imBinFileSeekOffset(imBinFile* bfile, long pOffset) +{ + assert(bfile); + bfile->binfile->SeekOffset(pOffset); +} + +void imBinFileSeekFrom(imBinFile* bfile, long pOffset) +{ + assert(bfile); + bfile->binfile->SeekFrom(pOffset); +} + +unsigned long imBinFileTell(imBinFile* bfile) +{ + assert(bfile); + return bfile->binfile->Tell(); +} + +int imBinFileEndOfFile(imBinFile* bfile) +{ + assert(bfile); + return bfile->binfile->EndOfFile(); +} + +unsigned long imBinFilePrintf(imBinFile* bfile, char *format, ...) +{ + va_list arglist; + va_start(arglist, format); + char buffer[4096]; + int size = vsprintf(buffer, format, arglist); + return imBinFileWrite(bfile, buffer, size, 1); +} + +static imBinFileBase* iBinFileBaseHandle(const char* pFileName) +{ + imBinFile* bfile = (imBinFile*)pFileName; + return (imBinFileBase*)bfile->binfile; +} |