Last active
August 29, 2015 14:13
-
-
Save maddingue/c657eca920185042ad8e to your computer and use it in GitHub Desktop.
types coercion
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
sub coerce_types { | |
my $struct = shift; | |
my $ref = ref $struct; | |
croak "can only work with references" unless $ref; | |
if ($ref eq "ARRAY") { | |
for my $i (0..$#{$struct}) { | |
next unless defined $struct->[$i]; | |
# recurse into array/hash-refs | |
coerce_types($struct->[$i]), next if ref $struct->[$i]; | |
my $value = $struct->[$i]; | |
my $copy = $struct->[$i]; | |
# we must treat the NV before because floats without decimals | |
# are printed without decimal part, therefore 1.0 becomes 1 | |
# and will be incorrectly catched by the boolean conversion | |
my $sv = svref_2object(\$struct->[$i]); | |
$struct->[$i] = $struct->[$i] / 1.0, next | |
if $sv->FLAGS & SVf_NOK; | |
# special case: coerce booleans into integers | |
$value = int $value if $copy eq "0" or $copy eq "1"; | |
# special case: coerce integers given as strings | |
# iff they're at most 8 digits long & do not start with a zero | |
$value = int $value if $copy =~ /^[1-9][0-9]{0,7}$/; | |
$sv = svref_2object(\$value); | |
$value = int $value if $sv->FLAGS & SVf_IOK; | |
$struct->[$i] = $value; | |
} | |
} | |
elsif ($ref eq "HASH") { | |
for my $key (keys %$struct) { | |
next unless defined $struct->{$key}; | |
# recurse into array/hash-refs | |
coerce_types($struct->{$key}), next if ref $struct->{$key}; | |
my $value = $struct->{$key}; | |
my $copy = $struct->{$key}; | |
# we must treat the NV before because floats without decimals | |
# are printed without decimal part, therefore 1.0 becomes 1 | |
# and will be incorrectly catched by the boolean conversion | |
my $sv = svref_2object(\$struct->{$key}); | |
$struct->{$key} = $struct->{$key} / 1.0, next | |
if $sv->FLAGS & SVf_NOK; | |
# special case: coerce booleans into integers | |
$value = int $value if $copy eq "0" or $copy eq "1"; | |
# special case: coerce integers given as strings | |
# iff they're at most 8 digits long & do not start with a zero | |
$value = int $value if $copy =~ /^[1-9][0-9]{0,7}$/; | |
$sv = svref_2object(\$value); | |
$value = int $value if $sv->FLAGS & SVf_IOK; | |
$struct->{$key} = $value; | |
} | |
} | |
else { | |
croak "don't know how to handle \L$ref reference" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment