Author: joes
Date: Wed Feb 23 13:47:52 2005
New Revision: 155078

URL: http://svn.apache.org/viewcvs?view=rev&rev=155078
Log:

Change v->size semantics: now it represents the total
amount of memory appended to the apreq_value_t struct.
Added supporting apreq_param_nlen(), apreq_param_vlen(), 
apreq_param_size(), apreq_cookie_nlen(), apreq_cookie_vlen(), 
apreq_cookie_size(), apreq_value_table_add().

Also a few more performance tweaks for the new perl APIs.




Added:
    
httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/APR/Request/Cookie/APR__Request__Cookie.h
    
httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/APR/Request/Param/APR__Request__Param.h
Modified:
    httpd/apreq/branches/multi-env-unstable/CHANGES
    httpd/apreq/branches/multi-env-unstable/glue/perl/lib/Apache/Cookie.pm
    httpd/apreq/branches/multi-env-unstable/glue/perl/lib/Apache/Request.pm
    
httpd/apreq/branches/multi-env-unstable/glue/perl/t/response/TestAPI/cookie.pm
    
httpd/apreq/branches/multi-env-unstable/glue/perl/t/response/TestAPI/param.pm
    
httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/APR/Request/Apache2/APR__Request__Apache2.h
    
httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/APR/Request/Cookie/Cookie.xs
    
httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/APR/Request/Param/Param.xs
    
httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/apreq_xs_postperl.h
    
httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/apreq_xs_tables.h
    httpd/apreq/branches/multi-env-unstable/include/apreq.h
    httpd/apreq/branches/multi-env-unstable/include/apreq_cookie.h
    httpd/apreq/branches/multi-env-unstable/include/apreq_param.h
    httpd/apreq/branches/multi-env-unstable/include/apreq_parser.h
    httpd/apreq/branches/multi-env-unstable/library/cookie.c
    httpd/apreq/branches/multi-env-unstable/library/param.c
    httpd/apreq/branches/multi-env-unstable/library/parser_header.c
    httpd/apreq/branches/multi-env-unstable/library/parser_multipart.c
    httpd/apreq/branches/multi-env-unstable/library/parser_urlencoded.c
    httpd/apreq/branches/multi-env-unstable/library/t/params.c
    httpd/apreq/branches/multi-env-unstable/library/util.c
    httpd/apreq/branches/multi-env-unstable/module/test_cgi.c

Modified: httpd/apreq/branches/multi-env-unstable/CHANGES
URL: 
http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/CHANGES?view=diff&r1=155077&r2=155078
==============================================================================
--- httpd/apreq/branches/multi-env-unstable/CHANGES (original)
+++ httpd/apreq/branches/multi-env-unstable/CHANGES Wed Feb 23 13:47:52 2005
@@ -4,6 +4,12 @@
 
 @section v2_05_dev Changes with libapreq2-2.05-dev
 
+- C API [joes]
+  Change v->size semantics: now it represents the total
+  amount of memory appended to the apreq_value_t struct.
+  Added supporting apreq_param_nlen(), apreq_param_vlen(), 
+  apreq_param_size(), apreq_cookie_nlen(), apreq_cookie_vlen(), 
+  apreq_cookie_size(), apreq_value_table_add().
 
 - C API [joes]
   Remove apreq_cookie_attr().

Modified: httpd/apreq/branches/multi-env-unstable/glue/perl/lib/Apache/Cookie.pm
URL: 
http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/glue/perl/lib/Apache/Cookie.pm?view=diff&r1=155077&r2=155078
==============================================================================
--- httpd/apreq/branches/multi-env-unstable/glue/perl/lib/Apache/Cookie.pm 
(original)
+++ httpd/apreq/branches/multi-env-unstable/glue/perl/lib/Apache/Cookie.pm Wed 
Feb 23 13:47:52 2005
@@ -81,6 +81,6 @@
 package Apache::Cookie::Jar;
 use APR::Request::Apache2;
 push our @ISA, qw/APR::Request::Apache2/;
-sub cookies { shift->jar(@_) }
+sub cookies { Apache::Cookie->fetch(shift) }
 
 1;

Modified: 
httpd/apreq/branches/multi-env-unstable/glue/perl/lib/Apache/Request.pm
URL: 
http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/glue/perl/lib/Apache/Request.pm?view=diff&r1=155077&r2=155078
==============================================================================
--- httpd/apreq/branches/multi-env-unstable/glue/perl/lib/Apache/Request.pm 
(original)
+++ httpd/apreq/branches/multi-env-unstable/glue/perl/lib/Apache/Request.pm Wed 
Feb 23 13:47:52 2005
@@ -1,4 +1,5 @@
 package Apache::Request;
+use APR::Request::Param;
 use APR::Request::Apache2;
 use Apache::RequestRec;
 push our @ISA, qw/Apache::RequestRec APR::Request::Apache2/;

