Here is my second attempt at implementing an TIEHASH interface for APR::Table

It is now complete according to the Tied hash interface and make test passes
without any warning ;-)

There aren't a lot of outstanding issues about this patch, except:

1.  I am not sure where to put mpxs_typemap_(in/out)put_APR__Table... right
    now I placed them in modperl_util.[ch] as other people will need it.
2.  I still have to define this:
    
        #define mp_xs_sv2_APR__Table(sv) mpxs_typemap_input_APR__Table(aTHX_ sv, NULL)

    And I can forsee problems if other modules start playing with tables in the
    'standard' way using mpxs_usage_va*, as it will revert back to it's default
    behaviour and things will start to break ;-(
3.  I can't generate the xs/tables/current/*.pm since source_scan seems to be broken
    now...

That's all I can think of for now, and I love how all of a sudden 
$r->headers_out->{KEY}
suddently works.  Didn't add test for them though... should I ?

This time I also spent quite some time fiddling with gnu-indent and all it's millions
of options to try and proprely indent the whole thing.  I think I might have succeded
this time, and if I did, I will share my indent receipe (still needed manual fixing
a couple of times)

Let me know if this works for anybody but me.

-- 
+----------------------------------------------------+
| Philippe M. Chiasson  <[EMAIL PROTECTED]>             |
+----------------------------------------------------+
| F9BF E0C2 480E 7680 1AE5  3631 CB32 A107 88C3 A5A5 |
+----------------------------------------------------+
gethostent not implemented : Your C library apparently
doesn't implement gethostent(), probably because if it did,
it'd feel morally obligated to return every hostname on the
Internet. 
        -- perldiag(1)

perl -e '$$=\${gozer};{$_=unpack(P26,pack(L,$$));/^Just Another Perl 
Hacker!\n$/&&print||$$++&&redo}'


Index: lib/ModPerl/WrapXS.pm
===================================================================
RCS file: /home/anoncvs/mod_perl-2-cvs/lib/ModPerl/WrapXS.pm,v
retrieving revision 1.21
diff -u -U5 -b -B -I'$Id' -I'$Revision' -r1.21 WrapXS.pm
--- lib/ModPerl/WrapXS.pm       2001/09/13 02:37:37     1.21
+++ lib/ModPerl/WrapXS.pm       2001/09/19 07:01:49
@@ -504,10 +504,11 @@
 }
 
 my %typemap = (
     'Apache::RequestRec' => 'T_APACHEOBJ',
     'apr_time_t' => 'T_APR_TIME',
+    'APR::Table' => 'T_APRTABLEOBJ',
 );
 
 sub write_typemap {
     my $self = shift;
     my $typemap = $self->typemap;

Index: src/modules/perl/modperl_perl_includes.h
===================================================================
RCS file: /home/anoncvs/mod_perl-2-cvs/src/modules/perl/modperl_perl_includes.h,v
retrieving revision 1.4
diff -u -U5 -b -B -I'$Id' -I'$Revision' -r1.4 modperl_perl_includes.h
--- src/modules/perl/modperl_perl_includes.h    2001/03/15 01:26:18     1.4
+++ src/modules/perl/modperl_perl_includes.h    2001/09/23 11:37:01
@@ -41,6 +41,10 @@
 
 #ifndef G_METHOD
 #   define G_METHOD 64
 #endif
 
+#ifndef PERL_MAGIC_tied
+#   define PERL_MAGIC_tied 'P'
+#endif
+
 #endif /* MODPERL_PERL_INCLUDES_H */

Index: src/modules/perl/modperl_util.c
===================================================================
RCS file: /home/anoncvs/mod_perl-2-cvs/src/modules/perl/modperl_util.c,v
retrieving revision 1.17
diff -u -U5 -b -B -I'$Id' -I'$Revision' -r1.17 modperl_util.c
--- src/modules/perl/modperl_util.c     2001/08/08 16:20:32     1.17
+++ src/modules/perl/modperl_util.c     2001/09/23 14:11:59
@@ -337,5 +337,51 @@
     modperl_uri_t *uri = (modperl_uri_t *)apr_pcalloc(p, sizeof(*uri));
     uri->pool = p;
     return uri;
 }
 
