You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
208 lines
5.1 KiB
208 lines
5.1 KiB
//===- 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
|