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