Modified: 
httpd/apreq/branches/multi-env-unstable/glue/perl/t/response/TestAPI/cookie.pm
URL: 
http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/glue/perl/t/response/TestAPI/cookie.pm?view=diff&r1=155077&r2=155078
==============================================================================
--- 
httpd/apreq/branches/multi-env-unstable/glue/perl/t/response/TestAPI/cookie.pm 
(original)
+++ 
httpd/apreq/branches/multi-env-unstable/glue/perl/t/response/TestAPI/cookie.pm 
Wed Feb 23 13:47:52 2005
@@ -12,7 +12,7 @@
 
 sub handler {
     my $r = shift;
-    plan $r, tests => 28;
+    plan $r, tests => 30;
     $r->headers_in->{Cookie} = "foo=1;bar=2;foo=3;quux=4";
 
     my $req = APR::Request::Apache2->new($r);
@@ -46,6 +46,7 @@
 
     ok t_cmp join(" ", $jar->get("foo")), "1 3", '$jar->get("foo")';
 
+    ok not defined $jar->cookie_class("APR::Request::Cookie");
     ok t_cmp $_->tainted, 1, "is tainted: $_" for values %$jar;
     $_->tainted(0) for values %$jar;
     ok t_cmp $_->tainted, 0, "not tainted: $_" for values %$jar;
@@ -53,7 +54,7 @@
     eval { $jar->cookie_class("APR::Request::Param") };
     ok t_cmp qr/^Usage/, $@, "Bad class name";
 
-    $jar->cookie_class(__PACKAGE__);
+    ok t_cmp $jar->cookie_class(__PACKAGE__), "APR::Request::Cookie", "class 
upgrade";
     ok $jar->{foo}->isa(__PACKAGE__);
 
     return 0;

Modified: 
httpd/apreq/branches/multi-env-unstable/glue/perl/t/response/TestAPI/param.pm
URL: 
http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/glue/perl/t/response/TestAPI/param.pm?view=diff&r1=155077&r2=155078
==============================================================================
--- 
httpd/apreq/branches/multi-env-unstable/glue/perl/t/response/TestAPI/param.pm 
(original)
+++ 
httpd/apreq/branches/multi-env-unstable/glue/perl/t/response/TestAPI/param.pm 
Wed Feb 23 13:47:52 2005
@@ -13,7 +13,7 @@
 
 sub handler {
     my $r = shift;
-    plan $r, tests => 28;
+    plan $r, tests => 30;
     $r->args("foo=1;bar=2;foo=3;quux=4");
 
     my $req = APR::Request::Apache2->new($r);
@@ -46,6 +46,7 @@
 
     ok t_cmp join(" ", $args->get("foo")), "1 3", '$args->get("foo")';
 
+    ok not defined $args->param_class("APR::Request::Param");
     ok t_cmp $_->tainted, 1, "is tainted: $_" for values %$args;
     $_->tainted(0) for values %$args;
     ok t_cmp $_->tainted, 0, "not tainted: $_" for values %$args;
@@ -54,7 +55,7 @@
     eval { $args->param_class("APR::Request::Cookie") };
     ok t_cmp qr/^Usage/, $@, "Bad class name";
 
-    $args->param_class(__PACKAGE__);
+    ok t_cmp $args->param_class(__PACKAGE__), "APR::Request::Param", "class 
upgrade";
     ok $args->{foo}->isa(__PACKAGE__);
 
     return 0;

Modified: 
httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/APR/Request/Apache2/APR__Request__Apache2.h
URL: 
http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/APR/Request/Apache2/APR__Request__Apache2.h?view=diff&r1=155077&r2=155078
==============================================================================
--- 
httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/APR/Request/Apache2/APR__Request__Apache2.h
 (original)
+++ 
httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/APR/Request/Apache2/APR__Request__Apache2.h
 Wed Feb 23 13:47:52 2005
@@ -1,6 +1,80 @@
 #include "mod_perl.h"
 #include "apreq_xs_tables.h"
-#define TABLE_CLASS "APR::Request::Param"
+#define TABLE_CLASS "APR::Request::Param::Table"
+
+
+
+#if (PERL_VERSION >= 8) /* MAGIC ITERATOR REQUIRES 5.8 */
+
+/* Requires perl 5.8 or better. 
+ * A custom MGVTBL with its "copy" slot filled allows
+ * us to FETCH a table entry immediately during iteration.
+ * For multivalued keys this is essential in order to get
+ * the value corresponding to the current key, otherwise
+ * values() will always report the first value repeatedly.
+ * With this MGVTBL the keys() list always matches up with
+ * the values() list, even in the multivalued case.
+ * We only prefetch the value during iteration, because the
+ * prefetch adds overhead to EXISTS and STORE operations.
+ * They are only "penalized" when the perl program is iterating
+ * via each(), which seems to be a reasonable tradeoff.
+ */
+
+static int apreq_xs_table_magic_copy(pTHX_ SV *sv, MAGIC *mg, SV *nsv, 
+                                  const char *name, int namelen)
+{
+    /* Prefetch the value whenever the table iterator is > 0 */
+    MAGIC *tie_magic = mg_find(nsv, PERL_MAGIC_tiedelem);
+    SV *obj = SvRV(tie_magic->mg_obj);
+    IV idx = SvIVX(obj);
+    const apr_table_t *t = INT2PTR(apr_table_t *, idx);
+    const apr_array_header_t *arr = apr_table_elts(t);
+
+    idx = SvCUR(obj);
+
+    if (idx > 0 && idx <= arr->nelts) {
+        const apr_table_entry_t *te = (const apr_table_entry_t *)arr->elts;
+        const char *param_class = mg_find(obj, PERL_MAGIC_ext)->mg_ptr;
+        apreq_param_t *p = apreq_value_to_param(te[idx-1].val);
+
+        SvMAGICAL_off(nsv);
+        sv_setsv(nsv, sv_2mortal(apreq_xs_param2sv(aTHX_ p, param_class, 
obj)));
+    }
+
+    return 0;
+}
+
+static const MGVTBL apreq_xs_table_magic = {0, 0, 0, 0, 0, 
+                                            apreq_xs_table_magic_copy};
+
+#endif
+
+static APR_INLINE
+SV *apreq_xs_table2sv(pTHX_ const apr_table_t *t, const char *class, SV 
*parent,
+                      const char *value_class, I32 vclen)
+{
+    SV *sv = (SV *)newHV();
+    SV *rv = sv_setref_pv(newSV(0), class, (void *)t);
+    sv_magic(SvRV(rv), parent, PERL_MAGIC_ext, value_class, vclen);
+
+#if (PERL_VERSION >= 8) /* MAGIC ITERATOR requires 5.8 */
+
+    sv_magic(sv, NULL, PERL_MAGIC_ext, Nullch, -1);
+    SvMAGIC(sv)->mg_virtual = (MGVTBL *)&apreq_xs_table_magic;
+    SvMAGIC(sv)->mg_flags |= MGf_COPY;
+
+#endif
+
+    sv_magic(sv, rv, PERL_MAGIC_tied, Nullch, 0);
+    SvREFCNT_dec(rv); /* corrects SvREFCNT_inc(rv) implicit in sv_magic */
+
+    return sv_bless(newRV_noinc(sv), SvSTASH(SvRV(rv)));
+}
+
+
+
+
+
 
 static int apreq_xs_table_keys(void *data, const char *key, const char *val)
 {
@@ -8,7 +82,7 @@
     dTHXa(d->perl);
     dSP;
     apreq_param_t *p = apreq_value_to_param(val);
-    SV *sv = newSVpv(key, 0);
+    SV *sv = newSVpvn(key, apreq_param_nlen(p));
     if (apreq_param_is_tainted(p))
         SvTAINTED_on(sv);
 
@@ -64,10 +138,6 @@
         const apr_table_t *t;
 
         r = modperl_xs_sv2request_rec(aTHX_ sv, "Apache::RequestRec", cv);
-        t = apreq_params(req, r->pool);
-
-        if (t == NULL)
-            XSRETURN_EMPTY;
 
         d.pkg = NULL;
         d.parent = obj;
@@ -77,21 +147,38 @@
         case G_ARRAY:
             XSprePUSH;
             PUTBACK;
-            if (items == 1)
-                apr_table_do(apreq_xs_table_keys, &d, t, NULL);
-            else
-                apr_table_do(apreq_xs_table_values, &d, t, 
-                             SvPV_nolen(ST(1)), NULL);
+            if (items == 1) {
+                apreq_args(req, &t);
+                if (t != NULL)
+                    apr_table_do(apreq_xs_table_keys, &d, t, NULL);
+                apreq_body(req, &t);
+                if (t != NULL)
+                    apr_table_do(apreq_xs_table_keys, &d, t, NULL);
+
+            }
+            else {
+                char *val = SvPV_nolen(ST(1));
+                apreq_args(req, &t);
+                if (t != NULL)
+                    apr_table_do(apreq_xs_table_values, &d, t, val, NULL);
+                apreq_body(req, &t);
+                if (t != NULL)
+                    apr_table_do(apreq_xs_table_values, &d, t, val, NULL);
+            }
             return;
 
         case G_SCALAR:
+            t = apreq_params(req, r->pool);
+            if (t == NULL)
+                XSRETURN_UNDEF;
+
             ST(0) = apreq_xs_table2sv(aTHX_ t, TABLE_CLASS, obj,
-                                      PARAM_CLASS, sizeof(PARAM_CLASS) -1);
+                                      NULL, 0);
             sv_2mortal(ST(0));
             XSRETURN(1);
 
         default:
-           XSRETURN(0);
+            XSRETURN(0);
         }
     }
 }

Added: 
httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/APR/Request/Cookie/APR__Request__Cookie.h
URL: 
http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/APR/Request/Cookie/APR__Request__Cookie.h?view=auto&rev=155078
==============================================================================
--- 
httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/APR/Request/Cookie/APR__Request__Cookie.h
 (added)
+++ 
httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/APR/Request/Cookie/APR__Request__Cookie.h
 Wed Feb 23 13:47:52 2005
@@ -0,0 +1,68 @@
+
+#if (PERL_VERSION >= 8) /* MAGIC ITERATOR REQUIRES 5.8 */
+
+/* Requires perl 5.8 or better. 
+ * A custom MGVTBL with its "copy" slot filled allows
+ * us to FETCH a table entry immediately during iteration.
+ * For multivalued keys this is essential in order to get
+ * the value corresponding to the current key, otherwise
+ * values() will always report the first value repeatedly.
+ * With this MGVTBL the keys() list always matches up with
+ * the values() list, even in the multivalued case.
+ * We only prefetch the value during iteration, because the
+ * prefetch adds overhead to EXISTS and STORE operations.
+ * They are only "penalized" when the perl program is iterating
+ * via each(), which seems to be a reasonable tradeoff.
+ */
+
+static int apreq_xs_table_magic_copy(pTHX_ SV *sv, MAGIC *mg, SV *nsv, 
+                                  const char *name, int namelen)
+{
+    /* Prefetch the value whenever the table iterator is > 0 */
+    MAGIC *tie_magic = mg_find(nsv, PERL_MAGIC_tiedelem);
+    SV *obj = SvRV(tie_magic->mg_obj);
+    IV idx = SvIVX(obj);
+    const apr_table_t *t = INT2PTR(apr_table_t *, idx);
+    const apr_array_header_t *arr = apr_table_elts(t);
+
+    idx = SvCUR(obj);
+
+    if (idx > 0 && idx <= arr->nelts) {
+        const apr_table_entry_t *te = (const apr_table_entry_t *)arr->elts;
+        const char *cookie_class = mg_find(obj, PERL_MAGIC_ext)->mg_ptr;
+        apreq_cookie_t *c = apreq_value_to_cookie(te[idx-1].val);
+        SV *parent = mg_find(obj, PERL_MAGIC_ext)->mg_obj;
+
+        SvMAGICAL_off(nsv);
+        sv_setsv(nsv, sv_2mortal(apreq_xs_cookie2sv(aTHX_ c, cookie_class, 
parent)));
+    }
+
+    return 0;
+}
+
+static const MGVTBL apreq_xs_table_magic = {0, 0, 0, 0, 0, 
+                                            apreq_xs_table_magic_copy};
+
+#endif
+
+static APR_INLINE
+SV *apreq_xs_table2sv(pTHX_ const apr_table_t *t, const char *class, SV 
*parent,
+                      const char *value_class, I32 vclen)
+{
+    SV *sv = (SV *)newHV();
+    SV *rv = sv_setref_pv(newSV(0), class, (void *)t);
+    sv_magic(SvRV(rv), parent, PERL_MAGIC_ext, value_class, vclen);
+
+#if (PERL_VERSION >= 8) /* MAGIC ITERATOR requires 5.8 */
+
+    sv_magic(sv, NULL, PERL_MAGIC_ext, Nullch, -1);
+    SvMAGIC(sv)->mg_virtual = (MGVTBL *)&apreq_xs_table_magic;
+    SvMAGIC(sv)->mg_flags |= MGf_COPY;
+
+#endif
+
+    sv_magic(sv, rv, PERL_MAGIC_tied, Nullch, 0);
+    SvREFCNT_dec(rv); /* corrects SvREFCNT_inc(rv) implicit in sv_magic */
+
+    return sv_bless(newRV_noinc(sv), SvSTASH(SvRV(rv)));
+}

