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 "mcld/Config/Config.h"
17
18#include <llvm/Support/raw_ostream.h>
19
20#include <iosfwd>
21#include <functional>
22#include <string>
23#include <locale>
24
25namespace mcld {
26namespace sys {
27namespace fs {
28
29#if defined(MCLD_ON_WIN32)
30const char preferred_separator = '/';
31const char separator = '/';
32#else
33const char preferred_separator = '/';
34const char separator = '/';
35#endif
36
37const char colon = ':';
38const char dot = '.';
39
40/** \class Path
41 *  \brief Path provides an abstraction for the path to a file or directory in
42 *   the operating system's filesystem.
43 */
44class Path {
45 public:
46  typedef char ValueType;
47  typedef std::string StringType;
48
49 public:
50  Path();
51  explicit Path(const ValueType* s);
52  explicit 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  Path& append(const StringType& pPath);
67
68  //  -----  observers  ----- //
69  bool empty() const;
70
71  bool isFromRoot() const;
72  bool isFromPWD() const;
73
74  const StringType& native() const { return m_PathName; }
75  StringType& native() { return m_PathName; }
76
77  const ValueType* c_str() const { 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
89 public:
90  StringType::size_type m_append_separator_if_needed();
91  void m_erase_redundant_separator(StringType::size_type sep_pos);
92
93 protected:
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>& operator<<(
110    std::basic_ostream<Char, Traits>& pOS,
111    const Path& pPath) {
112  return pOS << pPath.native();
113}
114
115template <class Char, class Traits>
116inline std::basic_istream<Char, Traits>& operator>>(
117    std::basic_istream<Char, Traits>& pOS,
118    Path& pPath) {
119  return pOS >> pPath.native();
120}
121
122inline llvm::raw_ostream& operator<<(llvm::raw_ostream& pOS,
123                                     const Path& pPath) {
124  return pOS << pPath.native();
125}
126
127//===----------------------------------------------------------------------===//
128// class path member template implementation
129//===----------------------------------------------------------------------===//
130template <class InputIterator>
131Path& Path::assign(InputIterator begin, InputIterator end) {
132  m_PathName.clear();
133  if (begin != end)
134    m_PathName.append<InputIterator>(begin, end);
135  return *this;
136}
137
138template <class InputIterator>
139Path& Path::append(InputIterator begin, InputIterator end) {
140  if (begin == end)
141    return *this;
142  StringType::size_type sep_pos(m_append_separator_if_needed());
143  m_PathName.append<InputIterator>(begin, end);
144  if (sep_pos)
145    m_erase_redundant_separator(sep_pos);
146  return *this;
147}
148
149}  // namespace fs
150}  // namespace sys
151}  // namespace mcld
152
153//===----------------------------------------------------------------------===//
154// STL compatible functions
155//===----------------------------------------------------------------------===//
156namespace std {
157
158template <>
159struct less<mcld::sys::fs::Path>
160    : public binary_function<mcld::sys::fs::Path, mcld::sys::fs::Path, bool> {
161  bool operator()(const mcld::sys::fs::Path& pX,
162                  const mcld::sys::fs::Path& pY) const {
163    if (pX.generic_string().size() < pY.generic_string().size())
164      return true;
165    return (pX.generic_string() < pY.generic_string());
166  }
167};
168
169}  // namespace std
170
171#endif  // MCLD_SUPPORT_PATH_H_
172