Is there a way to check if a scalar was compressed or not?

I am writing a thing to output something similar to JSON from a perl structure. I want the quote to behave like this:

"string" outputs "string"
"05" outputs "05"
"5" outputs "5"
5 outputs 5
05 outputs 5, or 05 would be acceptable

JSON :: XS handles this by testing if the scalar has been "stiffened" or not, which I think is very cool. But I can’t find a way to do this test myself without writing an XS, which I would rather avoid. Is it possible? I cannot find it anywhere in CPAN without finding extensive pedantry about Scalar :: Util :: looks_like_number etc., which is completely not what I want. The only stop I can find is Devel :: Peek, which feels evil. And also, like JSON :: XS, I'm fine with this secret:

my $a = 5;
print $a."\n";
# now $a outputs "5" instead of 5)
+5
source share
3 answers

Check the output B::svref_2object:

use B;
($x, $y, $z) = ("5", 5, 5.0);

print ref(B::svref_2object( \$x )), "\n";
print ref(B::svref_2object( \$y )), "\n";
print ref(B::svref_2object( \$z )), "\n";

:

B::PV
B::IV
B::NV

, ikegami, pPOK:

if (B::svref_2object( \$x )->FLAGS & B::SVp_POK) {
    print "I guess \$x is stringy\n";
}
+5

, , :

$x = 0+$x;

,

$ perl -MJSON::XS -E'
   $_ = 4;
   say encode_json([$_]);  # [4]
   "".$_;
   say encode_json([$_]);  # ["4"]
   $_ = 0 + $_;
   say encode_json([$_]);  # [4]
'

, - , , JSON:: XS Perl. :

sub is_stringy {
   { no warnings 'void'; "".$_[0]; }
   return 1;
}

, :) , "" XS. , , SvPOKp ( SvGETMAGIC ).

use Inline C => <<'__EOI__';

   SV* is_stringy(SV* sv) {
      SvGETMAGIC(sv);
      return SvPOKp(sv) ? &PL_sv_yes : &PL_sv_no;
   }

__EOI__

$_ = 4;
say is_stringy($_) ?1:0;   # 0
{ no warnings 'void'; "".$_; }
say is_stringy($_) ?1:0;   # 1
$_ = 0+$_;
say is_stringy($_) ?1:0;   # 0

! , B SVp_POK, () XS

use B qw( svref_2object SVp_POK );

sub is_stringy {
   my ($s) = @_;
   my $sv = svref_2object(\$s);
   #$sv->GETMAGIC();  # Not available
   return $sv->FLAGS & SVp_POK;
}

SvGETMAGIC , .

+4

This is probably not the best way, but if you JSONdo what you want, why not use it?

sub is_stringy {
    encode_json([$_[0]]) =~ /["']/
}

is_stringy(5);      # undef
is_string("5");     # 1
+2
source

All Articles