1
0
Files
irix-657m-src/eoe/lib/ns/files/dstring.c
2022-09-29 17:59:04 +03:00

317 lines
5.1 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "memory.h"
#include "dstring.h"
/*
** This routine just sets all the items in a dstring_t structure to zero.
** It should be called before first use to insure that the structure is in
** a known state.
*/
int
ds_init(dstring_t *ds, int len, void *arena)
{
if (! ds) {
return 0;
}
if (len) {
ds->data = (char *)m_malloc(len, arena);
if (! ds->data) {
return 0;
}
*ds->data = 0;
}
ds->size = len;
ds->used = 0;
return 1;
}
/*
** This routine frees any dynamically allocated memory associated with
** a dynamic string.
*/
void
ds_clear(dstring_t *ds, void *arena)
{
if (ds && ds->data) {
m_free(ds->data, arena);
ds->size = ds->used = 0;
ds->data = 0;
}
}
/*
** This clears the string and frees the structure.
*/
void
ds_free(dstring_t *ds, void *arena)
{
if (ds) {
ds_clear(ds, arena);
m_free(ds, arena);
}
}
/*
** This routine simply resets the data to null without releasing the
** memory. It is useful when the string is going to be reused.
*/
void
ds_reset(dstring_t *ds)
{
if (ds && ds->data) {
*ds->data = 0;
}
ds->used = 0;
}
/*
** This routine is used to allocate memory for the dynamic string. It
** simply allocates a new chunk of memory, copies in the old data, and
** frees the old memory. We don't use realloc so that we are not
** destructive if we could not allocate the memory.
*/
int
ds_grow(dstring_t *ds, int len, void *arena)
{
char *n;
if (! ds) {
return 0;
}
if (ds->size < len) {
n = (char *)m_realloc(ds->data, len, arena);
if (! n) {
return 0;
}
ds->size = len;
ds->data = n;
}
return 1;
}
/*
** This just appends the given string onto the end of the dynamic string,
** reallocating memory if needed.
*/
int
ds_append(dstring_t *ds, char *s, int len, void *arena)
{
int needed;
if (! ds || ! s) {
return 0;
}
if (! len) {
len = strlen(s);
}
needed = len + ds->used + 1;
if (ds->size > needed || ds_grow(ds, needed, arena)) {
memcpy(ds->data + ds->used, s, len);
ds->used += len;
ds->data[ds->used] = 0;
return 1;
}
return 0;
}
/*
** This routine inserts the given string at the beginning of a dynamic
** string, reallocating memory if needed.
*/
int
ds_prepend(dstring_t *ds, char *s, int len, void *arena)
{
int needed;
if (! ds || ! s) {
return 0;
}
if (! len) {
len = strlen(s);
}
needed = len + ds->used + 1;
if (ds->size < needed || ds_grow(ds, needed, arena)) {
memmove(ds->data + len, ds->data, ds->used);
memcpy(ds->data, s, len);
ds->used += len;
ds->data[ds->used] = 0;
return 1;
}
return 0;
}
/*
** This routine resets the dynamic string to null then appends the given
** string reallocating space if needed.
*/
int
ds_set(dstring_t *ds, char *s, int len, void *arena)
{
ds_reset(ds);
return ds_append(ds, s, len, arena);
}
/*
** This routine does a blind memory compare on two dynamic strings.
*/
int
ds_cmp(dstring_t *a, dstring_t *b)
{
int result;
if (! a || ! a->used) {
return -1;
}
if (! b || ! b->used) {
return 1;
}
result = memcmp(a->data, b->data,
(a->used < b->used) ? a->used : b->used);
if (result == 0 && a->used != b->used) {
if (a->used > b->used) {
return 1;
}
return -1;
}
return result;
}
/*
** This does a case-insensitive comparison between two dynamic strings.
*/
int
ds_casecmp(dstring_t *a, dstring_t *b)
{
int result;
if (! a || ! a->used) {
return -1;
}
if (! b || ! b->used) {
return 1;
}
result = strncasecmp(a->data, b->data,
(a->used < b->used) ? a->used : b->used);
if (result == 0 && a->used != b->used) {
if (a->used > b->used) {
return 1;
}
return -1;
}
return result;
}
/*
** This routine compares a dynamic string to a passed string, if the len is
** non-zero then only go that far.
*/
int
ds_scmp(dstring_t *ds, char *s, int len)
{
if (! ds || ! ds->used) {
return -1;
}
if (! s) {
return 1;
}
if (len) {
return strncmp(ds->data, s, len);
}
return strcmp(ds->data, s);
}
/*
** Just like the above, but case insensitive.
*/
int
ds_scasecmp(dstring_t *ds, char *s, int len)
{
if (! ds || ! ds->used) {
return -1;
}
if (! s) {
return 1;
}
if (len) {
return strncasecmp(ds->data, s, len);
}
return strcasecmp(ds->data, s);
}
/*
** This function will copy b into a, allocating space if needed.
*/
int
ds_cpy(dstring_t *a, dstring_t *b, void *arena)
{
if (! a || ! b || ! b->used) {
return 0;
}
return ds_append(a, b->data, b->used, arena);
}
/*
** This is just like the above, but allocates the structure.
*/
dstring_t *
ds_dup(dstring_t *ds, void *arena)
{
dstring_t *r;
r = m_calloc(1, sizeof(*r), arena);
if (! r) {
return 0;
}
if (! ds_append(r, ds->data, ds->used, arena)) {
m_free(r, arena);
return 0;
}
return r;
}
/*
** This routine allocates a new dstring and initializes it to the
** given value;
*/
dstring_t *
ds_new(char *s, int len, void *arena)
{
dstring_t *ds;
ds = m_calloc(1, sizeof(*ds), arena);
if (! ds) {
return 0;
}
if (len) {
if (! ds_grow(ds, len + 1, arena)) {
m_free(ds, arena);
return 0;
}
if (s) {
memcpy(ds->data, s, len);
ds->data[len] = 0;
ds->used = len;
}
}
return ds;
}