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