/******************************************************************************
 JUNIXDirEntry.h

	Interface for the JUNIXDirEntry class

	Copyright © 1996 by Glenn W. Bach. All rights reserved.

 ******************************************************************************/

#ifndef _H_JUNIXDirEntry
#define _H_JUNIXDirEntry

#include <JOrderedSet.h>
#include <JError.h>
#include <JString.h>	// avoid allocating fragments

#ifdef __MWERKS__
	#include <stat.h>
#else
	#include <sys/stat.h>
#endif

#include <jMissingProto.h>

class JUNIXDirInfo;
class JRegex;

class JUNIXDirEntry 
{
	friend class JUNIXDirInfo;

public:

	enum Type
	{
		kDoesNotExist = 0,
		kDir,
		kFile,
		kUnknown,
		kDirLink,
		kFileLink,
		kBrokenLink,
		kUnknownLink
	};

	enum ModeBit
	{
		kOtherExec = 0,
		kOtherWrite,
		kOtherRead,
		kGroupExec,
		kGroupWrite,
		kGroupRead,
		kUserExec,
		kUserWrite,
		kUserRead
	};

public:

	JUNIXDirEntry(const JCharacter* fullName);
	JUNIXDirEntry(const JCharacter* pathName, const JCharacter* fileName);
	JUNIXDirEntry(const JUNIXDirEntry& source);

	~JUNIXDirEntry();

	const JUNIXDirEntry& operator=(const JUNIXDirEntry& source);

	JString	GetPath() const;
	JString	GetName() const;
	JString	GetFullName() const;
	JString	GetLinkName() const;
	JString	GetUserName() const;
	JString	GetGroupName() const;

	Type		GetType() const;
	JBoolean	IsFile() const;
	JBoolean	IsDirectory() const;
	JBoolean	IsLink() const;
	JBoolean	IsWorkingLink() const;
	JBoolean	IsBrokenLink() const;
	JBoolean	IsUnknown() const;

	JSize	GetSize() const;

	mode_t	GetMode() const;
	JError	SetMode(const mode_t mode);
	JError	SetMode(const ModeBit bit, const JBoolean allow);
	JString	GetModeString() const;

	JBoolean	IsReadable() const;
	JBoolean	IsWritable() const;
	JBoolean	IsExecutable() const;

	time_t	GetModTime() const;
	time_t	GetStatusTime() const;

	JIndex	GetUserID() const;
	JIndex	GetGroupID() const;

	JUNIXDirEntry	FollowLink() const;

	JBoolean	NeedsUpdate();
	JBoolean	Update();			// updates if necessary
	void		ForceUpdate();		// updates regardless

	JBoolean	MatchesContentFilter(const JRegex& regex,
									 const JSize kBlockSize = 1024) const;

	static JOrderedSetT::CompareResult
		CompareNames(JUNIXDirEntry * const & e1, JUNIXDirEntry * const & e2);
	static JOrderedSetT::CompareResult
		CompareSizes(JUNIXDirEntry * const & e1, JUNIXDirEntry * const & e2);
	static JOrderedSetT::CompareResult
		CompareModTimes(JUNIXDirEntry * const & e1, JUNIXDirEntry * const & e2);

private:

	JString		itsPath;
	JString		itsName;
	JString		itsLinkName;

	Type		itsType;
	JSize		itsSize;
	mode_t		itsMode;
	time_t		itsModTime;			// from lstat
	time_t		itsStatusTime;
	time_t		itsSModTime;		// from stat
	time_t		itsSStatusTime;
	uid_t		itsUserID;
	gid_t		itsGroupID;

	JBoolean	itsIsReadableFlag;
	JBoolean	itsIsWritableFlag;
	JBoolean	itsIsExecutableFlag;

private:

	void	JUNIXDirEntryX(const JCharacter* fullName);

	// called by JUNIXDirInfo when building search targets

	JUNIXDirEntry(const JCharacter* fileName, int x);
};


/*****************************************************************************
 GetType

 ******************************************************************************/

inline JUNIXDirEntry::Type
JUNIXDirEntry::GetType()
	const
{
	return itsType;
}

inline JBoolean
JUNIXDirEntry::IsFile()
	const
{
	return JConvertToBoolean( itsType == kFile || itsType == kFileLink );
}

inline JBoolean
JUNIXDirEntry::IsDirectory()
	const
{
	return JConvertToBoolean( itsType == kDir || itsType == kDirLink );
}

inline JBoolean
JUNIXDirEntry::IsLink()
	const
{
	return JConvertToBoolean( itsType == kFileLink || itsType == kDirLink ||
							  itsType == kBrokenLink || itsType == kUnknownLink );
}

inline JBoolean
JUNIXDirEntry::IsWorkingLink()
	const
{
	return JConvertToBoolean( itsType == kFileLink || itsType == kDirLink ||
							  itsType == kUnknownLink );
}

inline JBoolean
JUNIXDirEntry::IsBrokenLink()
	const
{
	return JConvertToBoolean( itsType == kBrokenLink );
}

inline JBoolean
JUNIXDirEntry::IsUnknown()
	const
{
	return JConvertToBoolean( itsType == kUnknown || itsType == kUnknownLink );
}

/*****************************************************************************
 GetPath

 ******************************************************************************/

inline JString
JUNIXDirEntry::GetPath()
	const
{
	return itsPath;
}

/*****************************************************************************
 GetName

 ******************************************************************************/

inline JString
JUNIXDirEntry::GetName()
	const
{
	return itsName;
}

/*****************************************************************************
 GetFullName

 ******************************************************************************/

inline JString
JUNIXDirEntry::GetFullName()
	const
{
	return itsPath + itsName;
}

/******************************************************************************
 GetLinkName

 ******************************************************************************/

inline JString
JUNIXDirEntry::GetLinkName()
	const
{
	return itsLinkName;
}

/*****************************************************************************
 GetSize

 ******************************************************************************/

inline JSize
JUNIXDirEntry::GetSize()
	const
{
	return itsSize;
}

/*****************************************************************************
 GetMode

 ******************************************************************************/

inline mode_t
JUNIXDirEntry::GetMode()
	const
{
	return itsMode;
}

/*****************************************************************************
 GetModTime

 ******************************************************************************/

inline time_t
JUNIXDirEntry::GetModTime()
	const
{
	return itsModTime;
}

/*****************************************************************************
 GetStatusTime

 ******************************************************************************/

inline time_t
JUNIXDirEntry::GetStatusTime()
	const
{
	return itsStatusTime;
}

/*****************************************************************************
 Access

 ******************************************************************************/

inline JBoolean
JUNIXDirEntry::IsReadable()
	const
{
	return itsIsReadableFlag;
}

inline JBoolean
JUNIXDirEntry::IsWritable()
	const
{
	return itsIsWritableFlag;
}

inline JBoolean
JUNIXDirEntry::IsExecutable()
	const
{
	return itsIsExecutableFlag;
}

/*****************************************************************************
 GetUserID

 ******************************************************************************/

inline JIndex
JUNIXDirEntry::GetUserID()
	const
{
	return itsUserID;
}

/****************************************************************************
 GetGroupID

 ******************************************************************************/

inline JIndex
JUNIXDirEntry::GetGroupID()
	const
{
	return itsGroupID;
}

#endif
