/* -*- Mode: C -*- */
/* filament.h --- a bit like a string but different =)O|
* Copyright (C) 1998, 1999, 2000, 2002 Gary V. Vaughan
* Originally by Gary V. Vaughan, 1998
* This file is part of Snprintfv
*
* Snprintfv 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.
*
* Snprintfv 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. If not, see <http://www.gnu.org/licenses>.
*
* 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 */
#define FILAMENT_BUFSIZ (512 - sizeof(char *) - (2 * sizeof(size_t)))
/**
* 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 struct filament Filament;
struct filament
{
char *value; /* pointer to the start of the string */
size_t length; /* length of the string */
size_t size; /* total memory allocated */
char buffer[FILAMENT_BUFSIZ]; /* usually string == &buffer[0] */
};
/**
* 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 (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 (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 (Filament *fil);
/**
* _fil_extend:
* @fil: The Filament object which may need more string space.
* @len: The length of the data to be stored in @fil.
* @copy: whether to copy data from the static buffer on reallocation.
*
* This function will will assign a bigger block of memory to @fil
* considering the space left in @fil and @len, the length required
* for the prospective contents.
*/
extern void
_fil_extend (Filament *fil, size_t len, bool copy);
#line 60 "filament.in"
/* Save the overhead of a function call in the great majority of cases. */
#define fil_maybe_extend(fil, len, copy) \
(((len)>=(fil)->size) ? _fil_extend((fil), (len), (copy)) : (void)0)
/**
* filval:
* @fil: The Filament object being queried.
*
* Return value:
* A pointer to the 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.
**/
SNV_INLINE char *
filval (Filament *fil)
{
/* Because we have been careful to ensure there is always at least
one spare byte of allocated memory, it is safe to set it here. */
fil->value[fil->length] = '\0';
return (char *) (fil->value);
}
/**
* fillen:
* @fil: The Filament object being queried.
*
* Return value:
* The length of @fil, including any embedded nulls, but excluding the
* terminating null, is returned.
**/
SNV_INLINE size_t
fillen (Filament *fil)
{
return fil->length;
}
/**
* 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.
**/
SNV_INLINE int
filelt (Filament *fil, ssize_t n)
{
if ((n >= 0) && (n < (ssize_t)fil->length))
return (int) fil->value[n];
else
return -1;
}
/**
* 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 (not null terminated) string which is the result
* of this concatenation is returned.
**/
SNV_INLINE char *
filncat (Filament *fil, const char *str, size_t n)
{
fil_maybe_extend (fil, n + fil->length, true);
memcpy (fil->value + fil->length, str, n);
fil->length += n;
return fil->value;
}
/**
* 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 (not null terminated) string which is the result
* of this concatenation is returned.
**/
SNV_INLINE char *
filcat (Filament *fil, const char *str)
{
size_t length = strlen (str);
return filncat (fil, str, length);
}
/**
* 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 less efficient than %filncat,
* since it must check whether to extend the filament before each
* character is appended.
*
* Return value:
* A pointer to the (not null terminated) string which is the result
* of this concatenation is returned.
**/
SNV_INLINE char *
filccat (Filament *fil, int c)
{
fil_maybe_extend (fil, 1 + fil->length, true);
fil->value[fil->length++] = (char)(c & 0xFF);
return fil->value;
}
#ifdef __cplusplus
#if 0
/* This brace is so that emacs can still indent properly: */
{
#endif
}
#endif /* __cplusplus */
#endif /* FILAMENT_H */
/* filament.h ends here */