/*
    GDAM - Geoff & Dave's Audio Mixer
    Copyright (C) 1999    Dave Benson, Geoff Matters.

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library 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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA

    Contact:
        daveb@ffem.org <Dave Benson>
        geoff@ugcs.caltech.edu <Geoff Matters>
*/
#ifndef __GDAM_BUFFER_H_
#define __GDAM_BUFFER_H_

#include <glib.h>
#include <gdam/common/gdamdebug.h>

typedef struct _GdamBuffer GdamBuffer;
typedef struct _GdamBufferFragment GdamBufferFragment;

struct _GdamBuffer {
	GdamBufferFragment*	first, *last;
	int size;
};


typedef gint64 GdamTime;

#if G_CAN_INLINE
static inline gint64 gdam_time_difference(GdamTime* t1, GdamTime* t2)
{
	return (gint64)(*t1 - *t2);
}
#else
#define gdam_time_difference(t1, t2)      ( *(t1) - *(t2) )
#endif

void        gdam_buffer_construct     (GdamBuffer*    buffer);
void        gdam_buffer_destruct      (GdamBuffer*    buffer);


GdamBuffer* gdam_buffer_new           ();
void        gdam_buffer_destroy       (GdamBuffer*    buffer);
int         gdam_buffer_read          (GdamBuffer*    buffer,
                                       void*          out,
				       int            out_max);
int         gdam_buffer_discard       (GdamBuffer*    buffer,
				       int            discard_max);
void        gdam_buffer_append        (GdamBuffer*    buffer,
                                       const void*    in,
				       int            in_len);
void        gdam_buffer_append_buffer (GdamBuffer*    buffer,
                                       GdamBuffer*    source,
				       gboolean       drain);
void        gdam_buffer_send_buffer   (GdamBuffer*    buffer,
                                       GdamBuffer*    source,
				       int            length,
				       gboolean       drain);
void        gdam_buffer_prepend       (GdamBuffer*    buffer,
                                       const void*    in,
				       int            in_len);
gboolean    gdam_buffer_write_one     (GdamBuffer*    buffer,
                                       int            fd);
gboolean    gdam_buffer_read_one      (GdamBuffer*    buffer,
                                       int            fd);
int         gdam_buffer_peek          (const GdamBuffer* buffer,
                                       void*          out,
				       int            out_max);
void        gdam_buffer_append_alloced(GdamBuffer    *buffer,
                                       gconstpointer  data,
                                       int            length,
                                       gpointer       destroy_data,
                                       GDestroyNotify destroy);

/* Returns the index of the first occurence of the given
 * character `to_find', on or after `start_index',
 * or -1 if the character wasn't found. */
int         gdam_buffer_index_of      (GdamBuffer*    buffer, 
                                       char           to_find,
				       int            start_index);


/* Convenience routines for building messages. */

/* These two functions remove all data from the GdamBuffers that
 * you pass in. */
GdamBuffer* gdam_buffer_package       (int prefix, int n, ...);
GdamBuffer* gdam_buffer_package_v     (int prefix, int n, GdamBuffer**);

void        gdam_buffer_prepend_length(GdamBuffer* buffer);
void        gdam_buffer_append_string (GdamBuffer* buffer,
                                       const char* string);
void        gdam_buffer_append_string0(GdamBuffer* buffer,
                                       const char* string);
char*       gdam_buffer_parse_string0 (GdamBuffer* buffer);
void        gdam_buffer_append_int    (GdamBuffer* buffer, int i);
void        gdam_buffer_append_int64  (GdamBuffer* buffer, gint64 i);
void        gdam_buffer_append_double (GdamBuffer* buffer, gdouble i);
void        gdam_buffer_append_time   (GdamBuffer* buffer, GdamTime t);
gboolean    gdam_buffer_parse_int     (GdamBuffer* buffer,
                                       int*        returned_i);
gboolean    gdam_buffer_parse_int64   (GdamBuffer* buffer,
                                       gint64*     returned_i);
gboolean    gdam_buffer_parse_double  (GdamBuffer* buffer,
                                       double*     returned_double);
gboolean    gdam_buffer_parse_time    (GdamBuffer* buffer,
                                       GdamTime*   returned_i);
gboolean    gdam_buffer_peek_int      (GdamBuffer* buffer,
                                       int*        returned_i);
void        gdam_buffer_append_zeroes (GdamBuffer* buffer,
                                       int         zero);
#endif
