1package t_enum; 2 3use strict; 4use vars qw(@ISA); 5 6#require ktemplate; 7require t_template; 8require t_array; 9 10@ISA=qw(t_template); 11 12my @parms = qw(NAME TYPE COMPARE); 13my %defaults = ( ); 14my @templatelines = <DATA>; 15 16sub new { # no args 17 my $self = {}; 18 bless $self; 19 $self->init(\@parms, \%defaults, \@templatelines); 20 return $self; 21} 22 23sub output { 24 my ($self, $fh) = @_; 25 my $a = new t_array; 26 $a->setparm("NAME", $self->{values}{"NAME"} . "__enumerator_array"); 27 $a->setparm("TYPE", $self->{values}{"TYPE"}); 28 $a->output($fh); 29 $self->SUPER::output($fh); 30} 31 321; 33 34__DATA__ 35 36/* 37 * an enumerated collection type, generated from template 38 * 39 * Methods: 40 * int init() -> returns nonzero on alloc failure 41 * long size() 42 * long find(match) -> -1 or index of any match 43 * long append(value) -> -1 or new index 44 * <TYPE> get(index) -> aborts if out of range 45 * void destroy() -> frees array data 46 * 47 * Errors adding elements don't distinguish between "out of memory" 48 * and "too big for size_t". 49 * 50 * Initial implementation: A flat array, reallocated as needed. Our 51 * uses probably aren't going to get very large. 52 */ 53 54struct <NAME>__enumerator { 55 <NAME>__enumerator_array a; 56 size_t used; /* number of entries used, idx used-1 is last */ 57}; 58typedef struct <NAME>__enumerator <NAME>; 59 60static inline int 61<NAME>_init(<NAME> *en) 62{ 63 en->used = 0; 64 return <NAME>__enumerator_array_init(&en->a); 65} 66 67static inline long 68<NAME>_size(<NAME> *en) 69{ 70 return en->used; 71} 72 73static inline long 74<NAME>__s2l(size_t idx) 75{ 76 long l; 77 if (idx > LONG_MAX) 78 abort(); 79 l = idx; 80 if (l != idx) 81 abort(); 82 return l; 83} 84 85static inline long 86<NAME>_find(<NAME> *en, <TYPE> value) 87{ 88 size_t i; 89 for (i = 0; i < en->used; i++) { 90 if (<COMPARE> (value, <NAME>__enumerator_array_get(&en->a, <NAME>__s2l(i))) == 0) 91 return i; 92 } 93 return -1; 94} 95 96static inline long 97<NAME>_append(<NAME> *en, <TYPE> value) 98{ 99 if (en->used >= LONG_MAX - 1) 100 return -1; 101 if (en->used >= SIZE_MAX - 1) 102 return -1; 103 if (<NAME>__enumerator_array_size(&en->a) == en->used) { 104 if (<NAME>__enumerator_array_grow(&en->a, en->used + 1) < 0) 105 return -1; 106 } 107 <NAME>__enumerator_array_set(&en->a, <NAME>__s2l(en->used), value); 108 en->used++; 109 return en->used-1; 110} 111 112static inline <TYPE> 113<NAME>_get(<NAME> *en, size_t idx) 114{ 115 return <NAME>__enumerator_array_get(&en->a, <NAME>__s2l(idx)); 116} 117 118static inline void 119<NAME>_destroy(<NAME> *en) 120{ 121 <NAME>__enumerator_array_destroy(&en->a); 122 en->used = 0; 123} 124 125static inline void 126<NAME>_foreach(<NAME> *en, int (*fn)(size_t i, <TYPE> t, void *p), void *p) 127{ 128 size_t i; 129 for (i = 0; i < en->used; i++) { 130 if (fn (i, <NAME>__enumerator_array_get(&en->a, <NAME>__s2l(i)), p) != 0) 131 break; 132 } 133} 134