1 //===- Path.cpp -----------------------------------------------------------===// 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 #include "mcld/Support/FileSystem.h" 10 #include "mcld/Support/Path.h" 11 #include <llvm/ADT/StringRef.h> 12 13 #include <locale> 14 #include <stdio.h> 15 #include <string.h> 16 17 #include <iostream> 18 19 using namespace mcld; 20 using namespace mcld::sys::fs; 21 22 //===--------------------------------------------------------------------===// 23 // Path 24 Path::Path() 25 : m_PathName() { 26 } 27 28 Path::Path(const Path::ValueType* s ) 29 : m_PathName(s) { 30 } 31 32 Path::Path(const Path::StringType &s ) 33 : m_PathName(s) { 34 } 35 36 Path::Path(const Path& pCopy) 37 : m_PathName(pCopy.m_PathName) { 38 } 39 40 Path::~Path() 41 { 42 } 43 44 bool Path::isFromRoot() const 45 { 46 if (m_PathName.empty()) 47 return false; 48 return (separator == m_PathName[0]); 49 } 50 51 bool Path::isFromPWD() const 52 { 53 if (2 > m_PathName.size()) 54 return false; 55 return ('.' == m_PathName[0] && separator == m_PathName[1]); 56 } 57 58 Path& Path::assign(const Path::StringType &s) 59 { 60 m_PathName.assign(s); 61 return *this; 62 } 63 64 Path& Path::assign(const Path::ValueType* s, unsigned int length) 65 { 66 if (0 == s || 0 == length) 67 assert(0 && "assign a null or empty string to Path"); 68 m_PathName.assign(s, length); 69 return *this; 70 } 71 72 //a,/b a/,b a/,b/ a,b is a/b 73 Path& Path::append(const Path& pPath) 74 { 75 //first path is a/,second path is /b 76 if(m_PathName[m_PathName.length()-1] == separator && 77 pPath.native()[0] == separator) { 78 unsigned int old_size = m_PathName.size()-1; 79 unsigned int new_size = old_size + pPath.native().size(); 80 81 m_PathName.resize(new_size); 82 strcpy(const_cast<char*>(m_PathName.data()+old_size), pPath.native().data()); 83 } 84 //first path is a,second path is b 85 else if(this->string()[this->native().size()-1] != separator && 86 pPath.string()[0] != separator) { 87 m_PathName.append("/"); 88 m_PathName.append(pPath.native()); 89 } 90 // a/,b or a,/b just append 91 else { 92 m_PathName.append(pPath.native()); 93 } 94 return *this; 95 } 96 97 bool Path::empty() const 98 { 99 return m_PathName.empty(); 100 } 101 102 std::string Path::string() const 103 { 104 return m_PathName; 105 } 106 107 Path::StringType Path::generic_string() const 108 { 109 std::string result = m_PathName; 110 detail::canonicalize(result); 111 return result; 112 } 113 114 bool Path::canonicalize() 115 { 116 return detail::canonicalize(m_PathName); 117 } 118 119 Path::StringType::size_type Path::m_append_separator_if_needed() 120 { 121 if (!m_PathName.empty() && 122 #ifdef LLVM_ON_WIN32 123 *(m_PathName.end()-1) != colon && 124 #endif 125 !is_separator(*(m_PathName.end()-1))) { 126 StringType::size_type tmp(m_PathName.size()); 127 m_PathName += preferred_separator; 128 return tmp; 129 } 130 return 0; 131 } 132 133 void Path::m_erase_redundant_separator(Path::StringType::size_type pSepPos) 134 { 135 size_t begin=pSepPos; 136 // skip '/' 137 while(separator == m_PathName[pSepPos]) 138 ++pSepPos; 139 140 if(begin!=pSepPos) 141 m_PathName.erase(begin+1,pSepPos-begin-1); 142 } 143 144 Path Path::stem() const 145 { 146 size_t begin_pos = m_PathName.find_last_of(separator)+1; 147 size_t end_pos = m_PathName.find_first_of(".", begin_pos); 148 Path result_path(m_PathName.substr(begin_pos, end_pos - begin_pos)); 149 return result_path; 150 } 151 152 Path Path::extension() const 153 { 154 size_t begin_pos = m_PathName.find_last_of('.'); 155 Path result_path(m_PathName.substr(begin_pos)); 156 return result_path; 157 } 158 159 //===--------------------------------------------------------------------===// 160 // non-member functions 161 bool mcld::sys::fs::operator==(const Path& pLHS,const Path& pRHS) 162 { 163 return (pLHS.generic_string()==pRHS.generic_string()); 164 } 165 166 bool mcld::sys::fs::operator!=(const Path& pLHS,const Path& pRHS) 167 { 168 return !(pLHS==pRHS); 169 } 170 171 bool mcld::sys::fs::is_separator(char value) 172 { 173 return (value == separator 174 #ifdef LLVM_ON_WIN32 175 || value == preferred_separator 176 #endif 177 ); 178 } 179 180 bool mcld::sys::fs::exists(const Path &pPath) 181 { 182 FileStatus pFileStatus; 183 detail::status(pPath, pFileStatus); 184 return exists(pFileStatus); 185 } 186 187 bool mcld::sys::fs::is_directory(const Path &pPath) 188 { 189 FileStatus pFileStatus; 190 detail::status(pPath, pFileStatus); 191 return is_directory(pFileStatus); 192 } 193 194 std::ostream &mcld::sys::fs::operator<<(std::ostream& pOS, 195 const Path& pPath) 196 { 197 return pOS << pPath.native(); 198 } 199 200 std::istream &mcld::sys::fs::operator>>(std::istream& pOS, 201 Path& pPath) 202 { 203 return pOS >> pPath.native(); 204 } 205 206 llvm::raw_ostream &mcld::sys::fs::operator<<(llvm::raw_ostream &pOS, 207 const Path &pPath) 208 { 209 return pOS << pPath.native(); 210 } 211 212