Modified: 
httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/APR/Request/Cookie/Cookie.xs
URL: 
http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/APR/Request/Cookie/Cookie.xs?view=diff&r1=155077&r2=155078
==============================================================================
--- 
httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/APR/Request/Cookie/Cookie.xs
 (original)
+++ 
httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/APR/Request/Cookie/Cookie.xs
 Wed Feb 23 13:47:52 2005
@@ -92,8 +92,7 @@
             return;
 
         case G_SCALAR:
-            ST(0) = apreq_xs_table2sv(aTHX_ t, TABLE_CLASS, obj,
-                                      COOKIE_CLASS, sizeof(COOKIE_CLASS)-1);
+            ST(0) = apreq_xs_table2sv(aTHX_ t, TABLE_CLASS, obj, NULL, 0);
             sv_2mortal(ST(0));
             XSRETURN(1);
 
@@ -159,8 +158,7 @@
         d.parent = parent;
         XSprePUSH;
         PUTBACK;
-        apr_table_do(apreq_xs_table_values, &d, t, 
-                     SvPV_nolen(ST(1)), NULL);
+        apr_table_do(apreq_xs_table_values, &d, t, SvPV_nolen(ST(1)), NULL);
     }
     else
         XSRETURN(0);
@@ -219,7 +217,7 @@
     /*nada*/
 
   CODE:
-    RETVAL = newSVpvn(obj->v.data, obj->v.size);
+    RETVAL = newSVpvn(obj->v.data, apreq_cookie_vlen(obj));
     if (apreq_cookie_is_tainted(obj))
         SvTAINTED_on(RETVAL);
 
@@ -249,7 +247,7 @@
     APR::Request::Cookie obj
 
   CODE:
-    RETVAL = newSVpv(obj->v.name, 0);
+    RETVAL = newSVpvn(obj->v.name, apreq_cookie_nlen(obj));
     if (apreq_cookie_is_tainted(obj))
         SvTAINTED_on(RETVAL);
 
@@ -367,20 +365,26 @@
 cookie_class(t, newclass=NULL)
     APR::Request::Cookie::Table t
     char *newclass
+
   PREINIT:
     SV *obj = apreq_xs_sv2object(aTHX_ ST(0), TABLE_CLASS, 't');
     MAGIC *mg = mg_find(obj, PERL_MAGIC_ext);
     char *curclass = mg->mg_ptr;
 
   CODE:
-    RETVAL = newSVpv(curclass, 0);
-    if (items == 2) {
-        if (!sv_derived_from(ST(1), curclass))
+    RETVAL = (curclass == NULL) ? &PL_sv_undef : newSVpv(curclass, 0);
+
+    if (newclass != NULL) {
+        if (!sv_derived_from(ST(1), COOKIE_CLASS))
             Perl_croak(aTHX_ "Usage: " TABLE_CLASS "::cookie_class($table, 
$class): "
-                             "class %s is not derived from %s", newclass, 
curclass);
-        Safefree(curclass);
+                             "class %s is not derived from " COOKIE_CLASS, 
newclass);
         mg->mg_ptr = savepv(newclass);
+        mg->mg_len = strlen(newclass);
+
+        if (curclass != NULL)
+            Safefree(curclass);
     }
 
   OUTPUT:
     RETVAL
+

Added: 
httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/APR/Request/Param/APR__Request__Param.h
URL: 
http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/APR/Request/Param/APR__Request__Param.h?view=auto&rev=155078
==============================================================================
--- 
httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/APR/Request/Param/APR__Request__Param.h
 (added)
+++ 
httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/APR/Request/Param/APR__Request__Param.h
 Wed Feb 23 13:47:52 2005
@@ -0,0 +1,67 @@
+
+#if (PERL_VERSION >= 8) /* MAGIC ITERATOR REQUIRES 5.8 */
+
+/* Requires perl 5.8 or better. 
+ * A custom MGVTBL with its "copy" slot filled allows
+ * us to FETCH a table entry immediately during iteration.
+ * For multivalued keys this is essential in order to get
+ * the value corresponding to the current key, otherwise
+ * values() will always report the first value repeatedly.
+ * With this MGVTBL the keys() list always matches up with
+ * the values() list, even in the multivalued case.
+ * We only prefetch the value during iteration, because the
+ * prefetch adds overhead to EXISTS and STORE operations.
+ * They are only "penalized" when the perl program is iterating
+ * via each(), which seems to be a reasonable tradeoff.
+ */
+
+static int apreq_xs_table_magic_copy(pTHX_ SV *sv, MAGIC *mg, SV *nsv, 
+                                  const char *name, int namelen)
+{
+    /* Prefetch the value whenever the table iterator is > 0 */
+    MAGIC *tie_magic = mg_find(nsv, PERL_MAGIC_tiedelem);
+    SV *obj = SvRV(tie_magic->mg_obj);
+    IV idx = SvIVX(obj);
+    const apr_table_t *t = INT2PTR(apr_table_t *, idx);
+    const apr_array_header_t *arr = apr_table_elts(t);
+
+    idx = SvCUR(obj);
+
+    if (idx > 0 && idx <= arr->nelts) {
+        const apr_table_entry_t *te = (const apr_table_entry_t *)arr->elts;
+        const char *param_class = mg_find(obj, PERL_MAGIC_ext)->mg_ptr;
+        apreq_param_t *p = apreq_value_to_param(te[idx-1].val);
+
+        SvMAGICAL_off(nsv);
+        sv_setsv(nsv, sv_2mortal(apreq_xs_param2sv(aTHX_ p, param_class, 
obj)));
+    }
+
+    return 0;
+}
+
+static const MGVTBL apreq_xs_table_magic = {0, 0, 0, 0, 0, 
+                                            apreq_xs_table_magic_copy};
+
+#endif
+
+static APR_INLINE
+SV *apreq_xs_table2sv(pTHX_ const apr_table_t *t, const char *class, SV 
*parent,
+                      const char *value_class, I32 vclen)
+{
+    SV *sv = (SV *)newHV();
+    SV *rv = sv_setref_pv(newSV(0), class, (void *)t);
+    sv_magic(SvRV(rv), parent, PERL_MAGIC_ext, value_class, vclen);
+
+#if (PERL_VERSION >= 8) /* MAGIC ITERATOR requires 5.8 */
+
+    sv_magic(sv, NULL, PERL_MAGIC_ext, Nullch, -1);
+    SvMAGIC(sv)->mg_virtual = (MGVTBL *)&apreq_xs_table_magic;
+    SvMAGIC(sv)->mg_flags |= MGf_COPY;
+
+#endif
+
+    sv_magic(sv, rv, PERL_MAGIC_tied, Nullch, 0);
+    SvREFCNT_dec(rv); /* corrects SvREFCNT_inc(rv) implicit in sv_magic */
+
+    return sv_bless(newRV_noinc(sv), SvSTASH(SvRV(rv)));
+}

Modified: 
httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/APR/Request/Param/Param.xs
URL: 
http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/APR/Request/Param/Param.xs?view=diff&r1=155077&r2=155078
==============================================================================
--- 
httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/APR/Request/Param/Param.xs
 (original)
+++ 
httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/APR/Request/Param/Param.xs
 Wed Feb 23 13:47:52 2005
@@ -7,7 +7,7 @@
     dTHXa(d->perl);
     dSP;
     apreq_param_t *p = apreq_value_to_param(val);
-    SV *sv = newSVpv(key, 0);
+    SV *sv = newSVpvn(key, apreq_param_nlen(p));
     if (apreq_param_is_tainted(p))
         SvTAINTED_on(sv);
 
@@ -94,8 +94,7 @@
             return;
 
         case G_SCALAR:
-            ST(0) = apreq_xs_table2sv(aTHX_ t, TABLE_CLASS, obj,
-                                      PARAM_CLASS, sizeof(PARAM_CLASS) -1);
+            ST(0) = apreq_xs_table2sv(aTHX_ t, TABLE_CLASS, obj, NULL, 0);
             sv_2mortal(ST(0));
             XSRETURN(1);
 
