Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl YAML module does not recognize types of scalars

Tags:

yaml

perl

I load the following .yaml file

foo : bar
s : 1
hx: 0x34

with this piece of code:

use YAML qw(LoadFile Dump); 
use Data::Dumper; 
my $d=LoadFile("test.yaml"); 
print Dumper($d);
print "x        =", $d->{hx},"\n";
print "x/2      =", $d->{hx}/2,"\n";
print "hex(x)/2 =", hex($d->{hx})/2,"\n";

and the output is

Output:
> ./yaml.pl
$VAR1 = {
          'foo' => 'bar',
          'hx' => '0x34',
          's' => '1'
        };
x        =0x34
x/2      =0
hex(x)/2 =26

This means it treats all scalars as strings, which I did not expect. From the YAML documentation at CPAN http://metacpan.org/pod/YAML I assumed that this is handled by implicit tagging and that the module would recognize the hex number.

Does anybody know how to do this ?

like image 681
Thorsten Avatar asked Jan 30 '14 16:01

Thorsten


1 Answers

If you examine the loader class, you will find that the _parse_inline sub has a few branches for sequences, mappings, single and double-quoted strings and a few other cases. All you need to do is add a branch for values starting with 0x. I wrote that branch and a sub for dealing with hex values for YAML 0.900.0. I tried with some basic input, and it seems to do what you wanted. If it works for you as well, consider submitting the patch.

dump.pl

use YAML qw(LoadFile Dump); 
use Data::Dumper; 
my $d=LoadFile("test.yaml"); 
$d=LoadFile("test.yaml"); 
print Dumper($d);
print "x        =", $d->{hx},"\n";
print "x/2      =", $d->{hx}/2,"\n";
print "hex(x)/2 =", hex($d->{hx})/2,"\n";



$d=LoadFile("sym1.yaml"); 
print Dumper($d);

print "dodo[4]  =", $d->{dodo}->{doto}[4], "\n";
print "dodo[3]  =", $d->{dodo}->{doto}[3], "\n";

sym1.yaml

"symfony 1.0":
  PHP:    5.0
  Propel: 1.2
"symfony 1.2":
  PHP:    5.2
  Propel: 1.3

dodo:
  doto: [1,23,4, 0x34, 0x16 ]
  dozo: [1,23,4, 0x12, 0x11 ]
  dofo: { a: 2,  358: 0x166, 255: 0xff, 255: 0xFF}
ffa: 0xFfA

$ perl dump.pl

$VAR1 = {
          'foo' => 'bar',
          'hx' => 52,
          's' => '1'
        };
x        =52
x/2      =26
hex(x)/2 =41
$VAR1 = {
          'ffa' => 4090,
          'symfony 1.2' => {
                           'PHP' => '5.2',
                           'Propel' => '1.3'
                         },
          'dodo' => {
                    'dofo' => {
                              'a' => '2',
                              '255' => 255,
                              '358' => 358
                            },
                    'dozo' => [ '1','23', '4', 18, 17 ],
                    'doto' => [ '1', '23', '4', 52, 22 ]
                  },
          'symfony 1.0' => {
                           'PHP' => '5.0',
                           'Propel' => '1.2'
                         }
        };

doto[4]  =22
doto[3]  =52

patch for YAML 0.900.0

diff --git a/Loader.pm b/Loader.pm
index 3bf20c7..d7096df 100644
--- a/Loader.pm
+++ b/Loader.pm
@@ -437,6 +437,10 @@ sub _parse_inline {
         $node = $self->_parse_inline_single_quoted();
         $node = $self->_parse_implicit($node) if $implicit;
     }
+    elsif ($self->inline =~ /^0x/) {
+        $node = $self->_parse_inline_single_hex();
+        # do something if implicit?
+    }
     else {
         if ($top) {
             $node = $self->inline;
@@ -541,6 +545,21 @@ sub _parse_inline_single_quoted {
     return $node;
 }
 
+# Parse the inline hex value
+sub _parse_inline_single_hex {
+    my $self = shift;
+    my $node;
+    if ($self->inline =~ /^0x([A-Fa-f0-9]+)(,?.*)?$/) {
+        $node = hex($1);
+        $self->inline($2);
+        $node =~ s/''/'/g;
+    }
+    else {
+        $self->die('YAML_PARSE_ERR_BAD_HEX');
+    }
+    return $node;
+}
+
 # Parse the inline unquoted string and do implicit typing.
 sub _parse_inline_simple {
     my $self = shift;
like image 116
Ярослав Рахматуллин Avatar answered Sep 21 '22 20:09

Ярослав Рахматуллин