#include "mod_perl.h"
typedef
struct
{
SV *cv;
table *only;
} TableDo;
#define table_pool(t) ((array_header *)(t))->pool
static
int
Apache_table_do(TableDo *td,
const
char
*key,
const
char
*val)
{
int
count=0, rv=1;
dSP;
if
(td->only && !table_get(td->only, key))
return
1;
ENTER;SAVETMPS;
PUSHMARK(sp);
XPUSHs(sv_2mortal(newSVpv((
char
*)key,0)));
XPUSHs(sv_2mortal(newSVpv((
char
*)val,0)));
PUTBACK;
count = perl_call_sv(td->cv, G_SCALAR);
SPAGAIN;
if
(count == 1)
rv = POPi;
PUTBACK;
FREETMPS;LEAVE;
return
rv;
}
typedef
void
(
#ifdef WIN32
_stdcall
#endif
*TABFUNC) (table *,
const
char
*,
const
char
*);
static
void
table_modify(TiedTable *self,
const
char
*key, SV *sv,
TABFUNC tabfunc)
{
dTHR;
const
char
*val;
if
(!self->utable)
return
;
if
(SvROK(sv) && (SvTYPE(SvRV(sv)) == SVt_PVAV)) {
I32 i;
AV *av = (AV*)SvRV(sv);
for
(i=0; i<=AvFILL(av); i++) {
val = (
const
char
*)SvPV(*av_fetch(av, i, FALSE),na);
(*tabfunc)(self->utable, key, val);
}
}
else
{
val = (
const
char
*)SvPV(sv,na);
(*tabfunc)(self->utable, key, val);
}
}
static
void
#ifdef WIN32
_stdcall
#endif
table_delete(table *tab,
const
char
*key,
const
char
*val)
{
table_unset(tab, val);
}
static
Apache__Table ApacheTable_new(table *utable)
{
Apache__Table RETVAL = (Apache__Table)safemalloc(
sizeof
(TiedTable));
RETVAL->utable = utable;
RETVAL->ix = 0;
RETVAL->elts = NULL;
RETVAL->arr = NULL;
return
RETVAL;
}
MODULE = Apache::Table PACKAGE = Apache::Table
PROTOTYPES: DISABLE
BOOT:
items = items;
Apache::Table
TIEHASH(pclass, table)
SV *pclass
Apache::table table
CODE:
if
(!pclass) XSRETURN_UNDEF;
RETVAL = ApacheTable_new(table);
OUTPUT:
RETVAL
void
new
(pclass, r, nalloc=10)
SV *pclass
Apache r
int
nalloc
CODE:
if
(!pclass) XSRETURN_UNDEF;
ST(0) = mod_perl_tie_table(make_table(r->pool, nalloc));
void
DESTROY(self)
SV *self
PREINIT:
Apache__Table tab;
CODE:
tab = (Apache__Table)hvrv2table(self);
if
(SvROK(self) && SvTYPE(SvRV(self)) == SVt_PVHV)
safefree(tab);
void
FETCH(self, key)
Apache::Table self
const
char
*key
ALIAS:
get = 1
PPCODE:
ix = ix;
if
(!self->utable) XSRETURN_UNDEF;
if
(GIMME == G_SCALAR) {
const
char
*val = table_get(self->utable, key);
if
(val) XPUSHs(sv_2mortal(newSVpv((
char
*)val,0)));
else
XSRETURN_UNDEF;
}
else
{
int
i;
array_header *arr = table_elts(self->utable);
table_entry *elts = (table_entry *)arr->elts;
for
(i = 0; i < arr->nelts; ++i) {
if
(!elts[i].key || strcasecmp(elts[i].key, key))
continue
;
XPUSHs(sv_2mortal(newSVpv(elts[i].val,0)));
}
}
bool
EXISTS(self, key)
Apache::Table self
const
char
*key
CODE:
if
(!self->utable) XSRETURN_UNDEF;
RETVAL = table_get(self->utable, key) ? TRUE : FALSE;
OUTPUT:
RETVAL
const
char
*
DELETE(self, sv)
Apache::Table self
SV *sv
ALIAS:
unset = 1
PREINIT:
I32 gimme = GIMME_V;
CODE:
ix = ix;
if
(!self->utable) XSRETURN_UNDEF;
RETVAL = NULL;
if
((ix == 0) && (gimme != G_VOID)) {
STRLEN n_a;
RETVAL = table_get(self->utable, SvPV(sv,n_a));
}
table_modify(self, NULL, sv, (TABFUNC)table_delete);
if
(!RETVAL) XSRETURN_UNDEF;
OUTPUT:
RETVAL
void
STORE(self, key, val)
Apache::Table self
const
char
*key
const
char
*val
ALIAS:
set = 1
CODE:
ix = ix;
if
(!self->utable) XSRETURN_UNDEF;
table_set(self->utable, key, val);
void
CLEAR(self)
Apache::Table self
ALIAS:
clear = 1
CODE:
ix = ix;
if
(!self->utable) XSRETURN_UNDEF;
clear_table(self->utable);
const
char
*
NEXTKEY(self, lastkey=Nullsv)
Apache::Table self
SV *lastkey
CODE:
if
(self->ix >= self->arr->nelts) XSRETURN_UNDEF;
RETVAL = self->elts[self->ix++].key;
OUTPUT:
RETVAL
const
char
*
FIRSTKEY(self)
Apache::Table self
CODE:
if
(!self->utable) XSRETURN_UNDEF;
self->arr = table_elts(self->utable);
if
(!self->arr->nelts) XSRETURN_UNDEF;
self->elts = (table_entry *)self->arr->elts;
self->ix = 0;
RETVAL = self->elts[self->ix++].key;
OUTPUT:
RETVAL
void
add(self, key, sv)
Apache::Table self
const
char
*key
SV *sv;
CODE:
table_modify(self, key, sv, (TABFUNC)table_add);
void
merge(self, key, sv)
Apache::Table self
const
char
*key
SV *sv
CODE:
table_modify(self, key, sv, (TABFUNC)table_merge);
void
do
(self, cv, ...)
Apache::Table self
SV *cv
PREINIT:
TableDo td;
td.only = (table *)NULL;
CODE:
if
(items > 2) {
int
i;
STRLEN len;
td.only = make_table(table_pool(self->utable), items-2);
for
(i=2; ; i++) {
char
*key = SvPV(ST(i),len);
table_set(td.only, key,
"1"
);
if
(i == (items - 1))
break
;
}
}
td.cv = cv;
table_do((
int
(*) (
void
*,
const
char
*,
const
char
*)) Apache_table_do,
(
void
*) &td, self->utable, NULL);