Blame tools/dstring.c

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
}