diff --git a/Bin/LibD.pro b/Bin/LibD.pro index 72cb8d3..a16cd08 100644 --- a/Bin/LibD.pro +++ b/Bin/LibD.pro @@ -43,6 +43,8 @@ HEADERS += ../src/Actor/Player.h \ ../src/System/Filesystem/IFileList.h \ ../src/System/Filesystem/IFilePackage.h \ ../src/System/Filesystem/FileList.h \ + ../src/System/Filesystem/InputFileStream.h \ + ../src/System/Filesystem/FilePackageManager.h \ ../src/Texture/Texture.h \ ../src/Sound/Music.h \ ../src/TMXParser/base64.h \ @@ -95,6 +97,8 @@ SOURCES += ../src/Actor/Player.cpp \ ../src/System/Debug.cpp \ ../src/System/Filesystem/InputStream.cpp \ ../src/System/Filesystem/FileList.cpp \ + ../src/System/Filesystem/InputFileStream.cpp \ + ../src/System/Filesystem/FilePackageManager.cpp \ ../src/Texture/Texture.cpp \ ../src/Sound/Music.cpp \ ../src/Actor/NPC.cpp \ diff --git a/src/System/Filesystem/EmptyBuffer.h b/src/System/Filesystem/EmptyBuffer.h index 802dca5..498e657 100644 --- a/src/System/Filesystem/EmptyBuffer.h +++ b/src/System/Filesystem/EmptyBuffer.h @@ -5,7 +5,7 @@ namespace saracraft { namespace filesystem { -struct EmptyBuffer: public IINputStreamBuffer { +struct EmptyBuffer: public IInputStreamBuffer { unsigned char PopByte(void) { return 0; } bool IsEof(void) const { return true; } int GetSize(void) const { return 0; } diff --git a/src/System/Filesystem/FileInputStream.cpp b/src/System/Filesystem/FileInputStream.cpp new file mode 100644 index 0000000..45d9619 --- /dev/null +++ b/src/System/Filesystem/FileInputStream.cpp @@ -0,0 +1,119 @@ +#include +#include "../Debug.h" +#include "InputFileStream.h" + +namespace saracraft { +namespace filesystem { + +struct InputFileStreamBufferData { + FILE* fp; + size_t size; + + InputFileStreamBufferData(const std::string filename) : fp(0), size(0) { + fp = fopen(filename.c_str(), "rb"); + +#ifdef __UNIX__ + // Another ugly as hell case sensitive hack. + // if anyone finds a nice way to handle this. Please implement it. -- Allanis + if(!fp) { + std::string filename = filename; + for(unsigned int i = 0; i < filename.size(); i++) { + if(isupper(filename[i])) + filename[i] = tolower(filename[i]); + else if(filename[i] == '\\') + filename[i] = '/'; + } + fp = fopen(filename.c_str(), "rb"); + } +#endif + if(fp) { + fseek(fp, 0, SEEK_END); + size = ftell(fp); + fseek(fp, 0, SEEK_SET); + } + if(!size) + Close(); + } + + ~InputFileStreamBufferData(void) { + Close(); + } + + void Close(void) { + if(fp) { + fclose(fp); + fp = 0; + } + } +}; + +InputFileStreamBuffer::~InputFileStreamBuffer(void) { + +} + +unsigned char InputFileStreamBuffer::PopByte(void) { + char byte = 0; + if(_data->fp) { + int input = fgetc(_data->fp); + if(input == EOF) + _data->Close(); + else + byte = (char)input; + } + return byte; +} + +bool InputFileStreamBuffer::IsEof(void) const { + if(!_data->fp) + return true; + + return false; +} + +int InputFileStreamBuffer::GetSize(void) const { + if(!_data->fp) + return 0; + + // This could cause maybe about a 2GB limimitation to file size + // by casting to int. Feel free to FIXME. + // -- Allanis + return int(_data->size); +} + +void InputFileStreamBuffer::PopBytes(char* buffer, int bytes) { + if(!_data->fp) { + for(int i = 0; i < bytes; ++i) + buffer[i] = 0; + } else { + //_data->stream.read(buffer, bytes); + if(fread(buffer, 1, bytes, _data->fp) != (unsigned)bytes) + _data->Close(); + } +} + +// HACK: ffs. This is needed to get some sense into the input stream error reporting. +//bool input_file_stream_no_nonexisting_error_message = false; + +//void SetInputStreamErrorReporting(bool logNonExisting) { +// input_file_stream_no_nonexisting_error_message = !logNonExisting; +//} + +InputStream CreateInputFileStream(const std::string& filename) { + + InputStream inputStream; + boost::shared_ptr inputBuffer(new InputBuffer(filename)); + // Eh.. No. + // TODO: Would need a seperate error check, eof is not the same as the file does not exist.. + // This would just spam error messages. We don't want that. + /*if(!inputBuffer->IsEof()) { + if(!input_file_stream_no_nonexisting_error_message) { + Debug->logger("CreateInputFileStream - File \"%s\"does not exist or is zero length.", filename.c_str()); + } + }*/ + inputStream.SetBuffer(inputBuffer); + return inputStream; +} + +} // Namespace filesystem. +} // Namespace saracraft. + diff --git a/src/System/Filesystem/FilePackageManager.cpp b/src/System/Filesystem/FilePackageManager.cpp new file mode 100644 index 0000000..f7226e8 --- /dev/null +++ b/src/System/Filesystem/FilePackageManager.cpp @@ -0,0 +1,106 @@ +#include +#include "../Debug.h" +#include "FilePackageManager.h" +#include "EmptyBuffer.h" +#include "FileList.h" + +// HACK: This is not a good dependancy for error reporting. +// We are going to use it anyway though. +#include "InputFileStream.h" + +namespace saracraft { +namespace filesystem { +namespace { +typedef std::multimap > PackageMap; + FilePackageManager instance; + FilePackageManager* instancePtr = 0; +} // Unamed namespace. + +struct FilePackageManagerData { + PackageMap packages; + bool logNonExisting; + + FilePackageManagerData(void) : logNonExisting(true) {} + + InputStream GetFile(std::string filename) { + for(unsigned int i = 0; i < filename.size(); ++i) { + if(filename[i] == '\\') + filename[i] = '/'; + } + + for(PackageMap::reverse_iterator it = packages.rbegin(); it != packages.rend(); ++it) { + InputStream result = it->second->GetFile(filename); + if(!result.IsEof()) + return result; + } + + // This is a bit of a hack. + // Fix all data to use only lowercase letters if you + // want it to work right. But you know me and upercase characters. --Allanis + for(unsigned int i = 0; i < filename.size(); ++i) { + // Not found try again in lowercase.. + if(isupper(filename[i])) + filename[i] = tolower(filename[i]); + } + + // Nothing has been found. + if(logNonExisting) { + Debug::logger->message("FilePackageManager::GetFile - File: \"%s\" does not exist or is zero in length!", filename.c_str()); + } + InputStream inputStream; + boost::shared_ptr inputBuffer(new EmptyBuffer()); + + inputStream.SetBuffer(inputBuffer); + return inputStream; + } +}; + +FilePackageManager::FilePackageManager(void) { + boost::scoped_ptr tempData(new FilePackageManagerData()); + _data.swap(tempData); +} + +FilePackageManager::~FilePackageManager(void) { +} + +void FilePackageManager::AddPackage(boost::shared_ptr filePackage, int priority) { + std::pair > value(priority, filePackage); + _data->packages.insert(value); +} + +boost::shared_ptr FilePackageManager::FindFiles(const std::string& dir, const std::string& extension, bool caseSensitive) { + boost::shared_ptr result(new FileList()); + result->SetCaseSensitivity(caseSensitive); + + for(PackageMap::iterator it = _data->packages.begin(); it != _data->packages.end(); ++it) + it->second->FindFiles(dir, extension, *result); + + return result; +} + +InputStream FilePackageManager::GetFile(const std::string& filename) { + return _data->GetFile(filename); +} + +void FilePackageManager::SetInputStreamErrorReporting(bool logNonExisting) { + // HACK: This goes directly to the input file stream... + _data->logNonExisting = logNonExisting; +} + +FilePackageManager& FilePackageManager::GetInstance(void) { + if(!instancePtr) + instancePtr = &instance; + return *instancePtr; +} + +void FilePackageManager::SetInstancePtr(FilePackageManager* newInstance) { + assert(newInstance); + instancePtr = newInstance; + + //FilePackageManager& oldInstance = GetInstance(); + //oldInstance._data->packages = newInstance->_data->packages; +} + +} // Namespace filesystem. +} // Namespace saracraft. + diff --git a/src/System/Filesystem/FilePackageManager.h b/src/System/Filesystem/FilePackageManager.h new file mode 100644 index 0000000..30d3b77 --- /dev/null +++ b/src/System/Filesystem/FilePackageManager.h @@ -0,0 +1,32 @@ +#pragma once + +#include +#include + +#include "IFilePackage.h" + +namespace saracraft { +namespace filesystem { + +class IFileList; +struct FilePackageManagerData; + +class FilePackageManager { + boost::scoped_ptr _data; +public: + FilePackageManager(void); + ~FilePackageManager(void); + + void AddPackage(boost::shared_ptr filePackae, int priority); + boost::shared_ptr FindFiles(const std::string& dir, const std::string& extension, bool caseSensitive = false); + InputStream GetFile(const std::string& filename); + + void SetInputStreamErrorReporting(bool logNonExisting); + + static FilePackageManager& GetInstance(void); + static void SetInstancePtr(FilePackageManager* instance); +}; + +} // Namespace filesystem. +} // Namespace saracraft. + diff --git a/src/System/Filesystem/IFilePackage.h b/src/System/Filesystem/IFilePackage.h index eda9537..2cd54f3 100644 --- a/src/System/Filesystem/IFilePackage.h +++ b/src/System/Filesystem/IFilePackage.h @@ -10,7 +10,7 @@ public: virtual ~IFilePackage(void) {} virtual void FindFiles(const std::string& dir, const std::string& extension, IFileList& result) = 0; - virtual InputStream getFile(const std::string& filename) = 0; + virtual InputStream GetFile(const std::string& filename) = 0; }; } // Namespace filesystem. diff --git a/src/System/Filesystem/InputFileStream.cpp b/src/System/Filesystem/InputFileStream.cpp new file mode 100644 index 0000000..27e659a --- /dev/null +++ b/src/System/Filesystem/InputFileStream.cpp @@ -0,0 +1,122 @@ +#include +#include "../Debug.h" +#include "InputFileStream.h" + +namespace saracraft { +namespace filesystem { + +struct InputFileStreamBufferData { + FILE* fp; + size_t size; + + InputFileStreamBufferData(const std::string filename) : fp(0), size(0) { + fp = fopen(filename.c_str(), "rb"); + +#ifdef __UNIX__ + // Another ugly as hell case sensitive hack. + // if anyone finds a nice way to handle this. Please implement it. -- Allanis + if(!fp) { + std::string filename = filename; + for(unsigned int i = 0; i < filename.size(); i++) { + if(isupper(filename[i])) + filename[i] = tolower(filename[i]); + else if(filename[i] == '\\') + filename[i] = '/'; + } + fp = fopen(filename.c_str(), "rb"); + } +#endif + if(fp) { + fseek(fp, 0, SEEK_END); + size = ftell(fp); + fseek(fp, 0, SEEK_SET); + } + if(!size) + Close(); + } + + ~InputFileStreamBufferData(void) { + Close(); + } + + void Close(void) { + if(fp) { + fclose(fp); + fp = 0; + } + } +}; + +InputFileStreamBuffer::~InputFileStreamBuffer(void) { + +} + +unsigned char InputFileStreamBuffer::PopByte(void) { + char byte = 0; + if(_data->fp) { + int input = fgetc(_data->fp); + if(input == EOF) + _data->Close(); + else + byte = (char)input; + } + return byte; +} + +bool InputFileStreamBuffer::IsEof(void) const { + if(!_data->fp) + return true; + + return false; +} + +int InputFileStreamBuffer::GetSize(void) const { + if(!_data->fp) + return 0; + + // This could cause maybe about a 2GB limimitation to file size + // by casting to int. Feel free to FIXME. + // -- Allanis + return int(_data->size); +} + +void InputFileStreamBuffer::PopBytes(char* buffer, int bytes) { + if(!_data->fp) { + for(int i = 0; i < bytes; ++i) + buffer[i] = 0; + } else { + //_data->stream.read(buffer, bytes); + if(fread(buffer, 1, bytes, _data->fp) != (unsigned)bytes) + _data->Close(); + } +} + +// HACK: ffs. This is needed to get some sense into the input stream error reporting. +//bool input_file_stream_no_nonexisting_error_message = false; + +//void SetInputStreamErrorReporting(bool logNonExisting) { +// input_file_stream_no_nonexisting_error_message = !logNonExisting; +//} + +InputStream CreateInputFileStream(const std::string& filename) { + + // This whole method is pissing me off!!!!!!!!!! + //There.. + + //InputStream inputStream; + //boost::shared_ptr inputBuffer(new InputFileStreamBuffer(filename)); + // Eh.. No. + // TODO: Would need a seperate error check, eof is not the same as the file does not exist.. + // This would just spam error messages. We don't want that. + /*if(!inputBuffer->IsEof()) { + if(!input_file_stream_no_nonexisting_error_message) { + Debug->logger("CreateInputFileStream - File \"%s\"does not exist or is zero length.", filename.c_str()); + } + }*/ + //inputStream.SetBuffer(inputBuffer); + //return inputStream; +} + +} // Namespace filesystem. +} // Namespace saracraft. + diff --git a/src/System/Filesystem/InputFileStream.h b/src/System/Filesystem/InputFileStream.h new file mode 100644 index 0000000..7285ff2 --- /dev/null +++ b/src/System/Filesystem/InputFileStream.h @@ -0,0 +1,30 @@ +// I forgot some code.. +#pragma once +#include +#include "InputStream.h" + +namespace saracraft { +namespace filesystem { + +struct InputFileStreamBufferData; + +class InputFileStreamBuffer: public IInputStreamBuffer { + boost::scoped_ptr _data; + +public: + InputFileStreamBuffer(const std::string& filename); + ~InputFileStreamBuffer(void); + + unsigned char PopByte(void); + bool IsEof(void) const; + int GetSize(void) const; + + void PopBytes(char* buffer, int bytes); +}; + +InputStream CreateInputFileStream(const std::string& filename); +void SetInputStreamErrorReporting(bool logNonExisting); + +} // Namespace filesystem. +} // Namespace saracraft. +