+MP_INLINE SV *mpxs_typemap_output_APR__Table(pTHX_ SV *sv,
+                                             apr_table_t *t)
+{
+    SV *hv = (SV *)newHV();
+    SV *rsv = newSViv(0);
+
+    sv_setref_pv(rsv, "APR::Table", t);
+    sv_magic(hv, rsv, PERL_MAGIC_tied, Nullch, 0);
+    return SvREFCNT_inc(sv_bless
+                     (sv_2mortal(newRV_noinc(hv)),
+                      gv_stashpv("APR::Table", TRUE)));
+}
+
+MP_INLINE apr_table_t *mpxs_typemap_input_APR__Table(pTHX_ SV *sv,
+                                                     apr_table_t *t)
+{
+    if (sv_derived_from(sv, "APR::Table")) {
+        if (SVt_PVHV == SvTYPE(SvRV(sv))) {
+            SV *hv = SvRV(sv);
+            MAGIC *mg;
+
+            if (SvMAGICAL(hv)) {
+                if (mg = mg_find(hv, PERL_MAGIC_tied)) {
+                    return (apr_table_t *)SvIV((SV *)SvRV(mg->mg_obj));
+                }
+                else {
+                    Perl_warn(aTHX_ "Wrong Magick: (%c)\n", mg);
+                }
+
+            }
+            else {
+                Perl_warn(aTHX_ "Not Magick but should\n");
+            }
+
+        }
+        else {
+            return (apr_table_t *)SvIV((SV *)SvRV(sv));
+        }
+    }
+    else {
+        Perl_croak(aTHX_
+                   "argument is not a blessed reference (expecting an APR::Table 
+derived object)");
+    }
+
+    return NULL;
+}

Index: src/modules/perl/modperl_util.h
===================================================================
RCS file: /home/anoncvs/mod_perl-2-cvs/src/modules/perl/modperl_util.h,v
retrieving revision 1.16
diff -u -U5 -b -B -I'$Id' -I'$Revision' -r1.16 modperl_util.h
--- src/modules/perl/modperl_util.h     2001/08/08 07:02:41     1.16
+++ src/modules/perl/modperl_util.h     2001/09/23 12:53:01
@@ -48,6 +48,9 @@
 
 modperl_cleanup_data_t *modperl_cleanup_data_new(apr_pool_t *p, void *data);
 
 MP_INLINE modperl_uri_t *modperl_uri_new(apr_pool_t *p);
 
+MP_INLINE SV *mpxs_typemap_output_APR__Table(pTHX_ SV *, apr_table_t *);
+MP_INLINE apr_table_t *mpxs_typemap_input_APR__Table(pTHX_ SV *, apr_table_t *);
+
 #endif /* MODPERL_UTIL_H */

