/* === S Y N F I G ========================================================= */ /*! \file filesystem.h ** \brief FileSystem ** ** $Id$ ** ** \legal ** ......... ... 2013 Ivan Mahonin ** ** This package is free software; you can redistribute it and/or ** modify it under the terms of the GNU General Public License as ** published by the Free Software Foundation; either version 2 of ** the License, or (at your option) any later version. ** ** This package is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ** General Public License for more details. ** \endlegal */ /* ========================================================================= */ /* === S T A R T =========================================================== */ #ifndef __SYNFIG_FILESYSTEM_H #define __SYNFIG_FILESYSTEM_H /* === H E A D E R S ======================================================= */ #include #include #include #include #include #include #include "string.h" /* === M A C R O S ========================================================= */ /* === T Y P E D E F S ===================================================== */ /* === C L A S S E S & S T R U C T S ======================================= */ namespace synfig { class FileSystem : public etl::shared_object { public: typedef etl::handle Handle; typedef std::vector FileList; class Stream : public etl::shared_object { public: typedef etl::handle Handle; protected: FileSystem::Handle file_system_; Stream(FileSystem::Handle file_system); public: virtual ~Stream(); FileSystem::Handle file_system() const { return file_system_; } }; class ReadStream : public Stream, private std::streambuf, public std::istream { public: typedef etl::handle Handle; protected: char buffer_; ReadStream(FileSystem::Handle file_system); virtual int underflow(); virtual size_t internal_read(void *buffer, size_t size) = 0; public: size_t read_block(void *buffer, size_t size) { return read((char*)buffer, size).gcount(); } bool read_whole_block(void *buffer, size_t size) { return size == read_block(buffer, size); } template bool read_variable(T &v) { return read_whole_block(&v, sizeof(T)); } }; class WriteStream : public Stream, private std::streambuf, public std::ostream { public: typedef etl::handle Handle; protected: WriteStream(FileSystem::Handle file_system); virtual int overflow(int ch); virtual size_t internal_write(const void *buffer, size_t size) = 0; public: bool write_block(const void *buffer, size_t size) { for(size_t i = 0; i < size; i++) if (!put(((const char*)buffer)[i]).good()) return i; return size; } bool write_whole_block(const void *buffer, size_t size) { return size == write_block(buffer, size); } bool write_whole_stream(std::streambuf &streambuf) { return (*this << &streambuf).good(); } bool write_whole_stream(std::istream &stream) { return write_whole_stream(*stream.rdbuf()); } bool write_whole_stream(ReadStream::Handle stream) { return !stream || write_whole_stream(*(std::istream*)&(*stream)); } template bool write_variable(const T &v) { return write_whole_block(&v, sizeof(T)); } }; class Identifier { public: FileSystem::Handle file_system; String filename; Identifier() { } Identifier(const FileSystem::Handle &file_system, const String &filename): file_system(file_system), filename(filename) { } bool empty() const { return file_system; } operator bool () const { return !empty(); } bool operator < (const Identifier &other) const { if (file_system.get() < other.file_system.get()) return true; if (other.file_system.get() < file_system.get()) return false; if (filename < other.filename) return true; if (other.filename < filename) return false; return false; } bool operator > (const Identifier &other) const { return other < *this; } bool operator != (const Identifier &other) const { return *this > other || other < *this; } bool operator == (const Identifier &other) const { return !(*this != other); } ReadStream::Handle get_read_stream() const; WriteStream::Handle get_write_stream() const; }; FileSystem(); virtual ~FileSystem(); virtual bool is_file(const String &filename) = 0; virtual bool is_directory(const String &filename) = 0; virtual bool directory_create(const String &dirname) = 0; virtual bool directory_scan(const String &dirname, FileList &out_files) = 0; virtual bool file_remove(const String &filename) = 0; virtual bool file_rename(const String &from_filename, const String &to_filename); virtual ReadStream::Handle get_read_stream(const String &filename) = 0; virtual WriteStream::Handle get_write_stream(const String &filename) = 0; virtual String get_real_uri(const String &filename); inline bool is_exists(const String filename) { return is_file(filename) || is_directory(filename); } String get_real_filename(const String &filename); Identifier get_identifier(const String &filename) { return Identifier(this, filename); } bool directory_create_recursive(const String &dirname); bool remove_recursive(const String &filename); static bool copy(Handle from_file_system, const String &from_filename, Handle to_file_system, const String &to_filename); static bool copy_recursive(Handle from_file_system, const String &from_filename, Handle to_file_system, const String &to_filename); static String fix_slashes(const String &filename); ///!@brief Read a stream line by line even '\r\n' ended static std::istream& safe_get_line(std::istream& is, String& t); }; //! Always empty filesystem (dummy) class FileSystemEmpty : public FileSystem { public: typedef etl::handle Handle; FileSystemEmpty(); virtual ~FileSystemEmpty(); virtual bool is_file(const String & /*filename*/) { return false; } virtual bool is_directory(const String &filename) { return fix_slashes(filename).empty(); } virtual bool directory_create(const String &dirname) { return is_directory(dirname); } virtual bool directory_scan(const String &dirname, FileList &out_files) { out_files.clear(); return is_directory(dirname); } virtual bool file_remove(const String &filename) { return !is_directory(filename); } virtual bool file_rename(const String &from_filename, const String &to_filename) { return is_directory(from_filename) && is_directory(to_filename); } virtual FileSystem::ReadStream::Handle get_read_stream(const String &/*filename*/) { return ReadStream::Handle(); } virtual FileSystem::WriteStream::Handle get_write_stream(const String &/*filename*/) { return WriteStream::Handle(); } }; } /* === E N D =============================================================== */ #endif