• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)
is_separator(char value)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 //===--------------------------------------------------------------------===//
Path()49 Path::Path()
50   : m_PathName() {
51 }
52 
Path(const Path::ValueType * s)53 Path::Path(const Path::ValueType* s )
54   : m_PathName(s) {
55 }
56 
Path(const Path::StringType & s)57 Path::Path(const Path::StringType &s )
58   : m_PathName(s) {
59 }
60 
Path(const Path & pCopy)61 Path::Path(const Path& pCopy)
62  : m_PathName(pCopy.m_PathName) {
63 }
64 
~Path()65 Path::~Path()
66 {
67 }
68 
isFromRoot() const69 bool Path::isFromRoot() const
70 {
71   if (m_PathName.empty())
72     return false;
73   return (separator == m_PathName[0]);
74 }
75 
isFromPWD() const76 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 
assign(const Path::StringType & s)83 Path& Path::assign(const Path::StringType &s)
84 {
85   m_PathName.assign(s);
86   return *this;
87 }
88 
assign(const Path::ValueType * s,unsigned int length)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
append(const Path & pPath)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 
empty() const122 bool Path::empty() const
123 {
124   return m_PathName.empty();
125 }
126 
generic_string() const127 Path::StringType Path::generic_string() const
128 {
129   StringType result = m_PathName;
130   detail::canonicalize(result);
131   return result;
132 }
133 
canonicalize()134 bool Path::canonicalize()
135 {
136   return detail::canonicalize(m_PathName);
137 }
138 
m_append_separator_if_needed()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 
m_erase_redundant_separator(Path::StringType::size_type pSepPos)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 
parent_path() const172 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 
filename() const180 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 
stem() const190 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 
extension() const198 Path Path::extension() const
199 {
200   size_t pos = m_PathName.find_last_of('.');
201   if (pos == StringType::npos)
202     return Path();
203   return Path(m_PathName.substr(pos));
204 }
205 
206 //===--------------------------------------------------------------------===//
207 // non-member functions
208 //===--------------------------------------------------------------------===//
operator ==(const Path & pLHS,const Path & pRHS)209 bool mcld::sys::fs::operator==(const Path& pLHS,const Path& pRHS)
210 {
211   return (pLHS.generic_string()==pRHS.generic_string());
212 }
213 
operator !=(const Path & pLHS,const Path & pRHS)214 bool mcld::sys::fs::operator!=(const Path& pLHS,const Path& pRHS)
215 {
216   return !(pLHS==pRHS);
217 }
218 
operator +(const Path & pLHS,const Path & pRHS)219 Path mcld::sys::fs::operator+(const Path& pLHS, const Path& pRHS)
220 {
221   mcld::sys::fs::Path result = pLHS;
222   result.append(pRHS);
223   return result;
224 }
225 
226