@@ -170,8 +169,7 @@
             return;
 
         case G_SCALAR:
-            ST(0) = apreq_xs_table2sv(aTHX_ t, TABLE_CLASS, obj,
-                                      PARAM_CLASS, sizeof(PARAM_CLASS)-1);
+            ST(0) = apreq_xs_table2sv(aTHX_ t, TABLE_CLASS, obj, NULL, 0);
             sv_2mortal(ST(0));
             XSRETURN(1);
 
@@ -239,8 +237,7 @@
         d.parent = parent;
         XSprePUSH;
         PUTBACK;
-        apr_table_do(apreq_xs_table_values, &d, t, 
-                     SvPV_nolen(ST(1)), NULL);
+        apr_table_do(apreq_xs_table_values, &d, t, SvPV_nolen(ST(1)), NULL);
     }
     else
         XSRETURN(0);
@@ -299,7 +296,7 @@
     /*nada*/
 
   CODE:
-    RETVAL = newSVpvn(obj->v.data, obj->v.size);
+    RETVAL = newSVpvn(obj->v.data, apreq_param_vlen(obj));
     if (apreq_param_is_tainted(obj))
         SvTAINTED_on(RETVAL);
 
@@ -329,7 +326,7 @@
     APR::Request::Param obj
 
   CODE:
-    RETVAL = newSVpv(obj->v.name, 0);
+    RETVAL = newSVpvn(obj->v.name, apreq_param_nlen(obj));
     if (apreq_param_is_tainted(obj))
         SvTAINTED_on(RETVAL);
 
@@ -385,19 +382,24 @@
 param_class(t, newclass=NULL)
     APR::Request::Param::Table t
     char *newclass
+
   PREINIT:
     SV *obj = apreq_xs_sv2object(aTHX_ ST(0), TABLE_CLASS, 't');
     MAGIC *mg = mg_find(obj, PERL_MAGIC_ext);
     char *curclass = mg->mg_ptr;
 
   CODE:
-    RETVAL = newSVpv(curclass, 0);
-    if (items == 2) {
-        if (!sv_derived_from(ST(1), curclass))
+    RETVAL = (curclass == NULL) ? &PL_sv_undef : newSVpv(curclass, 0);
+
+    if (newclass != NULL) {
+        if (!sv_derived_from(ST(1), PARAM_CLASS))
             Perl_croak(aTHX_ "Usage: " TABLE_CLASS "::param_class($table, 
$class): "
-                             "class %s is not derived from %s", newclass, 
curclass);
-        Safefree(curclass);
+                             "class %s is not derived from " PARAM_CLASS, 
newclass);
         mg->mg_ptr = savepv(newclass);
+        mg->mg_len = strlen(newclass);
+
+        if (curclass != NULL)
+            Safefree(curclass);
     }
 
   OUTPUT:
@@ -445,8 +447,7 @@
     iv = SvIVX(obj);
     req = INT2PTR(apreq_handle_t *, iv);
     t = apreq_params(req, pool);
-    RETVAL = apreq_xs_table2sv(aTHX_ t, TABLE_CLASS, obj, 
-                               PARAM_CLASS, sizeof(PARAM_CLASS)-1);
+    RETVAL = apreq_xs_table2sv(aTHX_ t, TABLE_CLASS, obj, NULL, 0);
 
   OUTPUT:
     RETVAL

Modified: 
httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/apreq_xs_postperl.h
URL: 
http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/apreq_xs_postperl.h?view=diff&r1=155077&r2=155078
==============================================================================
--- 
httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/apreq_xs_postperl.h 
(original)
+++ 
httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/apreq_xs_postperl.h 
Wed Feb 23 13:47:52 2005
@@ -142,7 +142,7 @@
                               const char *class, SV *parent)
 {
     if (class == NULL) {
-        SV *rv = newSVpvn(p->v.data, p->v.size);
+        SV *rv = newSVpvn(p->v.data, apreq_param_vlen(p));
         if (apreq_param_is_tainted(p))
             SvTAINTED_on(rv);
         /*XXX add charset fixups */
@@ -157,7 +157,7 @@
                               const char *class, SV *parent)
 {
     if (class == NULL) {
-        SV *rv = newSVpvn(c->v.data, c->v.size);
+        SV *rv = newSVpvn(c->v.data, apreq_cookie_vlen(c));
         if (apreq_cookie_is_tainted(c))
             SvTAINTED_on(rv);
         /*XXX add charset fixups? */

Modified: 
httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/apreq_xs_tables.h
URL: 
http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/apreq_xs_tables.h?view=diff&r1=155077&r2=155078
==============================================================================
--- 
httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/apreq_xs_tables.h 
(original)
+++ 
httpd/apreq/branches/multi-env-unstable/glue/perl/xsbuilder/apreq_xs_tables.h 
Wed Feb 23 13:47:52 2005
@@ -21,40 +21,6 @@
 
 #include "ppport.h"
 
-
-#if (PERL_VERSION >= 8) /* MAGIC ITERATOR REQUIRES 5.8 */
-
-/* Requires perl 5.8 or better. 
- * A custom MGVTBL with its "copy" slot filled allows
- * us to FETCH a table entry immediately during iteration.
- * For multivalued keys this is essential in order to get
- * the value corresponding to the current key, otherwise
- * values() will always report the first value repeatedly.
- * With this MGVTBL the keys() list always matches up with
- * the values() list, even in the multivalued case.
- * We only prefetch the value during iteration, because the
- * prefetch adds overhead to EXISTS and STORE operations.
- * They are only "penalized" when the perl program is iterating
- * via each(), which seems to be a reasonable tradeoff.
- */
-
-
-static int apreq_xs_table_magic_copy(pTHX_ SV *sv, MAGIC *mg, SV *nsv, 
-                                  const char *name, int namelen)
-{
-    /* Prefetch the value whenever the table iterator is > 0 */
-    MAGIC *tie_magic = mg_find(nsv, PERL_MAGIC_tiedelem);
-    SV *obj = SvRV(tie_magic->mg_obj);
-    if (SvCUR(obj))
-        SvGETMAGIC(nsv);
-    return 0;
-}
-
-static const MGVTBL apreq_xs_table_magic = {0, 0, 0, 0, 0, 
-                                            apreq_xs_table_magic_copy};
-
-#endif
-
 /**
  * Converts a C object, with environment, to a TIEHASH object.
  * @param obj C object.
@@ -63,27 +29,6 @@
  * @return Reference to a new TIEHASH object in class.
  */
 
-static APR_INLINE
-SV *apreq_xs_table2sv(pTHX_ const apr_table_t *t, const char *class, SV 
*parent,
-                      const char *value_class, I32 vclen)
-{
-    SV *sv = (SV *)newHV();
-    SV *rv = sv_setref_pv(newSV(0), class, (void *)t);
-    sv_magic(SvRV(rv), parent, PERL_MAGIC_ext, value_class, vclen);
-
-#if (PERL_VERSION >= 8) /* MAGIC ITERATOR requires 5.8 */
-
-    sv_magic(sv, NULL, PERL_MAGIC_ext, Nullch, -1);
-    SvMAGIC(sv)->mg_virtual = (MGVTBL *)&apreq_xs_table_magic;
-    SvMAGIC(sv)->mg_flags |= MGf_COPY;
-
-#endif
-
-    sv_magic(sv, rv, PERL_MAGIC_tied, Nullch, 0);
-    SvREFCNT_dec(rv); /* corrects SvREFCNT_inc(rv) implicit in sv_magic */
-
-    return sv_bless(newRV_noinc(sv), SvSTASH(SvRV(rv)));
-}
 
 
 /*#define apreq_xs_sv2table(sv)      ((apr_table_t *) SvIVX(SvRV(sv)))

Modified: httpd/apreq/branches/multi-env-unstable/include/apreq.h
URL: 
http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/include/apreq.h?view=diff&r1=155077&r2=155078
==============================================================================
--- httpd/apreq/branches/multi-env-unstable/include/apreq.h (original)
+++ httpd/apreq/branches/multi-env-unstable/include/apreq.h Wed Feb 23 13:47:52 
2005
@@ -17,6 +17,10 @@
 #ifndef APREQ_H
 #define APREQ_H
 
+#ifdef APREQ_DEBUG
+#include <assert.h>
+#endif
+
 #include "apr_tables.h"
 #include <stddef.h>
 
@@ -88,9 +92,17 @@
 /** @brief libapreq's pre-extensible string type */
 typedef struct apreq_value_t {
     char             *name;    /**< value name */
-    apr_size_t        size;    /**< value length (in bytes) */
+    apr_size_t        size;    /**< total size (nlen + dlen + 1) */
     char              data[1]; /**< value data  */
 } apreq_value_t;
+
+static APR_INLINE
+void apreq_value_table_add(const apreq_value_t *v, apr_table_t *t) {
+#ifdef APREQ_DEBUG
+    assert(v->size == (v->name - v->data) + strlen(v->name));
+#endif
+    apr_table_addn(t, v->name, v->data);
+}
 
 #define apreq_attr_to_type(T,A,P) ( (T*) ((char*)(P)-offsetof(T,A)) )
 

Modified: httpd/apreq/branches/multi-env-unstable/include/apreq_cookie.h
URL: 
http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/include/apreq_cookie.h?view=diff&r1=155077&r2=155078
==============================================================================
--- httpd/apreq/branches/multi-env-unstable/include/apreq_cookie.h (original)
+++ httpd/apreq/branches/multi-env-unstable/include/apreq_cookie.h Wed Feb 23 
13:47:52 2005
@@ -60,6 +60,8 @@
 
 } apreq_cookie_t;
 
+APREQ_DECLARE(apr_size_t)apreq_cookie_size(const apreq_cookie_t *c);
+
 
 /** Upgrades cookie jar table values to apreq_cookie_t structs. */
 static APR_INLINE
@@ -71,6 +73,17 @@
     return apreq_attr_to_type(apreq_cookie_t, v,
            apreq_attr_to_type(apreq_value_t, data, deconst.out));
 }
+
+static APR_INLINE
+apr_size_t apreq_cookie_nlen(const apreq_cookie_t *c) {
+    return c->v.size - (c->v.name - c->v.data);
+}
+
+static APR_INLINE
+apr_size_t apreq_cookie_vlen(const apreq_cookie_t *c) {
+    return (c->v.name - c->v.data) - 1;
+}
+
 
 /[EMAIL PROTECTED] 1 if this is an RFC cookie, 0 if its a Netscape cookie. */
 static APR_INLINE

Modified: httpd/apreq/branches/multi-env-unstable/include/apreq_param.h
URL: 
http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/include/apreq_param.h?view=diff&r1=155077&r2=155078
==============================================================================
--- httpd/apreq/branches/multi-env-unstable/include/apreq_param.h (original)
+++ httpd/apreq/branches/multi-env-unstable/include/apreq_param.h Wed Feb 23 
13:47:52 2005
@@ -37,9 +37,21 @@
     apr_table_t         *info;   /**< header table associated with the param */
     apr_bucket_brigade  *upload; /**< brigade used to spool upload files */
     unsigned             flags;  /**< charsets, taint marks, app-specific bits 
*/
-    const apreq_value_t  v;      /**< underlying name/value/status info */
+    const apreq_value_t  v;      /**< underlying name/value info */
 } apreq_param_t;
 
