diff --git a/Source/Core/Common/Src/ChunkFile.cpp b/Source/Core/Common/Src/ChunkFile.cpp index 849f692631..be2dad6788 100644 --- a/Source/Core/Common/Src/ChunkFile.cpp +++ b/Source/Core/Common/Src/ChunkFile.cpp @@ -25,151 +25,195 @@ ChunkFile::ChunkFile(const char *filename, ChunkFileMode _mode) { - mode = _mode; - data = 0; + mode = _mode; + data = 0; - didFail = false; - f = fopen(filename, mode == MODE_WRITE ? "wb" : "rb"); - if (!f) { - didFail = true; - return; - } + didFail = false; + f = fopen(filename, mode == MODE_WRITE ? "wb" : "rb"); + if (!f) { + didFail = true; + return; + } - fseek(f, 0, SEEK_END); - size = ftell(f); - eof = size; + fseek(f, 0, SEEK_END); + size = ftell(f); + eof = size; - stack_ptr = 0; + stack_ptr = 0; } ChunkFile::~ChunkFile() { - if (f) - fclose(f); + if (f) + fclose(f); } int ChunkFile::ReadInt() { - int x; - fread(&x, 4, 1, f); - return x; + int x; + fread(&x, 4, 1, f); + return x; } void ChunkFile::WriteInt(int x) { - fwrite(&x, 4, 1, f); + fwrite(&x, 4, 1, f); } bool ChunkFile::Do(void *ptr, int size) { - int sz; - switch (mode) { - case MODE_READ: - sz = ReadInt(); - if (sz != size) - return false; - fread(ptr, size, 1, f); - fseek(f, ((size + 3) & ~3) - size, SEEK_CUR); - break; - case MODE_WRITE: - WriteInt(size); - fwrite(ptr, size, 1, f); - fseek(f, ((size + 3) & ~3) - size, SEEK_CUR); - break; - case MODE_VERIFY: - sz = ReadInt(); - if (sz != size) - return false; - fseek(f, (size + 3) & ~3, SEEK_CUR); - break; - } - return true; + int sz; + switch (mode) { + case MODE_READ: + sz = ReadInt(); + if (sz != size) + return false; + fread(ptr, size, 1, f); + fseek(f, ((size + 3) & ~3) - size, SEEK_CUR); + break; + case MODE_WRITE: + WriteInt(size); + fwrite(ptr, size, 1, f); + fseek(f, ((size + 3) & ~3) - size, SEEK_CUR); + break; + case MODE_VERIFY: + sz = ReadInt(); + if (sz != size) + return false; + fseek(f, (size + 3) & ~3, SEEK_CUR); + break; + } + return true; +} + +// Do variable size array (probably heap-allocated) +bool DoArray(void *ptr, int size, int arrSize) { + int sz; + + if(ptr == NULL) + return false; + + switch (mode) { + case MODE_READ: + sz = ReadInt(); + if (sz != size) + return false; + sz = ReadInt(); + if (sz != arrSize) + return false; + + for(int i = 0; i < arrSize; i++) { + fread(ptr[i], size, 1, f); + fseek(f, ((size + 3) & ~3) - size, SEEK_CUR); + } + break; + case MODE_WRITE: + WriteInt(size); + WriteInt(arrSize); + for(int i = 0; i < arrSize; i++) { + fwrite(ptr[i], size, 1, f); + fseek(f, ((size + 3) & ~3) - size, SEEK_CUR); + } + break; + case MODE_VERIFY: + sz = ReadInt(); + if (sz != size) + return false; + sz = ReadInt(); + if (sz != arrSize) + return false; + + for(int i = 0; i < arrSize; i++) + fseek(f, (size + 3) & ~3, SEEK_CUR); + break; + } + return true; } //let's get into the business bool ChunkFile::Descend(const char *cid) { - unsigned int id = *reinterpret_cast(cid); - if (mode == MODE_READ) + unsigned int id = *reinterpret_cast(cid); + if (mode == MODE_READ) { - bool found = false; - int startPos = ftell(f); - ChunkInfo temp = stack[stack_ptr]; + bool found = false; + int startPos = ftell(f); + ChunkInfo temp = stack[stack_ptr]; - //save information to restore after the next Ascend - stack[stack_ptr].parentStartLocation = startPos; - stack[stack_ptr].parentEOF = eof; + //save information to restore after the next Ascend + stack[stack_ptr].parentStartLocation = startPos; + stack[stack_ptr].parentEOF = eof; - unsigned int firstID = 0; - //let's search through children.. - while (ftell(f) < eof) + unsigned int firstID = 0; + //let's search through children.. + while (ftell(f) < eof) { - stack[stack_ptr].ID = ReadInt(); - if (firstID == 0) - firstID = stack[stack_ptr].ID|1; - stack[stack_ptr].length = ReadInt(); - stack[stack_ptr].startLocation = ftell(f); - if (stack[stack_ptr].ID == id) + stack[stack_ptr].ID = ReadInt(); + if (firstID == 0) + firstID = stack[stack_ptr].ID|1; + stack[stack_ptr].length = ReadInt(); + stack[stack_ptr].startLocation = ftell(f); + if (stack[stack_ptr].ID == id) { - found = true; - break; + found = true; + break; } - else + else { - fseek(f, stack[stack_ptr].length, SEEK_CUR); //try next block + fseek(f, stack[stack_ptr].length, SEEK_CUR); //try next block } } - //if we found nothing, return false so the caller can skip this - if (!found) + //if we found nothing, return false so the caller can skip this + if (!found) { - stack[stack_ptr] = temp; - fseek(f, stack[stack_ptr].parentStartLocation, SEEK_SET); - return false; + stack[stack_ptr] = temp; + fseek(f, stack[stack_ptr].parentStartLocation, SEEK_SET); + return false; } - //descend into it - //pos was set inside the loop above - eof = stack[stack_ptr].startLocation + stack[stack_ptr].length; - stack_ptr++; - return true; + //descend into it + //pos was set inside the loop above + eof = stack[stack_ptr].startLocation + stack[stack_ptr].length; + stack_ptr++; + return true; } - else + else { - //write a chunk id, and prepare for filling in length later - WriteInt(id); - WriteInt(0); //will be filled in by Ascend - stack[stack_ptr].startLocation = ftell(f); - stack_ptr++; - return true; + //write a chunk id, and prepare for filling in length later + WriteInt(id); + WriteInt(0); //will be filled in by Ascend + stack[stack_ptr].startLocation = ftell(f); + stack_ptr++; + return true; } } //let's ascend out void ChunkFile::Ascend() { - if (mode == MODE_READ) + if (mode == MODE_READ) { - //ascend, and restore information - stack_ptr--; - fseek(f, stack[stack_ptr].parentStartLocation, SEEK_SET); - eof = stack[stack_ptr].parentEOF; + //ascend, and restore information + stack_ptr--; + fseek(f, stack[stack_ptr].parentStartLocation, SEEK_SET); + eof = stack[stack_ptr].parentEOF; } - else + else { - stack_ptr--; - //now fill in the written length automatically - int posNow = ftell(f); - fseek(f, stack[stack_ptr].startLocation - 4, SEEK_SET); - WriteInt(posNow - stack[stack_ptr].startLocation); - fseek(f, posNow, SEEK_SET); + stack_ptr--; + //now fill in the written length automatically + int posNow = ftell(f); + fseek(f, stack[stack_ptr].startLocation - 4, SEEK_SET); + WriteInt(posNow - stack[stack_ptr].startLocation); + fseek(f, posNow, SEEK_SET); } } int ChunkFile::GetCurrentChunkSize() { - if (stack_ptr) - return stack[stack_ptr - 1].length; - else - return 0; + if (stack_ptr) + return stack[stack_ptr - 1].length; + else + return 0; } diff --git a/Source/Core/Common/Src/ChunkFile.h b/Source/Core/Common/Src/ChunkFile.h index 8d579933f9..4c48a595fa 100644 --- a/Source/Core/Common/Src/ChunkFile.h +++ b/Source/Core/Common/Src/ChunkFile.h @@ -80,26 +80,35 @@ public: //void Do(int &i); //bool Do(std::string &s); bool Do(void *ptr, int size); + + bool DoArray(void *ptr, int size, int arrSize); // Future // bool DoCompressed(void *ptr, int size) // Store maps to file. Very useful. template - void Do(std::map &x) { - + bool Do(std::map &x) { + return false; } - + // Store vectors. template - void Do(std::vector &x) { - + bool Do(std::vector &x) { + return false; } + + // Disable size checks to save size for variable size array storing + template + bool DoArray(T *x, int size, int arrSize) { + return DoArray((void *)x, size, arrSize); + } + // Handle everything else template - void Do(T &x) { - Do((void *)&x, sizeof(x)); + bool Do(T &x) { + return Do((void *)&x, sizeof(x)); } int GetCurrentChunkSize();