//===- Directory.h --------------------------------------------------------===//
//
// The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef MCLD_DIRECTORY_H
#define MCLD_DIRECTORY_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
#include <mcld/ADT/TypeTraits.h>
#include <mcld/Support/FileSystem.h>
#include <mcld/Support/Path.h>
#include <llvm/Support/Allocator.h>
#include <cstddef>
#include "PathCache.h"
namespace mcld {
namespace sys {
namespace fs {
class DirIterator;
/** \class Directory
* \brief A Directory object stores a Path object, a FileStatus object for
* non-symbolic link status, and a FileStatus object for symbolic link
* status. The FileStatus objects act as value caches.
*/
class Directory
{
friend mcld::sys::fs::PathCache::entry_type* detail::bring_one_into_cache(DirIterator& pIter);
friend void detail::open_dir(Directory& pDir);
friend void detail::close_dir(Directory& pDir);
private:
friend class DirIterator;
public:
typedef DirIterator iterator;
public:
/// default constructor
Directory();
/// constructor - a directory whose path is pPath
explicit Directory(const Path& pPath,
FileStatus st = FileStatus(),
FileStatus symlink_st = FileStatus());
/// copy constructor
/// when a copying construction happens, the cache is not copied.
Directory(const Directory& pCopy);
/// assignment
/// When an assignment occurs, the cache is clear.
Directory& operator=(const Directory& pCopy);
/// destructor, inheritable.
virtual ~Directory();
/// Since we have default construtor, we must provide assign.
void assign(const Path& pPath,
FileStatus st = FileStatus(),
FileStatus symlink_st = FileStatus());
/// clear - clear the cache and close the directory handler
void clear();
bool isGood() const;
/// path - the path of the directory
const Path& path() const
{ return m_Path; }
FileStatus status() const;
FileStatus symlinkStatus() const;
// ----- iterators ----- //
// While the iterators move, the direcotry is modified.
// Thus, we only provide non-constant iterator.
iterator begin();
iterator end();
protected:
mcld::sys::fs::Path m_Path;
mutable FileStatus m_FileStatus;
mutable FileStatus m_SymLinkStatus;
intptr_t m_Handler;
// the cache of directory
mcld::sys::fs::PathCache m_Cache;
bool m_CacheFull;
};
/** \class DirIterator
* \brief A DirIterator object can traverse all entries in a Directory
*
* DirIterator will open the directory and add entry into Directory::m_Cache
* DirIterator() is the end of a directory.
* If the end of the directory elements is reached, the iterator becomes
* equal to the end iterator value - DirIterator().
*
* @see Directory
*/
class DirIterator
{
friend mcld::sys::fs::PathCache::entry_type* detail::bring_one_into_cache(DirIterator& pIter);
friend class Directory;
public:
typedef mcld::sys::fs::PathCache DirCache;
public:
typedef Directory value_type;
typedef ConstTraits<Directory> const_traits;
typedef NonConstTraits<Directory> non_const_traits;
typedef std::input_iterator_tag iterator_category;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
private:
explicit DirIterator(Directory* pParent,
const DirCache::iterator& pIter);
public:
// Since StringMapIterator has no default constructor, we also have none.
DirIterator(const DirIterator &X);
~DirIterator();
DirIterator& operator=(const DirIterator& pCopy);
DirIterator& operator++();
DirIterator operator++(int);
Path* generic_path();
Path* path();
const Path* path() const;
bool operator==(const DirIterator& y) const;
bool operator!=(const DirIterator& y) const;
private:
Directory* m_pParent; // get handler
DirCache::iterator m_Iter; // for full situation
DirCache::entry_type* m_pEntry;
};
} // namespace of fs
} // namespace of sys
} // namespace of mcld
#endif