+static APR_INLINE
+apr_size_t apreq_param_nlen(const apreq_param_t *p) {
+    return p->v.size - (p->v.name - p->v.data);
+}
+
+static APR_INLINE
+apr_size_t apreq_param_vlen(const apreq_param_t *p) {
+    return (p->v.name - p->v.data) - 1;
+}
+
+APREQ_DECLARE(apr_size_t)apreq_param_size(const apreq_param_t *p);
+
 
 /** @return 1 if the taint flag is set, 0 otherwise. */
 static APR_INLINE
@@ -72,6 +84,7 @@
 }
 
 
+
 /** creates a param from name/value information */
 APREQ_DECLARE(apreq_param_t *) apreq_param_make(apr_pool_t *p,
                                                 const char *name,
@@ -92,8 +105,8 @@
 APREQ_DECLARE(apr_status_t) apreq_param_decode(apreq_param_t **param,
                                                apr_pool_t *pool,
                                                const char *word,
-                                               const apr_size_t nlen,
-                                               const apr_size_t vlen);
+                                               apr_size_t nlen,
+                                               apr_size_t vlen);
 
 /**
  * Url-encodes the param into a name-value pair.

Modified: httpd/apreq/branches/multi-env-unstable/include/apreq_parser.h
URL: 
http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/include/apreq_parser.h?view=diff&r1=155077&r2=155078
==============================================================================
--- httpd/apreq/branches/multi-env-unstable/include/apreq_parser.h (original)
+++ httpd/apreq/branches/multi-env-unstable/include/apreq_parser.h Wed Feb 23 
13:47:52 2005
@@ -79,8 +79,6 @@
 };
 
 
-
-
 /**
  * Parse the incoming brigade into a table.  Parsers normally
  * consume all the buckets of the brigade during parsing. However

Modified: httpd/apreq/branches/multi-env-unstable/library/cookie.c
URL: 
http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/library/cookie.c?view=diff&r1=155077&r2=155078
==============================================================================
--- httpd/apreq/branches/multi-env-unstable/library/cookie.c (original)
+++ httpd/apreq/branches/multi-env-unstable/library/cookie.c Wed Feb 23 
13:47:52 2005
@@ -21,11 +21,30 @@
 #include "apr_lib.h"
 #include "apr_date.h"
 
+
 #define RFC      1
 #define NETSCAPE 0
 
-#define ADD_COOKIE(j,c) apr_table_addn(j, c->v.name, c->v.data)
+#define ADD_COOKIE(j,c) apreq_value_table_add(&c->v, j)
+
+APREQ_DECLARE(apr_size_t)apreq_cookie_size(const apreq_cookie_t *c)
+{
+    apr_size_t alen = 0;
+
+    if (c->path != NULL)
+        alen += strlen(c->path);
+    if (c->domain != NULL)
+        alen += strlen(c->domain);
+    if (c->port != NULL)
+        alen += strlen(c->port);
+    if (c->comment != NULL)
+        alen += strlen(c->comment);
+    if (c->commentURL != NULL)
+        alen += strlen(c->commentURL);
 
+    return (apr_size_t)alen + c->v.size + sizeof *c;
+
+}
  
 APREQ_DECLARE(void) apreq_cookie_expires(apreq_cookie_t *c, 
                                          const char *time_str)
@@ -138,14 +157,15 @@
         return NULL;
 
     *(const apreq_value_t **)&v = &c->v;
+    v->size = nlen + vlen + 1;
 
-    v->size = vlen;
-
-    memcpy(v->data, value, vlen);
+    if (vlen > 0 && value != NULL)
+        memcpy(v->data, value, vlen);
     v->data[vlen] = 0;
 
     v->name = v->data + vlen + 1;
-    memcpy (v->name, name, nlen);
+    if (name != NULL)
+        memcpy (v->name, name, nlen);
     v->name[nlen] = 0;
 
     /* session cookie is the default */

Modified: httpd/apreq/branches/multi-env-unstable/library/param.c
URL: 
http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/library/param.c?view=diff&r1=155077&r2=155078
==============================================================================
--- httpd/apreq/branches/multi-env-unstable/library/param.c (original)
+++ httpd/apreq/branches/multi-env-unstable/library/param.c Wed Feb 23 13:47:52 
2005
@@ -24,23 +24,32 @@
 #define MAX_BRIGADE_LEN (1024 * 256)
 #define MAX_READ_AHEAD  (1024 * 64)
 
+
 APREQ_DECLARE(apreq_param_t *) apreq_param_make(apr_pool_t *p, 
                                                 const char *name,
                                                 const apr_size_t nlen, 
                                                 const char *val,
                                                 const apr_size_t vlen)
 {
-    apreq_param_t *param = apr_palloc(p, nlen + vlen + 1 + sizeof *param);
+    apreq_param_t *param;
     apreq_value_t *v;
+
+    param = apr_palloc(p, nlen + vlen + 1 + sizeof *param);
+
+    if (param == NULL || nlen == 0)
+        return NULL;
+
     param->info = NULL;
     param->upload = NULL;
     param->flags = 0; 
 
     *(const apreq_value_t **)&v = &param->v;
-    v->size = vlen;
+    v->size = vlen + nlen + 1;
+
     if (vlen && val != NULL)
         memcpy(v->data, val, vlen);
     v->data[vlen] = 0;
+
     v->name = v->data + vlen + 1;
     if (nlen && name != NULL)
         memcpy(v->name, name, nlen);
@@ -49,20 +58,42 @@
     return param;
 }
 
