Path.h revision 87f34658dec9097d987d254a990ea7f311bfc95f
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#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#include <locale>
26
27namespace mcld {
28namespace sys  {
29namespace fs   {
30
31#if defined(MCLD_ON_WIN32)
32const char preferred_separator = '/';
33const char separator = '/';
34#else
35const char preferred_separator = '/';
36const char separator = '/';
37#endif
38
39const char colon = ':';
40const char dot = '.';
41
42/** \class Path
43 *  \brief Path provides an abstraction for the path to a file or directory in
44 *   the operating system's filesystem.
45 */
46class Path
47{
48public:
49  typedef char                               ValueType;
50  typedef std::string                        StringType;
51
52public:
53  Path();
54  Path(const ValueType* s);
55  Path(const StringType &s);
56  Path(const Path& pCopy);
57  virtual ~Path();
58
59  // -----  assignments  ----- //
60  template <class InputIterator>
61  Path& assign(InputIterator begin, InputIterator end);
62  Path& assign(const StringType &s);
63  Path& assign(const ValueType* s, unsigned int length);
64
65  //  -----  appends  ----- //
66  template <class InputIterator>
67  Path& append(InputIterator begin, InputIterator end);
68  Path& append(const Path& pPath);
69
70  //  -----  observers  ----- //
71  bool empty() const;
72
73  bool isFromRoot() const;
74  bool isFromPWD() const;
75
76  const StringType& native() const { return m_PathName; }
77  StringType&       native()       { return m_PathName; }
78
79  const ValueType* c_str() const
80  { return m_PathName.c_str(); }
81
82  // -----  decomposition  ----- //
83  Path parent_path() const;
84  Path filename() const;
85  Path stem() const;
86  Path extension() const;
87
88  // -----  generic form observers  ----- //
89  StringType generic_string() const;
90  bool canonicalize();
91
92public:
93  StringType::size_type m_append_separator_if_needed();
94  void m_erase_redundant_separator(StringType::size_type sep_pos);
95
96protected:
97  StringType m_PathName;
98};
99
100bool operator==(const Path& pLHS,const Path& pRHS);
101bool operator!=(const Path& pLHS,const Path& pRHS);
102Path operator+(const Path& pLHS, const Path& pRHS);
103
104//===----------------------------------------------------------------------===//
105// Non-member Functions
106//===----------------------------------------------------------------------===//
107bool exists(const Path &pPath);
108
109bool is_directory(const Path &pPath);
110
111template <class Char, class Traits>
112inline std::basic_ostream<Char, Traits>&
113operator<<(std::basic_ostream<Char, Traits>& pOS, const Path& pPath)
114{
115  return pOS << pPath.native();
116}
117
118template <class Char, class Traits>
119inline std::basic_istream<Char, Traits>&
120operator>>(std::basic_istream<Char, Traits>& pOS, Path& pPath)
121{
122  return pOS >> pPath.native();
123}
124
125inline llvm::raw_ostream&
126operator<<(llvm::raw_ostream& pOS, const Path& pPath)
127{
128  return pOS << pPath.native();
129}
130
131//===----------------------------------------------------------------------===//
132// class path member template implementation
133//===----------------------------------------------------------------------===//
134template <class InputIterator>
135Path& Path::assign(InputIterator begin, InputIterator end)
136{
137  m_PathName.clear();
138  if (begin != end)
139    m_PathName.append<InputIterator>(begin, end);
140  return *this;
141}
142
143template <class InputIterator>
144Path& Path::append(InputIterator begin, InputIterator end)
145{
146  if (begin == end)
147    return *this;
148  StringType::size_type sep_pos(m_append_separator_if_needed());
149  m_PathName.append<InputIterator>(begin, end);
150  if (sep_pos)
151    m_erase_redundant_separator(sep_pos);
152  return *this;
153}
154
155} // namespace of fs
156} // namespace of sys
157} // namespace of mcld
158
159//===----------------------------------------------------------------------===//
160// STL compatible functions
161//===----------------------------------------------------------------------===//
162namespace std {
163
164template<>
165struct less<mcld::sys::fs::Path> : public binary_function<mcld::sys::fs::Path,
166                                                         mcld::sys::fs::Path,
167                                                         bool>
168{
169  bool operator() (const mcld::sys::fs::Path& pX,const mcld::sys::fs::Path& pY) const {
170    if (pX.generic_string().size() < pY.generic_string().size())
171      return true;
172    return (pX.generic_string() < pY.generic_string());
173  }
174};
175
176} // namespace of std
177
178#endif
179
180