|
Packit |
022b05 |
/*
|
|
Packit |
022b05 |
* dstring.c --
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Implementation of the dynamic string abstract data type.
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* Copyright (c) 2006 Juergen Schoenwaelder, International University Bremen.
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* See the file "COPYING" for information on usage and redistribution
|
|
Packit |
022b05 |
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
|
Packit |
022b05 |
*
|
|
Packit |
022b05 |
* @(#) $Id: smilint.c 1867 2004-10-06 13:45:31Z strauss $
|
|
Packit |
022b05 |
*/
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
#include <config.h>
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
#include <stdlib.h>
|
|
Packit |
022b05 |
#include <string.h>
|
|
Packit |
022b05 |
#include <stdarg.h>
|
|
Packit |
022b05 |
#include <stdio.h>
|
|
Packit |
022b05 |
#ifdef HAVE_WIN_H
|
|
Packit |
022b05 |
#include "win.h"
|
|
Packit |
022b05 |
#endif
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
#include "dstring.h"
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
#if !defined va_copy
|
|
Packit |
022b05 |
# if defined __va_copy
|
|
Packit |
022b05 |
# define va_copy __va_copy /* C99 draft proposal */
|
|
Packit |
022b05 |
# else
|
|
Packit |
022b05 |
# define va_copy(lhs,rhs) (lhs) = (rhs)
|
|
Packit |
022b05 |
# endif
|
|
Packit |
022b05 |
#endif
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
#if 0
|
|
Packit |
022b05 |
/* These functions should not be needed if inlining works properly. */
|
|
Packit |
022b05 |
char*
|
|
Packit |
022b05 |
dstring_str(dstring_t *ds)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
return ds ? ds->str : NULL;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
size_t
|
|
Packit |
022b05 |
dstring_len(dstring_t *ds)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
return ds ? ds->len : 0;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
#endif
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
static inline dstring_t*
|
|
Packit |
022b05 |
dstring_grow(dstring_t *ds, size_t len)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
if (ds) {
|
|
Packit |
022b05 |
ds->str = realloc(ds->str, len + 1);
|
|
Packit |
022b05 |
if (! ds->str) {
|
|
Packit |
022b05 |
exit(EXIT_FAILURE);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
ds->str[len] = '\0';
|
|
Packit |
022b05 |
ds->len = len;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
return ds;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
dstring_t*
|
|
Packit |
022b05 |
dstring_new(void)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
dstring_t *ds;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
ds = calloc(1, sizeof(dstring_t));
|
|
Packit |
022b05 |
if (! ds) {
|
|
Packit |
022b05 |
exit(EXIT_FAILURE);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
return dstring_grow(ds, 0);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
dstring_t*
|
|
Packit |
022b05 |
dstring_delete(dstring_t *ds)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
if (ds) {
|
|
Packit |
022b05 |
if (ds->str) free(ds->str);
|
|
Packit |
022b05 |
free(ds);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
return NULL;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
dstring_t*
|
|
Packit |
022b05 |
dstring_assign(dstring_t *ds, const char *s)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
if (ds && s) {
|
|
Packit |
022b05 |
ds = dstring_grow(ds, strlen(s));
|
|
Packit |
022b05 |
strcpy(ds->str, s);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
return ds;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
dstring_t*
|
|
Packit |
022b05 |
dstring_append(dstring_t *ds, const char *s)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
if (ds && s) {
|
|
Packit |
022b05 |
ds = dstring_grow(ds, ds->len + strlen(s));
|
|
Packit |
022b05 |
strcat(ds->str, s);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
return ds;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
dstring_t*
|
|
Packit |
022b05 |
dstring_append_char(dstring_t *ds, const char c)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
if (ds) {
|
|
Packit |
022b05 |
ds = dstring_grow(ds, ds->len + 1);
|
|
Packit |
022b05 |
ds->str[ds->len-1] = c;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
return ds;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
dstring_t*
|
|
Packit |
022b05 |
dstring_concat(dstring_t *ds, ...)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
va_list ap;
|
|
Packit |
022b05 |
const char *s;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (ds) {
|
|
Packit |
022b05 |
va_start(ap, ds);
|
|
Packit |
022b05 |
for (s = va_arg(ap, char*); s; s = va_arg(ap, char*)) {
|
|
Packit |
022b05 |
ds = dstring_append(ds, s);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
va_end(ap);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
return ds;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
dstring_t*
|
|
Packit |
022b05 |
dstring_append_printf(dstring_t *ds, const char *format, ...)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
va_list ap;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
va_start(ap, format);
|
|
Packit |
022b05 |
ds = dstring_append_vprintf(ds, format, ap);
|
|
Packit |
022b05 |
va_end(ap);
|
|
Packit |
022b05 |
return ds;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
dstring_t *
|
|
Packit |
022b05 |
dstring_append_vprintf(dstring_t *ds, const char *format, va_list _ap)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
int n, o;
|
|
Packit |
022b05 |
va_list ap;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (ds) {
|
|
Packit |
022b05 |
o = ds->len;
|
|
Packit |
022b05 |
while (1) {
|
|
Packit |
022b05 |
va_copy(ap, _ap);
|
|
Packit |
022b05 |
n = vsnprintf(ds->str + o, ds->len+1 - o, format, ap);
|
|
Packit |
022b05 |
va_end(ap);
|
|
Packit |
022b05 |
if (n > -1 && n+o <= ds->len) {
|
|
Packit |
022b05 |
if (n+o < ds->len) {
|
|
Packit |
022b05 |
dstring_truncate(ds, n+o);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
return ds;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
if (n > 0) {
|
|
Packit |
022b05 |
ds = dstring_grow(ds, n + o); /* C99 */
|
|
Packit |
022b05 |
} else {
|
|
Packit |
022b05 |
ds = dstring_grow(ds, ds->len + ds->len); /* GLIBC */
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
return ds;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
dstring_t*
|
|
Packit |
022b05 |
dstring_printf(dstring_t *ds, const char *format, ...)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
va_list ap;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
va_start(ap, format);
|
|
Packit |
022b05 |
ds = dstring_vprintf(ds, format, ap);
|
|
Packit |
022b05 |
va_end(ap);
|
|
Packit |
022b05 |
return ds;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
dstring_t*
|
|
Packit |
022b05 |
dstring_vprintf(dstring_t *ds, const char *format, va_list _ap)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
int n;
|
|
Packit |
022b05 |
va_list ap;
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
if (ds) {
|
|
Packit |
022b05 |
while (1) {
|
|
Packit |
022b05 |
va_copy(ap, _ap);
|
|
Packit |
022b05 |
n = vsnprintf(ds->str, ds->len+1, format, ap);
|
|
Packit |
022b05 |
va_end(ap);
|
|
Packit |
022b05 |
if (n > -1 && n <= ds->len) {
|
|
Packit |
022b05 |
if (n < ds->len) {
|
|
Packit |
022b05 |
dstring_truncate(ds, n);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
return ds;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
if (n > 0) {
|
|
Packit |
022b05 |
ds = dstring_grow(ds, n); /* C99 */
|
|
Packit |
022b05 |
} else {
|
|
Packit |
022b05 |
ds = dstring_grow(ds, ds->len + ds->len); /* GLIBC */
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
return ds;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
dstring_t*
|
|
Packit |
022b05 |
dstring_truncate(dstring_t *ds, int len)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
if (ds && len < ds->len) {
|
|
Packit |
022b05 |
ds = dstring_grow(ds, len);
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
return ds;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
|
|
Packit |
022b05 |
dstring_t*
|
|
Packit |
022b05 |
dstring_expand(dstring_t *ds, int len, char fill)
|
|
Packit |
022b05 |
{
|
|
Packit |
022b05 |
if (ds && len > ds->len) {
|
|
Packit |
022b05 |
int i, old = ds->len;
|
|
Packit |
022b05 |
ds = dstring_grow(ds, len);
|
|
Packit |
022b05 |
for (i = old; i < len; i++) {
|
|
Packit |
022b05 |
ds->str[i] = fill;
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
}
|
|
Packit |
022b05 |
return ds;
|
|
Packit |
022b05 |
}
|