quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

getpart.pm (9418B)


      1 #***************************************************************************
      2 #                                  _   _ ____  _
      3 #  Project                     ___| | | |  _ \| |
      4 #                             / __| | | | |_) | |
      5 #                            | (__| |_| |  _ <| |___
      6 #                             \___|\___/|_| \_\_____|
      7 #
      8 # Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
      9 #
     10 # This software is licensed as described in the file COPYING, which
     11 # you should have received as part of this distribution. The terms
     12 # are also available at https://curl.se/docs/copyright.html.
     13 #
     14 # You may opt to use, copy, modify, merge, publish, distribute and/or sell
     15 # copies of the Software, and permit persons to whom the Software is
     16 # furnished to do so, under the terms of the COPYING file.
     17 #
     18 # This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     19 # KIND, either express or implied.
     20 #
     21 # SPDX-License-Identifier: curl
     22 #
     23 ###########################################################################
     24 
     25 package getpart;
     26 
     27 use strict;
     28 use warnings;
     29 
     30 BEGIN {
     31     use base qw(Exporter);
     32 
     33     our @EXPORT = qw(
     34         compareparts
     35         fulltest
     36         getpart
     37         getpartattr
     38         loadarray
     39         loadtest
     40         partexists
     41         striparray
     42         writearray
     43     );
     44 }
     45 
     46 use Memoize;
     47 
     48 my @xml;      # test data file contents
     49 my $xmlfile;  # test data file name
     50 
     51 my $warning=0;
     52 my $trace=0;
     53 
     54 # Normalize the part function arguments for proper caching. This includes the
     55 # file name in the arguments since that is an implied parameter that affects the
     56 # return value.  Any error messages will only be displayed the first time, but
     57 # those are disabled by default anyway, so should never been seen outside
     58 # development.
     59 sub normalize_part {
     60     push @_, $xmlfile;
     61     return join("\t", @_);
     62 }
     63 
     64 sub decode_hex {
     65     my $s = $_;
     66     # remove everything not hex
     67     $s =~ s/[^A-Fa-f0-9]//g;
     68     # encode everything
     69     $s =~ s/([a-fA-F0-9][a-fA-F0-9])/chr(hex($1))/eg;
     70     return $s;
     71 }
     72 
     73 sub testcaseattr {
     74     my %hash;
     75     for(@xml) {
     76         if(($_ =~ /^ *\<testcase ([^>]*)/)) {
     77             my $attr=$1;
     78             while($attr =~ s/ *([^=]*)= *(\"([^\"]*)\"|([^\> ]*))//) {
     79                 my ($var, $cont)=($1, $2);
     80                 $cont =~ s/^\"(.*)\"$/$1/;
     81                 $hash{$var}=$cont;
     82             }
     83         }
     84     }
     85     return %hash;
     86 }
     87 
     88 sub getpartattr {
     89     # if $part is undefined (ie only one argument) then
     90     # return the attributes of the section
     91 
     92     my ($section, $part)=@_;
     93 
     94     my %hash;
     95     my $inside=0;
     96 
     97  #   print "Section: $section, part: $part\n";
     98 
     99     for(@xml) {
    100  #       print "$inside: $_";
    101         if(!$inside && ($_ =~ /^ *\<$section/)) {
    102             $inside++;
    103         }
    104         if((1 ==$inside) && ( ($_ =~ /^ *\<$part ([^>]*)/) ||
    105                               !(defined($part)) )
    106              ) {
    107             $inside++;
    108             my $attr=$1;
    109 
    110             while($attr =~ s/ *([^=]*)= *(\"([^\"]*)\"|([^\> ]*))//) {
    111                 my ($var, $cont)=($1, $2);
    112                 $cont =~ s/^\"(.*)\"$/$1/;
    113                 $hash{$var}=$cont;
    114             }
    115             last;
    116         }
    117         # detect end of section when part wasn't found
    118         elsif((1 ==$inside) && ($_ =~ /^ *\<\/$section\>/)) {
    119             last;
    120         }
    121         elsif((2 ==$inside) && ($_ =~ /^ *\<\/$part/)) {
    122             $inside--;
    123         }
    124     }
    125     return %hash;
    126 }
    127 memoize('getpartattr', NORMALIZER => 'normalize_part');  # cache each result
    128 
    129 sub getpart {
    130     my ($section, $part)=@_;
    131 
    132     my @this;
    133     my $inside=0;
    134     my $hex=0;
    135     my $line;
    136 
    137     for(@xml) {
    138         $line++;
    139         if(!$inside && ($_ =~ /^ *\<$section/)) {
    140             $inside++;
    141         }
    142         elsif(($inside >= 1) && ($_ =~ /^ *\<$part[ \>]/)) {
    143             if($inside > 1) {
    144                 push @this, $_;
    145             }
    146             elsif($_ =~ /$part [^>]*hex=/) {
    147                 # attempt to detect a hex-encoded part
    148                 $hex=1;
    149             }
    150             $inside++;
    151         }
    152         elsif(($inside >= 2) && ($_ =~ /^ *\<\/$part[ \>]/)) {
    153             if($inside > 2) {
    154                 push @this, $_;
    155             }
    156             $inside--;
    157         }
    158         elsif(($inside >= 1) && ($_ =~ /^ *\<\/$section/)) {
    159             if($inside > 1) {
    160                 print STDERR "$xmlfile:$line:1: error: missing </$part> tag before </$section>\n";
    161                 @this = ("format error in $xmlfile");
    162             }
    163             if($trace && @this) {
    164                 print STDERR "*** getpart.pm: $section/$part returned data!\n";
    165             }
    166             if($warning && !@this) {
    167                 print STDERR "*** getpart.pm: $section/$part returned empty!\n";
    168             }
    169             if($hex) {
    170                 # decode the whole array before returning it!
    171                 for(@this) {
    172                     my $decoded = decode_hex($_);
    173                     $_ = $decoded;
    174                 }
    175             }
    176             return @this;
    177         }
    178         elsif($inside >= 2) {
    179             push @this, $_;
    180         }
    181     }
    182     if($trace && @this) {
    183         # section/part has data but end of section not detected,
    184         # end of file implies end of section.
    185         print STDERR "*** getpart.pm: $section/$part returned data!\n";
    186     }
    187     if($warning && !@this) {
    188         # section/part does not exist or has no data without an end of
    189         # section; end of file implies end of section.
    190         print STDERR "*** getpart.pm: $section/$part returned empty!\n";
    191     }
    192     return @this;
    193 }
    194 memoize('getpart', NORMALIZER => 'normalize_part');  # cache each result
    195 
    196 sub partexists {
    197     my ($section, $part)=@_;
    198 
    199     my $inside = 0;
    200 
    201     for(@xml) {
    202         if(!$inside && ($_ =~ /^ *\<$section/)) {
    203             $inside++;
    204         }
    205         elsif((1 == $inside) && ($_ =~ /^ *\<$part[ \>]/)) {
    206             return 1; # exists
    207         }
    208         elsif((1 == $inside) && ($_ =~ /^ *\<\/$section/)) {
    209             return 0; # does not exist
    210         }
    211     }
    212     return 0; # does not exist
    213 }
    214 # The code currently never calls this more than once per part per file, so
    215 # caching a result that will never be used again just slows things down.
    216 # memoize('partexists', NORMALIZER => 'normalize_part');  # cache each result
    217 
    218 sub loadtest {
    219     my ($file)=@_;
    220 
    221     if(defined $xmlfile && $file eq $xmlfile) {
    222         # This test is already loaded
    223         return
    224     }
    225 
    226     undef @xml;
    227     $xmlfile = "";
    228 
    229     if(open(my $xmlh, "<", "$file")) {
    230         binmode $xmlh; # for crapage systems, use binary
    231         while(<$xmlh>) {
    232             push @xml, $_;
    233         }
    234         close($xmlh);
    235     }
    236     else {
    237         # failure
    238         if($warning) {
    239             print STDERR "file $file wouldn't open!\n";
    240         }
    241         return 1;
    242     }
    243     $xmlfile = $file;
    244     return 0;
    245 }
    246 
    247 
    248 # Return entire document as list of lines
    249 sub fulltest {
    250     return @xml;
    251 }
    252 
    253 # write the test to the given file
    254 sub savetest {
    255     my ($file)=@_;
    256 
    257     if(open(my $xmlh, ">", "$file")) {
    258         binmode $xmlh; # for crapage systems, use binary
    259         for(@xml) {
    260             print $xmlh $_;
    261         }
    262         close($xmlh);
    263     }
    264     else {
    265         # failure
    266         if($warning) {
    267             print STDERR "file $file wouldn't open!\n";
    268         }
    269         return 1;
    270     }
    271     return 0;
    272 }
    273 
    274 #
    275 # Strip off all lines that match the specified pattern and return
    276 # the new array.
    277 #
    278 
    279 sub striparray {
    280     my ($pattern, $arrayref) = @_;
    281 
    282     my @array;
    283 
    284     for(@$arrayref) {
    285         if($_ !~ /$pattern/) {
    286             push @array, $_;
    287         }
    288     }
    289     return @array;
    290 }
    291 
    292 #
    293 # pass array *REFERENCES* !
    294 #
    295 sub compareparts {
    296     my ($firstref, $secondref)=@_;
    297 
    298     # we cannot compare arrays index per index since with data chunks,
    299     # they may not be "evenly" distributed
    300     my $first = join("", @$firstref);
    301     my $second = join("", @$secondref);
    302 
    303     if($first =~ /%alternatives\[/) {
    304         die "bad use of compareparts\n";
    305     }
    306 
    307     if($second =~ /%alternatives\[([^,]*),([^\]]*)\]/) {
    308         # there can be many %alternatives in this chunk, so we call
    309         # this function recursively
    310         my $alt = $second;
    311         $alt =~ s/%alternatives\[([^,]*),([^\]]*)\]/$1/;
    312 
    313         # check first alternative
    314         {
    315             my @f;
    316             my @s;
    317             push @f, $first;
    318             push @s, $alt;
    319             if(!compareparts(\@f, \@s)) {
    320                 return 0;
    321             }
    322         }
    323 
    324         $alt = $second;
    325         $alt =~ s/%alternatives\[([^,]*),([^\]]*)\]/$2/;
    326         # check second alternative
    327         {
    328             my @f;
    329             my @s;
    330             push @f, $first;
    331             push @s, $alt;
    332             if(!compareparts(\@f, \@s)) {
    333                 return 0;
    334             }
    335         }
    336 
    337         # neither matched
    338         return 1;
    339     }
    340 
    341     if($first ne $second) {
    342         return 1;
    343     }
    344 
    345     return 0;
    346 }
    347 
    348 #
    349 # Write a given array to the specified file
    350 #
    351 sub writearray {
    352     my ($filename, $arrayref)=@_;
    353 
    354     open(my $temp, ">", "$filename") || die "Failure writing file";
    355     binmode($temp,":raw");  # Cygwin fix by Kevin Roth
    356     for(@$arrayref) {
    357         print $temp $_;
    358     }
    359     close($temp) || die "Failure writing file";
    360 }
    361 
    362 #
    363 # Load a specified file and return it as an array
    364 #
    365 sub loadarray {
    366     my ($filename)=@_;
    367     my @array;
    368 
    369     if(open(my $temp, "<", "$filename")) {
    370         while(<$temp>) {
    371             push @array, $_;
    372         }
    373         close($temp);
    374     }
    375     return @array;
    376 }
    377 
    378 
    379 1;