From 48d85b777fa0516d729e3a40e796b11b2ef357b0 Mon Sep 17 00:00:00 2001 From: Rtch90 Date: Sun, 2 Sep 2012 22:00:18 +0100 Subject: [PATCH] [Add] Adding some more Filesystem stuff. This will allow you to manipulate files at your will. -- Kinda. --- Bin/LibD.pro | 5 + src/System/Filesystem/EmptyBuffer.h | 17 ++ src/System/Filesystem/FileList.cpp | 280 +++++++++++++++++++++++++++ src/System/Filesystem/FileList.h | 31 +++ src/System/Filesystem/IFileList.h | 28 +++ src/System/Filesystem/IFilePackage.h | 18 ++ 6 files changed, 379 insertions(+) create mode 100644 src/System/Filesystem/EmptyBuffer.h create mode 100644 src/System/Filesystem/FileList.cpp create mode 100644 src/System/Filesystem/FileList.h create mode 100644 src/System/Filesystem/IFileList.h create mode 100644 src/System/Filesystem/IFilePackage.h diff --git a/Bin/LibD.pro b/Bin/LibD.pro index a354021..72cb8d3 100644 --- a/Bin/LibD.pro +++ b/Bin/LibD.pro @@ -39,6 +39,10 @@ HEADERS += ../src/Actor/Player.h \ ../src/System/ResourceManager.h \ ../src/System/ConvertType.h \ ../src/System/Filesystem/InputStream.h \ + ../src/System/Filesystem/EmptyBuffer.h \ + ../src/System/Filesystem/IFileList.h \ + ../src/System/Filesystem/IFilePackage.h \ + ../src/System/Filesystem/FileList.h \ ../src/Texture/Texture.h \ ../src/Sound/Music.h \ ../src/TMXParser/base64.h \ @@ -90,6 +94,7 @@ SOURCES += ../src/Actor/Player.cpp \ ../src/Sprite/Sprite.cpp \ ../src/System/Debug.cpp \ ../src/System/Filesystem/InputStream.cpp \ + ../src/System/Filesystem/FileList.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 new file mode 100644 index 0000000..802dca5 --- /dev/null +++ b/src/System/Filesystem/EmptyBuffer.h @@ -0,0 +1,17 @@ +#pragma once + +#include "InputStream.h" + +namespace saracraft { +namespace filesystem { + +struct EmptyBuffer: public IINputStreamBuffer { + unsigned char PopByte(void) { return 0; } + bool IsEof(void) const { return true; } + int GetSize(void) const { return 0; } + void PopBytes(char*, int) { } +}; + +} // Namespace filesystem. +} // Namespace saracraft. + diff --git a/src/System/Filesystem/FileList.cpp b/src/System/Filesystem/FileList.cpp new file mode 100644 index 0000000..485b3a9 --- /dev/null +++ b/src/System/Filesystem/FileList.cpp @@ -0,0 +1,280 @@ +#include +#include +#include +#include +#include "FileList.h" + +using namespace std; +using namespace boost; + +namespace saracraft { +namespace filesystem { +namespace { + +struct Dir; +typedef vector StringList; +typedef map DirList; +typedef vector IteratorList; + +struct Dir { + StringList files; + IteratorList subDirs; + + void AddFile(const string& file) { + for(unsigned int i = 0; i < files.size(); ++i) { + if(file == files[i]) + return; + } + files.push_back(file); + } +}; + +void HaxFile(string& str) { + for(unsigned int i = 0; i < str.size(); ++i) { + if(str[i] == '\\') + str[i] = '/'; + } +} + +void ConvertLower(string& str) { + for(unsigned int i = 0; i < str.size(); ++i) { + str[i] = tolower(str[i]); + } +} + +void GetDirPart(const string& file, string& dir) { + string::size_type index = file.find_last_of("\\/"); + if(index == file.npos) { + dir = string(); + return; + } + dir = file.substr(0, index); +} + +int GetDirAmountImpl(const IteratorList& list) { + int result = list.size(); + /*for(IteratorList::const_iterator it = list.begin(); it != list.end(); ++i) { + const DirList::const_iterator& i = *it; + result += GetDirAmountImpl(i->second.subDirs); + }*/ + return result; +} + +int GetDirNameImpl(const IteratorList& list, string& result, int currentIndex, int findIndex) { + int original = currentIndex; + for(IteratorList::const_iterator it = list.begin(); it != list.end(); ++it) { + const DirList::const_iterator& i = *it; + if(currentIndex++ == findIndex) { + result = i->first; + break; + } + //currentIndex += GetDirNameImpl(i->second.subDirs + } + return currentIndex - original; +} +string empty; + +} // Namespace unamed. +struct FileList::Data { + bool caseSensitive; + DirList dirs; + + Data(void) : caseSensitive(false) {} + + // Might want to put some directory hierarchy stuff here? + + void AddDir(const string& dir) { + DirList::iterator it; + if(!FindDir(it, dir)) { + dirs[dir] = Dir(); + FindDir(it, dir); + + // Add a parent to the list. + string current = dir; + DirList::iterator currentIt = it; + + for(int i = 0; ; ++i) { + string parent; + GetDirPart(current, parent); + if(parent.empty()) + break; + + bool needAdd = false; + + DirList::iterator parentIt; + if(!FindDir(parentIt, parent)) { + dirs[parent] = Dir(); + FindDir(parentIt, parent); + needAdd = true; + } + parentIt->second.subDirs.push_back(currentIt); + if(!needAdd) + break; + current = parent; + currentIt = parentIt; + } + } + } + + bool FindDir(DirList::iterator& it, const string& dir) { + it = dirs.find(dir); + if(it == dirs.end()) + return false; + + return true; + } +}; + +FileList::FileList(void) { + scoped_ptr tempData(new Data()); + _data.swap(tempData); +} + +FileList::~FileList(void) { + +} + +void FileList::SetCaseSensitivity(bool enable) { + _data->caseSensitive = enable; +} + +void FileList::AddDir(const string& dir_) { + string dir = dir_; + if(!_data->caseSensitive) + ConvertLower(dir); + + HaxFile(dir); + _data->AddDir(dir); +} + +void FileList::AddFile(const string& file_) { + string file = file_; + if(!_data->caseSensitive) + ConvertLower(file); + HaxFile(file); + + string dir; + GetDirPart(file, dir); + _data->AddDir(dir); + + DirList::iterator it; + _data->FindDir(it, dir); + it->second.AddFile(file); +} + +int FileList::GetDirAmount(const string& root_) const { + string root = root_; + if(!_data->caseSensitive) + ConvertLower(root); + HaxFile(root); + DirList::iterator it; + + if(!_data->FindDir(it, root)) + return 0; + return GetDirAmountImpl(it->second.subDirs); +} + +string FileList::GetDirName(const string& root_, int index) const { + string root = root_; + if(!_data->caseSensitive) + ConvertLower(root); + + HaxFile(root); + DirList::iterator it; + if(!_data->FindDir(it, root)) + return empty; + + string result; + GetDirNameImpl(it->second.subDirs, result, 0, index); + + return result; +} + +int FileList::GetFileAmount(const string& root_) const { + string root = root_; + if(!_data->caseSensitive) + ConvertLower(root); + HaxFile(root); + + DirList::iterator it; + if(!_data->FindDir(it, root)) + return 0; + return it->second.files.size(); +} + +const string& FileList::GetFileName(const string& root_, int index) const { + string root = root_; + if(!_data->caseSensitive) + ConvertLower(root); + HaxFile(root); + + DirList::iterator it; + if(!_data->FindDir(it, root)) + return empty; + return it->second.files[index]; +} + +// ============================================================ +namespace { + void GetAllFilesImpl(IFileList& list, const string& root, vector& result, bool recurse) { + //if(root.find(" + + // The hell is your problem?! + int fileAmount = list.GetFileAmount(root); + for(int i = 0; i < fileAmount; ++i) { + const string& file = list.GetFileName(root, i); + result.push_back(file); + } + if(recurse) { + int dirAmount = list.GetDirAmount(root); + for(int i = 0; i < dirAmount; ++i) { + const string& dir = list.GetDirName(root, i); + if(dir.length() > 4 && dir.substr(dir.length() - 4, 4) == ".svn") { + // We should never even get here.. + } else { + GetAllFilesImpl(list, dir, result, recurse); + } + } + } + } + + void GetAllDirsImpl(IFileList& list, const string& root, vector& result, bool recurse) { + int dirAmount = list.GetDirAmount(root); + for(int i = 0; i < dirAmount; ++i) { + const string& dir = list.GetDirName(root, i); + if(dir.length() > 4 && dir.substr(dir.length() - 4, 4) == ".svn") { + // We should never even get here.. + } else { + result.push_back(dir); + + if(recurse) + GetAllDirsImpl(list, dir, result, recurse); + } + } + } +} // Unamed namespace. + +void GetAllFiles(IFileList& list, const string& root_, vector& result, bool recurse, bool caseSensitive) { + string root = root_; + if(!caseSensitive) + ConvertLower(root); + HaxFile(root); + + GetAllFilesImpl(list, root, result, recurse); + std::sort(result.begin(), result.end()); +} + + +void GetAllDirs(IFileList& list, const string& root_, vector& result, bool recurse, bool caseSensitive) { + string root = root_; + if(!caseSensitive) + ConvertLower(root); + HaxFile(root); + + GetAllDirsImpl(list, root, result, recurse); + std::sort(result.begin(), result.end()); +} + +} // Namespace filesystem. +} // Namespace saracraft. + diff --git a/src/System/Filesystem/FileList.h b/src/System/Filesystem/FileList.h new file mode 100644 index 0000000..731e956 --- /dev/null +++ b/src/System/Filesystem/FileList.h @@ -0,0 +1,31 @@ +#pragma once +#include +#include +#include +#include "IFileList.h" + +namespace saracraft { +namespace filesystem { + +class FileList: public IFileList { +struct Data; +boost::scoped_ptr _data; + +public: + FileList(void); + ~FileList(void); + + void SetCaseSensitivity(bool enable); + + void AddDir(const std::string& dir); + void AddFile(const std::string& file); + + int GetDirAmount(const std::string& root) const; + std::string GetDirName(const std::string& root, int index) const; + int GetFileAmount(const std::string& root) const; + const std::string& GetFileName(const std::string& root, int index) const; +}; + +} // Namespace filesystem. +} // Namespace saracraft. + diff --git a/src/System/Filesystem/IFileList.h b/src/System/Filesystem/IFileList.h new file mode 100644 index 0000000..c0f8c87 --- /dev/null +++ b/src/System/Filesystem/IFileList.h @@ -0,0 +1,28 @@ +#pragma once +#include +#include + +namespace saracraft { +namespace filesystem { + +class IFileList { +public: + virtual ~IFileList(void) {} + + virtual void SetCaseSensitivity(bool enable) = 0; + + virtual void AddDir(const std::string& dir) = 0; + virtual void AddFile(const std::string& file) = 0; + + virtual int GetDirAmount(const std::string& root) const = 0; + virtual std::string GetDirName(const std::string& root, int index) const = 0; + virtual int GetFileAmount(const std::string& root) const = 0; + virtual const std::string& GetFileName(const std::string& root, int index) const = 0; +}; + +void GetAllFiles(IFileList& list, const std::string& root, std::vector& result, bool recurse, bool caseSensitive = false); +void GetAllDirs(IFileList& list, const std::string& root, std::vector& result, bool recurse, bool caseSensitive = false); + +} // Namespace filesystem. +} // Namespace saracraft. + diff --git a/src/System/Filesystem/IFilePackage.h b/src/System/Filesystem/IFilePackage.h new file mode 100644 index 0000000..eda9537 --- /dev/null +++ b/src/System/Filesystem/IFilePackage.h @@ -0,0 +1,18 @@ +#pragma once +#include "InputStream.h" + +namespace saracraft { +namespace filesystem { + +class IFileList; +class IFilePackage { +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; +}; + +} // Namespace filesystem. +} // Namespace saracraft. +