package t_enum; use strict; use vars qw(@ISA); #require ktemplate; require t_template; require t_array; @ISA=qw(t_template); my @parms = qw(NAME TYPE COMPARE); my %defaults = ( ); my @templatelines = ; sub new { # no args my $self = {}; bless $self; $self->init(\@parms, \%defaults, \@templatelines); return $self; } sub output { my ($self, $fh) = @_; my $a = new t_array; $a->setparm("NAME", $self->{values}{"NAME"} . "__enumerator_array"); $a->setparm("TYPE", $self->{values}{"TYPE"}); $a->output($fh); $self->SUPER::output($fh); } 1; __DATA__ /* * an enumerated collection type, generated from template * * Methods: * int init() -> returns nonzero on alloc failure * long size() * long find(match) -> -1 or index of any match * long append(value) -> -1 or new index * get(index) -> aborts if out of range * void destroy() -> frees array data * * Errors adding elements don't distinguish between "out of memory" * and "too big for size_t". * * Initial implementation: A flat array, reallocated as needed. Our * uses probably aren't going to get very large. */ struct __enumerator { __enumerator_array a; size_t used; /* number of entries used, idx used-1 is last */ }; typedef struct __enumerator ; static inline int _init( *en) { en->used = 0; return __enumerator_array_init(&en->a); } static inline long _size( *en) { return en->used; } static inline long __s2l(size_t idx) { long l; if (idx > LONG_MAX) abort(); l = idx; if (l != idx) abort(); return l; } static inline long _find( *en, value) { size_t i; for (i = 0; i < en->used; i++) { if ( (value, __enumerator_array_get(&en->a, __s2l(i))) == 0) return i; } return -1; } static inline long _append( *en, value) { if (en->used >= LONG_MAX - 1) return -1; if (en->used >= SIZE_MAX - 1) return -1; if (__enumerator_array_size(&en->a) == en->used) { if (__enumerator_array_grow(&en->a, en->used + 1) < 0) return -1; } __enumerator_array_set(&en->a, __s2l(en->used), value); en->used++; return en->used-1; } static inline _get( *en, size_t idx) { return __enumerator_array_get(&en->a, __s2l(idx)); } static inline void _destroy( *en) { __enumerator_array_destroy(&en->a); en->used = 0; } static inline void _foreach( *en, int (*fn)(size_t i, t, void *p), void *p) { size_t i; for (i = 0; i < en->used; i++) { if (fn (i, __enumerator_array_get(&en->a, __s2l(i)), p) != 0) break; } }