/*
-Copyright (C) 2001-2006, William Joseph.
-All Rights Reserved.
+ Copyright (C) 2001-2006, William Joseph.
+ All Rights Reserved.
-This file is part of GtkRadiant.
+ This file is part of GtkRadiant.
-GtkRadiant 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.
+ GtkRadiant 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.
-GtkRadiant 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.
+ GtkRadiant 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.
-You should have received a copy of the GNU General Public License
-along with GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-*/
+ You should have received a copy of the GNU General Public License
+ along with GtkRadiant; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
-#if !defined(INCLUDED_FS_FILESYSTEM_H)
+#if !defined( INCLUDED_FS_FILESYSTEM_H )
#define INCLUDED_FS_FILESYSTEM_H
#include "string/string.h"
#include <map>
-inline unsigned int path_get_depth(const char* path)
-{
- unsigned int depth = 0;
- while(path != 0 && path[0] != '\0')
- {
- path = strchr(path, '/');
- if(path != 0)
- {
- ++path;
- }
- ++depth;
- }
- return depth;
+inline unsigned int path_get_depth( const char* path ){
+ unsigned int depth = 0;
+ while ( path != 0 && path[0] != '\0' )
+ {
+ path = strchr( path, '/' );
+ if ( path != 0 ) {
+ ++path;
+ }
+ ++depth;
+ }
+ return depth;
}
/// \brief A generic unix-style file-system which maps paths to files and directories.
template<typename file_type>
class GenericFileSystem
{
- class Path
- {
- CopiedString m_path;
- unsigned int m_depth;
- public:
- Path(const char* path)
- : m_path(path), m_depth(path_get_depth(c_str()))
- {
- }
- Path(StringRange range)
- : m_path(range), m_depth(path_get_depth(c_str()))
- {
- }
- bool operator<(const Path& other) const
- {
- return string_less_nocase(c_str(), other.c_str());
- }
- unsigned int depth() const
- {
- return m_depth;
- }
- const char* c_str() const
- {
- return m_path.c_str();
- }
- };
-
- class Entry
- {
- file_type* m_file;
- public:
- Entry() : m_file(0)
- {
- }
- Entry(file_type* file) : m_file(file)
- {
- }
- file_type* file() const
- {
- return m_file;
- }
- bool is_directory() const
- {
- return file() == 0;
- }
- };
-
- typedef std::map<Path, Entry> Entries;
- Entries m_entries;
+class Path
+{
+CopiedString m_path;
+unsigned int m_depth;
+public:
+Path( const char* path )
+ : m_path( path ), m_depth( path_get_depth( c_str() ) ){
+}
+Path( StringRange range )
+ : m_path( range ), m_depth( path_get_depth( c_str() ) ){
+}
+bool operator<( const Path& other ) const {
+ return string_less_nocase( c_str(), other.c_str() );
+}
+unsigned int depth() const {
+ return m_depth;
+}
+const char* c_str() const {
+ return m_path.c_str();
+}
+};
+class Entry
+{
+file_type* m_file;
public:
- typedef typename Entries::iterator iterator;
- typedef typename Entries::value_type value_type;
- typedef Entry entry_type;
-
- iterator begin()
- {
- return m_entries.begin();
- }
- iterator end()
- {
- return m_entries.end();
- }
-
- /// \brief Returns the file at \p path.
- /// Creates all directories below \p path if they do not exist.
- /// O(log n) on average.
- entry_type& operator[](const Path& path)
- {
- {
- const char* end = path_remove_directory(path.c_str());
- while(end[0] != '\0')
- {
- Path dir(StringRange(path.c_str(), end));
- m_entries.insert(value_type(dir, Entry(0)));
- end = path_remove_directory(end);
- }
- }
-
- return m_entries[path];
- }
-
- /// \brief Returns the file at \p path or end() if not found.
- iterator find(const Path& path)
- {
- return m_entries.find(path);
- }
-
- iterator begin(const char* root)
- {
- if(root[0] == '\0')
- {
- return m_entries.begin();
- }
- iterator i = m_entries.find(root);
- if(i == m_entries.end())
- {
- return i;
- }
- return ++i;
- }
-
- /// \brief Performs a depth-first traversal of the file-system subtree rooted at \p root.
- /// Traverses the entire tree if \p root is "".
- /// Calls \p visitor.file() with the path to each file relative to the filesystem root.
- /// Calls \p visitor.directory() with the path to each directory relative to the filesystem root.
- template<typename visitor_type>
- void traverse(visitor_type visitor, const char* root)
- {
- unsigned int start_depth = path_get_depth(root);
- unsigned int skip_depth = 0;
- for(iterator i = begin(root); i != end() && i->first.depth() > start_depth; ++i)
- {
- if(i->first.depth() == skip_depth)
- {
- skip_depth = 0;
- }
- if(skip_depth == 0)
- {
- if(!i->second.is_directory())
- {
- visitor.file(i->first.c_str());
- }
- else if(visitor.directory(i->first.c_str(), i->first.depth() - start_depth))
- {
- skip_depth = i->first.depth();
- }
- }
- }
- }
+Entry() : m_file( 0 ){
+}
+Entry( file_type* file ) : m_file( file ){
+}
+file_type* file() const {
+ return m_file;
+}
+bool is_directory() const {
+ return file() == 0;
+}
+};
+
+typedef std::map<Path, Entry> Entries;
+Entries m_entries;
+
+public:
+typedef typename Entries::iterator iterator;
+typedef typename Entries::value_type value_type;
+typedef Entry entry_type;
+
+iterator begin(){
+ return m_entries.begin();
+}
+iterator end(){
+ return m_entries.end();
+}
+
+/// \brief Returns the file at \p path.
+/// Creates all directories below \p path if they do not exist.
+/// O(log n) on average.
+entry_type& operator[]( const Path& path ){
+ {
+ const char* end = path_remove_directory( path.c_str() );
+ while ( end[0] != '\0' )
+ {
+ Path dir( StringRange( path.c_str(), end ) );
+ m_entries.insert( value_type( dir, Entry( 0 ) ) );
+ end = path_remove_directory( end );
+ }
+ }
+
+ return m_entries[path];
+}
+
+/// \brief Returns the file at \p path or end() if not found.
+iterator find( const Path& path ){
+ return m_entries.find( path );
+}
+
+iterator begin( const char* root ){
+ if ( root[0] == '\0' ) {
+ return m_entries.begin();
+ }
+ iterator i = m_entries.find( root );
+ if ( i == m_entries.end() ) {
+ return i;
+ }
+ return ++i;
+}
+
+/// \brief Performs a depth-first traversal of the file-system subtree rooted at \p root.
+/// Traverses the entire tree if \p root is "".
+/// Calls \p visitor.file() with the path to each file relative to the filesystem root.
+/// Calls \p visitor.directory() with the path to each directory relative to the filesystem root.
+template<typename visitor_type>
+void traverse( visitor_type visitor, const char* root ){
+ unsigned int start_depth = path_get_depth( root );
+ unsigned int skip_depth = 0;
+ for ( iterator i = begin( root ); i != end() && i->first.depth() > start_depth; ++i )
+ {
+ if ( i->first.depth() == skip_depth ) {
+ skip_depth = 0;
+ }
+ if ( skip_depth == 0 ) {
+ if ( !i->second.is_directory() ) {
+ visitor.file( i->first.c_str() );
+ }
+ else if ( visitor.directory( i->first.c_str(), i->first.depth() - start_depth ) ) {
+ skip_depth = i->first.depth();
+ }
+ }
+ }
+}
};
#endif