Use #ifdef _WIN32 rather than WIN32
[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         public:
40                 typedef PositionArray::difference_type difference_type;
41                 typedef const std::string value_type;
42                 typedef const std::string *pointer;
43                 typedef const std::string &reference;
44                 typedef std::input_iterator_tag iterator_category;
45
46         private:
47                 const Path *path;
48                 PositionArray::const_iterator iter;
49                 bool end;
50                 std::string current;
51
52                 Iterator(const Path &, bool = false);
53         public:
54                 static Iterator at_begin(const Path &p) { return Iterator(p); }
55                 static Iterator at_end(const Path &p) { return Iterator(p, true); }
56
57                 Iterator &operator++();
58                 Iterator operator++(int) { Iterator i = *this; ++*this; return i; }
59                 Iterator &operator--();
60                 const std::string &operator*() const { return current; }
61                 const std::string *operator->() const { return &current; }
62                 bool operator==(const Iterator &i) const { return (iter==i.iter && end==i.end); }
63                 bool operator!=(const Iterator &i) const { return !(*this==i); }
64         private:
65                 void update();
66         };
67
68 private:
69         std::string path;
70         std::vector<std::string::size_type> separators;
71
72 public:
73         Path();
74         Path(const std::string &);
75         Path(const char *);
76 private:
77         void init(const std::string &);
78
79 public:
80         /// Returns the path as a string.
81         const std::string &str() const { return path; }
82
83         /// Returns the path as a pointer to a null-terminated string.
84         const char *c_str() const { return path.c_str(); }
85
86         /// Returns the number of components in the path.
87         unsigned size() const;
88
89         /** Indicates whether the path is empty.  This really means empty; a path
90         pointing to the current directory is not empty. */
91         bool empty() const { return path.empty(); }
92
93         /// Determines whether the path starts from the root directory.
94         bool is_absolute() const;
95
96         /// Extracts a range of components from the path.
97         Path subpath(unsigned start, unsigned count = static_cast<unsigned>(-1)) const;
98
99         /// Concatenates this path with another one, with usual filesystem semantics.
100         Path operator/(const Path &p) const;
101         Path &operator/=(const Path &);
102
103 private:
104         /** Adds a component to the path.  It must not contain the directory
105         separator character. */
106         void add_component(const std::string &);
107
108 public:
109         /** Extracts a single component from the path.  Negative indices count from
110         the end of the path. */
111         std::string operator[](int) const;
112
113         bool operator==(const Path &) const;
114         bool operator<(const Path &) const;
115         bool operator>(const Path &) const;
116         bool operator<=(const Path &other) const { return !(*this>other); }
117         bool operator>=(const Path &other) const { return !(*this<other); }
118         bool operator!=(const Path &other) const { return !(*this==other); }
119
120         Iterator begin() const { return Iterator::at_begin(*this); }
121         Iterator end() const { return Iterator::at_end(*this); }
122 };
123
124 inline std::ostream &operator<<(std::ostream &o, const Path &p) { o<<p.str(); return o; }
125
126 } // namespace FS
127 } // namespace Msp
128
129 #endif