|
Packit |
fd8b60 |
package t_array;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
use strict;
|
|
Packit |
fd8b60 |
use vars qw(@ISA);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#require ktemplate;
|
|
Packit |
fd8b60 |
require t_template;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
@ISA=qw(t_template);
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
my @parms = qw(NAME TYPE);
|
|
Packit |
fd8b60 |
my %defaults = ( );
|
|
Packit |
fd8b60 |
my @templatelines = <DATA>;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
sub new { # no args
|
|
Packit |
fd8b60 |
my $self = {};
|
|
Packit |
fd8b60 |
bless $self;
|
|
Packit |
fd8b60 |
$self->init(\@parms, \%defaults, \@templatelines);
|
|
Packit |
fd8b60 |
return $self;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
__DATA__
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
/*
|
|
Packit |
fd8b60 |
* array type, derived from template
|
|
Packit |
fd8b60 |
*
|
|
Packit |
fd8b60 |
* parameters:
|
|
Packit |
fd8b60 |
* NAME: <NAME>
|
|
Packit |
fd8b60 |
* TYPE: <TYPE>
|
|
Packit |
fd8b60 |
*
|
|
Packit |
fd8b60 |
* methods:
|
|
Packit |
fd8b60 |
* int init() -> nonzero if fail initial allocation
|
|
Packit |
fd8b60 |
* unsigned long size() -> nonnegative number of values stored
|
|
Packit |
fd8b60 |
* int grow(newsize) -> negative if fail allocation, memset(,0,) new space
|
|
Packit |
fd8b60 |
* <TYPE> *getaddr(idx) -> aborts if out of range
|
|
Packit |
fd8b60 |
* void set(idx, value) -> aborts if out of range
|
|
Packit |
fd8b60 |
* <TYPE> get(idx) -> value, or aborts if out of range
|
|
Packit |
fd8b60 |
*/
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
#include <stdlib.h>
|
|
Packit |
fd8b60 |
#include <errno.h>
|
|
Packit |
fd8b60 |
#include <limits.h>
|
|
Packit |
fd8b60 |
#include <string.h>
|
|
Packit |
fd8b60 |
#include <stdint.h>
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
struct <NAME>__header {
|
|
Packit |
fd8b60 |
size_t allocated;
|
|
Packit |
fd8b60 |
<TYPE> *elts;
|
|
Packit |
fd8b60 |
};
|
|
Packit |
fd8b60 |
typedef struct <NAME>__header <NAME>;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static inline int
|
|
Packit |
fd8b60 |
<NAME>_init(<NAME> *arr)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
arr->elts = calloc(10, sizeof(<TYPE>));
|
|
Packit |
fd8b60 |
if (arr->elts == NULL)
|
|
Packit |
fd8b60 |
return ENOMEM;
|
|
Packit |
fd8b60 |
arr->allocated = 10;
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static inline long
|
|
Packit |
fd8b60 |
<NAME>_size(<NAME> *arr)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
return arr->allocated;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static inline unsigned long
|
|
Packit |
fd8b60 |
<NAME>_max_size(<NAME> *arr)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
size_t upper_bound;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
upper_bound = SIZE_MAX / sizeof(*arr->elts);
|
|
Packit |
fd8b60 |
if (upper_bound > ULONG_MAX)
|
|
Packit |
fd8b60 |
upper_bound = ULONG_MAX;
|
|
Packit |
fd8b60 |
return (unsigned long) upper_bound;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static inline int
|
|
Packit |
fd8b60 |
<NAME>_grow(<NAME> *arr, unsigned long newcount)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
size_t oldsize = sizeof(*arr->elts) * arr->allocated;
|
|
Packit |
fd8b60 |
size_t newsize;
|
|
Packit |
fd8b60 |
void *ptr;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
if (newcount > LONG_MAX)
|
|
Packit |
fd8b60 |
return -1;
|
|
Packit |
fd8b60 |
if (newcount < arr->allocated)
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
if (newcount > <NAME>_max_size(arr))
|
|
Packit |
fd8b60 |
return -1;
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
newsize = sizeof(*arr->elts) * newcount;
|
|
Packit |
fd8b60 |
ptr = realloc(arr->elts, newsize);
|
|
Packit |
fd8b60 |
if (ptr == NULL)
|
|
Packit |
fd8b60 |
return -1;
|
|
Packit |
fd8b60 |
memset((char *)ptr + oldsize, 0, newsize - oldsize);
|
|
Packit |
fd8b60 |
arr->elts = ptr;
|
|
Packit |
fd8b60 |
arr->allocated = newcount;
|
|
Packit |
fd8b60 |
return 0;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static inline <TYPE> *
|
|
Packit |
fd8b60 |
<NAME>_getaddr (<NAME> *arr, long idx)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
if (idx < 0 || (unsigned long) idx >= arr->allocated)
|
|
Packit |
fd8b60 |
abort();
|
|
Packit |
fd8b60 |
return arr->elts + idx;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static inline void
|
|
Packit |
fd8b60 |
<NAME>_set (<NAME> *arr, long idx, <TYPE> value)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
<TYPE> *newvalp;
|
|
Packit |
fd8b60 |
newvalp = <NAME>_getaddr(arr, idx);
|
|
Packit |
fd8b60 |
*newvalp = value;
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static inline <TYPE>
|
|
Packit |
fd8b60 |
<NAME>_get (<NAME> *arr, long idx)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
return *<NAME>_getaddr(arr, idx);
|
|
Packit |
fd8b60 |
}
|
|
Packit |
fd8b60 |
|
|
Packit |
fd8b60 |
static inline void
|
|
Packit |
fd8b60 |
<NAME>_destroy (<NAME> *arr)
|
|
Packit |
fd8b60 |
{
|
|
Packit |
fd8b60 |
free(arr->elts);
|
|
Packit |
fd8b60 |
arr->elts = 0;
|
|
Packit |
fd8b60 |
}
|