fs_filesystem.h
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #if !defined(INCLUDED_FS_FILESYSTEM_H)
00023 #define INCLUDED_FS_FILESYSTEM_H
00024
00025 #include "string/string.h"
00026 #include "os/path.h"
00027
00028 #include <string>
00029 #include <map>
00030
00031 inline unsigned int path_get_depth (const std::string& path)
00032 {
00033 unsigned int depth = 0;
00034 const char *cstr = path.c_str();
00035 while (cstr != 0 && cstr[0] != '\0') {
00036 cstr = strchr(cstr, '/');
00037 if (cstr != 0) {
00038 ++cstr;
00039 }
00040 ++depth;
00041 }
00042 return depth;
00043 }
00044
00047 inline const char* path_remove_directory (const char* path)
00048 {
00049 const char* first_separator = strchr(path, '/');
00050 if (first_separator != 0) {
00051 return ++first_separator;
00052 }
00053 return "";
00054 }
00055
00059 template<typename file_type>
00060 class GenericFileSystem
00061 {
00062 class Path
00063 {
00064 std::string m_path;
00065 unsigned int m_depth;
00066 public:
00067 Path (const std::string& path) :
00068 m_path(path), m_depth(path_get_depth(c_str()))
00069 {
00070 }
00071 Path (const char* start, std::size_t length) :
00072 m_path(start, length), m_depth(path_get_depth(m_path))
00073 {
00074 }
00075 bool operator< (const Path& other) const
00076 {
00077 return string_less_nocase(c_str(), other.c_str());
00078 }
00079 unsigned int depth () const
00080 {
00081 return m_depth;
00082 }
00083 const char* c_str () const
00084 {
00085 return m_path.c_str();
00086 }
00087 const std::string& string () const
00088 {
00089 return m_path;
00090 }
00091 };
00092
00093 class Entry
00094 {
00095 file_type* m_file;
00096 public:
00097 Entry () :
00098 m_file(0)
00099 {
00100 }
00101 Entry (file_type* file) :
00102 m_file(file)
00103 {
00104 }
00105 file_type* file () const
00106 {
00107 return m_file;
00108 }
00109 bool is_directory () const
00110 {
00111 return file() == 0;
00112 }
00113 };
00114
00115 typedef std::map<Path, Entry> Entries;
00116 Entries m_entries;
00117
00118 public:
00119 typedef typename Entries::iterator iterator;
00120 typedef typename Entries::value_type value_type;
00121 typedef Entry entry_type;
00122
00123 iterator begin ()
00124 {
00125 return m_entries.begin();
00126 }
00127 iterator end ()
00128 {
00129 return m_entries.end();
00130 }
00131
00135 entry_type& operator[] (const Path& path)
00136 {
00137 const char* start = path.c_str();
00138 const char* end = path_remove_directory(path.c_str());
00139
00140 while (end[0] != '\0') {
00141
00142 Path dir(start, end - start);
00143
00144
00145 m_entries.insert(value_type(dir, Entry(NULL)));
00146
00147 end = path_remove_directory(end);
00148 }
00149
00150 return m_entries[path];
00151 }
00152
00154 iterator find (const Path& path)
00155 {
00156 return m_entries.find(path);
00157 }
00158
00159 iterator begin (const std::string& root)
00160 {
00161 if (root[0] == '\0') {
00162 return m_entries.begin();
00163 }
00164 iterator i = m_entries.find(root);
00165 if (i == m_entries.end()) {
00166 return i;
00167 }
00168 return ++i;
00169 }
00170
00175 template<typename visitor_type>
00176 void traverse (visitor_type visitor, const std::string& root)
00177 {
00178 unsigned int start_depth = path_get_depth(root);
00179 unsigned int skip_depth = 0;
00180 for (iterator i = begin(root); i != end() && i->first.depth() > start_depth; ++i) {
00181 if (i->first.depth() == skip_depth) {
00182 skip_depth = 0;
00183 }
00184 if (skip_depth == 0) {
00185 if (!i->second.is_directory()) {
00186 visitor.file(i->first.c_str());
00187 } else if (visitor.directory(i->first.c_str(), i->first.depth() - start_depth)) {
00188 skip_depth = i->first.depth();
00189 }
00190 }
00191 }
00192 }
00193 };
00194
00195 #endif