1 /* === S Y N F I G ========================================================= */ 2 /*! \file filesystem.h 3 ** \brief FileSystem 4 ** 5 ** $Id$ 6 ** 7 ** \legal 8 ** ......... ... 2013 Ivan Mahonin 9 ** 10 ** This package is free software; you can redistribute it and/or 11 ** modify it under the terms of the GNU General Public License as 12 ** published by the Free Software Foundation; either version 2 of 13 ** the License, or (at your option) any later version. 14 ** 15 ** This package is distributed in the hope that it will be useful, 16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 ** General Public License for more details. 19 ** \endlegal 20 */ 21 /* ========================================================================= */ 22 23 /* === S T A R T =========================================================== */ 24 25 #ifndef __SYNFIG_FILESYSTEM_H 26 #define __SYNFIG_FILESYSTEM_H 27 28 /* === H E A D E R S ======================================================= */ 29 30 #include <cstdio> 31 32 #include <istream> 33 #include <ostream> 34 #include <streambuf> 35 #include <vector> 36 37 #include <ETL/handle> 38 39 #include "string.h" 40 41 /* === M A C R O S ========================================================= */ 42 43 /* === T Y P E D E F S ===================================================== */ 44 45 /* === C L A S S E S & S T R U C T S ======================================= */ 46 47 namespace synfig 48 { 49 50 class FileSystem : public etl::shared_object 51 { 52 public: 53 typedef etl::handle<FileSystem> Handle; 54 typedef std::vector<String> FileList; 55 56 class Stream : public etl::shared_object 57 { 58 public: 59 typedef etl::handle<Stream> Handle; 60 61 protected: 62 FileSystem::Handle file_system_; 63 Stream(FileSystem::Handle file_system); 64 public: 65 virtual ~Stream(); file_system()66 FileSystem::Handle file_system() const { return file_system_; } 67 }; 68 69 class ReadStream : 70 public Stream, 71 private std::streambuf, 72 public std::istream 73 { 74 public: 75 typedef etl::handle<ReadStream> Handle; 76 77 protected: 78 char buffer_; 79 80 ReadStream(FileSystem::Handle file_system); 81 virtual int underflow(); 82 virtual size_t internal_read(void *buffer, size_t size) = 0; 83 84 public: read_block(void * buffer,size_t size)85 size_t read_block(void *buffer, size_t size) 86 { return read((char*)buffer, size).gcount(); } read_whole_block(void * buffer,size_t size)87 bool read_whole_block(void *buffer, size_t size) 88 { return size == read_block(buffer, size); } read_variable(T & v)89 template<typename T> bool read_variable(T &v) 90 { return read_whole_block(&v, sizeof(T)); } 91 }; 92 93 class WriteStream : 94 public Stream, 95 private std::streambuf, 96 public std::ostream 97 { 98 public: 99 typedef etl::handle<WriteStream> Handle; 100 101 protected: 102 WriteStream(FileSystem::Handle file_system); 103 virtual int overflow(int ch); 104 virtual size_t internal_write(const void *buffer, size_t size) = 0; 105 106 public: write_block(const void * buffer,size_t size)107 bool write_block(const void *buffer, size_t size) 108 { 109 for(size_t i = 0; i < size; i++) 110 if (!put(((const char*)buffer)[i]).good()) 111 return i; 112 return size; 113 } write_whole_block(const void * buffer,size_t size)114 bool write_whole_block(const void *buffer, size_t size) 115 { return size == write_block(buffer, size); } write_whole_stream(std::streambuf & streambuf)116 bool write_whole_stream(std::streambuf &streambuf) 117 { return (*this << &streambuf).good(); } write_whole_stream(std::istream & stream)118 bool write_whole_stream(std::istream &stream) 119 { return write_whole_stream(*stream.rdbuf()); } write_whole_stream(ReadStream::Handle stream)120 bool write_whole_stream(ReadStream::Handle stream) 121 { return !stream || write_whole_stream(*(std::istream*)&(*stream)); } write_variable(const T & v)122 template<typename T> bool write_variable(const T &v) 123 { return write_whole_block(&v, sizeof(T)); } 124 }; 125 126 class Identifier { 127 public: 128 FileSystem::Handle file_system; 129 String filename; Identifier()130 Identifier() { } Identifier(const FileSystem::Handle & file_system,const String & filename)131 Identifier(const FileSystem::Handle &file_system, const String &filename): 132 file_system(file_system), filename(filename) { } 133 empty()134 bool empty() const { return file_system; } 135 operator bool () const { return !empty(); } 136 137 bool operator < (const Identifier &other) const 138 { 139 if (file_system.get() < other.file_system.get()) return true; 140 if (other.file_system.get() < file_system.get()) return false; 141 if (filename < other.filename) return true; 142 if (other.filename < filename) return false; 143 return false; 144 } 145 bool operator > (const Identifier &other) const 146 { return other < *this; } 147 bool operator != (const Identifier &other) const 148 { return *this > other || other < *this; } 149 bool operator == (const Identifier &other) const 150 { return !(*this != other); } 151 152 ReadStream::Handle get_read_stream() const; 153 WriteStream::Handle get_write_stream() const; 154 }; 155 156 FileSystem(); 157 virtual ~FileSystem(); 158 159 virtual bool is_file(const String &filename) = 0; 160 virtual bool is_directory(const String &filename) = 0; 161 162 virtual bool directory_create(const String &dirname) = 0; 163 virtual bool directory_scan(const String &dirname, FileList &out_files) = 0; 164 165 virtual bool file_remove(const String &filename) = 0; 166 virtual bool file_rename(const String &from_filename, const String &to_filename); 167 virtual ReadStream::Handle get_read_stream(const String &filename) = 0; 168 virtual WriteStream::Handle get_write_stream(const String &filename) = 0; 169 virtual String get_real_uri(const String &filename); 170 is_exists(const String filename)171 inline bool is_exists(const String filename) { return is_file(filename) || is_directory(filename); } 172 173 String get_real_filename(const String &filename); get_identifier(const String & filename)174 Identifier get_identifier(const String &filename) { return Identifier(this, filename); } 175 176 bool directory_create_recursive(const String &dirname); 177 bool remove_recursive(const String &filename); 178 179 static bool copy(Handle from_file_system, const String &from_filename, Handle to_file_system, const String &to_filename); 180 static bool copy_recursive(Handle from_file_system, const String &from_filename, Handle to_file_system, const String &to_filename); 181 182 static String fix_slashes(const String &filename); 183 184 ///!@brief Read a stream line by line even '\r\n' ended 185 static std::istream& safe_get_line(std::istream& is, String& t); 186 }; 187 188 //! Always empty filesystem (dummy) 189 class FileSystemEmpty : public FileSystem 190 { 191 public: 192 typedef etl::handle<FileSystemEmpty> Handle; 193 194 FileSystemEmpty(); 195 virtual ~FileSystemEmpty(); 196 is_file(const String &)197 virtual bool is_file(const String & /*filename*/) 198 { return false; } is_directory(const String & filename)199 virtual bool is_directory(const String &filename) 200 { return fix_slashes(filename).empty(); } 201 directory_create(const String & dirname)202 virtual bool directory_create(const String &dirname) 203 { return is_directory(dirname); } directory_scan(const String & dirname,FileList & out_files)204 virtual bool directory_scan(const String &dirname, FileList &out_files) 205 { out_files.clear(); return is_directory(dirname); } 206 file_remove(const String & filename)207 virtual bool file_remove(const String &filename) 208 { return !is_directory(filename); } file_rename(const String & from_filename,const String & to_filename)209 virtual bool file_rename(const String &from_filename, const String &to_filename) 210 { return is_directory(from_filename) && is_directory(to_filename); } get_read_stream(const String &)211 virtual FileSystem::ReadStream::Handle get_read_stream(const String &/*filename*/) 212 { return ReadStream::Handle(); } get_write_stream(const String &)213 virtual FileSystem::WriteStream::Handle get_write_stream(const String &/*filename*/) 214 { return WriteStream::Handle(); } 215 }; 216 } 217 218 /* === E N D =============================================================== */ 219 220 #endif 221