#include <spraak/def.h>
#include <spraak/core/spr_oo.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
spr_public_hi_doc
spr_cmdoc spr_public_lo_type
typedef struct
{SprObject interface_;
unsigned int ref_cnt;
} Item;
spr_public_hi_class
SPR_CLASS(Item : SprObject
{spr_public lock() := item_lock;
spr_public unlock() := item_unlock;
spr_public cmp[]() = item_cmp;
spr_public hash[]() = item_hash;
spr_public read[]() = item_read;
spr_public write[]() = item_write;
spr_public clone[]() = item_clone;
spr_public dtor[]() = item_dtor;
} )
#define SPR_CLASS_IMPORT_Item
#include <spraak_classdef/taipan_cpp.class.h>
spr_public_lo_ifunc
void item_lock(
Item *item)
{++item->ref_cnt;
}
spr_public_lo_ifunc
void item_unlock(
Item *item)
{if(--item->ref_cnt == 0)
}
spr_cmdoc spr_public_lo_afunc
int item_cmp(
const Item *item1,
const Item *item2)
;
spr_cmdoc spr_public_lo_afunc
uintptr_t item_hash(
const Item *item)
;
spr_cmdoc spr_public_lo_afunc
int item_read(
Item *item,
FILE *fd)
;
spr_cmdoc spr_public_lo_afunc
int item_write(
const Item *item,
FILE *fd)
;
spr_cmdoc spr_public_lo_afunc
Item *item_clone(
const Item *item)
;
spr_cmdoc spr_public_lo_afunc
void *item_dtor(
Item *item)
{free(item);
return(NULL);
}
#define SPR_CLASS_DEFINE_Item
#include <spraak_classdef/taipan_cpp.class.h>
spr_cmdoc spr_public_lo_type
typedef struct
{Item item;
long value;
} IntItem;
spr_public_hi_class
SPR_CLASS(IntItem : Item
{spr_public static ctor() = int_item_ctor;
spr_public cmp[]() := int_item_cmp;
spr_public hash[]() := int_item_hash;
spr_public read[]() := int_item_read;
spr_public write[]() := int_item_write;
spr_public clone[]() := int_item_clone;
} )
#define SPR_CLASS_IMPORT_IntItem
#include <spraak_classdef/taipan_cpp.class.h>
spr_cmdoc spr_public_lo_ifunc
IntItem *int_item_ctor(long value)
{IntItem *item;
if((item=malloc(sizeof(IntItem))) != NULL)
item->item.ref_cnt = 1;
item->value = value;
}
return(item);
}
spr_cmdoc spr_public_lo_afunc
int int_item_cmp(
const IntItem *item1,
const IntItem *item2)
{return((item1->value>item2->value)-(item1->value<item2->value));
}
spr_cmdoc spr_public_lo_afunc
uintptr_t int_item_hash(
const IntItem *item)
{return(item->value);
}
spr_cmdoc spr_public_lo_afunc
int int_item_read(
IntItem *item,
FILE *fd)
{return(fscanf(fd,"%li",&item->value));
}
spr_cmdoc spr_public_lo_afunc
int int_item_write(
const IntItem *item,
FILE *fd)
{return(fprintf(fd,"%li ",item->value));
}
spr_cmdoc spr_public_lo_afunc
IntItem *int_item_clone(
const IntItem *item)
{return(int_item_ctor(item->value));
}
#define SPR_CLASS_DEFINE_IntItem
#include <spraak_classdef/taipan_cpp.class.h>
spr_cmdoc spr_public_lo_type
typedef struct
{Item item;
double value;
} FltItem;
spr_public_hi_class
SPR_CLASS(FltItem : Item
{spr_public static ctor() = flt_item_ctor;
spr_public cmp[]() = flt_item_cmp;
spr_public hash[]() = flt_item_hash;
spr_public read[]() = flt_item_read;
spr_public write[]() = flt_item_write;
spr_public clone[]() = flt_item_clone;
} )
#define SPR_CLASS_IMPORT_FltItem
#include <spraak_classdef/taipan_cpp.class.h>
spr_cmdoc spr_public_lo_afunc
FltItem *flt_item_ctor(double value)
{FltItem *item;
if((item=malloc(sizeof(FltItem))) != NULL)
item->item.ref_cnt = 1;
item->value = value;
}
return(item);
}
spr_cmdoc spr_public_lo_afunc
int flt_item_cmp(
const FltItem *item1,
const FltItem *item2)
{return((item1->value>item2->value)-(item1->value<item2->value));
}
spr_cmdoc spr_public_lo_afunc
uintptr_t flt_item_hash(
const FltItem *item)
{uintptr_t hv = ((uintptr_t*)(void*)&item->value)[0];
if(sizeof(double) >= 2*sizeof(uintptr_t))
hv ^= ((uintptr_t*)&item->value)[1];
if(sizeof(double) >= 3*sizeof(uintptr_t))
hv ^= ((uintptr_t*)&item->value)[2];
if(sizeof(double) >= 4*sizeof(uintptr_t))
hv ^= ((uintptr_t*)&item->value)[3];
return(hv);
}
spr_cmdoc spr_public_lo_afunc
int flt_item_read(
FltItem *item,
FILE *fd)
{return(fscanf(fd,"%lf",&item->value));
}
spr_cmdoc spr_public_lo_afunc
int flt_item_write(
const FltItem *item,
FILE *fd)
{return(fprintf(fd,"%.15g ",item->value));
}
spr_cmdoc spr_public_lo_afunc
FltItem *flt_item_clone(
const FltItem *item)
{return(flt_item_ctor(item->value));
}
#define SPR_CLASS_DEFINE_FltItem
#include <spraak_classdef/taipan_cpp.class.h>
spr_cmdoc spr_public_lo_type
typedef struct
{Item item;
char *value;
} StrItem;
spr_public_hi_class
SPR_CLASS(StrItem : Item
{spr_public static ctor() = str_item_ctor;
spr_public cmp[]() = str_item_cmp;
spr_public hash[]() = str_item_hash;
spr_public read[]() = str_item_read;
spr_public write[]() = str_item_write;
spr_public clone[]() = str_item_clone;
spr_public dtor[]() = str_item_dtor;
} )
#define SPR_CLASS_IMPORT_StrItem
#include <spraak_classdef/taipan_cpp.class.h>
spr_cmdoc spr_public_lo_afunc
StrItem *str_item_ctor(const char *value)
{StrItem *item;
if((item=malloc(sizeof(StrItem))) != NULL)
{char *buf;
item->item.ref_cnt = 1;
if(value == NULL)
item->value = NULL;
else
{if((item->value=buf=malloc(strlen(value)+1)) == NULL)
goto ERROR_;
strcpy(buf,value);
}
}
return(item);
ERROR_:
free(item);
return(item);
}
spr_cmdoc spr_public_lo_afunc
int str_item_cmp(
const StrItem *item1,
const StrItem *item2)
{if(item1->value != NULL)
{if(item2->value != NULL)
return(strcmp(item1->value,item2->value));
else
return(0);
}
else
return(item2->value!=NULL);
}
spr_cmdoc spr_public_lo_afunc
uintptr_t str_item_hash(
const StrItem *item)
{uintptr_t hv = 1u;
const char *ptr;
if((ptr=item->value) != NULL)
{unsigned int chr;
do
{hv = hv*8191u + (chr=*ptr++);
} while(chr);
}
return(hv);
}
spr_cmdoc spr_public_lo_afunc
int str_item_read(
StrItem *item,
FILE *fd)
{char buf[1024];
int rv;
if((rv=fscanf(fd,"%1023s",buf)) == 1)
{char *ptr;
if((ptr=realloc(item->value,strlen(buf)+1)) == NULL)
goto ERROR_;
strcpy(ptr,buf);
item->value = ptr;
}
return(rv);
ERROR_:
return(-1);
}
spr_cmdoc spr_public_lo_afunc
int str_item_write(
const StrItem *item,
FILE *fd)
{return(fprintf(fd,"%s ",item->value));
}
spr_cmdoc spr_public_lo_afunc
StrItem *str_item_clone(
const StrItem *item)
{return(str_item_ctor(item->value));
}
spr_cmdoc spr_public_lo_afunc
void *str_item_dtor(
StrItem *item)
{free(item->value);
free(item);
return(NULL);
}
#define SPR_CLASS_DEFINE_StrItem
#include <spraak_classdef/taipan_cpp.class.h>
spr_cmdoc spr_public_lo_type
typedef struct
{Item item;
unsigned int N;
Item *el[];
} Tuple;
spr_public_hi_class
SPR_CLASS(Tuple : Item
{spr_public static ctor() = tuple_ctor;
spr_public static ctor_add() = tuple_ctor_add;
spr_public cmp[]() = tuple_cmp;
spr_public hash[]() = tuple_hash;
spr_public read[]() = tuple_read;
spr_public write[]() = tuple_write;
spr_public clone[]() = tuple_clone;
spr_public dtor[]() = tuple_dtor;
} )
#define SPR_CLASS_IMPORT_Tuple
#include <spraak_classdef/taipan_cpp.class.h>
spr_cmdoc spr_public_lo_afunc
Tuple *tuple_ctor(Item *item,...)
{va_list argptr;
Tuple *tuple;
va_start(argptr,item);
{int N;
if((N=(item!=NULL)))
while(va_arg(argptr,Item*) != NULL)
N++;
va_end(argptr);
if((tuple=malloc(offsetof(Tuple,el)+sizeof(Item*)*N)) == NULL)
goto ERROR_;
}
tuple->item.ref_cnt = 1;
va_start(argptr,item);
{int ndx = 0;
for( ;item!=NULL;item=va_arg(argptr,Item*))
{tuple->el[ndx] = item;
ndx++;
}
tuple->N = ndx;
va_end(argptr);
}
return(tuple);
ERROR_:
return(NULL);
}
spr_cmdoc spr_public_lo_afunc
Tuple *tuple_ctor_add(Tuple *tuple,Item *item)
{Tuple *new_tuple;
int ndx;
if((new_tuple=malloc(offsetof(Tuple,el)+sizeof(Item*)*((ndx=tuple->N)+1))) == NULL)
goto ERROR_;
new_tuple->item.ref_cnt = 1;
new_tuple->N = ndx+1;
for( ;; )
{new_tuple->el[ndx] = item;
if(--ndx < 0)
break;
item = tuple->el[ndx];
}
ERROR_:
return(new_tuple);
}
spr_cmdoc spr_public_lo_afunc
int tuple_cmp(
const Tuple *tuple1,
const Tuple *tuple2)
{unsigned int ndx,N;
if((N=tuple1->N) > tuple2->N)
N = tuple2->N;
for(ndx=0;ndx<N;ndx++)
{
int rv =
SPR_DO(Item,cmp,tuple1->el[ndx],tuple2->el[ndx]);
if(rv)
return(rv);
}
return(tuple1->N-tuple2->N);
}
spr_cmdoc spr_public_lo_afunc
uintptr_t tuple_hash(
const Tuple *tuple)
{int ndx = tuple->N;
const Item *const *el = tuple->el-1;
uintptr_t hv = 0;
while(--ndx >= 0)
{++el;
hv = hv*31 +
SPR_DO(Item,hash,*el);
}
return(hv);
}
spr_cmdoc spr_public_lo_afunc
int tuple_read(
Tuple *tuple,
FILE *fd)
{int ndx = tuple->N;
Item **el = tuple->el-1;
while(--ndx >= 0)
{++el;
if(
SPR_DO(Item,read,*el,fd) != 1)
return(ndx-tuple->N);
}
return(1);
}
spr_cmdoc spr_public_lo_afunc
int tuple_write(
const Tuple *tuple,
FILE *fd)
{int ndx = tuple->N;
const Item *const *el = tuple->el-1;
while(--ndx >= 0)
{++el;
if(
SPR_DO(Item,write,*el,fd) <= 0)
return(-1);
}
return(1);
}
spr_cmdoc spr_public_lo_afunc
void *tuple_dtor(
Tuple *tuple)
{int ndx = tuple->N;
Item **el = tuple->el-1;
while(--ndx >= 0)
{++el;
}
free(tuple);
return(NULL);
}
spr_cmdoc spr_public_lo_afunc
Tuple *tuple_clone(
const Tuple *tuple)
{int N = tuple->N;
Tuple *new_tuple;
if((new_tuple=malloc(offsetof(Tuple,el)+sizeof(Item*)*N)) != NULL)
{int ndx;
new_tuple->item.ref_cnt = 1;
new_tuple->N = N;
for(ndx=0;ndx<N;ndx++)
{const Item *el = tuple->el[ndx];
if((new_tuple->el[ndx]=
SPR_DO(Item,clone,el)) == NULL)
{new_tuple->N = ndx;
return(tuple_dtor(new_tuple));
}
}
}
return(new_tuple);
}
#define SPR_CLASS_DEFINE_Tuple
#include <spraak_classdef/taipan_cpp.class.h>
spr_cmdoc spr_public_lo_type
typedef struct
{SprObject interface_;
} Iterable;
spr_cmdoc spr_public_lo_type
typedef struct
{Iterable iterable;
} Iterator;
spr_public_hi_class
SPR_CLASSr(Iterable : SprObject
{spr_public iterator[]() = iterable_iterator;
} )
#define SPR_CLASS_IMPORT_Iterable
#include <spraak_classdef/taipan_cpp.class.h>
spr_cmdoc spr_public_lo_afunc
Iterator *iterable_iterator(
const Iterable *obj)
;
#define SPR_CLASS_DEFINE_Iterable
#include <spraak_classdef/taipan_cpp.class.h>
spr_public_hi_class
SPR_CLASS(Iterator : Iterable
{spr_public item[]() = iterator_item;
spr_public next[]() = iterator_next;
spr_public iterator[]() = iterator_iterator;
} )
#define SPR_CLASS_IMPORT_Iterator
#include <spraak_classdef/taipan_cpp.class.h>
spr_cmdoc spr_public_lo_afunc
Item *iterator_item(
Iterator *iter)
;
spr_cmdoc spr_public_lo_afunc
Iterator *iterator_next(
Iterator *iter)
;
spr_cmdoc spr_public_lo_afunc
Iterator *iterator_iterator(
const Iterator *iter)
;
#define SPR_CLASS_DEFINE_Iterator
#include <spraak_classdef/taipan_cpp.class.h>
spr_cmdoc spr_public_lo_type
typedef struct
{SprObject interface_;
} Queue;
spr_public_hi_class
SPR_CLASSr(Queue : SprObject
{spr_public push[]() = queue_push;
spr_public pop[]() = queue_pop;
spr_public toq[]() = queue_toq;
spr_public empty[]() = queue_empty;
} )
#define SPR_CLASS_IMPORT_Queue
#include <spraak_classdef/taipan_cpp.class.h>
spr_cmdoc spr_public_lo_afunc
Item *queue_push(
Queue *queue,
Item *item)
;
spr_cmdoc spr_public_lo_afunc
Item *queue_pop(
Queue *queue)
;
spr_cmdoc spr_public_lo_afunc
Item *queue_toq(
Queue *queue)
;
spr_cmdoc spr_public_lo_afunc
int queue_empty(
Queue *queue)
;
#define SPR_CLASS_DEFINE_Queue
#include <spraak_classdef/taipan_cpp.class.h>
spr_cmdoc spr_public_lo_type
typedef struct
{Iterable iterable;
} Container;
spr_public_hi_class
SPR_CLASS(Container : Iterable
{spr_public get[]() = container_get;
spr_public add[]() = container_add;
spr_public cadd[]() = container_cadd;
spr_public remove[]() = container_remove;
} )
#define SPR_CLASS_IMPORT_Container
#include <spraak_classdef/taipan_cpp.class.h>
spr_cmdoc spr_public_lo_afunc
Item *container_get(
const Container *container,
const Item *ndx)
;
spr_cmdoc spr_public_lo_afunc
Item *container_add(
Container *container,
Item *ndx,
Item *el)
;
spr_cmdoc spr_public_lo_afunc
Item *container_cadd(
Container *container,
Item *ndx,
Item *el)
;
spr_cmdoc spr_public_lo_afunc
Item *container_remove(
Container *container,
const Item *ndx)
;
#define SPR_CLASS_DEFINE_Container
#include <spraak_classdef/taipan_cpp.class.h>
spr_nodoc spr_public_lo_type
typedef struct t_stack_el
{Item *item;
struct t_stack_el *next;
} StackEl;
spr_cmdoc spr_public_lo_type
typedef struct
{spr_private Iterator iterator;
spr_private StackEl *stackel;
} StackIterator;
spr_public_hi_class
SPR_CLASS(StackIterator : Iterator
{
spr_public item[]() := stack_iterator_item;
spr_public next[]() := stack_iterator_next;
spr_public iterator[]() := stack_iterator_iterator;
} )
#define SPR_CLASS_IMPORT_StackIterator
#include <spraak_classdef/taipan_cpp.class.h>
spr_cmdoc spr_public_lo_afunc
Item *stack_iterator_item(
StackIterator *iter)
{return(iter->stackel->item);
}
spr_cmdoc spr_public_lo_afunc
StackIterator *stack_iterator_next(
StackIterator *iter)
{StackEl *stackel = iter->stackel->next;
if(stackel != NULL)
{iter->stackel = stackel;
return(iter);
}
else
{free(iter);
return(NULL);
}
}
spr_cmdoc spr_public_lo_afunc
StackIterator *stack_iterator_iterator(
const StackIterator *iter)
{if(iter != NULL)
{StackIterator *new_iter;
if((new_iter=malloc(sizeof(StackIterator))) != NULL)
*new_iter = *iter;
return(new_iter);
}
return((StackIterator*)iter);
}
#define SPR_CLASS_DEFINE_StackIterator
#include <spraak_classdef/taipan_cpp.class.h>
spr_cmdoc spr_public_lo_type
typedef struct
{Queue queue;
Iterable iterable;
StackEl *tos;
} Stack;
spr_public_hi_class
SPR_CLASS(Stack : Queue, Iterable
{
spr_public push[]() := stack_push;
spr_public pop[]() := stack_pop;
spr_public toq[]() := stack_tos;
spr_public empty[]() := stack_empty;
spr_public iterator[]() = stack_iterator;
spr_public dtor() = stack_dtor;
spr_public static ctor() = stack_ctor;
} )
#define SPR_CLASS_IMPORT_Stack
#include <spraak_classdef/taipan_cpp.class.h>
spr_cmdoc spr_public_lo_afunc
void *stack_dtor(
Stack *stack)
{StackEl *stackel;
for(stackel=stack->tos;stackel!=NULL; )
{StackEl *tmp = stackel;
stackel = stackel->next;
SPR_DO(Item,unlock,tmp->item);
free(tmp);
}
free(stack);
return(NULL);
}
spr_cmdoc spr_public_lo_afunc
Stack *stack_ctor(void)
{Stack *stack;
if((stack=malloc(sizeof(Stack))) != NULL)
stack->tos = NULL;
}
return(stack);
}
spr_cmdoc spr_public_lo_afunc
Item *stack_push(
Stack *stack,
Item *item)
{StackEl *stackel;
if((stackel=malloc(sizeof(StackEl))) == NULL)
goto ERROR_;
stackel->next = stack->tos;
stackel->item = item;
stack->tos = stackel;
return(item);
ERROR_:
return(NULL);
}
spr_cmdoc spr_public_lo_afunc
Item *stack_pop(
Stack *stack)
{StackEl *stackel = stack->tos;
Item *item;
if(stackel == NULL)
goto ERROR_;
stack->tos = stackel->next;
item = stackel->item;
free(stackel);
return(item);
ERROR_:
return(NULL);
}
spr_cmdoc spr_public_lo_afunc
Item *stack_tos(
Stack *stack)
{return((stack->tos!=NULL)?stack->tos->item:NULL);
}
spr_cmdoc spr_public_lo_afunc
int stack_empty(
Stack *stack)
{return(stack->tos==NULL);
}
spr_cmdoc spr_public_lo_afunc
StackIterator *stack_iterator(
const Stack *stack)
{StackIterator *iter;
if((iter=malloc(sizeof(StackIterator))) != NULL)
iter->stackel = stack->tos;
}
return(iter);
}
#define SPR_CLASS_DEFINE_Stack
#include <spraak_classdef/taipan_cpp.class.h>
spr_cmdoc spr_public_lo_type
typedef struct
{Queue queue;
Item **heap;
unsigned int size;
unsigned int fill;
} HeapMin;
spr_public_hi_class
SPR_CLASS(HeapMin : Queue
{
spr_public push[]() = heap_min_push;
spr_public pop[]() = heap_min_pop;
spr_public toq[]() = heap_min_toq;
spr_public empty[]() = heap_min_empty;
spr_public dtor() = heap_min_dtor;
spr_public static ctor() = heap_min_ctor;
} )
#define SPR_CLASS_IMPORT_HeapMin
#include <spraak_classdef/taipan_cpp.class.h>
spr_cmdoc spr_public_lo_afunc
void *heap_min_dtor(HeapMin *heap)
{int ndx = heap->fill;
Item **tbl = heap->heap;
while(--ndx >= 0)
free(tbl);
free(heap);
return(NULL);
}
spr_cmdoc spr_public_lo_afunc
HeapMin *heap_min_ctor(
int size)
{HeapMin *heap;
if((heap=malloc(sizeof(HeapMin))) != NULL)
heap->size = size;
heap->fill = 0;
if((heap->heap=malloc(sizeof(Item*)*size)) == NULL)
return(heap_min_dtor(heap));
}
return(heap);
}
spr_cmdoc spr_public_lo_afunc
Item *heap_min_push(
HeapMin *heap,
Item *item)
{Item **tbl = heap->heap;
unsigned int ndx_c,ndx_p;
if(heap->fill == heap->size)
{if((tbl=realloc(tbl,sizeof(Item*)*(heap->size+=31+(heap->size>>2)))) == NULL)
{heap->size = heap->fill;
goto ERROR_;
}
heap->heap = tbl;
}
ndx_c = heap->fill++;
while(ndx_c && (
SPR_DO(Item,cmp,item,tbl[ndx_p=(ndx_c-1)/2u])<0))
{tbl[ndx_c] = tbl[ndx_p];
ndx_c = ndx_p;
}
tbl[ndx_c] = item;
return(item);
ERROR_:
return(NULL);
}
spr_cmdoc spr_public_lo_afunc
Item *heap_min_pop(
HeapMin *heap)
{Item **tbl = heap->heap;
Item *rv,*item;
unsigned int ndx_c,ndx_p,fill;
if((fill=heap->fill) == 0)
goto ERROR_;
rv = tbl[0];
item = tbl[heap->fill=--fill];
ndx_p = 0;
ndx_c = 2;
while(ndx_c <= fill)
{
if((ndx_c==fill) || (
SPR_DO(Item,cmp,tbl[ndx_c-1],tbl[ndx_c])<0))
ndx_c--;
if(
SPR_DO(Item,cmp,item,tbl[ndx_c]) < 0)
break;
tbl[ndx_p] = tbl[ndx_c];
ndx_c = (ndx_p=ndx_c)*2+2;
}
tbl[ndx_p] = item;
if((fill*2+32<=heap->size) && ((tbl=realloc(tbl,sizeof(Item*)*(fill+=fill/2u)))!=NULL))
{heap->heap = tbl;
heap->size = fill;
}
return(rv);
ERROR_:
return(NULL);
}
spr_cmdoc spr_public_lo_afunc
Item *heap_min_toq(
HeapMin *heap)
{return(heap->fill?heap->heap[0]:NULL);
}
spr_cmdoc spr_public_lo_afunc
int heap_min_empty(
HeapMin *heap)
{return(heap->fill==0);
}
#define SPR_CLASS_DEFINE_HeapMin
#include <spraak_classdef/taipan_cpp.class.h>
spr_nodoc spr_public_lo_type
typedef struct t_hash_el
{const Item *ndx;
Item *value;
struct t_hash_el *next;
} HashEl;
spr_cmdoc spr_public_lo_type
typedef struct
{Container container;
Queue queue;
spr_private HashEl **htbl;
spr_private HashEl *list;
spr_private HashEl *free_list;
spr_private const HashEl *toq;
spr_private StrItem *none;
spr_private unsigned int size;
spr_private unsigned int fill;
spr_private unsigned int max_size;
} Hash;
spr_cmdoc spr_public_lo_type
typedef struct
{Iterator iterator;
spr_private const HashEl *ptr;
spr_private unsigned int rem_cnt;
spr_private const HashEl *list;
spr_private unsigned int size;
spr_private const Hash *hash;
} HashIterator;
spr_public_hi_class
SPR_CLASS(Hash : Container, Queue
{
spr_public get[]() = hash_get;
spr_public add[]() = hash_add;
spr_public cadd[]() = hash_cadd;
spr_public remove[]() = hash_remove;
spr_public iterator[]() = hash_iterator;
spr_public push[]() = hash_push;
spr_public pop[]() = hash_pop;
spr_public toq[]() = hash_toq;
spr_public empty[]() = hash_empty;
spr_public dtor() = hash_dtor;
spr_public static ctor() = hash_ctor;
} )
#define SPR_CLASS_IMPORT_Hash
#include <spraak_classdef/taipan_cpp.class.h>
spr_public_hi_class
SPR_CLASS(HashIterator : Iterator
{
spr_public item[]() := hash_iterator_item;
spr_public next[]() := hash_iterator_next;
spr_public iterator[]() := hash_iterator_iterator;
} )
#define SPR_CLASS_IMPORT_HashIterator
#include <spraak_classdef/taipan_cpp.class.h>
spr_cmdoc spr_public_lo_afunc
Hash *hash_dtor(
Hash *hash)
{HashEl *el = hash->list;
if(el != NULL)
{int cnt = hash->max_size;
while(--cnt >= 0)
{if(el->ndx != NULL)
SPR_DO(Item,unlock,(Item*)el->ndx);
if(el->value != NULL)
SPR_DO(Item,unlock,el->value);
el++;
}
}
if(hash->none != NULL)
SPR_DO(Tuple,unlock,hash->none);
free(hash->list);
free(hash->htbl);
free(hash);
return(NULL);
}
spr_private_func
Hash *hash_resize(
Hash *hash,
unsigned int size)
{Hash *rv = NULL;
if(size == 0)
{size = hash->fill;
size += (size>>1) + 15;
}
size |= 1;
{HashEl **htbl;
if((htbl=realloc(hash->htbl,sizeof(HashEl*)*size)) == NULL)
goto ERROR_;
hash->htbl = htbl;
}
rv = hash;
if(hash->max_size != hash->fill)
{unsigned int ndx = hash->fill;
HashEl *el = hash->list;
if((ndx))
{HashEl *free_list = NULL;
do
{if(el->ndx == NULL)
{el->next = free_list;
free_list = el;
}
++el;
} while(--ndx);
ndx = hash->max_size-hash->fill;
do
{if(el->ndx != NULL)
{free_list->ndx = el->ndx;
free_list->value = el->value;
free_list = free_list->next;
}
++el;
} while(--ndx);
}
hash->max_size = hash->fill;
rv = NULL;
}
{HashEl *list;
int ndx;
if((list=realloc(hash->list,sizeof(HashEl)*size)) != NULL)
{rv = hash;
hash->size = size;
hash->toq = hash->list = list;
}
else if(rv != NULL)
{rv = NULL;
goto ERROR_;
}
else
size = hash->size;
ndx = size-hash->fill;
hash->free_list = (list+=hash->fill);
while(--ndx > 0)
list = (list->next=list+1);
list->next = NULL;
}
{HashEl **htbl = hash->htbl + size;
int ndx = -(int)size;
do
{htbl[ndx] = NULL;
} while(++ndx);
if((ndx=hash->fill))
{HashEl *el = hash->list;
htbl = hash->htbl;
do
{HashEl **pos = &htbl[
SPR_DO(Item,hash,el->ndx)%size];
el->next = *pos;
*pos = el++;
} while(--ndx);
}
}
ERROR_:
return(rv);
}
spr_cmdoc spr_public_lo_afunc
Hash *hash_ctor(
int size)
{Hash *hash;
if((hash=malloc(sizeof(Hash))) != NULL)
hash->htbl = NULL;
hash->list = NULL;
hash->free_list = NULL;
hash->none = NULL;
hash->size = 0;
hash->fill = 0;
hash->max_size = 0;
if(hash_resize(hash,size) == NULL)
goto ERROR_;
if((hash->none=
SPR_DO(StrItem,ctor,NULL)) == NULL)
goto ERROR_;
}
return(hash);
ERROR_:
return(hash_dtor(hash));
}
spr_cmdoc spr_public_lo_afunc
Item *hash_get(
const Hash *hash,
const Item *ndx)
{const HashEl *el;
for(el=hash->htbl[
SPR_DO(Item,hash,ndx)%hash->size];el!=NULL;el=el->next)
if(
SPR_DO(Item,cmp,ndx,el->ndx) == 0)
return(el->value);
return(NULL);
}
spr_cmdoc spr_public_lo_afunc
Item *hash_add(
Hash *hash,
Item *ndx,
Item *value)
{HashEl **link,*el;
if((hash->free_list==NULL) && (hash_resize(hash,0)==NULL))
return(NULL);
for(el=*(link=&hash->htbl[
SPR_DO(Item,hash,ndx)%hash->size]);el!=NULL;el=el->next)
{
if(
SPR_DO(Item,cmp,ndx,el->ndx) == 0)
SPR_DO(Item,unlock,el->value);
el->value = value;
return(value);
}
}
el = hash->free_list;
if(++hash->fill > hash->max_size)
hash->max_size = hash->fill;
hash->free_list = el->next;
el->next = *link;
el->ndx = ndx;
el->value = value;
*link = el;
if(el < hash->toq)
hash->toq = el;
return(value);
}
spr_cmdoc spr_public_lo_afunc
Item *hash_cadd(
Hash *hash,
Item *ndx,
Item *value)
{HashEl **link,*el;
if((hash->free_list==NULL) && (hash_resize(hash,0)==NULL))
return(NULL);
for(el=*(link=&hash->htbl[
SPR_DO(Item,hash,ndx)%hash->size]);el!=NULL;el=el->next)
if(
SPR_DO(Item,cmp,ndx,el->ndx) == 0)
return(NULL);
el = hash->free_list;
if(++hash->fill > hash->max_size)
hash->max_size = hash->fill;
hash->free_list = el->next;
el->next = *link;
el->ndx = ndx;
el->value = value;
*link = el;
if(el < hash->toq)
hash->toq = el;
return(value);
}
spr_cmdoc spr_public_lo_afunc
Item *hash_remove(
Hash *hash,
const Item *ndx)
{HashEl **link,*el;
for(el=*(link=&hash->htbl[
SPR_DO(Item,hash,ndx)%hash->size]);el!=NULL;el=*(link=&el->next))
{
if(
SPR_DO(Item,cmp,ndx,el->ndx) == 0)
{Item *value = el->value;
*link = el->next;
SPR_DO(Item,unlock,(Item*)el->ndx);
el->next = hash->free_list;
el->ndx = NULL;
el->value = NULL;
hash->free_list = el;
if((--hash->fill)*2+48 <= hash->size)
hash_resize(hash,0);
return(value);
}
}
return(NULL);
}
spr_cmdoc spr_public_lo_afunc
Item *hash_push(
Hash *hash,
Item *item)
{
return(hash_cadd(hash,item,
SPR_CAST(Item,StrItem,hash->none)));
}
spr_cmdoc spr_public_lo_afunc
Item *hash_toq(
Hash *hash)
{const HashEl *el = hash->toq;
int cnt = hash->max_size-(el-hash->list);
for( ;--cnt>=0;++el)
if(el->ndx != NULL)
return((Item*)(hash->toq=el)->ndx);
return(NULL);
}
spr_cmdoc spr_public_lo_afunc
Item *hash_pop(
Hash *hash)
{HashEl *el = (HashEl*)hash->toq;
int cnt = hash->max_size-(el-hash->list);
for( ;--cnt>=0;++el)
{if(el->ndx != NULL)
{Item *ndx = (Item*)el->ndx;
HashEl **link = &hash->htbl[
SPR_DO(Item,hash,ndx)%hash->size];
hash->toq = el+1;
{HashEl *tmp;
while((tmp=*link) != el)
link = &tmp->next;
}
*link = el->next;
SPR_DO(Item,unlock,el->value);
el->ndx = NULL;
el->value = NULL;
el->next = hash->free_list;
hash->free_list = el;
if((--hash->fill)*2+48 <= hash->size)
hash_resize(hash,0);
return(ndx);
}
}
return(NULL);
}
spr_cmdoc spr_public_lo_afunc
int hash_empty(
Hash *hash)
{return(hash->fill==0);
}
spr_cmdoc spr_public_lo_afunc
Iterator *hash_iterator(
const Hash *hash)
{HashIterator *iter;
if((iter=malloc(sizeof(HashIterator))) != NULL)
{int rem_cnt;
const HashEl *ptr;
if((rem_cnt=hash->max_size-((ptr=hash->toq)-(iter->list=hash->list))) > 0)
{iter->size = hash->size;
iter->hash = hash;
do
{if(ptr->ndx != NULL)
{iter->rem_cnt = rem_cnt;
iter->ptr = ptr;
return(
SPR_CAST(Iterator,HashIterator,iter));
}
ptr++;
} while(--rem_cnt > 0);
}
free(iter);
}
return(NULL);
}
#define SPR_CLASS_DEFINE_Hash
#include <spraak_classdef/taipan_cpp.class.h>
spr_cmdoc spr_public_lo_afunc
Iterator *hash_iterator_next(
HashIterator *iter)
{if((iter->size==iter->hash->size) && (iter->list==iter->hash->list))
{const HashEl *ptr = iter->ptr;
int rem_cnt = iter->rem_cnt;
while(--rem_cnt> 0)
{if((++ptr)->ndx != NULL)
{iter->ptr = ptr;
iter->rem_cnt = rem_cnt;
return(
SPR_CAST(Iterator,HashIterator,iter));
}
}
}
else
fprintf(stderr,"Hash table %p was modified during loop\n",iter->hash);
free(iter);
return(NULL);
}
spr_cmdoc spr_public_lo_afunc
Item *hash_iterator_item(
HashIterator *iter)
{return((Item*)iter->ptr->ndx);
}
spr_cmdoc spr_public_lo_afunc
Iterator *hash_iterator_iterator(
const HashIterator *iter)
{if(iter != NULL)
{HashIterator *new_iter;
if((new_iter=malloc(sizeof(HashIterator))) != NULL)
*new_iter = *iter;
return(
SPR_CAST(Iterator,HashIterator,new_iter));
}
return((Iterator*)iter);
}
#define SPR_CLASS_DEFINE_HashIterator
#include <spraak_classdef/taipan_cpp.class.h>
static Item *make_item_example(const char *desc)
{Item *item = NULL;
if(strcmp(desc,"int") == 0)
else if(strcmp(desc,"float") == 0)
else if(strcmp(desc,"str") == 0)
else
fprintf(stderr,"datatype must be int, float or str\n");
return(item);
}
int main(
int argc,
char *argv[])
{int rv = 1;
void *op = NULL;
Item *item0 = NULL;
Item *item1 = NULL;
Queue *queue;
if((argc<3))
{fprintf(stderr,"Use: taipan_cpp <op>(sort/reverse/unique/unique1) <datatype1>(int/float/str) [datatype2](int/float/str) ...\nRead a sequence of <datatype1> items or (<datatype1>,<datatype2>,...) tuples from stdin (seperated by spaces and/or new-lines) and either sort them, reverse them or filter out duplicates (based on the first item in a tuple if op=unique1) and write the result to stdout.\n");
return(1);
}
if(strcmp(argv[1],"sort") == 0)
{op =
SPR_DO(HeapMin,ctor,100);
queue =
SPR_CAST(Queue,HeapMin,(HeapMin*)op);
}
else if(strcmp(argv[1],"reverse") == 0)
queue =
SPR_CAST(Queue,Stack,(Stack*)op);
}
else if((strcmp(argv[1],"unique")==0) || (strcmp(argv[1],"unique1")==0))
}
else
{fprintf(stderr,"op must be sort, reverse, unique or unique1\n");
goto ERROR_;
}
if((item0=make_item_example(argv[2])) == NULL)
goto ERROR_;
if(argc > 3)
{int iarg = 3;
if(strcmp(argv[1],"unique1") == 0)
{item1 = item0;
if((item0=make_item_example(argv[3])) == NULL)
goto ERROR_;
iarg = 4;
}
if(iarg < argc)
{Tuple *tuple;
if((tuple=
SPR_DO(Tuple,ctor,item0,NULL)) == NULL)
goto ERROR_;
while(iarg < argc)
{Item *item;
Tuple *prev_tuple;
if((item=make_item_example(argv[iarg++])) == NULL)
goto ERROR_;
prev_tuple = tuple;
tuple =
SPR_DO(Tuple,ctor_add,tuple,item);
SPR_DO(Tuple,unlock,prev_tuple);
if(tuple == NULL)
goto ERROR_;
}
}
}
if(item1 == NULL)
{int rv;
do
{Item *item =
SPR_DO(Item,clone,item0);
if((rv=
SPR_DO(Item,read,item,stdin)) == 1)
SPR_DO(Queue,push,queue,item);
} while(rv == 1);
if(rv < -1)
goto ERROR_;
}
else
{int rv;
Hash *htbl = op;
do
{Item *ndx =
SPR_DO(Item,clone,item1);
Item *val =
SPR_DO(Item,clone,item0);
if((rv=
SPR_DO(Item,read,ndx,stdin)) == 1)
{
if(
SPR_DO(Item,read,val,stdin) == 1)
SPR_DO(Hash,cadd,htbl,ndx,val);
else
rv = -2;
}
} while(rv == 1);
if(rv < -1)
goto ERROR_;
}
if(!feof(stdin))
goto ERROR_;
if(item1 == NULL)
{
while(!
SPR_DO(Queue,empty,queue))
{Item *item =
SPR_DO(Queue,pop,queue);
SPR_DO(Item,write,item,stdout);
fputc('\n',stdout);
}
}
else
{Hash *htbl = op;
Iterator *iter;
for(iter=
SPR_DO(Hash,iterator,htbl);iter!=NULL;iter=
SPR_DO(Iterator,next,iter))
{
const Item *ndx =
SPR_DO(Iterator,item,iter);
SPR_DO(Item,write,ndx,stdout);
fputc('\n',stdout);
}
}
rv = 0;
ERROR_:
if(rv)
fprintf(stderr,"failed to process the data -- %s\n",strerror(errno));
if(op != NULL)
SPR_DO(SprObject,dtor,(SprObject*)op);
if(item0 != NULL)
if(item1 != NULL)
return(rv);
}