+static int elt_size(void *data, const char *key, const char *val)
+{
+    apr_size_t *s = data;
+    *s = strlen(key) + strlen(val);
+    return 1; /* keep searching */
+}
+
+APREQ_DECLARE(apr_size_t)apreq_param_size(const apreq_param_t *p)
+{
+    apr_size_t tlen = 0;
+    apr_off_t blen = 0;
+
+    if (p->info != NULL)
+        apr_table_do(elt_size, &tlen, p->info, NULL);
+    if (p->upload != NULL)
+        apr_brigade_length(p->upload, 0, &blen);
+
+    return (apr_size_t)blen + tlen + p->v.size + sizeof *p;
+
+}
+
 
 APREQ_DECLARE(apr_status_t) apreq_param_decode(apreq_param_t **param,
                                                apr_pool_t *pool,
                                                const char *word,
-                                               const apr_size_t nlen,
-                                               const apr_size_t vlen)
+                                               apr_size_t nlen,
+                                               apr_size_t vlen)
 {
     apr_status_t status;
     apreq_value_t *v;
     apreq_param_t *p;
-    apr_size_t size;
 
-    if (nlen == 0)
+    if (nlen == 0) {
+        *param = NULL;
         return APR_EBADARG;
+    }
 
     p = apr_palloc(pool, nlen + vlen + 1 + sizeof *p);
     p->info = NULL;
@@ -70,7 +101,7 @@
     *(const apreq_value_t **)&v = &p->v;
 
     if (vlen > 0) {
-        status = apreq_decode(v->data, &v->size, word + nlen + 1, vlen);
+        status = apreq_decode(v->data, &vlen, word + nlen + 1, vlen);
         if (status != APR_SUCCESS) {
             *param = NULL;
             return status;
@@ -78,33 +109,36 @@
     }
     else {
         v->data[0] = 0;
-        v->size    = 0;
     }
-    v->name = v->data + v->size + 1;
+    v->name = v->data + vlen + 1;
+
+    status = apreq_decode(v->name, &nlen, word, nlen);
+    if (status != APR_SUCCESS) {
+        *param = NULL;
+        return status;
+    }
+    v->size = nlen + vlen + 1;
     *param = p;
 
-    return apreq_decode(v->name, &size, word, nlen);
+    return APR_SUCCESS;
 }
 
 
 APREQ_DECLARE(char *) apreq_param_encode(apr_pool_t *pool,
                                          const apreq_param_t *param)
 {
-    apreq_value_t *v;
-    apr_size_t nlen;
-
-    if (param->v.name == NULL)
-        return NULL;
+    apr_size_t dlen, nlen, vlen;
+    char *data;
 
-    nlen = strlen(param->v.name);
+    nlen = apreq_param_nlen(param);
+    vlen = apreq_param_vlen(param);
 
-    v = apr_palloc(pool, 3 * (nlen + param->v.size) + 2 + sizeof *v);
-    v->name = param->v.name;
-    v->size = apreq_encode(v->data, param->v.name, nlen);
-    v->data[v->size++] = '=';
-    v->size += apreq_encode(v->data + v->size, param->v.data, param->v.size);
+    data = apr_palloc(pool, 3 * (nlen + vlen) + 2);
+    dlen = apreq_encode(data, param->v.name, nlen);
+    data[dlen++] = '=';
+    dlen += apreq_encode(data + dlen, param->v.data, vlen);
 
-    return v->data;
+    return data;
 }
 
 APREQ_DECLARE(apr_status_t) apreq_parse_query_string(apr_pool_t *pool,
@@ -140,7 +174,7 @@
                     return s;
 
                 APREQ_FLAGS_ON(param->flags, APREQ_TAINT);
-                apr_table_addn(t, param->v.name, param->v.data);
+                apreq_value_table_add(&param->v, t);
             }
 
             if (*qs == 0)
@@ -205,7 +239,7 @@
     apreq_param_t *p = apreq_value_to_param(val);
 
     if (p->upload != NULL)
-        apr_table_addn(t, key, val);
+        apreq_value_table_add(&p->v, t);
     return 1;   /* keep going */
 }
 

Modified: httpd/apreq/branches/multi-env-unstable/library/parser_header.c
URL: 
http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/library/parser_header.c?view=diff&r1=155077&r2=155078
==============================================================================
--- httpd/apreq/branches/multi-env-unstable/library/parser_header.c (original)
+++ httpd/apreq/branches/multi-env-unstable/library/parser_header.c Wed Feb 23 
13:47:52 2005
@@ -13,7 +13,7 @@
 **  See the License for the specific language governing permissions and
 **  limitations under the License.
 */
-
+#include <assert.h>
 #include "apreq_parser.h"
 #include "apreq_error.h"
 #include "apreq_util.h"
@@ -47,91 +47,101 @@
 static apr_status_t split_header_line(apreq_param_t **p,
                                       apr_pool_t *pool, 
                                       apr_bucket_brigade *bb,
-                                      const apr_size_t nlen, 
-                                      const apr_size_t glen,
-                                      const apr_size_t vlen)
+                                      apr_size_t nlen, 
+                                      apr_size_t glen,
+                                      apr_size_t vlen)
 {
     apreq_param_t *param;
     apreq_value_t *v;
-    apr_size_t off;
+    apr_bucket *e, *f;
+    apr_status_t s;
+    struct iovec vec[APREQ_DEFAULT_NELTS], *iov, *end;
+    apr_array_header_t arr;
+    char *dest;
+    const char *data;
+    apr_size_t dlen;
 
     if (nlen == 0)
         return APR_EBADARG;
 
-    param = apreq_param_make(pool, NULL, nlen, NULL, vlen);
+    param = apreq_param_make(pool, NULL, nlen, NULL, vlen - 1); /*drop (CR)LF 
*/ 
     *(const apreq_value_t **)&v = &param->v;
 
-    off = 0;
-    while (off < nlen) {
-        apr_size_t dlen;
-        const char *data;
-        apr_bucket *f = APR_BRIGADE_FIRST(bb);
-        apr_status_t s = apr_bucket_read(f, &data, &dlen, APR_BLOCK_READ);
-
-        if ( s != APR_SUCCESS )
+    arr.pool     = pool;
+    arr.elt_size = sizeof(struct iovec);
+    arr.nelts    = 0;
+    arr.nalloc   = APREQ_DEFAULT_NELTS;
+    arr.elts     = (char *)vec;
+
+    e = APR_BRIGADE_FIRST(bb);
+
+    /* store name in a temporary iovec array */
+
+    while (nlen > 0) {        
+        apr_size_t len;
+        end = apr_array_push(&arr);
+        s = apr_bucket_read(e, (const char **)&end->iov_base,
+                            &len, APR_BLOCK_READ);
+        if (s != APR_SUCCESS)
             return s;
 
-        if (dlen > nlen - off) {
-            apr_bucket_split(f, nlen - off);
-            dlen = nlen - off;
-        }
+        assert(nlen >= len);
+        end->iov_len = len;
+        nlen -= len;
 
-        memcpy(v->name + off, data, dlen);
-        off += dlen;
-        apr_bucket_delete(f);
+        e = APR_BUCKET_NEXT(e);
     }
 
     /* skip gap */
 
-    off = 0;
-    while (off < glen) {
-        apr_size_t dlen;
-        const char *data;
-        apr_bucket *f = APR_BRIGADE_FIRST(bb);
-        apr_status_t s = apr_bucket_read(f, &data, &dlen, APR_BLOCK_READ);
-
-        if ( s != APR_SUCCESS )
+    while (glen > 0) {
+        s = apr_bucket_read(e, &data, &dlen, APR_BLOCK_READ);
+        if (s != APR_SUCCESS)
             return s;
 
-        if (dlen > glen - off) {
-            apr_bucket_split(f, glen - off);
-            dlen = glen - off;
-        }
-
-        off += dlen;
-        apr_bucket_delete(f);
+        assert(glen >= dlen);
+        glen -= dlen;
+        e = APR_BUCKET_NEXT(e);
     }
 
     /* copy value */
+    assert(vlen > 0);
+    dest = v->data;
+    while (vlen > 0) {
 
-    off = 0;
-    while (off < vlen) {
-        apr_size_t dlen;
-        const char *data;
-        apr_bucket *f = APR_BRIGADE_FIRST(bb);
-        apr_status_t s = apr_bucket_read(f, &data, &dlen, APR_BLOCK_READ);
-
-        if ( s != APR_SUCCESS )
+        s = apr_bucket_read(e, &data, &dlen, APR_BLOCK_READ);
+        if (s != APR_SUCCESS)
             return s;
 
-        if (dlen > vlen - off) {
-            apr_bucket_split(f, vlen - off);
-            dlen = vlen - off;
-        }
-
-        memcpy(v->data + off, data, dlen);
-        off += dlen;
-        apr_bucket_delete(f);
+        memcpy(dest, data, dlen);
+        dest += dlen;
+        assert(vlen >= dlen);
+        vlen -= dlen;
+        e = APR_BUCKET_NEXT(e);
     }
 
-    v->name[nlen] = 0;
+    assert(dest[-1] == '\n');
+
+    if (dest[-2] == '\r')
+        --dest;
+
+    dest[-1] = 0;
 
-    /* remove trailing (CR)LF from value */
-    v->size = vlen - 1;
-    if ( v->size > 0 && v->data[v->size-1] == '\r')
-        v->size--;
+    /* write name */
+    v->name = dest;
+    iov = (struct iovec *)arr.elts;
+    
+    while (iov <= end) {
+        memcpy(dest, iov->iov_base, iov->iov_len);
+        dest += iov->iov_len;
+        ++iov;
+    }
+    *dest = 0;
+    v->size = dest - v->data;
+
+    while ((f = APR_BRIGADE_FIRST(bb)) != e)
+        apr_bucket_delete(f);
 
-    v->data[v->size] = 0;
     APREQ_FLAGS_ON(param->flags, APREQ_TAINT);
     *p = param;
     return APR_SUCCESS;
@@ -216,7 +226,14 @@
                     return APR_SUCCESS;
 
                 case ':':
-                    ++glen; 
+                    if (off > 1) {
+                        apr_bucket_split(e, off - 1);
+                        dlen -= off - 1;
+                        data += off - 1;
+                        off = 1;
+                        e = APR_BUCKET_NEXT(e);
+                    }
+                    ++glen;
                     ctx->status = HDR_GAP;
                     goto parse_hdr_bucket;
 
@@ -244,6 +261,13 @@
 
                 default:
                     ctx->status = HDR_VALUE;
+                    if (off > 1) {
+                        apr_bucket_split(e, off - 1);
+                        dlen -= off - 1;
+                        data += off - 1;
+                        off = 1;
+                        e = APR_BUCKET_NEXT(e);
+                    }
                     ++vlen;
                     goto parse_hdr_bucket;
                 }
@@ -290,7 +314,7 @@
                         return s;
                     }
 
-                    apr_table_addn(t, param->v.name, param->v.data);
+                    apreq_value_table_add(&param->v, t);
                     goto parse_hdr_brigade;
                 }
 

Modified: httpd/apreq/branches/multi-env-unstable/library/parser_multipart.c
URL: 
http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/library/parser_multipart.c?view=diff&r1=155077&r2=155078
==============================================================================
--- httpd/apreq/branches/multi-env-unstable/library/parser_multipart.c 
(original)
+++ httpd/apreq/branches/multi-env-unstable/library/parser_multipart.c Wed Feb 
23 13:47:52 2005
@@ -500,15 +500,14 @@
                     return s;
                 }
                 len = off;
