Home | History | Annotate | Download | only in Support
      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/Config/Config.h>
     10 #include <mcld/Support/FileSystem.h>
     11 #include <mcld/Support/Path.h>
     12 #include <llvm/ADT/StringRef.h>
     13 
     14 #include <locale>
     15 #include <string.h>
     16 #include <istream>
     17 #include <ostream>
     18 
     19 using namespace mcld;
     20 using namespace mcld::sys::fs;
     21 
     22 //===--------------------------------------------------------------------===//
     23 // Helper
     24 //===--------------------------------------------------------------------===//
     25 namespace {
     26 #if defined(MCLD_ON_WIN32)
     27 bool is_separator(char value)
     28 {
     29   return (value == separator || value == preferred_separator);
     30 }
     31 
     32 const Path::StringType separator_str("/");
     33 
     34 #else
     35 bool is_separator(char value)
     36 {
     37   return (value == separator);
     38 }
     39 
     40 const Path::StringType separator_str("/");
     41 
     42 #endif
     43 } // anonymous namespace
     44 
     45 
     46 //===--------------------------------------------------------------------===//
     47 // Path
     48 //===--------------------------------------------------------------------===//
     49 Path::Path()
     50   : m_PathName() {
     51 }
     52 
     53 Path::Path(const Path::ValueType* s )
     54   : m_PathName(s) {
     55 }
     56 
     57 Path::Path(const Path::StringType &s )
     58   : m_PathName(s) {
     59 }
     60 
     61 Path::Path(const Path& pCopy)
     62  : m_PathName(pCopy.m_PathName) {
     63 }
     64 
     65 Path::~Path()
     66 {
     67 }
     68 
     69 bool Path::isFromRoot() const
     70 {
     71   if (m_PathName.empty())
     72     return false;
     73   return (separator == m_PathName[0]);
     74 }
     75 
     76 bool Path::isFromPWD() const
     77 {
     78   if (2 > m_PathName.size())
     79     return false;
     80   return ('.' == m_PathName[0] && separator == m_PathName[1]);
     81 }
     82 
     83 Path& Path::assign(const Path::StringType &s)
     84 {
     85   m_PathName.assign(s);
     86   return *this;
     87 }
     88 
     89 Path& Path::assign(const Path::ValueType* s, unsigned int length)
     90 {
     91   if (0 == s || 0 == length)
     92     assert(0 && "assign a null or empty string to Path");
     93   m_PathName.assign(s, length);
     94   return *this;
     95 }
     96 
     97 //a,/b a/,b a/,b/ a,b is a/b
     98 Path& Path::append(const Path& pPath)
     99 {
    100   //first path is a/,second path is /b
    101   if(m_PathName[m_PathName.length()-1] == separator &&
    102      pPath.native()[0] == separator) {
    103     unsigned int old_size = m_PathName.size()-1;
    104     unsigned int new_size = old_size + pPath.native().size();
    105 
    106     m_PathName.resize(new_size);
    107     strcpy(const_cast<ValueType*>(m_PathName.data()+old_size), pPath.native().data());
    108   }
    109   //first path is a,second path is b
    110   else if(this->native()[this->native().size()-1] != separator &&
    111           pPath.native()[0] != separator) {
    112     m_PathName.append(separator_str);
    113     m_PathName.append(pPath.native());
    114   }
    115   // a/,b or a,/b just append
    116   else {
    117     m_PathName.append(pPath.native());
    118   }
    119   return *this;
    120 }
    121 
    122 bool Path::empty() const
    123 {
    124   return m_PathName.empty();
    125 }
    126 
    127 Path::StringType Path::generic_string() const
    128 {
    129   StringType result = m_PathName;
    130   detail::canonicalize(result);
    131   return result;
    132 }
    133 
    134 bool Path::canonicalize()
    135 {
    136   return detail::canonicalize(m_PathName);
    137 }
    138 
    139 Path::StringType::size_type Path::m_append_separator_if_needed()
    140 {
    141 #if defined(MCLD_ON_WIN32)
    142   // On Windows platform, path can not append separator.
    143   return 0;
    144 #endif
    145 
    146   StringType::value_type last_char = m_PathName[m_PathName.size() - 1];
    147   if (!m_PathName.empty() &&
    148       !is_separator(last_char)) {
    149     StringType::size_type tmp(m_PathName.size());
    150     m_PathName += separator_str;
    151     return tmp;
    152   }
    153   return 0;
    154 }
    155 
    156 void Path::m_erase_redundant_separator(Path::StringType::size_type pSepPos)
    157 {
    158   size_t begin=pSepPos;
    159   // skip '/' or '\\'
    160   while(separator == m_PathName[pSepPos]) {
    161 #if defined(MCLD_ON_WIN32)
    162     pSepPos += 2;
    163 #else
    164     ++pSepPos;
    165 #endif
    166   }
    167 
    168   if(begin!=pSepPos)
    169     m_PathName.erase(begin+1,pSepPos-begin-1);
    170 }
    171 
    172 Path Path::parent_path() const
    173 {
    174   size_t end_pos = m_PathName.find_last_of(separator);
    175   if (end_pos != StringType::npos)
    176     return Path(m_PathName.substr(0, end_pos));
    177   return Path();
    178 }
    179 
    180 Path Path::filename() const
    181 {
    182   size_t pos = m_PathName.find_last_of(separator);
    183   if (pos != StringType::npos) {
    184     ++pos;
    185     return Path(m_PathName.substr(pos));
    186   }
    187   return Path(*this);
    188 }
    189 
    190 Path Path::stem() const
    191 {
    192   size_t begin_pos = m_PathName.find_last_of(separator)+1;
    193   size_t end_pos   = m_PathName.find_last_of(dot);
    194   Path result_path(m_PathName.substr(begin_pos, end_pos - begin_pos));
    195   return result_path;
    196 }
    197 
    198 Path Path::extension() const
    199 {
    200   size_t begin_pos = m_PathName.find_last_of('.');
    201   Path result_path(m_PathName.substr(begin_pos));
    202   return result_path;
    203 }
    204 
    205 //===--------------------------------------------------------------------===//
    206 // non-member functions
    207 //===--------------------------------------------------------------------===//
    208 bool mcld::sys::fs::operator==(const Path& pLHS,const Path& pRHS)
    209 {
    210   return (pLHS.generic_string()==pRHS.generic_string());
    211 }
    212 
    213 bool mcld::sys::fs::operator!=(const Path& pLHS,const Path& pRHS)
    214 {
    215   return !(pLHS==pRHS);
    216 }
    217 
    218 Path mcld::sys::fs::operator+(const Path& pLHS, const Path& pRHS)
    219 {
    220   mcld::sys::fs::Path result = pLHS;
    221   result.append(pRHS);
    222   return result;
    223 }
    224 
    225