Path.h revision 5460a1f25d9ddecb5c70667267d66d51af177a99
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
14#ifndef MCLD_PATH_H
15#define MCLD_PATH_H
16#ifdef ENABLE_UNITTEST
17#include <gtest.h>
18#endif
19
20#include <llvm/Support/raw_ostream.h>
21#include <functional>
22#include <string>
23
24//#include "mcld/Support/Directory.h"
25namespace mcld {
26namespace sys  {
27namespace fs   {
28
29#ifdef LLVM_ON_WIN32
30const wchar_t       separator = L'\\';
31const wchar_t       preferred_separator = L'\\';
32#else
33const char          separator = '/';
34const char          preferred_separator = '/';
35#endif
36
37/** \class Path
38 *  \brief Path provides an abstraction for the path to a file or directory in
39 *   the operating system's filesystem.
40 *
41 *  FIXME: current Path library only support UTF-8 chararcter set.
42 *
43 */
44class Path
45{
46public:
47#ifdef LLVM_ON_WIN32
48  typedef wchar_t                            ValueType;
49#else
50  typedef char                               ValueType;
51#endif
52  typedef std::basic_string<ValueType>       StringType;
53
54public:
55  Path();
56  Path(const ValueType* s);
57  Path(const StringType &s);
58  Path(const Path& pCopy);
59  virtual ~Path();
60
61  // -----  assignments  ----- //
62  template <class InputIterator>
63  Path& assign(InputIterator begin, InputIterator end);
64  Path& assign(const StringType &s);
65  Path& assign(const ValueType* s, unsigned int length);
66
67  //  -----  appends  ----- //
68  template <class InputIterator>
69  Path& append(InputIterator begin, InputIterator end);
70  Path& append(const Path& pPath);
71
72  //  -----  observers  ----- //
73  bool empty() const;
74
75  bool isFromRoot() const;
76  bool isFromPWD() const;
77
78  const StringType &native() const
79  { return m_PathName; }
80
81  StringType &native()
82  { return m_PathName; }
83
84  const ValueType* c_str() const
85  { return m_PathName.c_str(); }
86
87  std::string string() const;
88
89  // -----  decomposition  ----- //
90  Path stem() const;
91  Path extension() const;
92
93  // -----  generic form observers  ----- //
94  StringType generic_string() const;
95  bool canonicalize();
96
97public:
98  StringType::size_type m_append_separator_if_needed();
99  void m_erase_redundant_separator(StringType::size_type sep_pos);
100
101protected:
102  StringType m_PathName;
103};
104
105bool operator==(const Path& pLHS,const Path& pRHS);
106bool operator!=(const Path& pLHS,const Path& pRHS);
107
108//--------------------------------------------------------------------------//
109//                              non-member functions                        //
110//--------------------------------------------------------------------------//
111
112/// is_separator - is the given character a separator of a path.
113// @param value a character
114// @result true if \a value is a path separator character on the host OS
115//bool status_known(FileStatus f) { return f.type() != StatusError; }
116
117bool is_separator(char value);
118
119bool exists(const Path &pPath);
120
121bool is_directory(const Path &pPath);
122
123
124std::ostream &operator<<(std::ostream& pOS, const Path& pPath);
125
126std::istream &operator>>(std::istream& pOS, Path& pPath);
127
128llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Path &pPath);
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