]> git.tdb.fi Git - libs/core.git/blob - source/fs/path.h
210b5d93d14c88bf136d07f25a5ddc78c7fc89e2
[libs/core.git] / source / fs / path.h
1 #ifndef MSP_FS_PATH_H_
2 #define MSP_FS_PATH_H_
3
4 #include <ostream>
5 #include <string>
6 #include <vector>
7
8 namespace Msp {
9 namespace FS {
10
11 enum
12 {
13 #ifdef WIN32
14         DIRSEP = '\\'
15 #else
16         DIRSEP = '/'
17 #endif
18 };
19
20 /**
21 Stores a filesystem path.  Paths are always stored in a normalized form; there
22 are never any "." or ".." components in the middle of the path, and relative
23 paths always begin with a single "." component or a sequence ".." components.
24 As a special case, calling the constructor with no arguments or with an empty
25 string will construct an empty path; this can be usedful as an invalid value.
26
27 A path can also be treated as an array of components, supporting indexing,
28 iteration and slicing.  In this context the root directory is treated as a
29 component of its own.
30 */
31 class Path
32 {
33 private:
34         typedef std::vector<std::string::size_type> PositionArray;
35
36 public:
37         class Iterator
38         {
39         private:
40                 const Path *path;
41                 PositionArray::const_iterator iter;
42                 bool end;
43
44                 Iterator(const Path &, bool = false);
45         public:
46                 static Iterator at_begin(const Path &p) { return Iterator(p); }
47                 static Iterator at_end(const Path &p) { return Iterator(p, true); }
48
49                 Iterator &operator++();
50                 Iterator &operator--();
51                 std::string operator*() const;
52                 bool operator==(const Iterator &i) const { return (iter==i.iter && end==i.end); }
53                 bool operator!=(const Iterator &i) const { return !(*this==i); }
54         };
55
56 private:
57         std::string path;
58         std::vector<std::string::size_type> separators;
59
60 public:
61         Path();
62         Path(const std::string &);
63         Path(const char *);
64 private:
65         void init(const std::string &);
66
67 public:
68         /// Returns the path as a string.
69         const std::string &str() const { return path; }
70
71         /// Returns the number of components in the path.
72         unsigned size() const;
73
74         /** Indicates whether the path is empty.  This really means empty; a path
75         pointing to the current directory is not empty. */
76         bool empty() const { return path.empty(); }
77
78         /// Determines whether the path starts from the root directory.
79         bool is_absolute() const;
80
81         /// Extracts a range of components from the path.
82         Path subpath(unsigned start, unsigned count = static_cast<unsigned>(-1)) const;
83
84         /// Concatenates this path with another one, with usual filesystem semantics.
85         Path operator/(const Path &p) const;
86         Path &operator/=(const Path &);
87
88 private:
89         /** Adds a component to the path.  It must not contain the directory
90         separator character. */
91         void add_component(const std::string &);
92
93 public:
94         /** Extracts a single component from the path.  Negative indices count from
95         the end of the path. */
96         std::string operator[](int) const;
97
98         bool operator==(const Path &) const;
99         bool operator<(const Path &) const;
100         bool operator>(const Path &) const;
101         bool operator<=(const Path &other) const { return !(*this>other); }
102         bool operator>=(const Path &other) const { return !(*this<other); }
103         bool operator!=(const Path &other) const { return !(*this==other); }
104
105         Iterator begin() const { return Iterator::at_begin(*this); }
106         Iterator end() const { return Iterator::at_end(*this); }
107 };
108
109 inline std::ostream &operator<<(std::ostream &o, const Path &p) { o<<p.str(); return o; }
110
111 } // namespace FS
112 } // namespace Msp
113
114 #endif