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 <stdio.h>
15 #include <string.h>
16
17 #include <iostream>
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 #ifdef LLVM_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
stem() const144 Path Path::stem() const
145 {
146 size_t begin_pos = m_PathName.find_last_of(separator)+1;
147 size_t end_pos = m_PathName.find_first_of(".", begin_pos);
148 Path result_path(m_PathName.substr(begin_pos, end_pos - begin_pos));
149 return result_path;
150 }
151
extension() const152 Path Path::extension() const
153 {
154 size_t begin_pos = m_PathName.find_last_of('.');
155 Path result_path(m_PathName.substr(begin_pos));
156 return result_path;
157 }
158
159 //===--------------------------------------------------------------------===//
160 // non-member functions
operator ==(const Path & pLHS,const Path & pRHS)161 bool mcld::sys::fs::operator==(const Path& pLHS,const Path& pRHS)
162 {
163 return (pLHS.generic_string()==pRHS.generic_string());
164 }
165
operator !=(const Path & pLHS,const Path & pRHS)166 bool mcld::sys::fs::operator!=(const Path& pLHS,const Path& pRHS)
167 {
168 return !(pLHS==pRHS);
169 }
170
is_separator(char value)171 bool mcld::sys::fs::is_separator(char value)
172 {
173 return (value == separator
174 #ifdef LLVM_ON_WIN32
175 || value == preferred_separator
176 #endif
177 );
178 }
179
exists(const Path & pPath)180 bool mcld::sys::fs::exists(const Path &pPath)
181 {
182 FileStatus pFileStatus;
183 detail::status(pPath, pFileStatus);
184 return exists(pFileStatus);
185 }
186
is_directory(const Path & pPath)187 bool mcld::sys::fs::is_directory(const Path &pPath)
188 {
189 FileStatus pFileStatus;
190 detail::status(pPath, pFileStatus);
191 return is_directory(pFileStatus);
192 }
193
operator <<(std::ostream & pOS,const Path & pPath)194 std::ostream &mcld::sys::fs::operator<<(std::ostream& pOS,
195 const Path& pPath)
196 {
197 return pOS << pPath.native();
198 }
199
operator >>(std::istream & pOS,Path & pPath)200 std::istream &mcld::sys::fs::operator>>(std::istream& pOS,
201 Path& pPath)
202 {
203 return pOS >> pPath.native();
204 }
205
operator <<(llvm::raw_ostream & pOS,const Path & pPath)206 llvm::raw_ostream &mcld::sys::fs::operator<<(llvm::raw_ostream &pOS,
207 const Path &pPath)
208 {
209 return pOS << pPath.native();
210 }
211
212