blob: b53cd1ad31e81c9cefa37cff4b15b4bf7d3dcdd8 [file] [log] [blame]
//===- 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:: namespace. It follows TR2/boost
// filesystem (v3), but modified to remove exception handling and the
// path class.
//===----------------------------------------------------------------------===//
#ifndef MCLD_PATH_H
#define MCLD_PATH_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
#include <llvm/Support/raw_ostream.h>
#include <mcld/Config/Config.h>
#include <iosfwd>
#include <functional>
#include <string>
namespace mcld {
namespace sys {
namespace fs {
#if defined(MCLD_ON_WIN32)
const wchar_t separator = L'\\';
const wchar_t preferred_separator = L'\\';
#else
const char separator = '/';
const char preferred_separator = '/';
#endif
/** \class Path
* \brief Path provides an abstraction for the path to a file or directory in
* the operating system's filesystem.
*
* FIXME: current Path library only support UTF-8 chararcter set.
*
*/
class Path
{
public:
#if defined(MCLD_ON_WIN32)
typedef wchar_t ValueType;
#else
typedef char ValueType;
#endif
typedef std::basic_string<ValueType> StringType;
public:
Path();
Path(const ValueType* s);
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);
// ----- 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(); }
std::string string() const;
// ----- 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 //
//--------------------------------------------------------------------------//
/// is_separator - is the given character a separator of a path.
// @param value a character
// @result true if \a value is a path separator character on the host OS
//bool status_known(FileStatus f) { return f.type() != StatusError; }
bool is_separator(char value);
bool exists(const Path &pPath);
bool is_directory(const Path &pPath);
std::ostream &operator<<(std::ostream& pOS, const Path& pPath);
std::istream &operator>>(std::istream& pOS, Path& pPath);
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Path &pPath);
//--------------------------------------------------------------------------------------//
// 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 of fs
} // namespace of sys
} // namespace of 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 of std
#endif