1 //===- Path.h -------------------------------------------------------------===//
2 //
3 // The MCLinker Project
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 // This file declares the mcld::sys::fs::Path. It follows TR2/boost
10 // filesystem (v3), but modified to remove exception handling and the
11 // path class.
12 //===----------------------------------------------------------------------===//
13 #ifndef MCLD_SUPPORT_PATH_H_
14 #define MCLD_SUPPORT_PATH_H_
15
16 #include "mcld/Config/Config.h"
17
18 #include <llvm/Support/raw_ostream.h>
19
20 #include <iosfwd>
21 #include <functional>
22 #include <string>
23 #include <locale>
24
25 namespace mcld {
26 namespace sys {
27 namespace fs {
28
29 #if defined(MCLD_ON_WIN32)
30 const char preferred_separator = '/';
31 const char separator = '/';
32 #else
33 const char preferred_separator = '/';
34 const char separator = '/';
35 #endif
36
37 const char colon = ':';
38 const char dot = '.';
39
40 /** \class Path
41 * \brief Path provides an abstraction for the path to a file or directory in
42 * the operating system's filesystem.
43 */
44 class Path {
45 public:
46 typedef char ValueType;
47 typedef std::string StringType;
48
49 public:
50 Path();
51 explicit Path(const ValueType* s);
52 explicit Path(const StringType& s);
53 Path(const Path& pCopy);
54 virtual ~Path();
55
56 // ----- assignments ----- //
57 template <class InputIterator>
58 Path& assign(InputIterator begin, InputIterator end);
59 Path& assign(const StringType& s);
60 Path& assign(const ValueType* s, unsigned int length);
61
62 // ----- appends ----- //
63 template <class InputIterator>
64 Path& append(InputIterator begin, InputIterator end);
65 Path& append(const Path& pPath);
66 Path& append(const StringType& pPath);
67
68 // ----- observers ----- //
69 bool empty() const;
70
71 bool isFromRoot() const;
72 bool isFromPWD() const;
73
native()74 const StringType& native() const { return m_PathName; }
native()75 StringType& native() { return m_PathName; }
76
c_str()77 const ValueType* c_str() const { return m_PathName.c_str(); }
78
79 // ----- decomposition ----- //
80 Path parent_path() const;
81 Path filename() const;
82 Path stem() const;
83 Path extension() const;
84
85 // ----- generic form observers ----- //
86 StringType generic_string() const;
87 bool canonicalize();
88
89 public:
90 StringType::size_type m_append_separator_if_needed();
91 void m_erase_redundant_separator(StringType::size_type sep_pos);
92
93 protected:
94 StringType m_PathName;
95 };
96
97 bool operator==(const Path& pLHS, const Path& pRHS);
98 bool operator!=(const Path& pLHS, const Path& pRHS);
99 Path operator+(const Path& pLHS, const Path& pRHS);
100
101 //===----------------------------------------------------------------------===//
102 // Non-member Functions
103 //===----------------------------------------------------------------------===//
104 bool exists(const Path& pPath);
105
106 bool is_directory(const Path& pPath);
107
108 template <class Char, class Traits>
109 inline std::basic_ostream<Char, Traits>& operator<<(
110 std::basic_ostream<Char, Traits>& pOS,
111 const Path& pPath) {
112 return pOS << pPath.native();
113 }
114
115 template <class Char, class Traits>
116 inline std::basic_istream<Char, Traits>& operator>>(
117 std::basic_istream<Char, Traits>& pOS,
118 Path& pPath) {
119 return pOS >> pPath.native();
120 }
121
122 inline llvm::raw_ostream& operator<<(llvm::raw_ostream& pOS,
123 const Path& pPath) {
124 return pOS << pPath.native();
125 }
126
127 //===----------------------------------------------------------------------===//
128 // class path member template implementation
129 //===----------------------------------------------------------------------===//
130 template <class InputIterator>
assign(InputIterator begin,InputIterator end)131 Path& Path::assign(InputIterator begin, InputIterator end) {
132 m_PathName.clear();
133 if (begin != end)
134 m_PathName.append<InputIterator>(begin, end);
135 return *this;
136 }
137
138 template <class InputIterator>
append(InputIterator begin,InputIterator end)139 Path& Path::append(InputIterator begin, InputIterator end) {
140 if (begin == end)
141 return *this;
142 StringType::size_type sep_pos(m_append_separator_if_needed());
143 m_PathName.append<InputIterator>(begin, end);
144 if (sep_pos)
145 m_erase_redundant_separator(sep_pos);
146 return *this;
147 }
148
149 } // namespace fs
150 } // namespace sys
151 } // namespace mcld
152
153 //===----------------------------------------------------------------------===//
154 // STL compatible functions
155 //===----------------------------------------------------------------------===//
156 namespace std {
157
158 template <>
159 struct less<mcld::sys::fs::Path>
160 : public binary_function<mcld::sys::fs::Path, mcld::sys::fs::Path, bool> {
161 bool operator()(const mcld::sys::fs::Path& pX,
162 const mcld::sys::fs::Path& pY) const {
163 if (pX.generic_string().size() < pY.generic_string().size())
164 return true;
165 return (pX.generic_string() < pY.generic_string());
166 }
167 };
168
169 } // namespace std
170
171 #endif // MCLD_SUPPORT_PATH_H_
172