/* strlist.c - simple string list package
**
** Copyright © 2000 by Jef Poskanzer <jef@mail.acme.com>.
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
** 1. Redistributions of source code must retain the above copyright
**    notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
**    notice, this list of conditions and the following disclaimer in the
**    documentation and/or other materials provided with the distribution.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
** SUCH DAMAGE.
*/

#include <stdlib.h>
#include <string.h>

#include "strlist.h"

struct _strlist {
    int num, max;
    char** str;
    int* str_size;
    };

typedef struct _strlist* real_strlist;


strlist
strlist_new( void )
    {
    real_strlist rs;

    rs = (real_strlist) malloc( sizeof(struct _strlist) );
    if ( rs != (real_strlist) 0 )
        {
	rs->num = 0;
	rs->max = 0;
        }
    rs->str = (char**) 0;
    return rs;
    }


void
strlist_clear( strlist s )
    {
    real_strlist rs = (real_strlist) s;

    rs->num = 0;
    }


void
strlist_delete( strlist s )
    {
    real_strlist rs = (real_strlist) s;
    int i;

    strlist_clear( rs );
    if ( rs->max > 0 )
	{
	for ( i = 0; i < rs->num; ++i )
	    free( (void*) rs->str[i] );
	free( (void*) rs->str );
	free( (void*) rs->str_size );
	}
    free( (void*) rs );
    }


int
strlist_add( strlist s, const char* str )
    {
    real_strlist rs = (real_strlist) s;
    int len;

    if ( rs->num >= rs->max )
	{
	int new_max, i;
	if ( rs->max == 0 )
	    {
	    new_max = 20;
	    rs->str = (char**) malloc( new_max * sizeof(char*) );
	    rs->str_size = (int*) malloc( new_max * sizeof(int) );
	    }
	else
	    {
	    new_max = rs->max * 2;
	    rs->str = (char**) realloc(
		(void*) rs->str, new_max * sizeof(char*) );
	    rs->str_size = (int*) realloc(
		(void*) rs->str_size, new_max * sizeof(int) );
	    }
	if ( rs->str == (char**) 0 || rs->str_size == (int*) 0 )
	    return 0;
	for ( i = rs->max; i < new_max; ++i )
	    {
	    rs->str[i] = (char*) 0;
	    rs->str_size[i] = 0;
	    }
	rs->max = new_max;
	}
    len = strlen( str );
    if ( len + 1 >= rs->str_size[rs->num] )
	{
	rs->str_size[rs->num] = ( len + 1 ) * 2;
	if ( rs->str[rs->num] == (char*) 0 )
	    rs->str[rs->num] = (char*) malloc( rs->str_size[rs->num] );
	else
	    rs->str[rs->num] = (char*) realloc(
		(void*) rs->str[rs->num], rs->str_size[rs->num] );
	if ( rs->str[rs->num] == (char*) 0 )
	    return 0;
	}
    (void) strcpy( rs->str[rs->num], str );
    ++rs->num;
    return 1;
    }


const char*
strlist_get( strlist s, int i )
    {
    real_strlist rs = (real_strlist) s;

    if ( i < 0 || i >= rs->num )
	return (const char*) 0;
    return rs->str[i];
    }


int
strlist_includes( strlist s, const char* str )
    {
    real_strlist rs = (real_strlist) s;
    int i;

    for ( i = 0; i < rs->num; ++i )
	if ( strcmp( str, rs->str[i] ) == 0 )
	    return 1;
    return 0;
    }


int
strlist_size( strlist s )
    {
    real_strlist rs = (real_strlist) s;

    return rs->num;
    }
