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