/*---------McGill-Computer-Vision-and-Robotics-Laboratory--C-Module---------
 *		
 * NAME:	testchar(), testinput() -- see if input is ready
 *
 * USAGE:	status = testchar(time)
 *		  int status;
 *		  float time;
 *
 *		status = testinput(fd, time)
 *		  int status, fd;
 *		  float time;
 *
 * DESCRIPTION: These functions return TRUE (1) whenever there is input on the
 * 		indicated stream that has yet to be read. This can be used to
 *		effect polled asynchronous IO. 'testinput()' examines the
 *		stream indicated by the file descriptor 'fd'; 'testchar()' 
 *		uses stdin by default.
 *
 *		The variable 'time' is indicated in seconds and tells the
 *		routine how long to wait for a character to appear before
 *		returning. The routine thus returns whenever a character 
 *		appears, or the indicated amount of time expires.
 *
 * NOTES:	Timevalues are truncated as necessary to make sure the fit
 *		into the range allowed by a struct timeval; this range is
 *		2.14748e9 to 0 seconds. Negative values are assumed zero.
 *	
 * DIAGNOSTICS: The functions returns 1 or 0 normally. If they return -1, that
 *		means the call to select() is failing unexpectedly, and a
 *		guru should be consulted.
 *
 * GLOBAL VARS: None.
 *
 * AUTHOR/DATE:	John Lloyd, November, 1984
 *
 * UPDATES:
 *
 *-------------McGill-Computer-Vision-and-Robotics-Laboratory--------------*/

#ifndef VXWORKS_CFG
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#else
#include <vxWorks.h>
#include <stdioLib.h>
#include <ioLib.h>
#endif

testchar(time)
float time;
{
	/* First check to see if there is any data in the stdin buffer */

#ifdef LINUX_CFG
	if (stdin->_IO_read_ptr != stdin->_IO_read_end )
#else
	if (stdin->_cnt > 0)
#endif
	 { return (1);
	 }
	else
	 { return (testinput(fileno(stdin), time));
	 }
}

testinput (fd, time)
int fd;
float time;
{
#ifdef VXWORKS_CFG
	int stop;

	stop = tickGet() + time*sysClkRateGet();
	while (1)
	 { int nbytes;

	   if (ioctl(fd, FIONREAD, &nbytes) < 0)
	    { return (-1);
	    }
	   if (nbytes > 0)
	    { return (1);
	    }
	   if (tickGet() >= stop)
	    { return (0);
	    }
	   taskDelay(1);
	 }
#else
	struct timeval then;		/* time when select() must expire  */
	struct timeval tv;		/* timeout variable for select()   */
	struct timeval now;		/* current time value		   */
	fd_set rfds;			/* IO detection mask for select()  */
	int status;			/* status returned by select()	   */
 
	/* turn 'time' into the appropriate entry in struct timeval */
 
	if (time > 2.0e9)
	 { time = 2.0e9;
	 }
	if (time < 0)
	 { time = 0.0;
	 }
	then.tv_sec = time;
	then.tv_usec = (time - then.tv_sec) * 1000000;
	tv = then;

	/* Now perform the test on the stdin stream */

	while (1)
	 { FD_ZERO(&rfds);
	   FD_SET(fd,&rfds);
	   if (select(FD_SETSIZE,&rfds,(fd_set*)0,(fd_set*)0,&tv) >= 0)
	    { return (FD_ISSET(fd,&rfds));
	    }
	   gettimeofday(&now,(struct timezone*)0);
	   tv.tv_sec = then.tv_sec - now.tv_sec;
	   tv.tv_usec = then.tv_usec - now.tv_usec;
	   while (tv.tv_usec < 0)
	    { tv.tv_usec += 1000000;
	      tv.tv_sec --;
	    }
	   if (tv.tv_sec < 0)
	    { return(0);
	    }
	 }
#endif
}
