| //===- Path.cpp -----------------------------------------------------------===// |
| // |
| // The MCLinker Project |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| #include "mcld/Support/FileSystem.h" |
| #include "mcld/Support/Path.h" |
| #include <llvm/ADT/StringRef.h> |
| |
| #include <locale> |
| #include <stdio.h> |
| #include <string.h> |
| |
| #include <iostream> |
| |
| using namespace mcld; |
| using namespace mcld::sys::fs; |
| |
| //===--------------------------------------------------------------------===// |
| // Path |
| Path::Path() |
| : m_PathName() { |
| } |
| |
| Path::Path(const Path::ValueType* s ) |
| : m_PathName(s) { |
| } |
| |
| Path::Path(const Path::StringType &s ) |
| : m_PathName(s) { |
| } |
| |
| Path::Path(const Path& pCopy) |
| : m_PathName(pCopy.m_PathName) { |
| } |
| |
| Path::~Path() |
| { |
| } |
| |
| bool Path::isFromRoot() const |
| { |
| if (m_PathName.empty()) |
| return false; |
| return (separator == m_PathName[0]); |
| } |
| |
| bool Path::isFromPWD() const |
| { |
| if (2 > m_PathName.size()) |
| return false; |
| return ('.' == m_PathName[0] && separator == m_PathName[1]); |
| } |
| |
| Path& Path::assign(const Path::StringType &s) |
| { |
| m_PathName.assign(s); |
| return *this; |
| } |
| |
| Path& Path::assign(const Path::ValueType* s, unsigned int length) |
| { |
| if (0 == s || 0 == length) |
| assert(0 && "assign a null or empty string to Path"); |
| m_PathName.assign(s, length); |
| return *this; |
| } |
| |
| //a,/b a/,b a/,b/ a,b is a/b |
| Path& Path::append(const Path& pPath) |
| { |
| //first path is a/,second path is /b |
| if(m_PathName[m_PathName.length()-1] == separator && |
| pPath.native()[0] == separator) { |
| unsigned int old_size = m_PathName.size()-1; |
| unsigned int new_size = old_size + pPath.native().size(); |
| |
| m_PathName.resize(new_size); |
| strcpy(const_cast<char*>(m_PathName.data()+old_size), pPath.native().data()); |
| } |
| //first path is a,second path is b |
| else if(this->string()[this->native().size()-1] != separator && |
| pPath.string()[0] != separator) { |
| m_PathName.append("/"); |
| m_PathName.append(pPath.native()); |
| } |
| // a/,b or a,/b just append |
| else { |
| m_PathName.append(pPath.native()); |
| } |
| return *this; |
| } |
| |
| bool Path::empty() const |
| { |
| return m_PathName.empty(); |
| } |
| |
| std::string Path::string() const |
| { |
| return m_PathName; |
| } |
| |
| Path::StringType Path::generic_string() const |
| { |
| std::string result = m_PathName; |
| detail::canonicalize(result); |
| return result; |
| } |
| |
| bool Path::canonicalize() |
| { |
| return detail::canonicalize(m_PathName); |
| } |
| |
| Path::StringType::size_type Path::m_append_separator_if_needed() |
| { |
| if (!m_PathName.empty() && |
| #ifdef LLVM_ON_WIN32 |
| *(m_PathName.end()-1) != colon && |
| #endif |
| !is_separator(*(m_PathName.end()-1))) { |
| StringType::size_type tmp(m_PathName.size()); |
| m_PathName += preferred_separator; |
| return tmp; |
| } |
| return 0; |
| } |
| |
| void Path::m_erase_redundant_separator(Path::StringType::size_type pSepPos) |
| { |
| size_t begin=pSepPos; |
| // skip '/' |
| while(separator == m_PathName[pSepPos]) |
| ++pSepPos; |
| |
| if(begin!=pSepPos) |
| m_PathName.erase(begin+1,pSepPos-begin-1); |
| } |
| |
| Path Path::stem() const |
| { |
| size_t begin_pos = m_PathName.find_last_of(separator)+1; |
| size_t end_pos = m_PathName.find_first_of(".", begin_pos); |
| Path result_path(m_PathName.substr(begin_pos, end_pos - begin_pos)); |
| return result_path; |
| } |
| |
| Path Path::extension() const |
| { |
| size_t begin_pos = m_PathName.find_last_of('.'); |
| Path result_path(m_PathName.substr(begin_pos)); |
| return result_path; |
| } |
| |
| //===--------------------------------------------------------------------===// |
| // non-member functions |
| bool mcld::sys::fs::operator==(const Path& pLHS,const Path& pRHS) |
| { |
| return (pLHS.generic_string()==pRHS.generic_string()); |
| } |
| |
| bool mcld::sys::fs::operator!=(const Path& pLHS,const Path& pRHS) |
| { |
| return !(pLHS==pRHS); |
| } |
| |
| bool mcld::sys::fs::is_separator(char value) |
| { |
| return (value == separator |
| #ifdef LLVM_ON_WIN32 |
| || value == preferred_separator |
| #endif |
| ); |
| } |
| |
| bool mcld::sys::fs::exists(const Path &pPath) |
| { |
| FileStatus pFileStatus; |
| detail::status(pPath, pFileStatus); |
| return exists(pFileStatus); |
| } |
| |
| bool mcld::sys::fs::is_directory(const Path &pPath) |
| { |
| FileStatus pFileStatus; |
| detail::status(pPath, pFileStatus); |
| return is_directory(pFileStatus); |
| } |
| |
| std::ostream &mcld::sys::fs::operator<<(std::ostream& pOS, |
| const Path& pPath) |
| { |
| return pOS << pPath.native(); |
| } |
| |
| std::istream &mcld::sys::fs::operator>>(std::istream& pOS, |
| Path& pPath) |
| { |
| return pOS >> pPath.native(); |
| } |
| |
| llvm::raw_ostream &mcld::sys::fs::operator<<(llvm::raw_ostream &pOS, |
| const Path &pPath) |
| { |
| return pOS << pPath.native(); |
| } |
| |