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