From e0535ca6dfee3e5680d591e5764529596d4d412d Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Thu, 7 Feb 2013 09:15:55 +0000 Subject: Added a cGZipFile class for reading GZipped files. git-svn-id: http://mc-server.googlecode.com/svn/trunk@1196 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- VC2008/MCServer.vcproj | 8 +++++ source/BlockArea.cpp | 19 ++++------- source/OSSupport/File.cpp | 4 +-- source/OSSupport/File.h | 14 ++------ source/OSSupport/GZipFile.cpp | 79 +++++++++++++++++++++++++++++++++++++++++++ source/OSSupport/GZipFile.h | 49 +++++++++++++++++++++++++++ 6 files changed, 147 insertions(+), 26 deletions(-) create mode 100644 source/OSSupport/GZipFile.cpp create mode 100644 source/OSSupport/GZipFile.h diff --git a/VC2008/MCServer.vcproj b/VC2008/MCServer.vcproj index b9d671d0e..16f58fad6 100644 --- a/VC2008/MCServer.vcproj +++ b/VC2008/MCServer.vcproj @@ -1166,6 +1166,14 @@ RelativePath="..\source\OSSupport\File.h" > + + + + diff --git a/source/BlockArea.cpp b/source/BlockArea.cpp index cdabf0378..6a973efe6 100644 --- a/source/BlockArea.cpp +++ b/source/BlockArea.cpp @@ -7,7 +7,7 @@ #include "Globals.h" #include "BlockArea.h" #include "World.h" -#include "zlib.h" +#include "OSSupport/GZipFile.h" #include "WorldStorage/FastNBT.h" @@ -194,28 +194,21 @@ bool cBlockArea::LoadFromSchematicFile(const AString & a_FileName) { // Un-GZip the contents: AString Contents; - gzFile File = gzopen(a_FileName.c_str(), "rb"); - if (File == NULL) + cGZipFile File; + if (!File.Open(a_FileName, cGZipFile::fmRead)) { LOG("Cannot open the schematic file \"%s\".", a_FileName.c_str()); return false; } - // Since the gzip format doesn't really support getting the uncompressed length, we need to read incrementally. Yuck! - int NumBytesRead = 0; - char Buffer[32 KiB]; - while ((NumBytesRead = gzread(File, Buffer, sizeof(Buffer))) > 0) - { - Contents.append(Buffer, NumBytesRead); - } + int NumBytesRead = File.ReadRestOfFile(Contents); if (NumBytesRead < 0) { LOG("Cannot read GZipped data in the schematic file \"%s\", error %d", a_FileName.c_str(), NumBytesRead); - gzclose(File); return false; } - gzclose(File); + File.Close(); - // TODO: Parse the NBT: + // Parse the NBT: cParsedNBT NBT(Contents.data(), Contents.size()); if (!NBT.IsValid()) { diff --git a/source/OSSupport/File.cpp b/source/OSSupport/File.cpp index 7fbaf218f..15a37a36f 100644 --- a/source/OSSupport/File.cpp +++ b/source/OSSupport/File.cpp @@ -28,7 +28,7 @@ cFile::cFile(void) : /// Constructs and opens / creates the file specified, use IsOpen() to check for success -cFile::cFile(const AString & iFileName, EMode iMode) : +cFile::cFile(const AString & iFileName, eMode iMode) : #ifdef USE_STDIO_FILE m_File(NULL) #else @@ -55,7 +55,7 @@ cFile::~cFile() -bool cFile::Open(const AString & iFileName, EMode iMode) +bool cFile::Open(const AString & iFileName, eMode iMode) { ASSERT(!IsOpen()); // You should close the file before opening another one diff --git a/source/OSSupport/File.h b/source/OSSupport/File.h index 5e7cd4431..fe5d38bd0 100644 --- a/source/OSSupport/File.h +++ b/source/OSSupport/File.h @@ -25,8 +25,6 @@ Usage: #pragma once -#ifndef CFILE_H_INCLUDED -#define CFILE_H_INCLUDED @@ -53,7 +51,7 @@ public: #endif /// The mode in which to open the file - enum EMode + enum eMode { fmRead, // Read-only. If the file doesn't exist, object will not be valid fmWrite, // Write-only. If the file already exists, it will be overwritten @@ -64,12 +62,12 @@ public: cFile(void); /// Constructs and opens / creates the file specified, use IsOpen() to check for success - cFile(const AString & iFileName, EMode iMode); + cFile(const AString & iFileName, eMode iMode); /// Auto-closes the file, if open ~cFile(); - bool Open(const AString & iFileName, EMode iMode); + bool Open(const AString & iFileName, eMode iMode); void Close(void); bool IsOpen(void) const; bool IsEOF(void) const; @@ -108,9 +106,3 @@ private: - -#endif // CFILE_H_INCLUDED - - - - diff --git a/source/OSSupport/GZipFile.cpp b/source/OSSupport/GZipFile.cpp new file mode 100644 index 000000000..8f5edd3d7 --- /dev/null +++ b/source/OSSupport/GZipFile.cpp @@ -0,0 +1,79 @@ + +// GZipFile.cpp + +// Implements the cGZipFile class representing a RAII wrapper over zlib's GZip file routines + +#include "Globals.h" +#include "GZipFile.h" + + + + + +cGZipFile::cGZipFile(void) : + m_File(NULL) +{ +} + + + + + +cGZipFile::~cGZipFile() +{ + Close(); +} + + + + + +bool cGZipFile::Open(const AString & a_FileName, eMode a_Mode) +{ + if (m_File != NULL) + { + ASSERT(!"A file is already open in this object"); + return false; + } + m_File = gzopen(a_FileName.c_str(), (a_Mode == fmRead) ? "r" : "w"); + return (m_File != NULL); +} + + + + + +void cGZipFile::Close(void) +{ + if (m_File != NULL) + { + gzclose(m_File); + m_File = NULL; + } +} + + + + + +int cGZipFile::ReadRestOfFile(AString & a_Contents) +{ + if (m_File == NULL) + { + ASSERT(!"No file has been opened"); + return -1; + } + + // Since the gzip format doesn't really support getting the uncompressed length, we need to read incrementally. Yuck! + int NumBytesRead = 0; + char Buffer[64 KiB]; + while ((NumBytesRead = gzread(m_File, Buffer, sizeof(Buffer))) > 0) + { + a_Contents.append(Buffer, NumBytesRead); + } + return NumBytesRead; +} + + + + diff --git a/source/OSSupport/GZipFile.h b/source/OSSupport/GZipFile.h new file mode 100644 index 000000000..bb8a88ec8 --- /dev/null +++ b/source/OSSupport/GZipFile.h @@ -0,0 +1,49 @@ + +// GZipFile.h + +// Declares the cGZipFile class representing a RAII wrapper over zlib's GZip file routines + + + + + +#pragma once + +#include "zlib.h" + + + + + +class cGZipFile +{ +public: + enum eMode + { + fmRead, // Read-only. If the file doesn't exist, object will not be valid + fmWrite, // Write-only. If the file already exists, it will be overwritten + } ; + + cGZipFile(void); + ~cGZipFile(); + + /// Opens the file. Returns true if successful. Fails if a file has already been opened through this object. + bool Open(const AString & a_FileName, eMode a_Mode); + + /// Closes the file, flushing all buffers. This object may be then reused for a different file and / or mode + void Close(void); + + /// Reads the rest of the file and decompresses it into a_Contents. Returns the number of decompressed bytes, <0 for error + int ReadRestOfFile(AString & a_Contents); + + /// Writes a_Contents into file, compressing it along the way. Returns the number of decompressed bytes, <0 for error. Multiple writes are supported. + int Write(AString & a_Contents); + +protected: + gzFile m_File; +} ; + + + + + -- cgit v1.2.3