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