#include <iostream.h>

/*
 * Simple (and dumb) function to read a line of input and return it to
 * the caller.  The caller must provide the buffer that will receive
 * the line, and must tell us the size of the buffer.
 *
 * This routine does NOT return any EOF indication.  It is the
 * caller's responsibility to check for EOF on the stream.
 *
 * If a line is encountered that is longer than the buffer provided,
 * we simply print a message and abort the program.  It is this
 * behavior that qualifies the routine as "dumb".
 */

/*
 * Table of contents: the following routines are defined in this file.
 */
void		dumbReadLine(istream& stream, char buffer[],
		  unsigned int maxSize);

/*
 * Dumb read-line function.  See above for specifications.
 */
void dumbReadLine(
    istream&		stream,		// Stream to read from
    char		buffer[],	// Buffer to read into
    unsigned int	maxSize)	// Size of the buffer
    {
    /*
     * Make sure the caller didn't give us a too-small buffer.
     */
    if (maxSize < 2)
	{
	cerr << "dumbReadLine:  maxSize is ridiculously small.\n";
	exit(1);
	}

    /*
     * Character-collection loop.  We simply read characters, stuffing
     * them in the buffer, until we hit EOF or a newline.  If the
     * buffer overflows, we abort.
     */
    unsigned int i = 0;
    char ch;
    while (stream.get(ch))
	{
	if (ch == '\r')
	    continue;			// Strip carriage returns

	/*
	 * Check for buffer overflow
	 */
	if (i >= maxSize - 1)
	    {
	    cerr << "dumbReadLine:  line too long (over " << maxSize
	      << " characters).\n";
	    exit(1);
	    }

	/*
	 * We now know there is room in the buffer.  Store the
	 * character and check to see if it was a newline (end-of-line
	 * character).  If so, finish off the buffer with a NUL and
	 * return to the caller.
	 */
	buffer[i++] = ch;
	if (ch == '\n')
	    {
	    buffer[i] = '\0';		// Add NUL terminator
	    return;
	    }
	}

    /*
     * We only get here if end-of-file was encountered while reading
     * the line.  If we got no characters before the EOF, then
     * everything was fine and we're done.  If we got characters, then
     * the last line was partial (no newline at the end) and we need
     * to do some trickery to deliver that line to the caller.
     */
    if (i == 0)
	{
	/*
	 * EOF was hit, and we didn't put any characters in the
	 * buffer.  Just return, and let the caller check for EOF.
	 */
	return;
	}
    else
	{
	/*
	 * EOF was hit, but we had read some characters before we got
	 * there.  Undo the EOF so that the caller won't see it.  This
	 * code is a bit of C++ magic.
	 */
	stream.clear(stream.rdstate() & ~ios::failbit);

	/*
	 * Because this is a dumb implementation, we will guarantee
	 * the caller that the last line will be terminated by a
	 * newline, even if there wasn't one in the input.  We are
	 * guaranteed that there is room because when the loop exited,
	 * i was at least maxSize - 2.
	 */
	buffer[i++] = '\n';
	buffer[i] = '\0';		// Add NUL terminator
	}
    }
