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:: namespace. It follows TR2/boost
10 // filesystem (v3), but modified to remove exception handling and the
11 // path class.
12 //===----------------------------------------------------------------------===//
13 #ifndef MCLD_PATH_H
14 #define MCLD_PATH_H
15 #ifdef ENABLE_UNITTEST
16 #include <gtest.h>
17 #endif
18
19 #include <llvm/Support/raw_ostream.h>
20 #include <mcld/Config/Config.h>
21
22 #include <iosfwd>
23 #include <functional>
24 #include <string>
25
26 namespace mcld {
27 namespace sys {
28 namespace fs {
29
30 #if defined(MCLD_ON_WIN32)
31 const wchar_t separator = L'\\';
32 const wchar_t preferred_separator = L'\\';
33 #else
34 const char separator = '/';
35 const char preferred_separator = '/';
36 #endif
37
38 /** \class Path
39 * \brief Path provides an abstraction for the path to a file or directory in
40 * the operating system's filesystem.
41 *
42 * FIXME: current Path library only support UTF-8 chararcter set.
43 *
44 */
45 class Path
46 {
47 public:
48 #if defined(MCLD_ON_WIN32)
49 typedef wchar_t ValueType;
50 #else
51 typedef char ValueType;
52 #endif
53 typedef std::basic_string<ValueType> StringType;
54
55 public:
56 Path();
57 Path(const ValueType* s);
58 Path(const StringType &s);
59 Path(const Path& pCopy);
60 virtual ~Path();
61
62 // ----- assignments ----- //
63 template <class InputIterator>
64 Path& assign(InputIterator begin, InputIterator end);
65 Path& assign(const StringType &s);
66 Path& assign(const ValueType* s, unsigned int length);
67
68 // ----- appends ----- //
69 template <class InputIterator>
70 Path& append(InputIterator begin, InputIterator end);
71 Path& append(const Path& pPath);
72
73 // ----- observers ----- //
74 bool empty() const;
75
76 bool isFromRoot() const;
77 bool isFromPWD() const;
78
native()79 const StringType &native() const
80 { return m_PathName; }
81
native()82 StringType &native()
83 { return m_PathName; }
84
c_str()85 const ValueType* c_str() const
86 { return m_PathName.c_str(); }
87
88 std::string string() const;
89
90 // ----- decomposition ----- //
91 Path parent_path() const;
92 Path stem() const;
93 Path extension() const;
94
95 // ----- generic form observers ----- //
96 StringType generic_string() const;
97 bool canonicalize();
98
99 public:
100 StringType::size_type m_append_separator_if_needed();
101 void m_erase_redundant_separator(StringType::size_type sep_pos);
102
103 protected:
104 StringType m_PathName;
105 };
106
107 bool operator==(const Path& pLHS,const Path& pRHS);
108 bool operator!=(const Path& pLHS,const Path& pRHS);
109 Path operator+(const Path& pLHS, const Path& pRHS);
110
111 //--------------------------------------------------------------------------//
112 // non-member functions //
113 //--------------------------------------------------------------------------//
114
115 /// is_separator - is the given character a separator of a path.
116 // @param value a character
117 // @result true if \a value is a path separator character on the host OS
118 //bool status_known(FileStatus f) { return f.type() != StatusError; }
119
120 bool is_separator(char value);
121
122 bool exists(const Path &pPath);
123
124 bool is_directory(const Path &pPath);
125
126
127 std::ostream &operator<<(std::ostream& pOS, const Path& pPath);
128
129 std::istream &operator>>(std::istream& pOS, Path& pPath);
130
131 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Path &pPath);
132
133
134 //--------------------------------------------------------------------------------------//
135 // class path member template implementation //
136 //--------------------------------------------------------------------------------------//
137 template <class InputIterator>
assign(InputIterator begin,InputIterator end)138 Path& Path::assign(InputIterator begin, InputIterator end)
139 {
140 m_PathName.clear();
141 if (begin != end)
142 m_PathName.append<InputIterator>(begin, end);
143 return *this;
144 }
145
146 template <class InputIterator>
append(InputIterator begin,InputIterator end)147 Path& Path::append(InputIterator begin, InputIterator end)
148 {
149 if (begin == end)
150 return *this;
151 StringType::size_type sep_pos(m_append_separator_if_needed());
152 m_PathName.append<InputIterator>(begin, end);
153 if (sep_pos)
154 m_erase_redundant_separator(sep_pos);
155 return *this;
156 }
157
158 } // namespace of fs
159 } // namespace of sys
160 } // namespace of mcld
161
162 //-------------------------------------------------------------------------//
163 // STL compatible functions //
164 //-------------------------------------------------------------------------//
165 namespace std {
166
167 template<>
168 struct less<mcld::sys::fs::Path> : public binary_function<mcld::sys::fs::Path,
169 mcld::sys::fs::Path,
170 bool>
171 {
172 bool operator() (const mcld::sys::fs::Path& pX,const mcld::sys::fs::Path& pY) const {
173 if (pX.generic_string().size() < pY.generic_string().size())
174 return true;
175 return (pX.generic_string() < pY.generic_string());
176 }
177 };
178
179 } // namespace of std
180
181 #endif
182
183