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