C++程序  |  172行  |  4.78 KB

//===- Path.h -------------------------------------------------------------===//
//
//                     The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// This file declares the mcld::sys::fs::Path. It follows TR2/boost
// filesystem (v3), but modified to remove exception handling and the
// path class.
//===----------------------------------------------------------------------===//
#ifndef MCLD_SUPPORT_PATH_H_
#define MCLD_SUPPORT_PATH_H_

#include "mcld/Config/Config.h"

#include <llvm/Support/raw_ostream.h>

#include <iosfwd>
#include <functional>
#include <string>
#include <locale>

namespace mcld {
namespace sys {
namespace fs {

#if defined(MCLD_ON_WIN32)
const char preferred_separator = '/';
const char separator = '/';
#else
const char preferred_separator = '/';
const char separator = '/';
#endif

const char colon = ':';
const char dot = '.';

/** \class Path
 *  \brief Path provides an abstraction for the path to a file or directory in
 *   the operating system's filesystem.
 */
class Path {
 public:
  typedef char ValueType;
  typedef std::string StringType;

 public:
  Path();
  explicit Path(const ValueType* s);
  explicit Path(const StringType& s);
  Path(const Path& pCopy);
  virtual ~Path();

  // -----  assignments  ----- //
  template <class InputIterator>
  Path& assign(InputIterator begin, InputIterator end);
  Path& assign(const StringType& s);
  Path& assign(const ValueType* s, unsigned int length);

  //  -----  appends  ----- //
  template <class InputIterator>
  Path& append(InputIterator begin, InputIterator end);
  Path& append(const Path& pPath);
  Path& append(const StringType& pPath);

  //  -----  observers  ----- //
  bool empty() const;

  bool isFromRoot() const;
  bool isFromPWD() const;

  const StringType& native() const { return m_PathName; }
  StringType& native() { return m_PathName; }

  const ValueType* c_str() const { return m_PathName.c_str(); }

  // -----  decomposition  ----- //
  Path parent_path() const;
  Path filename() const;
  Path stem() const;
  Path extension() const;

  // -----  generic form observers  ----- //
  StringType generic_string() const;
  bool canonicalize();

 public:
  StringType::size_type m_append_separator_if_needed();
  void m_erase_redundant_separator(StringType::size_type sep_pos);

 protected:
  StringType m_PathName;
};

bool operator==(const Path& pLHS, const Path& pRHS);
bool operator!=(const Path& pLHS, const Path& pRHS);
Path operator+(const Path& pLHS, const Path& pRHS);

//===----------------------------------------------------------------------===//
// Non-member Functions
//===----------------------------------------------------------------------===//
bool exists(const Path& pPath);

bool is_directory(const Path& pPath);

template <class Char, class Traits>
inline std::basic_ostream<Char, Traits>& operator<<(
    std::basic_ostream<Char, Traits>& pOS,
    const Path& pPath) {
  return pOS << pPath.native();
}

template <class Char, class Traits>
inline std::basic_istream<Char, Traits>& operator>>(
    std::basic_istream<Char, Traits>& pOS,
    Path& pPath) {
  return pOS >> pPath.native();
}

inline llvm::raw_ostream& operator<<(llvm::raw_ostream& pOS,
                                     const Path& pPath) {
  return pOS << pPath.native();
}

//===----------------------------------------------------------------------===//
// class path member template implementation
//===----------------------------------------------------------------------===//
template <class InputIterator>
Path& Path::assign(InputIterator begin, InputIterator end) {
  m_PathName.clear();
  if (begin != end)
    m_PathName.append<InputIterator>(begin, end);
  return *this;
}

template <class InputIterator>
Path& Path::append(InputIterator begin, InputIterator end) {
  if (begin == end)
    return *this;
  StringType::size_type sep_pos(m_append_separator_if_needed());
  m_PathName.append<InputIterator>(begin, end);
  if (sep_pos)
    m_erase_redundant_separator(sep_pos);
  return *this;
}

}  // namespace fs
}  // namespace sys
}  // namespace mcld

//===----------------------------------------------------------------------===//
// STL compatible functions
//===----------------------------------------------------------------------===//
namespace std {

template <>
struct less<mcld::sys::fs::Path>
    : public binary_function<mcld::sys::fs::Path, mcld::sys::fs::Path, bool> {
  bool operator()(const mcld::sys::fs::Path& pX,
                  const mcld::sys::fs::Path& pY) const {
    if (pX.generic_string().size() < pY.generic_string().size())
      return true;
    return (pX.generic_string() < pY.generic_string());
  }
};

}  // namespace std

#endif  // MCLD_SUPPORT_PATH_H_