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