aboutsummaryrefslogtreecommitdiff
path: root/dep/g3dlite/source/BinaryInput.cpp
diff options
context:
space:
mode:
authorjackpoz <giacomopoz@gmail.com>2014-08-22 16:58:23 +0200
committerjackpoz <giacomopoz@gmail.com>2014-08-22 21:00:56 +0200
commit5e8277e923c5545a15bae7c740ab6afaa597a59f (patch)
tree4cf5212c080588a7e868ee60134fc7fff51e400a /dep/g3dlite/source/BinaryInput.cpp
parenta63aa858dcb400eafb97eed1f590e34c27d934a4 (diff)
Core/Dependencies: Update G3D to v9.0 r4036
Diffstat (limited to 'dep/g3dlite/source/BinaryInput.cpp')
-rw-r--r--dep/g3dlite/source/BinaryInput.cpp503
1 files changed, 268 insertions, 235 deletions
diff --git a/dep/g3dlite/source/BinaryInput.cpp b/dep/g3dlite/source/BinaryInput.cpp
index 19ab2722c5c..c6eafa5ce09 100644
--- a/dep/g3dlite/source/BinaryInput.cpp
+++ b/dep/g3dlite/source/BinaryInput.cpp
@@ -1,11 +1,11 @@
/**
- @file BinaryInput.cpp
+ \file BinaryInput.cpp
- @author Morgan McGuire, graphics3d.com
- Copyright 2001-2007, Morgan McGuire. All rights reserved.
+ \author Morgan McGuire, graphics3d.com
+ Copyright 2001-2013, Morgan McGuire. All rights reserved.
- @created 2001-08-09
- @edited 2010-03-05
+ \created 2001-08-09
+ \edited 2013-01-03
<PRE>
@@ -40,154 +40,17 @@
#include "G3D/FileSystem.h"
#include <zlib.h>
#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
- #include "zip.h"
+#include "../../zip.lib/include/zip.h"
#endif
#include <cstring>
namespace G3D {
-void BinaryInput::readBool8(std::vector<bool>& out, int64 n) {
- out.resize((int)n);
- // std::vector optimizes bool in a way that prevents fast reading
- for (int64 i = 0; i < n ; ++i) {
- out[i] = readBool8();
- }
-}
-
-
-void BinaryInput::readBool8(Array<bool>& out, int64 n) {
- out.resize(n);
- readBool8(out.begin(), n);
-}
-
-
-#define IMPLEMENT_READER(ucase, lcase)\
-void BinaryInput::read##ucase(std::vector<lcase>& out, int64 n) {\
- out.resize(n);\
- read##ucase(&out[0], n);\
-}\
-\
-\
-void BinaryInput::read##ucase(Array<lcase>& out, int64 n) {\
- out.resize(n);\
- read##ucase(out.begin(), n);\
-}
-
-
-IMPLEMENT_READER(UInt8, uint8)
-IMPLEMENT_READER(Int8, int8)
-IMPLEMENT_READER(UInt16, uint16)
-IMPLEMENT_READER(Int16, int16)
-IMPLEMENT_READER(UInt32, uint32)
-IMPLEMENT_READER(Int32, int32)
-IMPLEMENT_READER(UInt64, uint64)
-IMPLEMENT_READER(Int64, int64)
-IMPLEMENT_READER(Float32, float32)
-IMPLEMENT_READER(Float64, float64)
-
-#undef IMPLEMENT_READER
-
-// Data structures that are one byte per element can be
-// directly copied, regardles of endian-ness.
-#define IMPLEMENT_READER(ucase, lcase)\
-void BinaryInput::read##ucase(lcase* out, int64 n) {\
- if (sizeof(lcase) == 1) {\
- readBytes(out, n);\
- } else {\
- for (int64 i = 0; i < n ; ++i) {\
- out[i] = read##ucase();\
- }\
- }\
-}
-
-IMPLEMENT_READER(Bool8, bool)
-IMPLEMENT_READER(UInt8, uint8)
-IMPLEMENT_READER(Int8, int8)
-
-#undef IMPLEMENT_READER
-
-
-#define IMPLEMENT_READER(ucase, lcase)\
-void BinaryInput::read##ucase(lcase* out, int64 n) {\
- if (m_swapBytes) {\
- for (int64 i = 0; i < n; ++i) {\
- out[i] = read##ucase();\
- }\
- } else {\
- readBytes(out, sizeof(lcase) * n);\
- }\
-}
-
-
-IMPLEMENT_READER(UInt16, uint16)
-IMPLEMENT_READER(Int16, int16)
-IMPLEMENT_READER(UInt32, uint32)
-IMPLEMENT_READER(Int32, int32)
-IMPLEMENT_READER(UInt64, uint64)
-IMPLEMENT_READER(Int64, int64)
-IMPLEMENT_READER(Float32, float32)
-IMPLEMENT_READER(Float64, float64)
-
-#undef IMPLEMENT_READER
-
-void BinaryInput::loadIntoMemory(int64 startPosition, int64 minLength) {
- // Load the next section of the file
- debugAssertM(m_filename != "<memory>", "Read past end of file.");
-
- int64 absPos = m_alreadyRead + m_pos;
-
- if (m_bufferLength < minLength) {
- // The current buffer isn't big enough to hold the chunk we want to read.
- // This happens if there was little memory available during the initial constructor
- // read but more memory has since been freed.
- m_bufferLength = minLength;
- debugAssert(m_freeBuffer);
- m_buffer = (uint8*)System::realloc(m_buffer, m_bufferLength);
- if (m_buffer == NULL) {
- throw "Tried to read a larger memory chunk than could fit in memory. (2)";
- }
- }
-
- m_alreadyRead = startPosition;
-
-# ifdef G3D_WIN32
- FILE* file = fopen(m_filename.c_str(), "rb");
- debugAssert(file);
- int ret = fseek(file, (off_t)m_alreadyRead, SEEK_SET);
- debugAssert(ret == 0);
- size_t toRead = (size_t)G3D::min(m_bufferLength, m_length - m_alreadyRead);
- ret = fread(m_buffer, 1, toRead, file);
- debugAssert(ret == toRead);
- fclose(file);
- file = NULL;
-
-# else
- FILE* file = fopen(m_filename.c_str(), "rb");
- debugAssert(file);
- int ret = fseeko(file, (off_t)m_alreadyRead, SEEK_SET);
- debugAssert(ret == 0);
- size_t toRead = (size_t)G3D::min<int64>(m_bufferLength, m_length - m_alreadyRead);
- ret = fread(m_buffer, 1, toRead, file);
- debugAssert((size_t)ret == (size_t)toRead);
- fclose(file);
- file = NULL;
-# endif
-
- m_pos = absPos - m_alreadyRead;
- debugAssert(m_pos >= 0);
-}
-
-
-
const bool BinaryInput::NO_COPY = false;
-
-static bool needSwapBytes(G3DEndian fileEndian) {
- return (fileEndian != System::machineEndian());
-}
/** Helper used by the constructors for decompression */
-static uint32 readUInt32(const uint8* data, bool swapBytes) {
+static uint32 readUInt32FromBuffer(const uint8* data, bool swapBytes) {
if (swapBytes) {
uint8 out[4];
out[0] = data[3];
@@ -201,12 +64,6 @@ static uint32 readUInt32(const uint8* data, bool swapBytes) {
}
-void BinaryInput::setEndian(G3DEndian e) {
- m_fileEndian = e;
- m_swapBytes = needSwapBytes(m_fileEndian);
-}
-
-
BinaryInput::BinaryInput(
const uint8* data,
int64 dataLen,
@@ -227,26 +84,26 @@ BinaryInput::BinaryInput(
if (compressed) {
// Read the decompressed size from the first 4 bytes
- m_length = G3D::readUInt32(data, m_swapBytes);
+ m_length = readUInt32FromBuffer(data, m_swapBytes);
debugAssert(m_freeBuffer);
m_buffer = (uint8*)System::alignedMalloc(m_length, 16);
- unsigned long L = m_length;
+ unsigned long L = (unsigned long)m_length;
// Decompress with zlib
- int64 result = uncompress(m_buffer, (unsigned long*)&L, data + 4, dataLen - 4);
+ int64 result = uncompress(m_buffer, &L, data + 4, (uLong)dataLen - 4);
m_length = L;
m_bufferLength = L;
debugAssert(result == Z_OK); (void)result;
} else {
- m_length = dataLen;
+ m_length = dataLen;
m_bufferLength = m_length;
if (! copyMemory) {
- debugAssert(!m_freeBuffer);
+ debugAssert(!m_freeBuffer);
m_buffer = const_cast<uint8*>(data);
} else {
- debugAssert(m_freeBuffer);
+ debugAssert(m_freeBuffer);
m_buffer = (uint8*)System::alignedMalloc(m_length, 16);
System::memcpy(m_buffer, data, dataLen);
}
@@ -254,10 +111,10 @@ BinaryInput::BinaryInput(
}
-BinaryInput::BinaryInput(
- const std::string& filename,
- G3DEndian fileEndian,
- bool compressed) :
+BinaryInput::BinaryInput
+(const std::string& filename,
+ G3DEndian fileEndian,
+ bool compressed) :
m_filename(filename),
m_bitPos(0),
m_bitString(0),
@@ -270,18 +127,16 @@ BinaryInput::BinaryInput(
m_freeBuffer(true) {
setEndian(fileEndian);
-
- // Update global file tracker
- _internal::currentFilesUsed.insert(m_filename);
-
#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
std::string zipfile;
if (FileSystem::inZipfile(m_filename, zipfile)) {
// Load from zipfile
-// zipRead(filename, v, s);
+ FileSystem::markFileUsed(m_filename);
+ FileSystem::markFileUsed(zipfile);
- std::string internalFile = m_filename.substr(zipfile.length() + 1);
+ // Zipfiles require Unix-style slashes
+ std::string internalFile = FilePath::canonicalize(m_filename.substr(zipfile.length() + 1));
struct zip* z = zip_open(zipfile.c_str(), ZIP_CHECKCONS, NULL);
{
struct zip_stat info;
@@ -291,29 +146,31 @@ BinaryInput::BinaryInput(
// sets machines up to use MMX, if they want
m_buffer = reinterpret_cast<uint8*>(System::alignedMalloc(m_length, 16));
struct zip_file* zf = zip_fopen( z, internalFile.c_str(), ZIP_FL_NOCASE );
- {
- int64 test = zip_fread( zf, m_buffer, m_length );
- debugAssertM(test == m_length,
+ if (zf == NULL) {
+ throw std::string("\"") + internalFile + "\" inside \"" + zipfile + "\" could not be opened.";
+ } else {
+ const int64 bytesRead = zip_fread( zf, m_buffer, m_length );
+ debugAssertM(bytesRead == m_length,
internalFile + " was corrupt because it unzipped to the wrong size.");
- (void)test;
+ (void)bytesRead;
+ zip_fclose( zf );
}
- zip_fclose( zf );
}
zip_close( z );
if (compressed) {
decompress();
}
+
m_freeBuffer = true;
return;
}
#endif
-
// Figure out how big the file is and verify that it exists.
m_length = FileSystem::size(m_filename);
// Read the file into memory
- FILE* file = fopen(m_filename.c_str(), "rb");
+ FILE* file = FileSystem::fopen(m_filename.c_str(), "rb");
if (! file || (m_length == -1)) {
throw format("File not found: \"%s\"", m_filename.c_str());
@@ -346,8 +203,8 @@ BinaryInput::BinaryInput(
}
debugAssert(m_buffer);
- fread(m_buffer, m_bufferLength, sizeof(int8), file);
- fclose(file);
+ (void)fread(m_buffer, m_bufferLength, sizeof(int8), file);
+ FileSystem::fclose(file);
file = NULL;
if (compressed) {
@@ -359,13 +216,36 @@ BinaryInput::BinaryInput(
}
}
+BinaryInput::~BinaryInput() {
+
+ if (m_freeBuffer) {
+ System::alignedFree(m_buffer);
+ }
+ m_buffer = NULL;
+}
+
+
+std::string BinaryInput::readFixedLengthString(int numBytes) {
+ Array<char> str;
+ str.resize(numBytes + 1);
+
+ // Ensure NULL termination
+ str.last() = '\0';
+
+ readBytes(str.getCArray(), numBytes);
+
+ // Copy up to the first NULL
+ return std::string(str.getCArray());
+}
+
+
void BinaryInput::decompress() {
// Decompress
// Use the existing buffer as the source, allocate
// a new buffer to use as the destination.
int64 tempLength = m_length;
- m_length = G3D::readUInt32(m_buffer, m_swapBytes);
+ m_length = readUInt32FromBuffer(m_buffer, m_swapBytes);
// The file couldn't have better than 500:1 compression
alwaysAssertM(m_length < m_bufferLength * 500, "Compressed file header is corrupted");
@@ -377,8 +257,8 @@ void BinaryInput::decompress() {
debugAssert(isValidHeapPointer(tempBuffer));
debugAssert(isValidHeapPointer(m_buffer));
- unsigned long L = m_length;
- int64 result = uncompress(m_buffer, &L, tempBuffer + 4, tempLength - 4);
+ unsigned long L = (unsigned long)m_length;
+ int64 result = (int64)uncompress(m_buffer, &L, tempBuffer + 4, (uLong)tempLength - 4);
m_length = L;
m_bufferLength = m_length;
@@ -389,6 +269,70 @@ void BinaryInput::decompress() {
}
+void BinaryInput::setEndian(G3DEndian e) {
+ m_fileEndian = e;
+ m_swapBytes = (m_fileEndian != System::machineEndian());
+}
+
+
+void BinaryInput::loadIntoMemory(int64 startPosition, int64 minLength) {
+ // Load the next section of the file
+ debugAssertM(m_filename != "<memory>", "Read past end of file.");
+
+ int64 absPos = m_alreadyRead + m_pos;
+
+ if (m_bufferLength < minLength) {
+ // The current buffer isn't big enough to hold the chunk we want to read.
+ // This happens if there was little memory available during the initial constructor
+ // read but more memory has since been freed.
+ m_bufferLength = minLength;
+ debugAssert(m_freeBuffer);
+ m_buffer = (uint8*)System::realloc(m_buffer, m_bufferLength);
+ if (m_buffer == NULL) {
+ throw "Tried to read a larger memory chunk than could fit in memory. (2)";
+ }
+ }
+
+ m_alreadyRead = startPosition;
+
+# ifdef G3D_WINDOWS
+ FILE* file = fopen(m_filename.c_str(), "rb");
+ debugAssert(file);
+ size_t ret = fseek(file, (off_t)m_alreadyRead, SEEK_SET);
+ debugAssert(ret == 0);
+ size_t toRead = (size_t)G3D::min(m_bufferLength, m_length - m_alreadyRead);
+ ret = fread(m_buffer, 1, toRead, file);
+ debugAssert(ret == toRead);
+ fclose(file);
+ file = NULL;
+
+# else
+ FILE* file = fopen(m_filename.c_str(), "rb");
+ debugAssert(file);
+ int ret = fseeko(file, (off_t)m_alreadyRead, SEEK_SET);
+ debugAssert(ret == 0);
+ size_t toRead = (size_t)G3D::min<int64>(m_bufferLength, m_length - m_alreadyRead);
+ ret = fread(m_buffer, 1, toRead, file);
+ debugAssert((size_t)ret == (size_t)toRead);
+ fclose(file);
+ file = NULL;
+# endif
+
+ m_pos = absPos - m_alreadyRead;
+ debugAssert(m_pos >= 0);
+}
+
+
+void BinaryInput::prepareToRead(int64 nbytes) {
+ debugAssertM(m_length > 0, m_filename + " not found or corrupt.");
+ debugAssertM(m_pos + nbytes + m_alreadyRead <= m_length, "Read past end of file.");
+
+ if (m_pos + nbytes > m_bufferLength) {
+ loadIntoMemory(m_pos + m_alreadyRead, nbytes);
+ }
+}
+
+
void BinaryInput::readBytes(void* bytes, int64 n) {
prepareToRead(n);
debugAssert(isValidPointer(bytes));
@@ -398,14 +342,6 @@ void BinaryInput::readBytes(void* bytes, int64 n) {
}
-BinaryInput::~BinaryInput() {
-
- if (m_freeBuffer) {
- System::alignedFree(m_buffer);
- }
- m_buffer = NULL;
-}
-
uint64 BinaryInput::readUInt64() {
prepareToRead(8);
@@ -429,52 +365,47 @@ uint64 BinaryInput::readUInt64() {
}
-std::string BinaryInput::readString(int64 n) {
- prepareToRead(n);
- debugAssertM((m_pos + n) <= m_length, "Read past end of file");
-
- char *s = (char*)System::alignedMalloc(n + 1, 16);
- assert(s != NULL);
+std::string BinaryInput::readString(int64 maxLength) {
+ prepareToRead(maxLength);
- memcpy(s, m_buffer + m_pos, n);
- // There may not be a null, so make sure
- // we add one.
- s[n] = '\0';
-
- std::string out = s;
- System::alignedFree(s);
- s = NULL;
+ int64 n = 0;
+ while ((m_buffer[m_pos + n] != '\0') && (n != maxLength)) {
+ ++n;
+ }
- m_pos += n;
+ std::string s((char*)(m_buffer + m_pos), n);
- return out;
+ m_pos += maxLength;
+ return s;
}
std::string BinaryInput::readString() {
- int64 n = 0;
-
- if ((m_pos + m_alreadyRead + n) < (m_length - 1)) {
- prepareToRead(1);
- }
+ prepareToRead(1);
- if ( ((m_pos + m_alreadyRead + n) < (m_length - 1)) &&
- (m_buffer[m_pos + n] != '\0')) {
+ int64 n = 0;
+ bool hasNull = true;
+ while(m_buffer[m_pos + n] != '\0') {
++n;
- while ( ((m_pos + m_alreadyRead + n) < (m_length - 1)) &&
- (m_buffer[m_pos + n] != '\0')) {
- prepareToRead(1);
- ++n;
+ if ((m_pos + m_alreadyRead + n) == m_length) {
+ hasNull = false;
+ break;
}
+
+ prepareToRead(n + 1);
}
- // Consume NULL
- ++n;
+ std::string s((char*)(m_buffer + m_pos), n);
+ m_pos += n;
- return readString(n);
+ if (hasNull) {
+ skip(1);
+ }
+
+ return s;
}
static bool isNewline(char c) {
@@ -482,32 +413,48 @@ static bool isNewline(char c) {
}
std::string BinaryInput::readStringNewline() {
+ prepareToRead(1);
+
int64 n = 0;
+ bool hasNull = true;
+ bool hasNewline = false;
- if ((m_pos + m_alreadyRead + n) < (m_length - 1)) {
- prepareToRead(1);
- }
+ while(m_buffer[m_pos + n] != '\0') {
+ if ((m_pos + m_alreadyRead + n + 1) == m_length) {
+ hasNull = false;
+ break;
+ }
- if ( ((m_pos + m_alreadyRead + n) < (m_length - 1)) &&
- ! isNewline(m_buffer[m_pos + n])) {
+ if (isNewline(m_buffer[m_pos + n])) {
+ hasNull = false;
+ hasNewline = true;
+ break;
+ }
++n;
- while ( ((m_pos + m_alreadyRead + n) < (m_length - 1)) &&
- ! isNewline(m_buffer[m_pos + n])) {
-
- prepareToRead(1);
- ++n;
- }
+ prepareToRead(n + 1);
}
- const std::string s = readString(n);
-
- // Consume the newline
- char firstNLChar = readUInt8();
+ std::string s((char*)(m_buffer + m_pos), n);
+ m_pos += n;
- // Consume the 2nd newline
- if (isNewline(m_buffer[m_pos + 1]) && (m_buffer[m_pos + 1] != firstNLChar)) {
- readUInt8();
+ if (hasNull) {
+ skip(1);
+ }
+
+ if (hasNewline) {
+ if ((m_pos + m_alreadyRead + 2) != m_length) {
+ prepareToRead(2);
+ if (m_buffer[m_pos] == '\r' && m_buffer[m_pos + 1] == '\n') {
+ skip(2);
+ } else if (m_buffer[m_pos] == '\n' && m_buffer[m_pos + 1] == '\r') {
+ skip(2);
+ } else {
+ skip(1);
+ }
+ } else {
+ skip(1);
+ }
}
return s;
@@ -516,7 +463,7 @@ std::string BinaryInput::readStringNewline() {
std::string BinaryInput::readStringEven() {
std::string x = readString();
- if (hasMore() && (G3D::isOdd(x.length() + 1))) {
+ if (hasMore() && (G3D::isOdd((int)x.length() + 1))) {
skip(1);
}
return x;
@@ -618,4 +565,90 @@ void BinaryInput::endBits() {
m_bitPos = 0;
}
+
+void BinaryInput::readBool8(std::vector<bool>& out, int64 n) {
+ out.resize((int)n);
+ // std::vector optimizes bool in a way that prevents fast reading
+ for (int64 i = 0; i < n ; ++i) {
+ out[i] = readBool8();
+ }
+}
+
+
+void BinaryInput::readBool8(Array<bool>& out, int64 n) {
+ out.resize(n);
+ readBool8(out.begin(), n);
}
+
+
+#define IMPLEMENT_READER(ucase, lcase)\
+void BinaryInput::read##ucase(std::vector<lcase>& out, int64 n) {\
+ out.resize(n);\
+ read##ucase(&out[0], n);\
+}\
+\
+\
+void BinaryInput::read##ucase(Array<lcase>& out, int64 n) {\
+ out.resize(n);\
+ read##ucase(out.begin(), n);\
+}
+
+
+IMPLEMENT_READER(UInt8, uint8)
+IMPLEMENT_READER(Int8, int8)
+IMPLEMENT_READER(UInt16, uint16)
+IMPLEMENT_READER(Int16, int16)
+IMPLEMENT_READER(UInt32, uint32)
+IMPLEMENT_READER(Int32, int32)
+IMPLEMENT_READER(UInt64, uint64)
+IMPLEMENT_READER(Int64, int64)
+IMPLEMENT_READER(Float32, float32)
+IMPLEMENT_READER(Float64, float64)
+
+#undef IMPLEMENT_READER
+
+// Data structures that are one byte per element can be
+// directly copied, regardles of endian-ness.
+#define IMPLEMENT_READER(ucase, lcase)\
+void BinaryInput::read##ucase(lcase* out, int64 n) {\
+ if (sizeof(lcase) == 1) {\
+ readBytes(out, n);\
+ } else {\
+ for (int64 i = 0; i < n ; ++i) {\
+ out[i] = read##ucase();\
+ }\
+ }\
+}
+
+IMPLEMENT_READER(Bool8, bool)
+IMPLEMENT_READER(UInt8, uint8)
+IMPLEMENT_READER(Int8, int8)
+
+#undef IMPLEMENT_READER
+
+
+#define IMPLEMENT_READER(ucase, lcase)\
+void BinaryInput::read##ucase(lcase* out, int64 n) {\
+ if (m_swapBytes) {\
+ for (int64 i = 0; i < n; ++i) {\
+ out[i] = read##ucase();\
+ }\
+ } else {\
+ readBytes(out, sizeof(lcase) * n);\
+ }\
+}
+
+
+IMPLEMENT_READER(UInt16, uint16)
+IMPLEMENT_READER(Int16, int16)
+IMPLEMENT_READER(UInt32, uint32)
+IMPLEMENT_READER(Int32, int32)
+IMPLEMENT_READER(UInt64, uint64)
+IMPLEMENT_READER(Int64, int64)
+IMPLEMENT_READER(Float32, float32)
+IMPLEMENT_READER(Float64, float64)
+
+#undef IMPLEMENT_READER
+
+} // namespace G3D
+