/*  -*- Mode: C -*-  */

/* stream.c ---  */

/* Author:	       Gary V. Vaughan <gvv@techie.com>
 * Maintainer:	       Gary V. Vaughan <gvv@techie.com>
 * Created:	       Thu Apr 22 23:39:55 1999
 * Last Modified:      Wed Jul 14 15:08:34 1999
 *            by:      Gary V. Vaughan <gvv@techie.com>
 * ---------------------------------------------------------------------
 * @(#) $Id$
 * ---------------------------------------------------------------------
 */

/* Copyright (C) 1999 Gary V. Vaughan */

/* This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * As a special exception to the GNU General Public License, if you
 * distribute this file as part of a program that also links with and
 * uses the libopts library from AutoGen, you may include it under
 * the same distribution terms used by the libopts library.
 */

/* Code: */

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include "compat.h"
#include "stream.h"
#include "mem.h"

/**
 * stream_new: constructor
 * @dets: user supplied stream details to be passed into the various funcs.
 * @limit: the maximum number of consecutive bytes to fit in @dets.
 * @get_func: function to get a character from @dets stream.
 * @put_func: function to put a character in @dets stream.
 * @finalize_func: function to finalize @dets before the stream is recycled.
 * 
 * Allocate and initialize a new STREAM data type.
 * 
 * Return value:
 * The address of the newly allocated and initialised stream is returned.
 **/
STREAM*
stream_new (dets, limit, get_func, put_func, finalize_func)
    stream_gpointer dets;
    unsigned long limit;
    stream_get_function *get_func;
    stream_put_function *put_func;
    stream_finalize_function *finalize_func;
{
    STREAM *new = snv_new(STREAM, 1);

    stream_init(new, dets, limit, get_func, put_func);
    new->finalize_func	= finalize_func;

    return new;
}

/**
 * stream_init:
 * @stream: The stream to be initialized.
 * @dets: user supplied stream details to be passed into the various funcs.
 * @limit: the maximum number of consecutive bytes to fit in @dets.
 * @get_func: function to get a character from @dets stream.
 * @put_func: function to put a character in @dets stream.
 * 
 * Initialize @stream with the data contained in the arguments to this
 * function.
 **/
void
stream_init (stream, dets, limit, get_func, put_func)
    STREAM *stream;
    stream_gpointer dets;
    unsigned long limit;
    stream_get_function *get_func;
    stream_put_function *put_func;
{
    stream->stream 	= dets;
    stream->limit  	= limit;
    stream->get_func	= get_func;
    stream->put_func	= put_func;
    stream->finalize_func= NULL;
}

/**
 * stream_delete: destructor
 * @stream: The stream pending deletion
 * 
 * The finalization function specified when @stream was created (if any)
 * is called, and then the memory associated with @stream is recycled.
 * It is the responsibility of the finalization function to recycle, or
 * otherwise manage, any memory associated with the user supplied %dets.
 **/
void
stream_delete (stream)
    STREAM *stream;
{
    if (stream && stream->finalize_func)
    {
	(*stream->finalize_func)(stream->stream);
    }

    snv_delete(stream);
}

/**
 * stream_put:
 * @ch: A single character to be placed in @stream.
 * @stream: The stream to be written to.
 * 
 * This function will @ch in @stream if that stream's output limit will
 * not be exceeded.
 * 
 * Return value:
 * If @stream is full, or any other error occurs, that error code is
 * returned unchanged.  This is of course dependant on what the handler
 * function uses to indicate an error.  Otherwise, 1 (the number of
 * characters emitted!) is returned.
 **/
int
stream_put (ch, stream)
    int ch;
    STREAM *stream;
{
    int ch_or_errorcode;
    
    if (!stream || stream->limit < 1)
    {
	return -1;
    }
    
    stream->limit -= 1;
    ch_or_errorcode = stream->put_func ? (*stream->put_func)(ch, stream) : -1;
    
    return (ch_or_errorcode < 0) ? ch_or_errorcode : 1;
}

/**
 * stream_get:
 * @stream: The stream to be read from.
 * 
 * This function will try to read a single character from @stream.
 * 
 * Return value:
 * If an error occurs or the end of @stream is reached, -1 is returned.
 * Under normal circumstances the value if the character read (cast to
 * an int) is returned.
 **/
int
stream_get (stream)
    STREAM *stream;
{
    return stream->get_func ? (*stream->get_func)(stream) : -1;
}

/* stream.c ends here */