-                param = apreq_param_make(pool, NULL, 0, NULL, len);
+                param = apreq_param_make(pool, ctx->param_name, 
+                                         strlen(ctx->param_name), NULL, len);
                 APREQ_FLAGS_ON(param->flags, APREQ_TAINT);
                 param->info = ctx->info;
 
                 *(const apreq_value_t **)&v = &param->v;
-                v->name = ctx->param_name;
                 apr_brigade_flatten(ctx->bb, v->data, &len);
-                v->size = len;
-                v->data[v->size] = 0;
+                v->data[len] = 0;
 
                 if (parser->hook != NULL) {
                     s = apreq_hook_run(parser->hook, param, NULL);
@@ -518,7 +517,7 @@
                     }
                 }
 
-                apr_table_addn(t, v->name, v->data);
+                apreq_value_table_add(v, t);
                 ctx->status = MFD_NEXTLINE;
                 ctx->param_name = NULL;
                 apr_brigade_cleanup(ctx->bb);
@@ -564,7 +563,7 @@
                         return s;
                     }
                 }
-                apr_table_addn(t, param->v.name, param->v.data);
+                apreq_value_table_add(&param->v, t);
                 apreq_brigade_setaside(ctx->bb, pool);
                 s = apreq_brigade_concat(pool, parser->temp_dir, 
parser->brigade_limit,
                                          param->upload, ctx->bb);

Modified: httpd/apreq/branches/multi-env-unstable/library/parser_urlencoded.c
URL: 
http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/library/parser_urlencoded.c?view=diff&r1=155077&r2=155078
==============================================================================
--- httpd/apreq/branches/multi-env-unstable/library/parser_urlencoded.c 
(original)
+++ httpd/apreq/branches/multi-env-unstable/library/parser_urlencoded.c Wed Feb 
23 13:47:52 2005
@@ -13,10 +13,12 @@
 **  See the License for the specific language governing permissions and
 **  limitations under the License.
 */
+
 #include "apreq_parser.h"
 #include "apreq_util.h"
 #include "apreq_error.h"
 
