/*
* fhist - file history and comparison tools
* Copyright (C) 1998, 2001, 2002 Peter Miller;
* All rights reserved.
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
*
* MANIFEST: functions to manipulate lists of strings
*
* 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/string.h>
#include <ac/stdlib.h>
#include <ac/time.h>
#include <mem.h>
#include <str.h>
#include <str_list.h>
/*
* NAME
* string_list_append - append to a word list
*
* SYNOPSIS
* void string_list_append(string_list_ty *wlp, string_ty *wp);
*
* DESCRIPTION
* Wl_append is used to append to a word list.
*
* CAVEAT
* The word being appended IS copied.
*/
void
string_list_append(string_list_ty *wlp, string_ty *w)
{
/* assert(wlp); */
/* assert(w); */
if (wlp->nstrings >= wlp->nstrings_max)
{
size_t nbytes;
wlp->nstrings_max = wlp->nstrings_max * 2 + 16;
nbytes = wlp->nstrings_max * sizeof(string_ty *);
wlp->string = mem_change_size(wlp->string, nbytes);
}
wlp->string[wlp->nstrings++] = str_copy(w);
}
/*
* NAME
* string_list_append_list
*
* SYNOPSIS
* void string_list_append_list(string_list_ty *to, string_list_ty *from);
*
* DESCRIPTION
* The string_list_append_list function is used to append one
* string list (from) onto the end of another (to).
*/
void
string_list_append_list(string_list_ty *to, const string_list_ty *from)
{
size_t j;
for (j = 0; j < from->nstrings; ++j)
string_list_append(to, from->string[j]);
}
/*
* NAME
* string_list_prepend
*
* SYNOPSIS
* void string_list_prepend(string_list_ty *, string_ty *);
*
* DESCRIPTION
* The string_list_prepend function is used to insert a string at
* the beginning of a string list.
*/
void
string_list_prepend(string_list_ty *wlp, string_ty *w)
{
ptrdiff_t j;
/* assert(wlp); */
/* assert(w); */
if (wlp->nstrings >= wlp->nstrings_max)
{
size_t nbytes;
wlp->nstrings_max = wlp->nstrings_max * 2 + 16;
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
* string_list_destructor - free a word list
*
* SYNOPSIS
* void string_list_destructor(string_list_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 string_list_append().
*/
void
string_list_destructor(string_list_ty *wlp)
{
size_t j;
for (j = 0; j < wlp->nstrings; j++)
str_free(wlp->string[j]);
if (wlp->string)
mem_free(wlp->string);
wlp->nstrings = 0;
wlp->nstrings_max = 0;
wlp->string = 0;
}
/*
* NAME
* string_list_member - word list membership
*
* SYNOPSIS
* int string_list_member(string_list_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
string_list_member(const string_list_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
* string_list_intersect - word list intersection test
*
* SYNOPSIS
* int string_list_intersect(string_list_ty *wlp, string_list_ty *wp);
*
* DESCRIPTION
* Wl_intersect 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
string_list_intersect(const string_list_ty *wl1, const string_list_ty *wl2)
{
size_t j;
if (wl1->nstrings > wl2->nstrings)
{
for (j = 0; j < wl2->nstrings; j++)
if (string_list_member(wl1, wl2->string[j]))
return 1;
}
else
{
for (j = 0; j < wl1->nstrings; j++)
if (string_list_member(wl2, wl1->string[j]))
return 1;
}
return 0;
}
/*
* NAME
* string_list_copy_constructor - copy a word list
*
* SYNOPSIS
* void string_list_copy_constructor(string_list_ty *to, string_list_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 string_list_destructor().
*/
void
string_list_copy_constructor(string_list_ty *to, const string_list_ty *from)
{
size_t j;
string_list_constructor(to);
for (j = 0; j < from->nstrings; j++)
string_list_append(to, str_copy(from->string[j]));
}
/*
* NAME
* wl2str - form a string from a word list
*
* SYNOPSIS
* string_ty *wl2str(string_list_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 str_free().
*/
string_ty *
wl2str(const string_list_ty *wl, int start, int stop, char *sep)
{
int 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(string_list_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 string_list_append().
*
* CAVEAT
* Quoting is not understood.
*/
void
str2wl(string_list_ty *slp, string_ty *s, char *sep, int ewhite)
{
char *cp;
int more;
if (!sep)
{
sep = " \t\n\f\r";
ewhite = 1;
}
string_list_constructor(slp);
cp = s->str_text;
more = 0;
while (*cp || more)
{
string_ty *w;
char *cp1;
char *cp2;
if (ewhite)
while (isspace((unsigned char)*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((unsigned char)cp[-1]))
cp--;
w = str_n_from_c(cp1, cp - cp1);
string_list_append(slp, w);
str_free(w);
cp = cp2;
}
}
/*
* NAME
* wl_insert - a insert a word into a list
*
* SYNOPSIS
* void wl_insert(string_list_ty *wlp, string_ty *wp);
*
* DESCRIPTION
* Wl_insert is similar to string_list_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
string_list_append_unique(string_list_ty *wlp, string_ty *wp)
{
size_t j;
for (j = 0; j < wlp->nstrings; j++)
if (str_equal(wlp->string[j], wp))
return;
string_list_append(wlp, wp);
}
/*
* NAME
* string_list_append_list_unique
*
* SYNOPSIS
* void string_list_append_list_unique(string_list_ty *to, string_list_ty *from);
*
* DESCRIPTION
* The string_list_append_list_unique function is used to append
* the contents of one string list (from) to the end of another
* tring list (to). Entries which duplicate items already present
* will be ignored.
*/
void
string_list_append_list_unique(string_list_ty *to, const string_list_ty *from)
{
size_t j;
for (j = 0; j < from->nstrings; ++j)
string_list_append_unique(to, from->string[j]);
}
/*
* NAME
* string_list_remove - remove list member
*
* SYNOPSIS
* void string_list_remove(string_list_ty *wlp, string_ty *wp);
*
* DESCRIPTION
* The string_list_remove function is used to delete a member of a word list.
*
* RETURNS
* void
*/
void
string_list_remove(string_list_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;
}
}
}
/*
* NAME
* string_list_remove_list - remove list members
*
* SYNOPSIS
* void string_list_remove_list(string_list_ty *wlp, string_list_ty *wp);
*
* DESCRIPTION
* The string_list_remove_list function is used to delete all the
* members of a word list from another word list.
*
* RETURNS
* void
*/
void
string_list_remove_list(string_list_ty *wlp, const string_list_ty *nuke)
{
size_t j;
for (j = 0; j < nuke->nstrings; ++j)
string_list_remove(wlp, nuke->string[j]);
}
/*
* NAME
* string_list_constructor
*
* SYNOPSIS
* void string_list_constructor(string_list_ty *);
*
* DESCRIPTION
* The string_list_constructor function is used to prepare a string
* list for use. It will be empty.
*
* CAVEAT
* This must be called on the string list before any other action
* is taken. Use string_list_destructor when you are done.
*/
void
string_list_constructor(string_list_ty *wlp)
{
wlp->nstrings = 0;
wlp->nstrings_max = 0;
wlp->string = 0;
}
/*
* NAME
* string_list_new
*
* DESCRIPTION
* string_list_ty *string_list_new(void);
*
* DESCRIPTION
* The string_list_new function is used to allocate a new string
* list in dynamic memory. It will be empty.
*
* RETURNS
* string_list_ty *
*
* CAVEAT
* Use string_list_delete when you are done.
*/
string_list_ty *
string_list_new(void)
{
string_list_ty *slp;
slp = mem_alloc(sizeof(string_list_ty));
string_list_constructor(slp);
return slp;
}
/*
* NAME
* string_list_new_copy
*
* SYNOPSIS
* string_list_ty *string_list_new_copy(string_list_ty *);
*
* DESCRIPTION
* The string_list_new_copy function is used to allocate a new copy
* of a string list in dynamic memory.
*
* RETURNS
* string_list_ty *
*
* CAVEAT
* Use string_list_delete when you are done.
*/
string_list_ty *
string_list_new_copy(const string_list_ty *from)
{
string_list_ty *slp;
slp = mem_alloc(sizeof(string_list_ty));
string_list_copy_constructor(slp, from);
return slp;
}
/*
* NAME
* string_list_delete
*
* SYNOPSIS
* void string_list_delete(string_list_ty *);
*
* DESCRIPTION
* The string_list_delete function is used to release the resources
* held by a string list in dynamic memory.
*/
void
string_list_delete(string_list_ty *slp)
{
string_list_destructor(slp);
mem_free(slp);
}
/*
* NAME
* string_list_bool
*
* SYNOPSIS
* int string_list_bool(string_list_ty *);
*
* DESCRIPTION
* The string_list_bool function is used to perform a boolean
* evaluation on a list of strings. If any return str_bool of
* true, the list is true.
*/
int
string_list_bool(const string_list_ty *slp)
{
size_t j;
for (j = 0; j < slp->nstrings; ++j)
if (str_bool(slp->string[j]))
return 1;
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1