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 // Path
     24 Path::Path()
     25   : m_PathName() {
     26 }
     27 
     28 Path::Path(const Path::ValueType* s )
     29   : m_PathName(s) {
     30 }
     31 
     32 Path::Path(const Path::StringType &s )
     33   : m_PathName(s) {
     34 }
     35 
     36 Path::Path(const Path& pCopy)
     37  : m_PathName(pCopy.m_PathName) {
     38 }
     39 
     40 Path::~Path()
     41 {
     42 }
     43 
     44 bool Path::isFromRoot() const
     45 {
     46   if (m_PathName.empty())
     47     return false;
     48   return (separator == m_PathName[0]);
     49 }
     50 
     51 bool Path::isFromPWD() const
     52 {
     53   if (2 > m_PathName.size())
     54     return false;
     55   return ('.' == m_PathName[0] && separator == m_PathName[1]);
     56 }
     57 
     58 Path& Path::assign(const Path::StringType &s)
     59 {
     60   m_PathName.assign(s);
     61   return *this;
     62 }
     63 
     64 Path& 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
     73 Path& 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 
     97 bool Path::empty() const
     98 {
     99   return m_PathName.empty();
    100 }
    101 
    102 std::string Path::string() const
    103 {
    104   return m_PathName;
    105 }
    106 
    107 Path::StringType Path::generic_string() const
    108 {
    109   std::string result = m_PathName;
    110   detail::canonicalize(result);
    111   return result;
    112 }
    113 
    114 bool Path::canonicalize()
    115 {
    116   return detail::canonicalize(m_PathName);
    117 }
    118 
    119 Path::StringType::size_type Path::m_append_separator_if_needed()
    120 {
    121   if (!m_PathName.empty() &&
    122 #if defined(MCLD_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 
    133 void 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 
    144 Path Path::parent_path() const
    145 {
    146   size_t end_pos = m_PathName.find_last_of(separator);
    147   if (end_pos != StringType::npos)
    148     return Path(m_PathName.substr(0, end_pos));
    149   return Path();
    150 }
    151 
    152 Path Path::filename() const
    153 {
    154   size_t pos = m_PathName.find_last_of(separator);
    155   if (pos != StringType::npos) {
    156     ++pos;
    157     return Path(m_PathName.substr(pos));
    158   }
    159   return Path(*this);
    160 }
    161 
    162 Path Path::stem() const
    163 {
    164   size_t begin_pos = m_PathName.find_last_of(separator)+1;
    165   size_t end_pos   = m_PathName.find_last_of(".");
    166   Path result_path(m_PathName.substr(begin_pos, end_pos - begin_pos));
    167   return result_path;
    168 }
    169 
    170 Path Path::extension() const
    171 {
    172   size_t begin_pos = m_PathName.find_last_of('.');
    173   Path result_path(m_PathName.substr(begin_pos));
    174   return result_path;
    175 }
    176 
    177 //===--------------------------------------------------------------------===//
    178 // non-member functions
    179 //===--------------------------------------------------------------------===//
    180 bool mcld::sys::fs::operator==(const Path& pLHS,const Path& pRHS)
    181 {
    182   return (pLHS.generic_string()==pRHS.generic_string());
    183 }
    184 
    185 bool mcld::sys::fs::operator!=(const Path& pLHS,const Path& pRHS)
    186 {
    187   return !(pLHS==pRHS);
    188 }
    189 
    190 Path mcld::sys::fs::operator+(const Path& pLHS, const Path& pRHS)
    191 {
    192   mcld::sys::fs::Path result = pLHS;
    193   result.append(pRHS);
    194   return result;
    195 }
    196 
    197 bool mcld::sys::fs::is_separator(char value)
    198 {
    199   return (value == separator
    200 #if defined(MCLD_ON_WIN32)
    201           || value == preferred_separator
    202 #endif
    203           );
    204 }
    205 
    206 bool mcld::sys::fs::exists(const Path &pPath)
    207 {
    208   FileStatus pFileStatus;
    209   detail::status(pPath, pFileStatus);
    210   return exists(pFileStatus);
    211 }
    212 
    213 bool mcld::sys::fs::is_directory(const Path &pPath)
    214 {
    215   FileStatus pFileStatus;
    216   detail::status(pPath, pFileStatus);
    217   return is_directory(pFileStatus);
    218 }
    219 
    220 std::ostream &mcld::sys::fs::operator<<(std::ostream& pOS,
    221                                         const Path& pPath)
    222 {
    223   return pOS << pPath.native();
    224 }
    225 
    226 std::istream &mcld::sys::fs::operator>>(std::istream& pOS,
    227                                         Path& pPath)
    228 {
    229   return pOS >> pPath.native();
    230 }
    231 
    232 llvm::raw_ostream &mcld::sys::fs::operator<<(llvm::raw_ostream &pOS,
    233                                              const Path &pPath)
    234 {
    235   return pOS << pPath.native();
    236 }
    237 
    238