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