cURL / Mailing Lists / curl-library / Single Mail

curl-library

[PATCH 1/3] Add getparts() to fetch multiple parts with the same path.

From: Colin Hogben <curl_at_pythontech.co.uk>
Date: Wed, 18 Jan 2012 13:13:11 +0000

Rework test file parser as a new function getparts() which extracts
multiple parts with the same path. Re-implement getpart() and
getpartattr() in terms of getparts(), for backward compatibility.

---
 tests/getpart.pm |  156 ++++++++++++++++++++++++++++-------------------------
 1 files changed, 82 insertions(+), 74 deletions(-)
diff --git a/tests/getpart.pm b/tests/getpart.pm
index 83e56ca..5a40df9 100644
--- a/tests/getpart.pm
+++ b/tests/getpart.pm
@@ -34,94 +34,102 @@ sub decode_base64 {
   return unpack("u", $len . $_);         # uudecode and print
 }
 
-sub getpartattr {
-    # if $part is undefined (ie only one argument) then
-    # return the attributes of the section
+# Get a list of matching parts identified by section and part.
+# Each returned item is an array with a hash-of-attributes as
+# first element, followed by any content lines.
 
-    my ($section, $part)=@_;
+sub getparts {
+    # if $part is undefined (ie only one argument) then
+    # return the section
 
-    my %hash;
-    my $inside=0;
+    my($section, $part) = @_;
 
- #   print "Section: $section, part: $part\n";
+    my @want = ('testcase',$section);
+    push @want, $part if $part;
+    my @items;
+    my $level = 0;
+    my $item;
+    my $base64;
 
     for(@xml) {
- #       print "$inside: $_";
-        if(!$inside && ($_ =~ /^ *\<$section/)) {
-            $inside++;
-        }
-        if((1 ==$inside) && ( ($_ =~ /^ *\<$part([^>]*)/) ||
-                              !(defined($part)) )
-             ) {
-            $inside++;
-            my $attr=$1;
-
-            while($attr =~ s/ *([^=]*)= *(\"([^\"]*)\"|([^\"> ]*))//) {
-                my ($var, $cont)=($1, $2);
-                $cont =~ s/^\"(.*)\"$/$1/;
-                $hash{$var}=$cont;
+        pos($_) = 0;            # Reset to start for m//g
+        if(/^\s*<(\w+)/gc) {
+            my $tag = $1;
+            if($level < @want && $tag eq $want[$level]) {
+                ++ $level;
+                if($level == @want) {
+                    # Found the path of interest
+                    my %attr;
+                    while(/\G\s+(\w+)=/gc) {
+                        my $name = $1;
+                        if(/\G\"([^\"]*)\"/gc) {
+                            $attr{$name} = $1;
+                        }
+                        elsif(/\G(\w+)/gc) {
+                            $attr{$name} = $1;
+                        }
+                        else {
+                            # FIXME bad attr
+                            last;
+                        }
+                    }
+                    if(! /\G\s*>/) {
+                        # FIXME bad tag
+                    }
+                    $item = [\%attr];
+                    $base64 = exists $attr{'base64'};
+                }
             }
-            last;
-        }
-        # detect end of section when part wasn't found
-        elsif((1 ==$inside) && ($_ =~ /^ *\<\/$section\>/)) {
-            last;
-        }
-        elsif((2 ==$inside) && ($_ =~ /^ *\<\/$part/)) {
-            $inside--;
-        }
-    }
-    return %hash;
-}
-
-sub getpart {
-    my ($section, $part)=@_;
-
-    my @this;
-    my $inside=0;
-    my $base64=0;
-
- #   print "Section: $section, part: $part\n";
-
-    for(@xml) {
- #       print "$inside: $_";
-        if(!$inside && ($_ =~ /^ *\<$section/)) {
-            $inside++;
-        }
-        elsif((1 ==$inside) && ($_ =~ /^ *\<$part[ \>]/)) {
-            if($_ =~ /$part [^>]*base64=/) {
-                # attempt to detect base64 encoded parts
-                $base64=1;
+            else {
+                # Could be irrelevant tag, or real XML file content
+                if($item) {
+                    $_ = decode_base64($_)
+                        if $base64;
+                    push @$item, $_;
+                }
             }
-            $inside++;
         }
-        elsif((2 ==$inside) && ($_ =~ /^ *\<\/$part/)) {
-            $inside--;
-        }
-        elsif((1==$inside) && ($_ =~ /^ *\<\/$section/)) {
-            if($trace) {
-                print STDERR "*** getpart.pm: $section/$part returned data!\n";
-            }
-            if(!@this && $warning) {
-                print STDERR "*** getpart.pm: $section/$part returned empty!\n";
-            }
-            if($base64) {
-                # decode the whole array before returning it!
-                for(@this) {
-                    my $decoded = decode_base64($_);
-                    $_ = $decoded;
+        elsif(/^\s*<\/(\w+)>/) {
+            my $tag = $1;
+            if($level > 0 && $tag eq $want[$level-1]) {
+                # End of the innermost element
+                -- $level;
+                if($item) {
+                    push @items, $item;
+                    $item = undef;
                 }
             }
-            return @this;
         }
-        elsif(2==$inside) {
-            push @this, $_;
+        else {
+            if($item) {
+                $_ = decode_base64($_)
+                    if $base64;
+                push @$item, $_;
+            }
         }
     }
-    if($warning) {
-        print STDERR "*** getpart.pm: $section/$part returned empty!\n";
+    return @items;
+}
+
+sub getonepart {
+    my @parts = getparts(@_);
+    if(@parts > 1) {
+        die "More than one ".join('/',@_)." section defined\n";
     }
-    return @this; #empty!
+    return @{$parts[0]};
+}
+
+sub getpart {
+    my($attr, @lines) = getonepart(@_);
+    return @lines;
+}
+    
+sub getpartattr {
+    # if $part is undefined (ie only one argument) then
+    # return the attributes of the section
+
+    my($attr, @lines) = getonepart(@_);
+    return %$attr;
 }
 
 sub loadtest {
-- 
1.6.5.6
--------------030205040005020403060202
Content-Type: text/plain;
 name="0002-Allow-multiple-client-file-and-verify-file-parts.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename*0="0002-Allow-multiple-client-file-and-verify-file-parts.patch"
Received on 2001-09-17