/*
* fhist - file history and comparison tools
* Copyright (C) 1998, 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 wide strings
*/
#include <ac/string.h>
#include <wstr_list.h>
#include <mem.h>
/*
* NAME
* wstring_list_append - append to a wide string list
*
* SYNOPSIS
* void wstring_list_append(wstring_list_ty *wlp, wstring_ty *wp);
*
* DESCRIPTION
* The wstring_list_append function is used to append to a wide
* string list.
*
* CAVEAT
* The wide string being appended IS copied.
*/
void
wstring_list_append(wstring_list_ty *wlp, wstring_ty *w)
{
size_t nbytes;
if (wlp->nitems >= wlp->nitems_max)
{
/*
* always 8 less than a power of 2, which is
* most efficient for many memory allocators
*/
wlp->nitems_max = wlp->nitems_max * 2 + 8;
nbytes = wlp->nitems_max * sizeof(wstring_ty *);
wlp->item = mem_change_size(wlp->item, nbytes);
}
wlp->item[wlp->nitems++] = wstr_copy(w);
}
void
wstring_list_prepend(wstring_list_ty *wlp, wstring_ty *w)
{
size_t nbytes;
size_t j;
if (wlp->nitems >= wlp->nitems_max)
{
/*
* always 8 less than a power of 2, which is
* most efficient for many memory allocators
*/
wlp->nitems_max = wlp->nitems_max * 2 + 8;
nbytes = wlp->nitems_max * sizeof(wstring_ty *);
wlp->item = mem_change_size(wlp->item, nbytes);
}
for (j = wlp->nitems; j > 0; --j)
wlp->item[j] = wlp->item[j - 1];
wlp->nitems++;
wlp->item[0] = wstr_copy(w);
}
/*
* NAME
* wstring_list_free - free a wide string list
*
* SYNOPSIS
* void wstring_list_free(wstring_list_ty *wlp);
*
* DESCRIPTION
* The wstring_list_free function is used to free the contents of a
* wide string list when it is finished with.
*
* CAVEAT
* It is assumed that the contents of the wide string list were all
* created using strdup() or similar, and grown using
* wstring_list_append().
*/
void
wstring_list_free(wstring_list_ty *wlp)
{
size_t j;
for (j = 0; j < wlp->nitems; j++)
wstr_free(wlp->item[j]);
if (wlp->item)
mem_free(wlp->item);
wlp->nitems = 0;
wlp->nitems_max = 0;
wlp->item = 0;
}
/*
* NAME
* wstring_list_member - wide string list membership
*
* SYNOPSIS
* int wstring_list_member(wstring_list_ty *wlp, wstring_ty *wp);
*
* DESCRIPTION
* The wstring_list_member function is used to determine if the
* given wide string is contained in the given wide string list.
*
* RETURNS
* A zero if the wide string is not in the list, and a non-zero if it
* is.
*/
int
wstring_list_member(wstring_list_ty *wlp, wstring_ty *w)
{
size_t j;
for (j = 0; j < wlp->nitems; j++)
if (wstr_equal(wlp->item[j], w))
return 1;
return 0;
}
/*
* NAME
* wstring_list_copy - copy a wide string list
*
* SYNOPSIS
* void wstring_list_copy(wstring_list_ty *to, wstring_list_ty *from);
*
* DESCRIPTION
* The wstring_listl_copy function is used to copy wide string lists.
*
* RETURNS
* A copy of the 'to' wide string list is placed in 'from'.
*
* CAVEAT
* It is the responsibility of the caller to ensure that the new
* wide string list is freed when finished with, by a call to
* wstring_list_free().
*/
void
wstring_list_copy(wstring_list_ty *to, wstring_list_ty *from)
{
size_t j;
wstring_list_zero(to);
for (j = 0; j < from->nitems; j++)
wstring_list_append(to, wstr_copy(from->item[j]));
}
/*
* NAME
* wstring_list_to_wstring - form a string from a wide string list
*
* SYNOPSIS
* wstring_ty *wstring_list_to_wstring(wstring_list_ty *wlp, int start, int stop, char *sep);
*
* DESCRIPTION
* The wstring_list_to_wstring function is used to form a string
* from a wide string 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().
*/
wstring_ty *
wstring_list_to_wstring(wstring_list_ty *wl, int start, int stop, char *sep)
{
int j, k;
static wchar_t *tmp;
static size_t tmplen;
size_t length;
size_t seplen;
wchar_t *pos;
wstring_ty *s;
if (!sep)
sep = " ";
seplen = strlen(sep);
length = 0;
for (j = start; j <= stop && j < wl->nitems; ++j)
{
s = wl->item[j];
if (s->wstr_length)
{
if (length)
length += seplen;
length += s->wstr_length;
}
}
if (tmplen < length)
{
tmplen = length;
tmp = mem_change_size(tmp, tmplen * sizeof(wchar_t));
}
pos = tmp;
for (j = start; j <= stop && j < wl->nitems; j++)
{
s = wl->item[j];
if (s->wstr_length)
{
if (pos != tmp)
{
for (k = 0; k < seplen; ++k)
*pos++ = sep[k];
}
memcpy
(
pos,
s->wstr_text,
s->wstr_length * sizeof(wchar_t)
);
pos += s->wstr_length;
}
}
s = wstr_n_from_wc(tmp, length);
return s;
}
static int
wc_find(char *s, wchar_t c)
{
while (*s)
{
if (*s == c)
return 1;
++s;
}
return 0;
}
/*
* NAME
* wstring_to_wstring_list - string to wide string list
*
* SYNOPSIS
* void wstring_to_wstring_list(wstring_list_ty *wlp, wstring_ty *s, char *sep, int ewhite);
*
* DESCRIPTION
* The wstring_to_wstring_list function is used to form a wide string
* list from a string.
*
* ARGUMENTS
* wlp - where to put the wide string 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 wstring_list_append().
*
* CAVEAT
* Quoting is not understood.
*/
void
wstring_to_wstring_list(wstring_list_ty *slp, wstring_ty *s, char *sep,
int ewhite)
{
static char white[] = " \t\n\f\r";
wchar_t *cp;
int more;
if (!sep)
{
sep = white;
ewhite = 1;
}
wstring_list_zero(slp);
cp = s->wstr_text;
more = 0;
while (*cp || more)
{
wstring_ty *w;
wchar_t *cp1;
wchar_t *cp2;
if (ewhite)
while (wc_find(white, *cp))
cp++;
if (!*cp && !more)
break;
more = 0;
cp1 = cp;
while (*cp && !wc_find(sep, *cp))
cp++;
if (*cp)
{
cp2 = cp + 1;
more = 1;
}
else
cp2 = cp;
if (ewhite)
while (cp > cp1 && wc_find(white, cp[-1]))
cp--;
w = wstr_n_from_wc(cp1, cp - cp1);
wstring_list_append(slp, w);
wstr_free(w);
cp = cp2;
}
}
/*
* NAME
* wstring_list_insert - a insert a wide string into a list
*
* SYNOPSIS
* void wstring_list_insert(wstring_list_ty *wlp, wstring_ty *wp);
*
* DESCRIPTION
* The wstring_list_insert function is similar to the
* wstring_list_append function, however it does not append the
* wide string unless it is not already in the list.
*
* CAVEAT
* If the wide string is inserted it is copied.
*/
void
wstring_list_append_unique(wstring_list_ty *wlp, wstring_ty *wp)
{
size_t j;
for (j = 0; j < wlp->nitems; j++)
if (wstr_equal(wlp->item[j], wp))
return;
wstring_list_append(wlp, wp);
}
/*
* NAME
* wstring_list_delete - remove list member
*
* SYNOPSIS
* void wstring_list_delete(wstring_list_ty *wlp, wstring_ty *wp);
*
* DESCRIPTION
* The wstring_list_delete function is used to delete a member of a
* wide string list.
*
* RETURNS
* void
*/
void
wstring_list_delete(wstring_list_ty *wlp, wstring_ty *wp)
{
size_t j;
size_t k;
for (j = 0; j < wlp->nitems; ++j)
{
if (wstr_equal(wlp->item[j], wp))
{
wlp->nitems--;
for (k = j; k < wlp->nitems; ++k)
wlp->item[k] = wlp->item[k + 1];
wstr_free(wp);
break;
}
}
}
void
wstring_list_zero(wstring_list_ty *wlp)
{
wlp->nitems = 0;
wlp->nitems_max = 0;
wlp->item = 0;
}
int
wstring_list_equal(wstring_list_ty *a, wstring_list_ty *b)
{
size_t j, k;
for (j = 0; j < a->nitems; ++j)
{
for (k = 0; k < b->nitems; ++k)
if (wstr_equal(a->item[j], b->item[k]))
break;
if (k >= b->nitems)
return 0;
}
for (j = 0; j < b->nitems; ++j)
{
for (k = 0; k < a->nitems; ++k)
if (wstr_equal(b->item[j], a->item[k]))
break;
if (k >= a->nitems)
return 0;
}
return 1;
}
int
wstring_list_subset(wstring_list_ty *a, wstring_list_ty *b)
{
size_t j, k;
/*
* test if "a is a subset of b"
*/
if (a->nitems > b->nitems)
return 0;
for (j = 0; j < a->nitems; ++j)
{
for (k = 0; k < b->nitems; ++k)
if (wstr_equal(a->item[j], b->item[k]))
break;
if (k >= b->nitems)
return 0;
}
return 1;
}
syntax highlighted by Code2HTML, v. 0.9.1