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