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 stem() const;
93  Path extension() const;
94
95  // -----  generic form observers  ----- //
96  StringType generic_string() const;
97  bool canonicalize();
98
99public:
100  StringType::size_type m_append_separator_if_needed();
101  void m_erase_redundant_separator(StringType::size_type sep_pos);
102
103protected:
104  StringType m_PathName;
105};
106
107bool operator==(const Path& pLHS,const Path& pRHS);
108bool operator!=(const Path& pLHS,const Path& pRHS);
109Path operator+(const Path& pLHS, const Path& pRHS);
110
111//--------------------------------------------------------------------------//
112//                              non-member functions                        //
113//--------------------------------------------------------------------------//
114
115/// is_separator - is the given character a separator of a path.
116// @param value a character
117// @result true if \a value is a path separator character on the host OS
118//bool status_known(FileStatus f) { return f.type() != StatusError; }
119
120bool is_separator(char value);
121
122bool exists(const Path &pPath);
123
124bool is_directory(const Path &pPath);
125
126
127std::ostream &operator<<(std::ostream& pOS, const Path& pPath);
128
129std::istream &operator>>(std::istream& pOS, Path& pPath);
130
131llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Path &pPath);
132
133
134//--------------------------------------------------------------------------------------//
135//                     class path member template implementation                        //
136//--------------------------------------------------------------------------------------//
137template <class InputIterator>
138Path& Path::assign(InputIterator begin, InputIterator end)
139{
140  m_PathName.clear();
141  if (begin != end)
142    m_PathName.append<InputIterator>(begin, end);
143  return *this;
144}
145
146template <class InputIterator>
147Path& Path::append(InputIterator begin, InputIterator end)
148{
149  if (begin == end)
150    return *this;
151  StringType::size_type sep_pos(m_append_separator_if_needed());
152  m_PathName.append<InputIterator>(begin, end);
153  if (sep_pos)
154    m_erase_redundant_separator(sep_pos);
155  return *this;
156}
157
158} // namespace of fs
159} // namespace of sys
160} // namespace of mcld
161
162//-------------------------------------------------------------------------//
163//                              STL compatible functions                   //
164//-------------------------------------------------------------------------//
165namespace std {
166
167template<>
168struct less<mcld::sys::fs::Path> : public binary_function<mcld::sys::fs::Path,
169                                                         mcld::sys::fs::Path,
170                                                         bool>
171{
172  bool operator() (const mcld::sys::fs::Path& pX,const mcld::sys::fs::Path& pY) const {
173    if (pX.generic_string().size() < pY.generic_string().size())
174      return true;
175    return (pX.generic_string() < pY.generic_string());
176  }
177};
178
179} // namespace of std
180
181#endif
182
183