Path.h revision 533eae20118036f425f27bf0536ef0ccbb090b65
1//===- Path.h -------------------------------------------------------------===//
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// This file declares the mcld::sys::fs::Path. It follows TR2/boost
10// filesystem (v3), but modified to remove exception handling and the
11// path class.
12//===----------------------------------------------------------------------===//
13#ifndef MCLD_SUPPORT_PATH_H
14#define MCLD_SUPPORT_PATH_H
15
16#include <llvm/Support/raw_ostream.h>
17#include <mcld/Config/Config.h>
18
19#include <iosfwd>
20#include <functional>
21#include <string>
22#include <locale>
23
24namespace mcld {
25namespace sys  {
26namespace fs   {
27
28#if defined(MCLD_ON_WIN32)
29const char preferred_separator = '/';
30const char separator = '/';
31#else
32const char preferred_separator = '/';
33const char separator = '/';
34#endif
35
36const char colon = ':';
37const char dot = '.';
38
39/** \class Path
40 *  \brief Path provides an abstraction for the path to a file or directory in
41 *   the operating system's filesystem.
42 */
43class Path
44{
45public:
46  typedef char                               ValueType;
47  typedef std::string                        StringType;
48
49public:
50  Path();
51  Path(const ValueType* s);
52  Path(const StringType &s);
53  Path(const Path& pCopy);
54  virtual ~Path();
55
56  // -----  assignments  ----- //
57  template <class InputIterator>
58  Path& assign(InputIterator begin, InputIterator end);
59  Path& assign(const StringType &s);
60  Path& assign(const ValueType* s, unsigned int length);
61
62  //  -----  appends  ----- //
63  template <class InputIterator>
64  Path& append(InputIterator begin, InputIterator end);
65  Path& append(const Path& pPath);
66
67  //  -----  observers  ----- //
68  bool empty() const;
69
70  bool isFromRoot() const;
71  bool isFromPWD() const;
72
73  const StringType& native() const { return m_PathName; }
74  StringType&       native()       { return m_PathName; }
75
76  const ValueType* c_str() const
77  { return m_PathName.c_str(); }
78
79  // -----  decomposition  ----- //
80  Path parent_path() const;
81  Path filename() const;
82  Path stem() const;
83  Path extension() const;
84
85  // -----  generic form observers  ----- //
86  StringType generic_string() const;
87  bool canonicalize();
88
89public:
90  StringType::size_type m_append_separator_if_needed();
91  void m_erase_redundant_separator(StringType::size_type sep_pos);
92
93protected:
94  StringType m_PathName;
95};
96
97bool operator==(const Path& pLHS,const Path& pRHS);
98bool operator!=(const Path& pLHS,const Path& pRHS);
99Path operator+(const Path& pLHS, const Path& pRHS);
100
101//===----------------------------------------------------------------------===//
102// Non-member Functions
103//===----------------------------------------------------------------------===//
104bool exists(const Path &pPath);
105
106bool is_directory(const Path &pPath);
107
108template <class Char, class Traits>
109inline std::basic_ostream<Char, Traits>&
110operator<<(std::basic_ostream<Char, Traits>& pOS, const Path& pPath)
111{
112  return pOS << pPath.native();
113}
114
115template <class Char, class Traits>
116inline std::basic_istream<Char, Traits>&
117operator>>(std::basic_istream<Char, Traits>& pOS, Path& pPath)
118{
119  return pOS >> pPath.native();
120}
121
122inline llvm::raw_ostream&
123operator<<(llvm::raw_ostream& pOS, const Path& pPath)
124{
125  return pOS << pPath.native();
126}
127
128//===----------------------------------------------------------------------===//
129// class path member template implementation
130//===----------------------------------------------------------------------===//
131template <class InputIterator>
132Path& Path::assign(InputIterator begin, InputIterator end)
133{
134  m_PathName.clear();
135  if (begin != end)
136    m_PathName.append<InputIterator>(begin, end);
137  return *this;
138}
139
140template <class InputIterator>
141Path& Path::append(InputIterator begin, InputIterator end)
142{
143  if (begin == end)
144    return *this;
145  StringType::size_type sep_pos(m_append_separator_if_needed());
146  m_PathName.append<InputIterator>(begin, end);
147  if (sep_pos)
148    m_erase_redundant_separator(sep_pos);
149  return *this;
150}
151
152} // namespace of fs
153} // namespace of sys
154} // namespace of mcld
155
156//===----------------------------------------------------------------------===//
157// STL compatible functions
158//===----------------------------------------------------------------------===//
159namespace std {
160
161template<>
162struct less<mcld::sys::fs::Path> : public binary_function<mcld::sys::fs::Path,
163                                                         mcld::sys::fs::Path,
164                                                         bool>
165{
166  bool operator() (const mcld::sys::fs::Path& pX,const mcld::sys::fs::Path& pY) const {
167    if (pX.generic_string().size() < pY.generic_string().size())
168      return true;
169    return (pX.generic_string() < pY.generic_string());
170  }
171};
172
173} // namespace of std
174
175#endif
176
177