// -*- c++ -*-
//------------------------------------------------------------------------------
//                               FdSet.h
//------------------------------------------------------------------------------
//  Copyright (C) 1997-2002  Vladislav Grinchenko <vladg@erols.com>
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Library General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//------------------------------------------------------------------------------
#ifndef FDSET_H
#define FDSET_H

/** @file FdSet.h */

#include <string.h>

#include <sys/time.h>		/* select(3) */

#if defined(Linux)		/* select(3) */
#    include <sys/types.h>
#    include <unistd.h>
#endif

#include "assa/Logger.h"

namespace ASSA {

/** Class FdSet.

Wrapper around struct fd_set
*/

class FdSet : public fd_set
{
public:
	/** Constructor. 
	 */
	FdSet ();

	/** Destructor.
         */
	~FdSet () {}

	/** Set flag (ON) for the argument fd.
	    @param  fd_ Bit to set.
	    @return false if argument is out of bounds, true otherwise.
	 */
	bool setFd (const unsigned int fd_);

	/** Clear flag (OFF) for the argument fd.
	    @param fd_ Bit to clear
	    @return false if argument is out of bounds; true otherwise.
	 */
	bool clear (const unsigned int fd_);

	/** Test whether fd's flag is on.
	    @param fd_ Bit to test
	    @return true if fd_ bit is set; false otherwise
	 */
	bool isSet (const unsigned int fd_);

	/** Reset every bit in set (OFF).
	 */
	void reset (void);

	/** Determine how many bits are set (ON) in the set.
	    @return Number of bits set
	 */
	int numSet ();

	/** Write to debug log all bits set.
	 */
	void dump (void);
};

inline
FdSet::
FdSet () 
{
	reset (); 
}

inline bool
FdSet::
setFd (const unsigned int fd_) 
{ 
	if ( fd_ <= FD_SETSIZE ) {
		FD_SET (fd_, this); 
		return true;
	}
	return false;
}

inline bool 
FdSet::
clear (const unsigned int fd_) 
{
	if ( fd_ <= FD_SETSIZE ) {
		FD_CLR (fd_, this); 
		return true;
	}
	return false;
}

inline bool 
FdSet::
isSet (const unsigned int fd_) 
{ 
	return FD_ISSET (fd_, this); 
}

inline void 
FdSet::
reset (void) 
{ 
	::memset(this, 0, sizeof (*this)); 
}

inline int 
FdSet::
numSet () 
{
	register int i, n;

	for (i=0, n=0; i < FD_SETSIZE; i++) {
		if ( isSet (i) ) {
			n++;
		}
	}
	return n;
}

inline void 
FdSet::
dump (void) 
{
	for (int i=0; i< FD_SETSIZE; i++) {
		if ( isSet (i) ) {
			DL((REACT,"fd # %d\n",i));
		}
	}
}

} // end namespace ASSA

#endif /* FDSET_H */  
