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 79 const StringType &native() const 80 { return m_PathName; } 81 82 StringType &native() 83 { return m_PathName; } 84 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> 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> 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