/*
* dnsutl - utilities to make DNS easier to configure
* Copyright (C) 1990-1994, 1996, 1999, 2006, 2007 Peter Miller
*
* 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 3 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. If not, see
* <http://www.gnu.org/licenses/>.
*
* This file contains routines for mainpulating words and word lists.
* Much of the functionality of cook uses these routines.
*/
#include <ac/ctype.h>
#include <ac/stddef.h>
#include <ac/stdlib.h>
#include <ac/string.h>
#include <ac/time.h>
#include <error.h>
#include <mem.h>
#include <strlist.h>
/*
* NAME
* strlist_append - append to a word list
*
* SYNOPSIS
* void strlist_append(strlist_ty *wlp, string_ty *wp);
*
* DESCRIPTION
* Wl_append is used to append to a word list.
*
* CAVEAT
* The word being appended IS copied.
*/
void
strlist_append(strlist_ty *wlp, string_ty *w)
{
size_t nbytes;
assert(wlp);
assert(w);
if (wlp->nstrings >= wlp->nstrings_max)
{
wlp->nstrings_max = wlp->nstrings_max * 2 + 4;
nbytes = wlp->nstrings_max * sizeof(string_ty *);
wlp->string = mem_change_size(wlp->string, nbytes);
}
wlp->string[wlp->nstrings++] = str_copy(w);
}
void
strlist_prepend(strlist_ty *wlp, string_ty *w)
{
long j;
size_t nbytes;
assert(wlp);
assert(w);
if (wlp->nstrings >= wlp->nstrings_max)
{
wlp->nstrings_max = wlp->nstrings_max * 2 + 4;
nbytes = wlp->nstrings_max * sizeof(string_ty *);
wlp->string = mem_change_size(wlp->string, nbytes);
}
wlp->nstrings++;
for (j = wlp->nstrings - 1; j > 0; --j)
wlp->string[j] = wlp->string[j - 1];
wlp->string[0] = str_copy(w);
}
/*
* NAME
* strlist_free - free a word list
*
* SYNOPSIS
* void strlist_free(strlist_ty *wlp);
*
* DESCRIPTION
* Wl_free is used to free the contents of a word list
* when it is finished with.
*
* CAVEAT
* It is assumed that the contents of the word list were all
* created using strdup() or similar, and grown using strlist_append().
*/
void
strlist_free(strlist_ty *wlp)
{
size_t j;
for (j = 0; j < wlp->nstrings; j++)
str_free(wlp->string[j]);
if (wlp->nstrings)
free(wlp->string);
wlp->nstrings = 0;
wlp->nstrings_max = 0;
wlp->string = 0;
}
/*
* NAME
* strlist_member - word list membership
*
* SYNOPSIS
* int strlist_member(strlist_ty *wlp, string_ty *wp);
*
* DESCRIPTION
* Wl_member is used to determine if the given word is
* contained in the given word list.
*
* RETURNS
* A zero if the word is not in the list,
* and a non-zero if it is.
*/
int
strlist_member(strlist_ty *wlp, string_ty *w)
{
size_t j;
for (j = 0; j < wlp->nstrings; j++)
if (str_equal(wlp->string[j], w))
return 1;
return 0;
}
/*
* NAME
* strlist_copy - copy a word list
*
* SYNOPSIS
* void strlist_copy(strlist_ty *to, strlist_ty *from);
*
* DESCRIPTION
* Wl_copy is used to copy word lists.
*
* RETURNS
* A copy of the 'to' word list is placed in 'from'.
*
* CAVEAT
* It is the responsibility of the caller to ensure that the
* new word list is freed when finished with, by a call to strlist_free().
*/
void
strlist_copy(strlist_ty *to, strlist_ty *from)
{
size_t j;
strlist_zero(to);
for (j = 0; j < from->nstrings; j++)
strlist_append(to, str_copy(from->string[j]));
}
/*
* NAME
* wl2str - form a string from a word list
*
* SYNOPSIS
* string_ty *wl2str(strlist_ty *wlp, int start, int stop, char *sep);
*
* DESCRIPTION
* Wl2str is used to form a string from a word list.
*
* RETURNS
* A pointer to the newly formed string in dynamic memory.
*
* CAVEAT
* It is the responsibility of the caller to ensure that the
* new string is freed when finished with, by a call to free().
*/
string_ty *
wl2str(strlist_ty *wl, size_t start, size_t stop, const char *sep)
{
size_t j;
static char *tmp;
static size_t tmplen;
size_t length;
size_t seplen;
char *pos;
string_ty *s;
if (!sep)
sep = " ";
seplen = strlen(sep);
length = 0;
for (j = start; j <= stop && j < wl->nstrings; j++)
{
s = wl->string[j];
if (s->str_length)
{
if (length)
length += seplen;
length += s->str_length;
}
}
if (tmplen < length)
{
tmplen = length;
tmp = mem_change_size(tmp, tmplen);
}
pos = tmp;
for (j = start; j <= stop && j < wl->nstrings; j++)
{
s = wl->string[j];
if (s->str_length)
{
if (pos != tmp)
{
memcpy(pos, sep, seplen);
pos += seplen;
}
memcpy(pos, s->str_text, s->str_length);
pos += s->str_length;
}
}
s = str_n_from_c(tmp, length);
return s;
}
/*
* NAME
* str2wl - string to word list
*
* SYNOPSIS
* void str2wl(strlist_ty *wlp, string_ty *s, char *sep, int ewhite);
*
* DESCRIPTION
* Str2wl is used to form a word list from a string.
* wlp - where to put the word list
* s - string to break
* sep - separators, default to " " if 0 given
* ewhite - supress extra white space around separators
*
* RETURNS
* The string is broken on spaces into words,
* using strndup() and strlist_append().
*
* CAVEAT
* Quoting is not understood.
*/
void
str2wl(strlist_ty *slp, string_ty *s, const char *sep, int ewhite)
{
char *cp;
int more;
if (!sep)
{
sep = " \t\n\f\r";
ewhite = 1;
}
strlist_zero(slp);
cp = s->str_text;
more = 0;
while (*cp || more)
{
string_ty *w;
char *cp1;
char *cp2;
if (ewhite)
while (isspace(*cp))
cp++;
if (!*cp && !more)
break;
more = 0;
cp1 = cp;
while (*cp && !strchr(sep, *cp))
cp++;
if (*cp)
{
cp2 = cp + 1;
more = 1;
}
else
cp2 = cp;
if (ewhite)
while (cp > cp1 && isspace(cp[-1]))
cp--;
w = str_n_from_c(cp1, cp - cp1);
strlist_append(slp, w);
str_free(w);
cp = cp2;
}
}
/*
* NAME
* strlist_insert - a insert a word into a list
*
* SYNOPSIS
* void strlist_insert(strlist_ty *wlp, string_ty *wp);
*
* DESCRIPTION
* Wl_insert is similar to strlist_append, however it does not
* append the word unless it is not already in the list.
*
* CAVEAT
* If the word is inserted it is copied.
*/
void
strlist_append_unique(strlist_ty *wlp, string_ty *wp)
{
size_t j;
for (j = 0; j < wlp->nstrings; j++)
if (str_equal(wlp->string[j], wp))
return;
strlist_append(wlp, wp);
}
/*
* NAME
* strlist_delete - remove list member
*
* SYNOPSIS
* void strlist_delete(strlist_ty *wlp, string_ty *wp);
*
* DESCRIPTION
* The strlist_delete function is used to delete a member of a word list.
*
* RETURNS
* void
*/
void
strlist_delete(strlist_ty *wlp, string_ty *wp)
{
size_t j;
size_t k;
for (j = 0; j < wlp->nstrings; ++j)
{
if (str_equal(wlp->string[j], wp))
{
wlp->nstrings--;
for (k = j; k < wlp->nstrings; ++k)
wlp->string[k] = wlp->string[k + 1];
str_free(wp);
break;
}
}
}
void
strlist_zero(strlist_ty *wlp)
{
wlp->nstrings = 0;
wlp->nstrings_max = 0;
wlp->string = 0;
}
static int
cmp(const void *va, const void *vb)
{
string_ty *a;
string_ty *b;
a = *(string_ty **)va;
b = *(string_ty **)vb;
if (str_equal(a, b))
return 0;
return strcmp(a->str_text, b->str_text);
}
void
strlist_sort(strlist_ty *slp)
{
qsort(slp->string, slp->nstrings, sizeof(slp->string[0]), cmp);
}
syntax highlighted by Code2HTML, v. 0.9.1