+
 #define PARSER_STATUS_CHECK(PREFIX)   do {         \
     if (ctx->status == PREFIX##_ERROR)             \
         return APR_EGENERAL;                       \
@@ -48,10 +50,12 @@
 {
     apreq_param_t *param;
     apreq_value_t *v;
-    apr_bucket *e, *end;
+    apr_bucket *e, *f;
     apr_status_t s;
     struct iovec vec[APREQ_DEFAULT_NELTS];
     apr_array_header_t arr;
+    apr_size_t mark;
+
 
     if (nlen == 0)
         return APR_EBADARG;
@@ -65,52 +69,65 @@
     arr.nalloc   = APREQ_DEFAULT_NELTS;
     arr.elts     = (char *)vec;
 
-    apr_brigade_partition(bb, nlen+1, &end);
+    ++nlen, ++vlen;
+    e = APR_BRIGADE_FIRST(bb);
 
-    for (e = APR_BRIGADE_FIRST(bb); e != end; e = APR_BUCKET_NEXT(e)) {
+    while (!APR_BUCKET_IS_EOS(e)) {
         struct iovec *iov = apr_array_push(&arr);
         apr_size_t len;
         s = apr_bucket_read(e, (const char **)&iov->iov_base,
                             &len, APR_BLOCK_READ);
         if (s != APR_SUCCESS)
             return s;
-        iov->iov_len = len;
-    }
 
-    ((struct iovec *)arr.elts)[arr.nelts - 1].iov_len--; /* drop '=' sign */
+        iov->iov_len = len;
+        nlen -= len;
 
-    s = apreq_decodev(v->name, &nlen,
-                      (struct iovec *)arr.elts, arr.nelts);
-    if (s != APR_SUCCESS)
-        return s;
+        e = APR_BUCKET_NEXT(e);
 
-    while ((e = APR_BRIGADE_FIRST(bb)) != end)
-        apr_bucket_delete(e);
+        if (nlen == 0) {
+            iov->iov_len--;
+            break;
+        }
+    }
 
-    arr.nelts = 0;
-    apr_brigade_partition(bb, vlen + 1, &end);
+    mark = arr.nelts;
 
-    for (e = APR_BRIGADE_FIRST(bb); e != end; e = APR_BUCKET_NEXT(e)) {
+    while (!APR_BUCKET_IS_EOS(e)) {
         struct iovec *iov = apr_array_push(&arr);
         apr_size_t len;
-        s = apr_bucket_read(e, (const char **)&iov->iov_base, 
+        s = apr_bucket_read(e, (const char **)&iov->iov_base,
                             &len, APR_BLOCK_READ);
         if (s != APR_SUCCESS)
             return s;
+
         iov->iov_len = len;
-    }
+        vlen -= len;
+
+        e = APR_BUCKET_NEXT(e);
 
-    if (end != APR_BRIGADE_SENTINEL(bb))
-        ((struct iovec *)arr.elts)[arr.nelts - 1].iov_len--; /* drop [&;] */
+        if (vlen == 0) {
+            iov->iov_len--;
+            break;
+        }
+
+    }
 
     s = apreq_decodev(v->data, &vlen,
-                      (struct iovec *)arr.elts, arr.nelts);
+                      (struct iovec *)arr.elts + mark, arr.nelts - mark);
+    if (s != APR_SUCCESS)
+        return s;
 
+    v->name = v->data + vlen + 1;
+
+    s = apreq_decodev(v->name, &nlen, (struct iovec *)arr.elts, mark);
     if (s != APR_SUCCESS)
         return s;
 
-    while ((e = APR_BRIGADE_FIRST(bb)) != end)
-        apr_bucket_delete(e);
+    v->size = nlen + vlen + 1;
+
+    while ((f = APR_BRIGADE_FIRST(bb)) != e)
+        apr_bucket_delete(f);
 
     APREQ_FLAGS_ON(param->flags, APREQ_TAINT);
     *p = param;
@@ -159,7 +176,7 @@
                     s = apreq_hook_run(parser->hook, param, NULL);
 
                 if (s == APR_SUCCESS) {
-                    apr_table_addn(t, param->v.name,  param->v.data);
+                    apreq_value_table_add(&param->v, t);
                     ctx->status = URL_COMPLETE;
                 }
                 else {
@@ -185,6 +202,11 @@
             while (off < dlen) {
                 switch (data[off++]) {
                 case '=':
+                    apr_bucket_split(e, off);
+                    dlen -= off;
+                    data += off;
+                    off = 0;
+                    e = APR_BUCKET_NEXT(e);
                     ctx->status = URL_VALUE;
                     goto parse_url_bucket;
                 default:
@@ -199,6 +221,7 @@
                 switch (data[off++]) {
                 case '&':
                 case ';':
+                    apr_bucket_split(e, off);
                     s = split_urlword(&param, pool, ctx->bb, nlen, vlen);
                     if (parser->hook != NULL && s == APR_SUCCESS)
                         s = apreq_hook_run(parser->hook, param, NULL);
@@ -208,7 +231,7 @@
                         return s;
                     }
 
-                    apr_table_addn(t, param->v.name, param->v.data);
+                    apreq_value_table_add(&param->v, t);
                     goto parse_url_brigade;
 
                 default:

Modified: httpd/apreq/branches/multi-env-unstable/library/t/params.c
URL: 
http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/library/t/params.c?view=diff&r1=155077&r2=155078
==============================================================================
--- httpd/apreq/branches/multi-env-unstable/library/t/params.c (original)
+++ httpd/apreq/branches/multi-env-unstable/library/t/params.c Wed Feb 23 
13:47:52 2005
@@ -27,8 +27,6 @@
 static apr_table_t *args;
 static apr_pool_t *p;
 
-#define strtoval(s) \
-  ((const apreq_value_t *)(s - offsetof(apreq_value_t, data)))
 
 static void request_make(dAT)
 {
@@ -44,14 +42,14 @@
 static void request_args_get(dAT)
 {
     const char *val;
-    const apreq_value_t *v;
+    const apreq_param_t *param;
 
     AT_str_eq(apr_table_get(args,"a"), "1");
 
     val = apr_table_get(args,"quux");
     AT_str_eq(val, "foo bar");
-    v = strtoval(val);
-    AT_int_eq(v->size, 7);
+    param = apreq_value_to_param(val);
+    AT_int_eq(apreq_param_vlen(param), 7);
 
     AT_str_eq(apr_table_get(args,"plus"), "+");
     AT_str_eq(apr_table_get(args,"uplus"), "+");
@@ -148,7 +146,7 @@
  
     param = apreq_param_make(p, name, nlen, val, vlen);
     AT_str_eq(param->v.name, name);
-    AT_int_eq(param->v.size, vlen);
+    AT_int_eq(apreq_param_vlen(param), vlen);
     AT_str_eq(param->v.data, val);
 
     encode = apreq_param_encode(p, param);
@@ -157,7 +155,7 @@
     s = apreq_param_decode(&decode, p, encode, nlen, vlen+2);
     AT_int_eq(s, APR_SUCCESS);
     AT_str_eq(decode->v.name, name);
-    AT_int_eq(decode->v.size, vlen);
+    AT_int_eq(apreq_param_vlen(decode), vlen);
     AT_str_eq(decode->v.data, val);
 }
 

Modified: httpd/apreq/branches/multi-env-unstable/library/util.c
URL: 
http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/library/util.c?view=diff&r1=155077&r2=155078
==============================================================================
--- httpd/apreq/branches/multi-env-unstable/library/util.c (original)
+++ httpd/apreq/branches/multi-env-unstable/library/util.c Wed Feb 23 13:47:52 
2005
@@ -23,7 +23,6 @@
 #define MIN(a,b) ( (a) < (b) ? (a) : (b) )
 #define MAX(a,b) ( (a) > (b) ? (a) : (b) )
 
-
 /* used for specifying file sizes */
 
 APREQ_DECLARE(apr_int64_t) apreq_atoi64f(const char *s)
@@ -394,13 +393,16 @@
 }
 
 
+#define apreq_value_nlen(v) (v->size - (v->name - v->data))
+#define apreq_value_vlen(v) ((v->name - v->data) - 1)
+
 APREQ_DECLARE(char *) apreq_join(apr_pool_t *p, 
                                  const char *sep, 
                                  const apr_array_header_t *arr,
                                  apreq_join_t mode)
 {
     apr_ssize_t len, slen;
-    apreq_value_t *rv;
+    char *rv;
     const apreq_value_t **a = (const apreq_value_t **)arr->elts;
     char *d;
     const int n = arr->nelts;
@@ -412,7 +414,7 @@
         return NULL;
 
     for (j=0, len=0; j < n; ++j)
-        len += a[j]->size + slen;
+        len += apreq_value_vlen(a[j]) + slen;
 
     /* Allocated the required space */
 
@@ -428,32 +430,29 @@
         break;
     }
 
-    rv = apr_palloc(p, len + sizeof *rv);
-    rv->name = 0;
-    rv->size = 0;
-    rv->data[0] = 0;
+    rv = apr_palloc(p, len);
 
     if (n == 0)
-        return rv->data;
+        return rv;
 
     /* Pass two --- copy the argument strings into the result space */
 
-    d = rv->data;
+    d = rv;
 
     switch (mode) {
 
     case APREQ_JOIN_ENCODE:
-        d += apreq_encode(d, a[0]->data, a[0]->size);
+        d += apreq_encode(d, a[0]->data, apreq_value_vlen(a[0]));
 
         for (j = 1; j < n; ++j) {
                 memcpy(d, sep, slen);
                 d += slen;
-                d += apreq_encode(d, a[j]->data, a[j]->size);
+                d += apreq_encode(d, a[j]->data, apreq_value_vlen(a[j]));
         }
         break;
 
     case APREQ_JOIN_DECODE:
-        if (apreq_decode(d, &len, a[0]->data, a[0]->size))
+        if (apreq_decode(d, &len, a[0]->data, apreq_value_vlen(a[0])))
             return NULL;
         else
             d += len;
@@ -462,7 +461,7 @@
             memcpy(d, sep, slen);
             d += slen;
 
-            if (apreq_decode(d, &len, a[j]->data, a[j]->size))
+            if (apreq_decode(d, &len, a[j]->data, apreq_value_vlen(a[j])))
                 return NULL;
             else
                 d += len;
@@ -472,25 +471,25 @@
 
     case APREQ_JOIN_QUOTE:
 
-        d += apreq_quote_once(d, a[0]->data, a[0]->size);
+        d += apreq_quote_once(d, a[0]->data, apreq_value_vlen(a[0]));
 
         for (j = 1; j < n; ++j) {
             memcpy(d, sep, slen);
             d += slen;
-            d += apreq_quote_once(d, a[j]->data, a[j]->size);
+            d += apreq_quote_once(d, a[j]->data, apreq_value_vlen(a[j]));
         }
         break;
 
 
     case APREQ_JOIN_AS_IS:
-        memcpy(d,a[0]->data,a[0]->size);
-        d += a[0]->size;
+        memcpy(d,a[0]->data,apreq_value_vlen(a[0]));
+        d += apreq_value_vlen(a[0]);
 
         for (j = 1; j < n ; ++j) {
             memcpy(d, sep, slen);
             d += slen;
-            memcpy(d, a[j]->data, a[j]->size);
-            d += a[j]->size;
+            memcpy(d, a[j]->data, apreq_value_vlen(a[j]));
+            d += apreq_value_vlen(a[j]);
         }
         break;
 
@@ -499,8 +498,7 @@
     }
 
     *d = 0;
-    rv->size = d - rv->data;
-    return rv->data;
+    return rv;
 }
 
 APR_INLINE

Modified: httpd/apreq/branches/multi-env-unstable/module/test_cgi.c
URL: 
http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/module/test_cgi.c?view=diff&r1=155077&r2=155078
==============================================================================
--- httpd/apreq/branches/multi-env-unstable/module/test_cgi.c (original)
+++ httpd/apreq/branches/multi-env-unstable/module/test_cgi.c Wed Feb 23 
13:47:52 2005
@@ -24,7 +24,7 @@
 static int dump_table(void *count, const char *key, const char *value)
 {
     int *c = (int *) count;
-    int value_len = apreq_value_to_param(value)->v.size;
+    int value_len = key - value - 1; /* == strlen(value) by construction */
     if (value_len) 
         *c += strlen(key) + value_len;
     return 1;
@@ -105,7 +105,8 @@
 
         apr_file_printf(out, "%s", "Content-Type: text/plain\n\n");
         dest = apr_pcalloc(pool, cookie->v.size + 1);
-        if (apreq_decode(dest, &dlen, cookie->v.data, cookie->v.size) == 
APR_SUCCESS)
+        if (apreq_decode(dest, &dlen, cookie->v.data, 
+                         apreq_cookie_vlen(cookie)) == APR_SUCCESS)
             apr_file_printf(out, "%s", dest);
         else {
 //            apreq_log(APREQ_ERROR APR_EGENERAL, env,


Reply via email to