Index: t/response/TestAPR/table.pm
===================================================================
RCS file: /home/anoncvs/mod_perl-2-cvs/t/response/TestAPR/table.pm,v
retrieving revision 1.2
diff -u -U5 -b -B -I'$Id' -I'$Revision' -r1.2 table.pm
--- t/response/TestAPR/table.pm 2001/09/15 18:17:31     1.2
+++ t/response/TestAPR/table.pm 2001/09/23 13:58:30
@@ -12,13 +12,13 @@
 my $TABLE_SIZE = 20;
 
 sub handler {
     my $r = shift;
 
-    plan $r, tests => 9;
+    plan $r, tests => 16;
 
-    my $table = APR::Table::make($r->pool, 16);
+    my $table = APR::Table::make($r->pool, $TABLE_SIZE);
 
     ok (UNIVERSAL::isa($table, 'APR::Table'));
 
     ok $table->set('foo','bar') || 1;
 
@@ -57,10 +57,39 @@
 
     $filter_count = 0;
     $table->do("my_filter", "c", "b", "e");
     ok $filter_count == 3;
 
+    #Tied interface
+    {
+        my $table = APR::Table::make($r->pool, $TABLE_SIZE);
+        
+        ok (UNIVERSAL::isa($table, 'HASH'));
+    
+        ok (UNIVERSAL::isa($table, 'HASH')) && tied(%$table);
+        
+        ok $table->{'foo'} = 'bar';
+
+        ok $table->{'foo'} eq 'bar';
+
+        ok delete $table->{'foo'} || 1;
+
+        ok not exists $table->{'foo'};
+
+        for (1..$TABLE_SIZE) {
+                $table->{chr($_+97)} =  $_ ;  
+        }
+
+        $filter_count = 0;
+        
+        foreach my $key (sort keys %$table)
+            {
+                my_filter($key,$table->{$key});
+            }
+        ok $filter_count == $TABLE_SIZE;
+    }
+    
     Apache::OK;
 }
 
 sub my_filter {
     my ($key,$value) = @_;

Index: todo/api.txt
===================================================================
RCS file: /home/anoncvs/mod_perl-2-cvs/todo/api.txt,v
retrieving revision 1.4
diff -u -U5 -b -B -I'$Id' -I'$Revision' -r1.4 api.txt
--- todo/api.txt        2001/09/15 18:17:31     1.4
+++ todo/api.txt        2001/09/23 13:56:48
@@ -3,14 +3,10 @@
 ------------------------------------------
 
 tied filehandle interface:
  -CLOSE, GETC, PRINTF, READLINE
 
-APR::Table tie mechanism:
-$r->headers_out->{KEY} is not currently supported
-might want to make this optional, disabled by default
-
 $r->finfo:
 need apr_finfo_t <-> struct stat conversion (might already be there,
 haven't looked close enough yet)
 
 $r->header_{in,out}:

Index: xs/modperl_xs_util.h
===================================================================
RCS file: /home/anoncvs/mod_perl-2-cvs/xs/modperl_xs_util.h,v
retrieving revision 1.8
diff -u -U5 -b -B -I'$Id' -I'$Revision' -r1.8 modperl_xs_util.h

Index: xs/typemap
===================================================================
RCS file: /home/anoncvs/mod_perl-2-cvs/xs/typemap,v
retrieving revision 1.4
diff -u -U5 -b -B -I'$Id' -I'$Revision' -r1.4 typemap
--- xs/typemap  2001/05/04 21:21:49     1.4
+++ xs/typemap  2001/09/23 08:52:18
@@ -6,20 +6,26 @@
 ######################################################################
 OUTPUT
 T_APACHEOBJ
        sv_setref_pv($arg, \"${ntype}\", (void*)$var);
 
+T_APRTABLEOBJ
+     $arg = mpxs_typemap_output_APR__Table(aTHX_ $arg, $var);
+
 T_VPTR
        sv_setiv($arg, PTR2IV($var));
 
 T_APR_TIME
        sv_setnv($arg, (NV)($var / APR_USEC_PER_SEC));
 
 ######################################################################
 INPUT
 T_APACHEOBJ
        $var = modperl_xs_sv2request_rec(aTHX_ $arg, \"$ntype\", cv)
+    
+T_APRTABLEOBJ
+    $var = mpxs_typemap_input_APR__Table(aTHX_ $arg, $var)
 
 T_APACHEREF
        $var = modperl_xs_sv2request_rec(aTHX_ $arg, \"$ntype\", cv)
 
 T_VPTR

Index: xs/APR/Table/APR__Table.h
===================================================================
RCS file: /home/anoncvs/mod_perl-2-cvs/xs/APR/Table/APR__Table.h,v
retrieving revision 1.3
diff -u -U5 -b -B -I'$Id' -I'$Revision' -r1.3 APR__Table.h
--- xs/APR/Table/APR__Table.h   2001/09/19 23:08:07     1.3
+++ xs/APR/Table/APR__Table.h   2001/09/23 14:13:16
@@ -1,17 +1,24 @@
-typedef struct {
+#define mp_xs_sv2_APR__Table(sv) mpxs_typemap_input_APR__Table(aTHX_ sv, NULL)
+
+#define apr_table_FETCH apr_table_get
+#define apr_table_STORE apr_table_set
+#define apr_table_DELETE apr_table_unset
+
+typedef struct
+{
     SV *cv;
     apr_hash_t *filter;
     PerlInterpreter *perl;
 } mpxs_table_do_cb_data_t;
 
-typedef int (*mpxs_apr_table_do_cb_t)(void *, const char *, const char *);
+typedef int (*mpxs_apr_table_do_cb_t) (void *, const char *, const char *);
 
-static int mpxs_apr_table_do_cb(void *data,
-                                const char *key, const char *val)
+static int mpxs_apr_table_do_cb(void *data, const char *key, const char *val)
 {
     mpxs_table_do_cb_data_t *tdata = (mpxs_table_do_cb_data_t *)data;
+
     dTHXa(tdata->perl);
     dSP;
     int rv = 0;
 
     /* Skip completely if something is wrong */
@@ -28,12 +35,12 @@
     
     ENTER;
     SAVETMPS;
 
     PUSHMARK(sp);
-    XPUSHs(sv_2mortal(newSVpv(key,0)));
-    XPUSHs(sv_2mortal(newSVpv(val,0)));
+    XPUSHs(sv_2mortal(newSVpv(key, 0)));
+    XPUSHs(sv_2mortal(newSVpv(val, 0)));
     PUTBACK;
 
     rv = call_sv(tdata->cv, 0);
     SPAGAIN;
     rv = (1 == rv) ? POPi : 1;
@@ -44,12 +51,11 @@
     
     /* rv of 0 aborts the traversal */
     return rv;
 }
 
-static MP_INLINE 
-void mpxs_apr_table_do(pTHX_ I32 items, SV **MARK, SV **SP) 
+static MP_INLINE void mpxs_apr_table_do(pTHX_ I32 items, SV **MARK, SV **SP)
 {
     apr_table_t *table;
     SV *sub;
     mpxs_table_do_cb_data_t tdata;
     
@@ -82,6 +88,40 @@
     apr_table_do(mpxs_apr_table_do_cb, (void *)&tdata, table, NULL);
     
     /* Free tdata.filter or wait for the pool to go away? */
     
     return; 
+};
+
+static MP_INLINE int apr_table_EXISTS(apr_table_t *t, const char *key)
+{
+    return (NULL == apr_table_get(t, key)) ? 0 : 1;
+}
+
+static MP_INLINE const char *apr_table_FIRSTKEY(SV *tsv)
+{
+    dTHX;
+    apr_table_t *t = mpxs_typemap_input_APR__Table(aTHX_ tsv, NULL);
+
+    if (apr_is_empty_table(t))
+        return NULL;
+       
+       /* Note: SvCUR is used as the iterator state counter, why not ;-? */
+    return ((apr_table_entry_t *) t->a.elts)[SvCUR(SvRV(tsv))++].key;
+}
+
+static MP_INLINE const char *apr_table_NEXTKEY(SV *tsv, SV *p_key)
+{
+    dTHX;
+    apr_table_t *t = mpxs_typemap_input_APR__Table(aTHX_ tsv, NULL);
+
+    if (apr_is_empty_table(t))
+        return NULL;
+
+    if (SvCUR(SvRV(tsv)) < t->a.nelts) {
+               /* Note: SvCUR is used as the iterator state counter, why not ;-? */
+        return ((apr_table_entry_t *) t->a.elts)[((SvCUR(SvRV(tsv)))++)].key;
+    }
+    else {
+        return NULL;
+    }
 }

Index: xs/maps/apr_functions.map
===================================================================
RCS file: /home/anoncvs/mod_perl-2-cvs/xs/maps/apr_functions.map,v
retrieving revision 1.21
diff -u -U5 -b -B -I'$Id' -I'$Revision' -r1.21 apr_functions.map
--- xs/maps/apr_functions.map   2001/09/17 01:06:08     1.21
+++ xs/maps/apr_functions.map   2001/09/23 14:00:24
@@ -189,10 +189,17 @@
 -apr_table_mergen
  apr_table_set
 -apr_table_setn
  apr_table_unset
 -apr_table_vdo
+ apr_table_FETCH
+ apr_table_STORE
+ apr_table_DELETE
+ apr_table_CLEAR
+ apr_table_FIRSTKEY
+ apr_table_NEXTKEY
+ apr_table_EXISTS
 
 !MODULE=APR::File
 -apr_file_open
 -apr_file_close
 -apr_file_namedpipe_create

PGP signature

Reply via email to