/* Copyright (C) 1995 NetWin World, New Zealand, All rights reserved. */
/* General purpose array of string routines */

/* #include <stdlib.h> */
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <assert.h>
#include "lib.h"
#include "sary.h"

#define false 0
#ifdef true
#undef true
#endif
#define true (!false)


#define ifstrfree(x) if ((x)!=NULL) mystrfree(x,SD_SARY); x = NULL; 
#undef mymalloc
#undef myfree
#define mymalloc(x) mymalloc2(x,M_SARY)
#define myfree(x) myfree2(x,M_SARY)

#define iffree(x) iffree2(x,M_SARY)


void s_free(Sary *bf)
{
        int i;
        for (i=0; i<bf->len; i++) {
                ifstrfree( (*bf->ary)[i] );
        }
        iffree(bf->ary);
        iffree(bf);
}
Sary *s_alloc(void)
{
        Sary *bf;

        bf = (Sary *) mymalloc(sizeof(*bf));
        if (bf==NULL) die("sary alloc");
        s_init(bf);
        return bf;      
}
void s_clear(Sary *bf)
{
        int i;
        for (i=0; i<bf->len; i++) {
                ifstrfree( (*bf->ary)[i] );
        }
        bf->len = 0;
}
void s_init(Sary *bf)
{
        bf->ary = NULL;
        bf->len = 0;
        bf->total = 0;
}
void s_grow(Sary *bf, int sz)
{
        char *(*new)[];
        int i;
                
        new = (char *(*)[]) mymalloc(sz*sizeof(char *));
        if (new==NULL) die("sary alloc grow");
        for (i=0; i<bf->len; i++) {
                (*new)[i] = (*bf->ary)[i];
        }
        iffree(bf->ary);
        bf->ary = new;
        bf->total = sz;
}
void s_check(Sary *bf)
{
        if (bf->len+5 > bf->total) {
                s_grow(bf,(bf->total+5)*2);
        }
}
int  s_add(Sary *bf, char *s)
{
        s_check(bf);
        (*bf->ary)[bf->len++] = (char *) mystrdup(s,SD_SARY);
        return bf->len-1;
}

void s_set(Sary *bf, int n, char *s)
{
	int i;
        if (bf==NULL) dmsg("Array struct is null\n");
        if (n >= bf->total) {
                s_grow(bf,n*2+50);
	} 
	if (n >= bf->len) {
 		for (i=bf->len; i<=n; i++) {
		 	(*bf->ary)[i] = NULL;
		}
		bf->len = n+1;
        }
        if (n<0 || n>= bf->len) die("array subscript in set");

	ifstrfree((*bf->ary)[n]);
/*        if ((*bf->ary)[n]!=NULL) mystrfree();*/
        (*bf->ary)[n] = (char *) mystrdup(s,SD_SARY);
}
char *s_line(Sary *bf, int n)
{
        return (*bf->ary)[n];
}
int s_len(Sary *bf)
{
        return bf->len;
}
void s_print(Sary *bf)
{
        int i;
        for (i=0; i<s_len(bf); i++) {
                dmsg("[%d] {%s} \n",i,s_line(bf,i));
        }
}
void s_write(Sary *bf, char *file)
{
        FILE *f;
        int i;

        f = fopen(file,"w");
        if (f==NULL) { emsg("Unable to open {%s} ",file); return;}

        for (i=0; i<s_len(bf); i++) {
                fprintf(f,"%s\n",s_line(bf,i));
        }
        fclose(f);
}
void s_read(Sary *bf, char *file)
{
        FILE *f;
        char inbuff[201];
        int i;

        f = fopen(file,"r");
        if (f==NULL) { emsg("Unable to open {%s} ",file); return;}

        s_clear(bf);
	s_grow(bf,300);
        for (;!feof(f);) {
          if (fgets(inbuff,200,f)!=NULL) {
                i = strlen(inbuff);
                if (i>0) if (inbuff[i-1]=='\n') inbuff[i-1] = 0;
                s_add(bf,inbuff);                      
          }
        }
        fclose(f);
}
void s_read_sz(Sary *bf, char *file, int sz)
{
        FILE *f;
        char inbuff[20000];
        int i;
	if (sz>10000) sz = 10000;
        f = fopen(file,"r");
        if (f==NULL) { emsg("Unable to open {%s} ",file); return;}

        s_clear(bf);
	s_grow(bf,300);
        for (;!feof(f);) {
          if (fgets(inbuff,sz-1,f)!=NULL) {
                i = strlen(inbuff);
                if (i>0) if (inbuff[i-1]=='\n') inbuff[i-1] = 0;
                s_add(bf,inbuff);                      
          }
        }
        fclose(f);
}
void s_readtrim(Sary *bf, char *file)
{
        FILE *f;
        char inbuff[8001];
	char *s;
        int i;

        f = fopen(file,"r");
        if (f==NULL) { emsg("Unable to open {%s} ",file); return;}

        s_clear(bf);
	s_grow(bf,300);
        for (;!feof(f);) {
          if (fgets(inbuff,8000,f)!=NULL) {
                i = strlen(inbuff);
                if (i>0) if (inbuff[i-1]=='\n') inbuff[i-1] = 0;
		s = strchr(inbuff,'\r');
		if (s!=NULL) *s = 0;
		s = strchr(inbuff,'\n');
		if (s!=NULL) *s = 0;
                s_add(bf,inbuff);                      
          }
        }
        fclose(f);
}
void s_read_max(Sary *bf, char *file, int max)
{
        FILE *f;
        char inbuff[201];
        int i;

        f = fopen(file,"r");
        if (f==NULL) { emsg("Unable to open {%s} ",file); return;}

        s_clear(bf);
	s_grow(bf,300);
        for (;!feof(f);) {
          if (fgets(inbuff,200,f)!=NULL) {
                i = strlen(inbuff);
                if (i>0) if (inbuff[i-1]=='\n') inbuff[i-1] = 0;
                s_add(bf,inbuff);                      
          }
	  max--;
	  if (max<=0) {
	   	emsg("Truncating active.names, it's too long\n");
		break;
	  }
        }
        fclose(f);
}
void s_read_secure(Sary *bf, char *file)
{
        FILE *f;
        char inbuff[501];
        int i;

        f = fopen(file,"r");
        if (f==NULL) { return;}

        s_clear(bf);
        for (;!feof(f);) {
          if (fgets(inbuff,500,f)!=NULL) {
                i = strlen(inbuff);
                if (inbuff[i-1]=='\n') inbuff[i-1] = 0;
                s_add(bf,inbuff);                       
          }
        }
        fclose(f);
}
void s_read_long(Sary *bf, char *file)
{
        FILE *f;
        char inbuff[10000];
	char *s;
        int i;

        f = fopen(file,"r");
        if (f==NULL) { emsg("Unable to open {%s} ",file); return;}

        s_clear(bf);
	s_grow(bf,300);
        for (;!feof(f);) {
          if (fgets(inbuff,10000-1,f)!=NULL) {
                i = strlen(inbuff);
                if (i>0) if (inbuff[i-1]=='\n') inbuff[i-1] = 0;
		s = strchr(inbuff,'\r'); if (s!=NULL) *s = 0;
                s_add(bf,inbuff);                      
          }
        }
        fclose(f);
}
