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_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 #include <locale>
26
27 namespace mcld {
28 namespace sys {
29 namespace fs {
30
31 #if defined(MCLD_ON_WIN32)
32 const char preferred_separator = '/';
33 const char separator = '/';
34 #else
35 const char preferred_separator = '/';
36 const char separator = '/';
37 #endif
38
39 const char colon = ':';
40 const char dot = '.';
41
42 /** \class Path
43 * \brief Path provides an abstraction for the path to a file or directory in
44 * the operating system's filesystem.
45 */
46 class Path
47 {
48 public:
49 typedef char ValueType;
50 typedef std::string StringType;
51
52 public:
53 Path();
54 Path(const ValueType* s);
55 Path(const StringType &s);
56 Path(const Path& pCopy);
57 virtual ~Path();
58
59 // ----- assignments ----- //
60 template <class InputIterator>
61 Path& assign(InputIterator begin, InputIterator end);
62 Path& assign(const StringType &s);
63 Path& assign(const ValueType* s, unsigned int length);
64
65 // ----- appends ----- //
66 template <class InputIterator>
67 Path& append(InputIterator begin, InputIterator end);
68 Path& append(const Path& pPath);
69
70 // ----- observers ----- //
71 bool empty() const;
72
73 bool isFromRoot() const;
74 bool isFromPWD() const;
75
native()76 const StringType& native() const { return m_PathName; }
native()77 StringType& native() { return m_PathName; }
78
c_str()79 const ValueType* c_str() const
80 { return m_PathName.c_str(); }
81
82 // ----- decomposition ----- //
83 Path parent_path() const;
84 Path filename() const;
85 Path stem() const;
86 Path extension() const;
87
88 // ----- generic form observers ----- //
89 StringType generic_string() const;
90 bool canonicalize();
91
92 public:
93 StringType::size_type m_append_separator_if_needed();
94 void m_erase_redundant_separator(StringType::size_type sep_pos);
95
96 protected:
97 StringType m_PathName;
98 };
99
100 bool operator==(const Path& pLHS,const Path& pRHS);
101 bool operator!=(const Path& pLHS,const Path& pRHS);
102 Path operator+(const Path& pLHS, const Path& pRHS);
103
104 //===----------------------------------------------------------------------===//
105 // Non-member Functions
106 //===----------------------------------------------------------------------===//
107 bool exists(const Path &pPath);
108
109 bool is_directory(const Path &pPath);
110
111 template <class Char, class Traits>
112 inline std::basic_ostream<Char, Traits>&
113 operator<<(std::basic_ostream<Char, Traits>& pOS, const Path& pPath)
114 {
115 return pOS << pPath.native();
116 }
117
118 template <class Char, class Traits>
119 inline std::basic_istream<Char, Traits>&
120 operator>>(std::basic_istream<Char, Traits>& pOS, Path& pPath)
121 {
122 return pOS >> pPath.native();
123 }
124
125 inline llvm::raw_ostream&
126 operator<<(llvm::raw_ostream& pOS, const Path& pPath)
127 {
128 return pOS << pPath.native();
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