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 filename() const;
93 Path stem() const;
94 Path extension() const;
95
96 // ----- generic form observers ----- //
97 StringType generic_string() const;
98 bool canonicalize();
99
100 public:
101 StringType::size_type m_append_separator_if_needed();
102 void m_erase_redundant_separator(StringType::size_type sep_pos);
103
104 protected:
105 StringType m_PathName;
106 };
107
108 bool operator==(const Path& pLHS,const Path& pRHS);
109 bool operator!=(const Path& pLHS,const Path& pRHS);
110 Path operator+(const Path& pLHS, const Path& pRHS);
111
112 //--------------------------------------------------------------------------//
113 // non-member functions //
114 //--------------------------------------------------------------------------//
115
116 /// is_separator - is the given character a separator of a path.
117 // @param value a character
118 // @result true if \a value is a path separator character on the host OS
119 //bool status_known(FileStatus f) { return f.type() != StatusError; }
120
121 bool is_separator(char value);
122
123 bool exists(const Path &pPath);
124
125 bool is_directory(const Path &pPath);
126
127
128 std::ostream &operator<<(std::ostream& pOS, const Path& pPath);
129
130 std::istream &operator>>(std::istream& pOS, Path& pPath);
131
132 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Path &pPath);
133
134
135 //--------------------------------------------------------------------------------------//
136 // class path member template implementation //
137 //--------------------------------------------------------------------------------------//
138 template <class InputIterator>
assign(InputIterator begin,InputIterator end)139 Path& Path::assign(InputIterator begin, InputIterator end)
140 {
141 m_PathName.clear();
142 if (begin != end)
143 m_PathName.append<InputIterator>(begin, end);
144 return *this;
145 }
146
147 template <class InputIterator>
append(InputIterator begin,InputIterator end)148 Path& Path::append(InputIterator begin, InputIterator end)
149 {
150 if (begin == end)
151 return *this;
152 StringType::size_type sep_pos(m_append_separator_if_needed());
153 m_PathName.append<InputIterator>(begin, end);
154 if (sep_pos)
155 m_erase_redundant_separator(sep_pos);
156 return *this;
157 }
158
159 } // namespace of fs
160 } // namespace of sys
161 } // namespace of mcld
162
163 //-------------------------------------------------------------------------//
164 // STL compatible functions //
165 //-------------------------------------------------------------------------//
166 namespace std {
167
168 template<>
169 struct less<mcld::sys::fs::Path> : public binary_function<mcld::sys::fs::Path,
170 mcld::sys::fs::Path,
171 bool>
172 {
173 bool operator() (const mcld::sys::fs::Path& pX,const mcld::sys::fs::Path& pY) const {
174 if (pX.generic_string().size() < pY.generic_string().size())
175 return true;
176 return (pX.generic_string() < pY.generic_string());
177 }
178 };
179
180 } // namespace of std
181
182 #endif
183
184