//
// aegis - project change supervisor
// Copyright (C) 1995, 2002-2006, 2008 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
// .
//
#include
#include
#include
#include
wstring_list_ty::~wstring_list_ty()
{
clear();
delete [] item;
nitems_max = 0;
item = 0;
}
wstring_list_ty::wstring_list_ty() :
nitems(0),
nitems_max(0),
item(0)
{
}
wstring_list_ty::wstring_list_ty(const wstring_list_ty &arg) :
nitems(0),
nitems_max(0),
item(0)
{
for (size_t j = 0; j < arg.nitems; j++)
push_back(arg);
}
wstring_list_ty &
wstring_list_ty::operator=(const wstring_list_ty &arg)
{
if (this != &arg)
{
clear();
push_back(arg);
}
return *this;
}
void
wstring_list_ty::clear()
{
while (!empty())
pop_back();
}
void
wstring_list_ty::push_back(wstring_ty *w)
{
if (nitems >= nitems_max)
{
//
// always 8 less than a power of 2, which is
// most efficient for many memory allocators
//
size_t new_nitems_max = nitems_max * 2 + 8;
wstring_ty **new_item = new wstring_ty * [new_nitems_max];
if (nitems)
memcpy(new_item, item, nitems * sizeof(item[0]));
delete [] item;
item = new_item;
nitems_max = new_nitems_max;
}
item[nitems++] = wstr_copy(w);
}
void
wstring_list_ty::push_back(const wstring_list_ty &arg)
{
if (nitems + arg.nitems > nitems_max)
{
//
// always 8 less than a power of 2, which is
// most efficient for many memory allocators
//
size_t new_nitems_max = nitems_max * 2 + 8;
while (nitems + arg.nitems > new_nitems_max)
new_nitems_max = new_nitems_max * 2 + 8;
wstring_ty **new_item = new wstring_ty * [new_nitems_max];
if (nitems)
memcpy(new_item, item, nitems * sizeof(item[0]));
delete [] item;
item = new_item;
nitems_max = new_nitems_max;
}
//
// Copy the elements across.
//
for (size_t j = 0; j < arg.nitems; ++j)
item[nitems++] = wstr_copy(arg.item[j]);
}
void
wstring_list_ty::push_front(wstring_ty *w)
{
if (nitems >= nitems_max)
{
//
// always 8 less than a power of 2, which is
// most efficient for many memory allocators
//
size_t new_nitems_max = nitems_max * 2 + 8;
wstring_ty **new_item = new wstring_ty * [new_nitems_max];
if (nitems)
memcpy(new_item + 1, item, nitems * sizeof(item[0]));
item = new_item;
nitems_max = new_nitems_max;
}
else
{
for (size_t j = nitems; j > 0; --j)
item[j] = item[j - 1];
}
++nitems;
item[0] = wstr_copy(w);
}
bool
wstring_list_ty::member(wstring_ty *w)
const
{
for (size_t j = 0; j < nitems; j++)
if (wstr_equal(item[j], w))
return true;
return false;
}
wstring_ty *
wstring_list_ty::unsplit(const char *sep)
const
{
return unsplit(0, size(), sep);
}
wstring_ty *
wstring_list_ty::unsplit(size_t start, size_t stop, const char *sep)
const
{
static wchar_t *tmp;
static size_t tmplen;
if (!sep)
sep = " ";
size_t seplen = strlen(sep);
size_t length = 0;
for (size_t k = start; k <= stop && k < nitems; ++k)
{
wstring_ty *s = item[k];
if (s->wstr_length)
{
if (length)
length += seplen;
length += s->wstr_length;
}
}
if (tmplen < length)
{
delete tmp;
for (;;)
{
tmplen = tmplen * 2 + 8;
if (length <= tmplen)
break;
}
tmp = new wchar_t[tmplen];
}
wchar_t *pos = tmp;
for (size_t j = start; j <= stop && j < nitems; j++)
{
wstring_ty *s = item[j];
if (s->wstr_length)
{
if (pos != tmp)
{
// can't memcpy, because this is narrow to wide
for (size_t k = 0; k < seplen; ++k)
*pos++ = sep[k];
}
memcpy(pos, s->wstr_text, s->wstr_length * sizeof(wchar_t));
pos += s->wstr_length;
}
}
return wstr_n_from_wc(tmp, length);
}
static int
wc_find(const 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_list_ty::split(wstring_ty *s, const char *sep, bool ewhite)
{
static char white[] = " \t\n\f\r";
if (!sep)
{
sep = white;
ewhite = true;
}
clear();
const wchar_t *cp = s->wstr_text;
bool more = false;
while (*cp || more)
{
if (ewhite)
{
while (wc_find(white, *cp))
cp++;
}
if (!*cp && !more)
break;
more = false;
const wchar_t *cp1 = cp;
while (*cp && !wc_find(sep, *cp))
cp++;
const wchar_t *cp2 = cp;
if (*cp)
{
cp2 = cp + 1;
more = true;
}
if (ewhite)
{
while (cp > cp1 && wc_find(white, cp[-1]))
cp--;
}
wstring_ty *w = wstr_n_from_wc(cp1, cp - cp1);
push_back(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_ty::push_back_unique(wstring_ty *wp)
{
if (!member(wp))
push_back(wp);
}
void
wstring_list_ty::remove(wstring_ty *wp)
{
for (size_t j = 0; j < nitems; ++j)
{
if (wstr_equal(item[j], wp))
{
--nitems;
wstr_free(item[j]);
for (size_t k = j; k < nitems; ++k)
item[k] = item[k + 1];
break;
}
}
}
bool
wstring_list_ty::equal_to(const wstring_list_ty &rhs)
const
{
return is_a_subset_of(rhs) && rhs.is_a_subset_of(*this);
}
bool
wstring_list_ty::is_a_subset_of(const wstring_list_ty &rhs)
const
{
//
// test if "*this is a subset of rhs"
//
if (nitems > rhs.size())
return false;
for (size_t j = 0; j < nitems; ++j)
{
if (!rhs.member(item[j]))
return false;
}
return true;
}
void
wstring_list_ty::pop_back()
{
if (nitems > 0)
{
--nitems;
wstr_free(item[nitems]);
}
}