//===- 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/Path.h" #include "mcld/Config/Config.h" #include "mcld/Support/FileSystem.h" #include <llvm/ADT/StringRef.h> #include <istream> #include <locale> #include <ostream> #include <string.h> namespace mcld { namespace sys { namespace fs { //===--------------------------------------------------------------------===// // Helper //===--------------------------------------------------------------------===// namespace { #if defined(MCLD_ON_WIN32) bool is_separator(char value) { return (value == separator || value == preferred_separator); } const Path::StringType separator_str("/"); #else bool is_separator(char value) { return (value == separator); } const Path::StringType separator_str("/"); #endif } // anonymous namespace //===--------------------------------------------------------------------===// // 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 (m_PathName.size() < 2) 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 (s == 0 || length == 0) 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) { llvm::StringRef path(pPath.native()); m_PathName.append(path.begin() + 1, path.end()); } else if (this->native()[this->native().size() - 1] != separator && pPath.native()[0] != separator) { // first path is a,second path is b m_PathName.append(separator_str); m_PathName.append(pPath.native()); } else { // a/,b or a,/b just append m_PathName.append(pPath.native()); } return *this; } // a,/b a/,b a/,b/ a,b is a/b Path& Path::append(const StringType& pPath) { Path path(pPath); this->append(path); return *this; } bool Path::empty() const { return m_PathName.empty(); } Path::StringType Path::generic_string() const { StringType 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 defined(MCLD_ON_WIN32) // On Windows platform, path can not append separator. return 0; #endif StringType::value_type last_char = m_PathName[m_PathName.size() - 1]; if (!m_PathName.empty() && !is_separator(last_char)) { StringType::size_type tmp(m_PathName.size()); m_PathName += separator_str; return tmp; } return 0; } void Path::m_erase_redundant_separator(Path::StringType::size_type pSepPos) { size_t begin = pSepPos; // skip '/' or '\\' while (separator == m_PathName[pSepPos]) { #if defined(MCLD_ON_WIN32) pSepPos += 2; #else ++pSepPos; #endif } if (begin != pSepPos) m_PathName.erase(begin + 1, pSepPos - begin - 1); } Path Path::parent_path() const { size_t end_pos = m_PathName.find_last_of(separator); if (end_pos != StringType::npos) return Path(m_PathName.substr(0, end_pos)); return Path(); } Path Path::filename() const { size_t pos = m_PathName.find_last_of(separator); if (pos != StringType::npos) { ++pos; return Path(m_PathName.substr(pos)); } return Path(*this); } Path Path::stem() const { size_t begin_pos = m_PathName.find_last_of(separator) + 1; size_t end_pos = m_PathName.find_last_of(dot); Path result_path(m_PathName.substr(begin_pos, end_pos - begin_pos)); return result_path; } Path Path::extension() const { size_t pos = m_PathName.find_last_of('.'); if (pos == StringType::npos) return Path(); return Path(m_PathName.substr(pos)); } //===--------------------------------------------------------------------===// // non-member functions //===--------------------------------------------------------------------===// bool operator==(const Path& pLHS, const Path& pRHS) { return (pLHS.generic_string() == pRHS.generic_string()); } bool operator!=(const Path& pLHS, const Path& pRHS) { return !(pLHS == pRHS); } Path operator+(const Path& pLHS, const Path& pRHS) { mcld::sys::fs::Path result = pLHS; result.append(pRHS); return result; } } // namespace fs } // namespace sys } // namespace mcld