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

/* filament.h --- a bit like a string but different =)O| */

/* Author:	       Gary V. Vaughan <gvv@techie.com>
 * Maintainer:	       Gary V. Vaughan <gvv@techie.com>
 * Created:	       Fri Apr 23 10:52:55 1999
 * Last Modified:      Wed Jul 14 15:09:10 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: */

#ifndef FILAMENT_H
#define FILAMENT_H 1

#include <snprintfv/compat.h>

#ifdef __cplusplus
extern "C" {
#if 0
/* This brace is so that emacs can still indent properly: */ }
#endif
#endif /* __cplusplus */

#ifndef COMPILING_FILAMENT_C
#  ifdef __STDC__
/**
 * filament:
 * Opaque data type used to hold 8-bit clean dynamic strings which know
 * their own length and resize themselves to avoid buffer overruns.
 **/
typedef void *filament;
#  else
typedef char *filament;
#  endif
#else
typedef struct filament filament;
#endif

/**
 * filnew:  constructor 
 * @init: address of the first byte to copy into the new object.
 * @len:  the number of bytes to copy into the new object.
 *
 * Create a new filament object, initialised to hold a copy of the
 * first @len bytes starting at address @init.  If @init is NULL, or
 * @len is 0 (or less), then the initialised filament will return the
 * empty string, "", if its value is queried.
 *
 * Return value:
 * A newly created filament object is returned.
 **/
extern filament* filnew PARAMS((const char *const init, size_t len));

/**
 * filinit:   
 * @fil: The filament object to initialise.
 * @init: address of the first byte to copy into the new object.
 * @len:  the number of bytes to copy into the new object.
 *
 * Initialise a filament object to hold a copy of the first @len bytes
 * starting at address @init.  If @init is NULL, or @len is 0 (or less),
 * then the filament will be reset to hold the empty string, "".
 *
 * Return value:
 * The initialised filament object is returned.
 **/
extern filament* filinit PARAMS((filament *fil, const char *const init, size_t len));

/**
 * fildelete:  destructor 
 * @fil: The filament object for recycling.
 *
 * The memory being used by @fil is recycled.
 *
 * Return value:
 * The original contents of @fil are converted to a null terminated
 * string which is returned, either to be freed itself or else used
 * as a normal C string.  The entire filament contents are copied into
 * this string including any embedded nulls.
 **/
extern char* fildelete PARAMS((filament *fil));

/**
 * filval:   
 * @fil: The filament object being queried.
 *
 * Return value:
 * A pointer to the internal null terminated string held by the filament
 * object is returned.  Since the @fil may contain embedded nulls, it
 * is not entirely safe to use the strfoo() API to examine the contents
 * of the return value.
 **/
extern inline char* filval PARAMS((filament *fil));

/**
 * fillen:   
 * @fil: The filament object being queried.
 * 
 * Return value:
 * The length of @fil, including any embedded nulls, but excluding the
 * terminating null, is returned.
 **/
extern inline size_t fillen PARAMS((filament *fil));

/**
 * filelt:   
 * @fil: The filament being queried.
 * @n: A zero based index into @fil.
 * 
 * This function looks for the @n'th element of @fil.
 * 
 * Return value:
 * If @n is an index inside the filament @fil, then the character stored
 * at that index cast to an int is returned, otherwise @n is outside
 * this range and -1 is returned.
 **/
extern inline int filelt PARAMS((filament *fil, size_t n));

/**
 * filcat:   
 * @fil: The destination filament of the concatenation.
 * @str: The address of the source bytes for concatenation.
 * 
 * The bytes starting at address @str upto and including the first null
 * byte encountered are destructively concatenated to @fil.  If
 * necessary @fil is dynamically reallocated to make room for this
 * operation.
 * 
 * Return value: 
 * A pointer to the null terminated string (along with any embedded nulls)
 * which is the result of this concatenation is returned.
 **/
extern inline char* filcat PARAMS((filament *fil, const char *str));

/**
 * filncat:   
 * @fil: The destination filament of the concatenation.
 * @str: The address of the source bytes for concatenation.
 * @n: The number of bytes to be copied from @str.
 * 
 * @n bytes starting with the byte at address @str are destructively
 * concatenated to @fil.  If necessary, @fil is dynamically reallocated
 * to make room for this operation.
 * 
 * Return value:
 * A pointer to the null terminated string (along with any embedded nulls)
 * which is the result of this concatenation is returned.
 **/
extern char* filncat PARAMS((filament *fil, const char *str, size_t n));

/**
 * filccat:   
 * @fil: The destination filament of the concatenation.
 * @c: The character to append to @fil.
 * 
 * @c is destructively concatenated to @fil.  If necessary, @fil is
 * dynamically reallocated to make room for this operation.  When used
 * repeatedly this function is considerably less efficient than filncat(),
 * since it must maintain the '\0' suffix for C string compatibility
 * after every appended character, and then overwrite that '\0' on the
 * next call.
 * 
 * Return value:
 * A pointer to the null terminated string (along with any embedded nulls)
 * which is the result of this concatenation is returned.
 **/
extern char* filccat PARAMS((filament *fil, int c));


#ifdef __cplusplus
#if 0
/* This brace is so that emacs can still indent properly: */ {
#endif
}
#endif /* __cplusplus */

#endif /* FILAMENT_H */

/* filament.h ends here */
