2012-03-20 6 views
5

私は、JSONに似た何かをperl構造体から出力することを書いています。私はこのように動作するように引用したい: スカラーがストリング化されているかどうかをテストする方法はありますか?

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

JSON :: XSは、スカラーは、私は非常にクールだと思うこれは、ない「文字列化」されている場合、またはテストすることによって、これを処理します。しかし、XSを書くことなく自分でこのテストを行う方法は見つけられません。これは可能ですか?私はScalar :: Util :: looks_like_numberなどについて広範なpedantryを見つけることなく、CPAN上でこれを見つけることはできません。これは完全に私が望むものではありません。私が見つけることができる唯一の欠点はDevel :: Peekであり、これは悪を感じる。そしてまた、ちょうどJSON :: XSのように、私はこのsecenarioと元気です:

my $a = 5; 
print $a."\n"; 
# now $a outputs "5" instead of 5) 

答えて

5

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 

または、あなたはむしろpPOKフラグを検索したい場合:

if (B::svref_2object(\$x)->FLAGS & B::SVp_POK) { 
    print "I guess \$x is stringy\n"; 
} 
あなたがそれそう数はもはや、以下を使用して文字列化されているように見えることができます
+0

SVタイプとは関係ありません。これはpPOKフラグと関係しています。 – ikegami

+0

たとえば、 'my $ x =" "を見てください。 $ x = 5;私のy = 5; "" $ y; '。両方ともPVIVですが、1つだけが「弦」です。 – ikegami

+0

私はそれにも気づいた。 Bさんが実際に提供したものを掲載してくれればいいですね!残念ながら、 'SvGETMAGIC'は利用できません。 – ikegami

2

これはおそらく最良の方法はありませんが、JSONは、あなたが望むならば、なぜそれを使わないのでしょうか?

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

is_stringy(5);  # undef 
is_string("5");  # 1 
+0

私はより良い答えが見つからない場合は、おそらく私がやってしまうことでしょう。しかし、確かに無駄に感じる。私はJSON :: XSのスカラー出力をそのまま残していますが、残念ながら出力しているのはJSONではなく、異なるエスケープ・ルールなどです。 – Yobert

4

$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 

oo!それは(ほとんど)新しいXSコードSvGETMAGICは欠点を有しているが、それは、ほぼすべての時間の中に動作します呼び出すことができない

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; 
} 

を記述することなく、中に行うことができるようBは、SVp_POKを提供しないことが判明します。

+0

@Yobert、もう一度更新されました。 – ikegami

関連する問題