fs_filesystem.h

Go to the documentation of this file.
00001 /*
00002  Copyright (C) 2001-2006, William Joseph.
00003  All Rights Reserved.
00004 
00005  This file is part of GtkRadiant.
00006 
00007  GtkRadiant is free software; you can redistribute it and/or modify
00008  it under the terms of the GNU General Public License as published by
00009  the Free Software Foundation; either version 2 of the License, or
00010  (at your option) any later version.
00011 
00012  GtkRadiant is distributed in the hope that it will be useful,
00013  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  GNU General Public License for more details.
00016 
00017  You should have received a copy of the GNU General Public License
00018  along with GtkRadiant; if not, write to the Free Software
00019  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
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                 // greebo: Take the substring from start to end
00142                 Path dir(start, end - start);
00143 
00144                 // And insert it as directory (NULL)
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

Generated by  doxygen 1.6.2