#include "base/logging.h" #include "file/chunk_file.h" #include "file/zip_read.h" //#define CHUNKDEBUG ChunkFile::ChunkFile(const char *filename, bool _read) { data=0; fn = filename; fastMode=false; numLevels=0; read=_read; pos=0; didFail=false; fastMode = read ? true : false; if (fastMode) { size_t size; data = (uint8 *)VFSReadFile(filename, &size); if (!data) { ELOG("Chunkfile fail: %s", filename); didFail = true; return; } eof = size; return; } if (file.open(filename, FILE_WRITE)) { didFail=false; eof=file.fileSize(); } else { didFail=true; return; } } ChunkFile::~ChunkFile() { if (fastMode && data) delete [] data; else file.close(); } int ChunkFile::readInt() { if (pos>8, id>>16, id>>24); #endif stack[numLevels]=temp; seekTo(stack[numLevels].parentStartLocation); return false; } //descend into it //pos was set inside the loop above eof = stack[numLevels].startLocation + stack[numLevels].length; numLevels++; #ifdef CHUNKDEBUG ILOG("Descended into %c%c%c%c", id, id>>8, id>>16, id>>24); #endif return true; } else { #ifndef DEMO_VERSION //if this is missing.. heheh //write a chunk id, and prepare for filling in length later writeInt(id); writeInt(0); //will be filled in by Ascend stack[numLevels].startLocation=pos; numLevels++; return true; #else return true; #endif } } void ChunkFile::seekTo(int _pos) { if (!fastMode) file.seekBeg(_pos); pos=_pos; } //let's ascend out void ChunkFile::ascend() { if (read) { //ascend, and restore information numLevels--; seekTo(stack[numLevels].parentStartLocation); eof = stack[numLevels].parentEOF; #ifdef CHUNKDEBUG int id = stack[numLevels].ID; ILOG("Ascended out of %c%c%c%c", id, id>>8, id>>16, id>>24); #endif } else { numLevels--; //now fill in the written length automatically int posNow = pos; seekTo(stack[numLevels].startLocation - 4); writeInt(posNow-stack[numLevels].startLocation); seekTo(posNow); } } //read a block void ChunkFile::readData(void *what, int count) { if (fastMode) memcpy(what, data + pos, count); else file.read(what,count); pos+=count; char temp[4]; //discarded count &= 3; if (count) { count=4-count; if (!fastMode) file.read(temp,count); pos+=count; } } //write a block void ChunkFile::writeData(const void *what, int count) { file.write(what, count); pos+=count; char temp[5]={0,0,0,0,0}; count &= 3; if (count) { count=4-count; file.write(temp,count); pos+=count; } } void ChunkFile::writeWString(String str) { wchar_t *text; int len=str.length(); #ifdef UNICODE text = str.getPointer(); #else text=new wchar_t[len+1]; str.toUnicode(text); #endif writeInt(len); writeData((char *)text,len*sizeof(wchar_t)); #ifndef UNICODE delete [] text; #endif } String ChunkFile::readWString() { int len=readInt(); wchar_t *text = new wchar_t[len+1]; readData((char *)text,len*sizeof(wchar_t)); text[len]=0; #ifdef UNICODE String s(text); delete [] text; return s; #else String temp; temp.fromUnicode(text); delete [] text; return temp; #endif } static void toUnicode(const std::string &str, uint16 *t) { for (int i=0; i<(int)str.size(); i++) { *t++ = str[i]; } *t++ = '\0'; } static std::string fromUnicode(const uint16 *src, int len) { struct Local { static int clamp(int i) { return i>255?' ':i; } }; std::string str; str.resize(len); for (int i=0; i