Path.cpp revision cedee4b38f4786845183be7f5916dd520a170ae0
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::stem() const 152{ 153 size_t begin_pos = m_PathName.find_last_of(separator)+1; 154 size_t end_pos = m_PathName.find_last_of("."); 155 Path result_path(m_PathName.substr(begin_pos, end_pos - begin_pos)); 156 return result_path; 157} 158 159Path Path::extension() const 160{ 161 size_t begin_pos = m_PathName.find_last_of('.'); 162 Path result_path(m_PathName.substr(begin_pos)); 163 return result_path; 164} 165 166//===--------------------------------------------------------------------===// 167// non-member functions 168//===--------------------------------------------------------------------===// 169bool mcld::sys::fs::operator==(const Path& pLHS,const Path& pRHS) 170{ 171 return (pLHS.generic_string()==pRHS.generic_string()); 172} 173 174bool mcld::sys::fs::operator!=(const Path& pLHS,const Path& pRHS) 175{ 176 return !(pLHS==pRHS); 177} 178 179Path mcld::sys::fs::operator+(const Path& pLHS, const Path& pRHS) 180{ 181 mcld::sys::fs::Path result = pLHS; 182 result.append(pRHS); 183 return result; 184} 185 186bool mcld::sys::fs::is_separator(char value) 187{ 188 return (value == separator 189#if defined(MCLD_ON_WIN32) 190 || value == preferred_separator 191#endif 192 ); 193} 194 195bool mcld::sys::fs::exists(const Path &pPath) 196{ 197 FileStatus pFileStatus; 198 detail::status(pPath, pFileStatus); 199 return exists(pFileStatus); 200} 201 202bool mcld::sys::fs::is_directory(const Path &pPath) 203{ 204 FileStatus pFileStatus; 205 detail::status(pPath, pFileStatus); 206 return is_directory(pFileStatus); 207} 208 209std::ostream &mcld::sys::fs::operator<<(std::ostream& pOS, 210 const Path& pPath) 211{ 212 return pOS << pPath.native(); 213} 214 215std::istream &mcld::sys::fs::operator>>(std::istream& pOS, 216 Path& pPath) 217{ 218 return pOS >> pPath.native(); 219} 220 221llvm::raw_ostream &mcld::sys::fs::operator<<(llvm::raw_ostream &pOS, 222 const Path &pPath) 223{ 224 return pOS << pPath.native(); 225} 226 227