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