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