• 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 // Path
Path()24 Path::Path()
25   : m_PathName() {
26 }
27 
Path(const Path::ValueType * s)28 Path::Path(const Path::ValueType* s )
29   : m_PathName(s) {
30 }
31 
Path(const Path::StringType & s)32 Path::Path(const Path::StringType &s )
33   : m_PathName(s) {
34 }
35 
Path(const Path & pCopy)36 Path::Path(const Path& pCopy)
37  : m_PathName(pCopy.m_PathName) {
38 }
39 
~Path()40 Path::~Path()
41 {
42 }
43 
isFromRoot() const44 bool Path::isFromRoot() const
45 {
46   if (m_PathName.empty())
47     return false;
48   return (separator == m_PathName[0]);
49 }
50 
isFromPWD() const51 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 
assign(const Path::StringType & s)58 Path& Path::assign(const Path::StringType &s)
59 {
60   m_PathName.assign(s);
61   return *this;
62 }
63 
assign(const Path::ValueType * s,unsigned int length)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
append(const Path & pPath)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 
empty() const97 bool Path::empty() const
98 {
99   return m_PathName.empty();
100 }
101 
string() const102 std::string Path::string() const
103 {
104   return m_PathName;
105 }
106 
generic_string() const107 Path::StringType Path::generic_string() const
108 {
109   std::string result = m_PathName;
110   detail::canonicalize(result);
111   return result;
112 }
113 
canonicalize()114 bool Path::canonicalize()
115 {
116   return detail::canonicalize(m_PathName);
117 }
118 
m_append_separator_if_needed()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 
m_erase_redundant_separator(Path::StringType::size_type pSepPos)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 
parent_path() const144 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 
filename() const152 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 
stem() const162 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 
extension() const170 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 //===--------------------------------------------------------------------===//
operator ==(const Path & pLHS,const Path & pRHS)180 bool mcld::sys::fs::operator==(const Path& pLHS,const Path& pRHS)
181 {
182   return (pLHS.generic_string()==pRHS.generic_string());
183 }
184 
operator !=(const Path & pLHS,const Path & pRHS)185 bool mcld::sys::fs::operator!=(const Path& pLHS,const Path& pRHS)
186 {
187   return !(pLHS==pRHS);
188 }
189 
operator +(const Path & pLHS,const Path & pRHS)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 
is_separator(char value)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 
exists(const Path & pPath)206 bool mcld::sys::fs::exists(const Path &pPath)
207 {
208   FileStatus pFileStatus;
209   detail::status(pPath, pFileStatus);
210   return exists(pFileStatus);
211 }
212 
is_directory(const Path & pPath)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 
operator <<(std::ostream & pOS,const Path & pPath)220 std::ostream &mcld::sys::fs::operator<<(std::ostream& pOS,
221                                         const Path& pPath)
222 {
223   return pOS << pPath.native();
224 }
225 
operator >>(std::istream & pOS,Path & pPath)226 std::istream &mcld::sys::fs::operator>>(std::istream& pOS,
227                                         Path& pPath)
228 {
229   return pOS >> pPath.native();
230 }
231 
operator <<(llvm::raw_ostream & pOS,const Path & pPath)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