Path.cpp revision 5460a1f25d9ddecb5c70667267d66d51af177a99
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 19using namespace mcld; 20using namespace mcld::sys::fs; 21 22//===--------------------------------------------------------------------===// 23// Path 24Path::Path() 25 : m_PathName() { 26} 27 28Path::Path(const Path::ValueType* s ) 29 : m_PathName(s) { 30} 31 32Path::Path(const Path::StringType &s ) 33 : m_PathName(s) { 34} 35 36Path::Path(const Path& pCopy) 37 : m_PathName(pCopy.m_PathName) { 38} 39 40Path::~Path() 41{ 42} 43 44bool Path::isFromRoot() const 45{ 46 if (m_PathName.empty()) 47 return false; 48 return (separator == m_PathName[0]); 49} 50 51bool Path::isFromPWD() const 52{ 53 if (2 > m_PathName.size()) 54 return false; 55 return ('.' == m_PathName[0] && separator == m_PathName[1]); 56} 57 58Path& Path::assign(const Path::StringType &s) 59{ 60 m_PathName.assign(s); 61 return *this; 62} 63 64Path& 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 73Path& 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 97bool Path::empty() const 98{ 99 return m_PathName.empty(); 100} 101 102std::string Path::string() const 103{ 104 return m_PathName; 105} 106 107Path::StringType Path::generic_string() const 108{ 109 std::string result = m_PathName; 110 detail::canonicalize(result); 111 return result; 112} 113 114bool Path::canonicalize() 115{ 116 return detail::canonicalize(m_PathName); 117} 118 119Path::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 133void 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 144Path 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 152Path 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 161bool mcld::sys::fs::operator==(const Path& pLHS,const Path& pRHS) 162{ 163 return (pLHS.generic_string()==pRHS.generic_string()); 164} 165 166bool mcld::sys::fs::operator!=(const Path& pLHS,const Path& pRHS) 167{ 168 return !(pLHS==pRHS); 169} 170 171bool 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 180bool mcld::sys::fs::exists(const Path &pPath) 181{ 182 FileStatus pFileStatus; 183 detail::status(pPath, pFileStatus); 184 return exists(pFileStatus); 185} 186 187bool mcld::sys::fs::is_directory(const Path &pPath) 188{ 189 FileStatus pFileStatus; 190 detail::status(pPath, pFileStatus); 191 return is_directory(pFileStatus); 192} 193 194std::ostream &mcld::sys::fs::operator<<(std::ostream& pOS, 195 const Path& pPath) 196{ 197 return pOS << pPath.native(); 198} 199 200std::istream &mcld::sys::fs::operator>>(std::istream& pOS, 201 Path& pPath) 202{ 203 return pOS >> pPath.native(); 204} 205 206llvm::raw_ostream &mcld::sys::fs::operator<<(llvm::raw_ostream &pOS, 207 const Path &pPath) 208{ 209 return pOS << pPath.native(); 210} 211 212