#!/usr/bin/perl

# BEGIN DATAPACK CODE
{
    my $toc;
    my $data_linepos = 1;
    unshift @INC, sub {
        $toc ||= do {

            my $fh = \*DATA;

        my $header_line;
        my $header_found;
        while (1) {
            my $header_line = <$fh>;
            defined($header_line)
                or die "Unexpected end of data section while reading header line";
            chomp($header_line);
            if ($header_line eq 'Data::Section::Seekable v1') {
                $header_found++;
                last;
            }
        }
        die "Can't find header 'Data::Section::Seekable v1'"
            unless $header_found;

        my %toc;
        my $i = 0;
        while (1) {
            $i++;
            my $toc_line = <$fh>;
            defined($toc_line)
                or die "Unexpected end of data section while reading TOC line #$i";
            chomp($toc_line);
            $toc_line =~ /\S/ or last;
            $toc_line =~ /^([^,]+),(\d+),(\d+)(?:,(.*))?$/
                or die "Invalid TOC line #$i in data section: $toc_line";
            $toc{$1} = [$2, $3, $4];
        }
        my $pos = tell $fh;
        $toc{$_}[0] += $pos for keys %toc;


            # calculate the line number of data section
            my $data_pos = tell(DATA);
            seek DATA, 0, 0;
            my $pos = 0;
            while (1) {
                my $line = <DATA>;
                $pos += length($line);
                $data_linepos++;
                last if $pos >= $data_pos;
            }
            seek DATA, $data_pos, 0;

            \%toc;
        };
        if ($toc->{$_[1]}) {
            seek DATA, $toc->{$_[1]}[0], 0;
            read DATA, my($content), $toc->{$_[1]}[1];
            my ($order, $lineoffset) = split(';', $toc->{$_[1]}[2]);
            $content =~ s/^#//gm;
            $content = "# line ".($data_linepos + $order+1 + $lineoffset)." \"".__FILE__."\"\n" . $content;
            open my $fh, '<', \$content
                or die "DataPacker error loading $_[1]: $!";
            return $fh;
        }
        return;
    };
}
# END DATAPACK CODE

use strict;
use warnings;

# since we are datapack-ing this script, we avoid 'use' and use 'require'. see
# Module::DataPack for more details.
require Devel::Platform::Info;
require JSON::PP;

print JSON::PP->new->pretty->canonical->encode(
    Devel::Platform::Info->new->get_info);

# ABSTRACT: Print platform information gathered by Devel::Platform::Info
# PODNAME: platform-info

__END__

=pod

=encoding UTF-8

=head1 NAME

platform-info - Print platform information gathered by Devel::Platform::Info

=head1 VERSION

This document describes version 0.006 of platform-info (from Perl distribution App-PlatformInfo), released on 2020-11-02.

=head1 HOMEPAGE

Please visit the project's homepage at L<https://metacpan.org/release/App-PlatformInfo>.

=head1 SOURCE

Source repository is at L<https://github.com/perlancar/perl-App-PlatformInfo>.

=head1 BUGS

Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=App-PlatformInfo>

When submitting a bug or request, please include a test-file or a
patch to an existing test-file that illustrates the bug or desired
feature.

=head1 AUTHOR

perlancar <perlancar@cpan.org>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2020, 2019, 2016 by perlancar@cpan.org.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut

__DATA__
Data::Section::Seekable v1
App/PlatformInfo.pm,28,137,0;0
Devel/Platform/Info.pm,196,2134,1;10
Devel/Platform/Info/BSD.pm,2365,1392,2;107
Devel/Platform/Info/BeOS.pm,3793,1527,3;163
Devel/Platform/Info/Irix.pm,5356,1316,4;227
Devel/Platform/Info/Linux.pm,6709,18721,5;283
Devel/Platform/Info/Mac.pm,25465,2005,6;763
Devel/Platform/Info/SCO.pm,27505,2502,7;854
Devel/Platform/Info/Solaris.pm,30046,1574,8;923
Devel/Platform/Info/Win32.pm,31657,3303,9;984
JSON/PP.pm,34979,47916,10;1115
JSON/PP/Boolean.pm,82922,319,11;2818

### App/PlatformInfo.pm ###
#package App::PlatformInfo;
#
#our $DATE = '2020-11-02'; 
#our $DIST = 'App-PlatformInfo'; 
#our $VERSION = '0.006'; 
#
#1;
#
#__END__
#
### Devel/Platform/Info.pm ###
#package Devel::Platform::Info;
#
#use strict;
#use warnings;
#
#use vars qw($VERSION);
#$VERSION = '0.16';
#
#
#my %map = (
#    'freebsd'       => 'BSD',
#    'openbsd'       => 'BSD',
#    'netbsd'        => 'BSD',
#    'mirbsd'        => 'BSD',
#    'dragonfly'     => 'BSD',
#    'midnightbsd'   => 'BSD',
#    
#    'irix'          => 'Irix',
#    
#    'linux'         => 'Linux',
#    'aix'           => 'Linux',
#    'bsdos'         => 'Linux',
#    'dgux'          => 'Linux',
#    'dynixptx'      => 'Linux',
#    'hpux'          => 'Linux',
#    'dec_osf'       => 'Linux',
#    'svr4'          => 'Linux',
#    'unicos'        => 'Linux',
#    'unicosmk'      => 'Linux',
#    'ultrix'        => 'Linux',
#    
#    'sco_sv'        => 'SCO',
#    'sco3'          => 'SCO',
#    'sco'           => 'SCO',
#
#    'solaris'       => 'Solaris',
#    'sunos'         => 'Solaris',
#
#    'beos'          => 'BeOS',
#
#    'dos'           => 'Win32',
#    'os2'           => 'Win32',
#    'mswin32'       => 'Win32',
#    'netware'       => 'Win32',
#    'cygwin'        => 'Win32',
#
#    'macos'         => 'Mac',
#    'rhapsody'      => 'Mac',
#    'darwin'        => 'Mac',
#
#    'vms'           => 'Linux',
#    'vos'           => 'Linux',
#    'os390'         => 'Linux',
#    'vmesa'         => 'Linux',
#    'riscos'        => 'Linux',
#    'amigaos'       => 'Linux',
#    'beos'          => 'Linux',
#    'machten'       => 'Linux',
#    'mpeix'         => 'Linux',
#    'bitrig'        => 'Linux',
#    'minix'         => 'Linux',
#    'nto'           => 'Linux',
#);
#
#
#sub new {
#    my ($class) = @_;
#    my $self    = {};
#    bless  $self, $class;
#    return $self;
#}
#
#sub get_info {
#    my $self  = shift;
#    my $data;
#
#    my $plugin = $map{ lc $^O } || 'Linux';
#
#    my $driver = 'Devel::Platform::Info::' . $plugin;
#    my $require = "$driver.pm";
#    $require =~ s!::!/!g;
#
#    eval {
#        require $require;
#        $self->{driver} = $driver->new();
#        $data = $self->{driver}->get_info();
#    };
#
#    $data->{error} = $@ if($@);
#
#    return $data;
#}
#
#1;
#
#__END__
#
### Devel/Platform/Info/BSD.pm ###
#package Devel::Platform::Info::BSD;
#
#use strict;
#use warnings;
#
#use vars qw($VERSION);
#$VERSION = '0.16';
#
#
#my %commands = (
#    '_uname1'   => 'uname -a',
#    '_uname2'   => 'uname -mrr',
#    'kname'     => 'uname -s',
#    'kvers'     => 'uname -r',
#    'osname'    => 'uname -o',
#    'archname'  => 'uname -m',
#);
#
#
#sub new {
#    my ($class) = @_;
#    my $self = {};
#    bless $self, $class;
#
#    return $self;
#}
#
#sub get_info {
#    my $self  = shift;
#
#    for my $cmd (keys %commands) {
#        $self->{cmds}{$cmd} = `$commands{$cmd} 2>/dev/null`;
#        $self->{cmds}{$cmd} =~ s/\s+$//s;
#        $self->{info}{$cmd} = $self->{cmds}{$cmd}   if($cmd !~ /^_/);
#    }
#
#    $self->{info}{osflag}   = $^O;
#    $self->{info}{kvers}    = lc $self->{info}{kvers};
#    $self->{info}{kernel}   = lc($self->{info}{kname}) . '-' . $self->{info}{kvers};
#    $self->{info}{osname}   = $self->{info}{kname};
#    $self->{info}{oslabel}  = $self->{info}{kname};
#    $self->{info}{osvers}   = $self->{info}{kvers};
#    $self->{info}{osvers}   =~ s/-release.*//;
#    $self->{info}{is32bit}  = $self->{info}{archname} !~ /(64|alpha)/ ? 1 : 0;
#    $self->{info}{is64bit}  = $self->{info}{archname} =~ /(64|alpha)/ ? 1 : 0;
#
#
#    $self->{info}{source}{$commands{$_}} = $self->{cmds}{$_}    for(keys %commands);
#    return $self->{info};
#}
#
#
#1;
#
#__END__
#
### Devel/Platform/Info/BeOS.pm ###
#package Devel::Platform::Info::BeOS;
#
#use strict;
#use warnings;
#
#use vars qw($VERSION);
#$VERSION = '0.16';
#
#
#my %commands = (
#    '_uname1'   => 'uname -a',
#    '_uname2'   => 'uname -mrr',
#    'kname'     => 'uname -s',
#    'kvers'     => 'uname -r',
#    'osname'    => 'uname -o',
#    'archname'  => 'uname -m',
#);
#
#
#sub new {
#    my ($class) = @_;
#    my $self = {};
#    bless $self, $class;
#
#    return $self;
#}
#
#sub get_info {
#    my $self  = shift;
#
#    for my $cmd (keys %commands) {
#        $self->{cmds}{$cmd} = `$commands{$cmd} 2>/dev/null`;
#        $self->{cmds}{$cmd} =~ s/\s+$//s;
#        $self->{info}{$cmd} = $self->{cmds}{$cmd}   if($cmd !~ /^_/);
#    }
#
#    $self->{info}{osflag}   = $^O;
#    $self->{info}{kvers}    = lc $self->{info}{kvers};
#    $self->{info}{kernel}   = lc($self->{info}{kname}) . '-' . $self->{info}{kvers};
#    $self->{info}{osname}   = $self->{info}{kname};
#    $self->{info}{oslabel}  = $self->{info}{kname};
#    $self->{info}{osvers}   = $self->{info}{kvers};
#    $self->{info}{osvers}   =~ s/-release.*//;
#    $self->{info}{is32bit}  = $self->{info}{archname} !~ /(64|alpha)/ ? 1 : 0;
#    $self->{info}{is64bit}  = $self->{info}{archname} =~ /(64|alpha)/ ? 1 : 0;
#
#    $self->{info}{source}{$commands{$_}} = $self->{cmds}{$_}    for(keys %commands);
#    return $self->{info};
#}
#
#sub _beos_versions {
#    return {
#        'R4.5'  => 'Genki',
#        'R5'    => 'Maui',
#        'R5.1'  => 'Dano',
#    };
#}
#
#
#
#1;
#
#__END__
#
### Devel/Platform/Info/Irix.pm ###
#package Devel::Platform::Info::Irix;
#
#use strict;
#use warnings;
#
#use vars qw($VERSION);
#$VERSION = '0.16';
#
#
#my %commands = (
#    '_issue1'   => 'cat /etc/issue',
#    '_issue2'   => 'cat /etc/.issue',
#    '_uname'    => 'uname -a',
#    'kname'     => 'uname -s',
#    'kvers'     => 'uname -r',
#    'osname'    => 'uname -o',
#    'archname'  => 'uname -m',
#
#    '_irix1'   => 'uname -R',   
#);
#
#
#sub new {
#    my ($class) = @_;
#    my $self = {};
#    bless $self, $class;
#
#    return $self;
#}
#
#sub get_info {
#    my $self  = shift;
#
#    for my $cmd (keys %commands) {
#        $self->{cmds}{$cmd} = `$commands{$cmd} 2>/dev/null`;
#        $self->{cmds}{$cmd} =~ s/\s+$//s;
#        $self->{info}{$cmd} = $self->{cmds}{$cmd}   if($cmd !~ /^_/);
#    }
#
#    $self->{info}{osflag}   = $^O;
#    $self->{info}{kernel}   = lc($self->{info}{kname}) . '-' . $self->{info}{kvers};
#    $self->{info}{osname}   = 'IRIX';
#    $self->{info}{oslabel}  = 'IRIX';
#    $self->{info}{osvers}   = $self->{info}{kvers};
#    $self->{info}{is32bit}  = $self->{info}{kname} !~ /64/ ? 1 : 0;
#    $self->{info}{is64bit}  = $self->{info}{kname} =~ /64/ ? 1 : 0;
#
#    $self->{info}{source}{$commands{$_}} = $self->{cmds}{$_}    for(keys %commands);
#    return $self->{info};
#}
#
#
#1;
#
#__END__
#
### Devel/Platform/Info/Linux.pm ###
#package Devel::Platform::Info::Linux;
#
#use strict;
#use warnings;
#
#use vars qw($VERSION);
#$VERSION = '0.16';
#
#
#
#my %commands = (
#    '_issue1'   => 'cat /etc/issue',
#    '_issue2'   => 'cat /etc/.issue',
#    '_uname'    => 'uname -a',
#    '_lsb'      => 'lsb_release -a',
#    'kname'     => 'uname -s',
#    'kvers'     => 'uname -r',
#    'osname'    => 'uname -o',
#    'archname'  => 'uname -m',
#);
#
#my %default = ();
#
#my %archlinux = (
#    '0.1'           => 'Homer',
#    '0.2'           => 'Vega',
#    '0.3'           => 'Firefly',
#    '0.4'           => 'Dragon',
#    '0.5'           => 'Nova',
#    '0.6'           => 'Widget',
#    '0.7'           => 'Wombat',
#    '0.8'           => 'Voodoo',
#    '2007.05'       => 'Duke',
#    '2007.08'       => "Don't Panic",
#    '2008.06'       => 'Overlord',
#    '2009.02'       => '2009.02',
#    '2009.08'       => '2009.08',
#    '2010.05'       => '2010.05',
#    '2011.08.19'    => '2011.08.19',
#);
#
#
#my %crunch = (
#    '8.04.02'       => 'Back in Black',
#    '10'            => 'Statler',
#    '11'            => 'Waldorf',
#);
#
#my %debian = (
#    '1.1'       => 'buzz',
#    '1.2'       => 'rex',
#    '1.3'       => 'bo',
#    '2.0'       => 'hamm',
#    '2.1'       => 'slink',
#    '2.2'       => 'potato',
#    '3.0'       => 'woody',
#    '3.1'       => 'sarge',
#    '4.0'       => 'etch',
#    '4.1'       => 'etch',
#    '4.2'       => 'etch',
#    '4.3'       => 'etch',
#    '4.4'       => 'etch',
#    '4.5'       => 'etch',
#    '4.6'       => 'etch',
#    '4.7'       => 'etch',
#    '4.8'       => 'etch',
#    '4.9'       => 'etch',
#    '5.0'       => 'lenny',
#    '5.1'       => 'lenny',
#    '5.2'       => 'lenny',
#    '5.3'       => 'lenny',
#    '5.4'       => 'lenny',
#    '5.5'       => 'lenny',
#    '5.6'       => 'lenny',
#    '5.7'       => 'lenny',
#    '5.8'       => 'lenny',
#    '5.9'       => 'lenny',
#    '5.10'      => 'lenny',
#    '6.0'       => 'squeeze',
#    '6.1'       => 'squeeze',
#    '6.2'       => 'squeeze',
#    '6.3'       => 'squeeze',
#    '6.4'       => 'squeeze',
#    '6.5'       => 'squeeze',
#    '6.6'       => 'squeeze',
#    '6.7'       => 'squeeze',
#    '6.8'       => 'squeeze',
#    '6.9'       => 'squeeze',
#    '6.10'      => 'squeeze',
#    '7.0'       => 'wheezy',
#    '7.1'       => 'wheezy',
#    '7.2'       => 'wheezy',
#    '7.3'       => 'wheezy',
#    '7.4'       => 'wheezy',
#    '7.5'       => 'wheezy',
#    '7.6'       => 'wheezy',
#    '7.7'       => 'wheezy',
#    '7.8'       => 'wheezy',
#    '7.9'       => 'wheezy',
#    '7.10'      => 'wheezy',
#    '8.0'       => 'jessie',
#    '8.1'       => 'jessie',
#    '8.2'       => 'jessie',
#    '8.3'       => 'jessie',
#    '8.4'       => 'jessie',
#    '9.0'       => 'stretch',
#    '10.0'      => 'buster',
#);
#
#
#my %fedora = (
#    '1'         => 'Yarrow',
#    '2'         => 'Tettnang',
#    '3'         => 'Heidelberg',
#    '4'         => 'Stentz',
#    '5'         => 'Bordeaux',
#    '6'         => 'Zod',
#    '7'         => 'Moonshine',
#    '8'         => 'Werewolf',
#    '9'         => 'Sulphur',
#    '10'        => 'Cambridge',
#    '11'        => 'Leonidas',
#    '12'        => 'Constantine',
#    '13'        => 'Goddard',
#    '14'        => 'Laughlin',
#    '15'        => 'Lovelock',
#    '16'        => 'Verne',
#    '17'        => 'Beefy Miracle',
#    '18'        => 'Spherical Cow',
#    '19'        => q[Schrdinger's Cat],
#    '20'        => 'Heisenbug',
#);
#
#my %mandriva = (
#    '5.1'       => 'Venice',
#    '5.2'       => 'Leeloo',
#    '5.3'       => 'Festen',
#    '6.0'       => 'Venus',
#    '6.1'       => 'Helios',
#    '7.0'       => 'Air',
#    '7.1'       => 'Helium',
#    '7.2'       => 'Odyssey (called Ulysses during beta)',
#    '8.0'       => 'Traktopel',
#    '8.1'       => 'Vitamin',
#    '8.2'       => 'Bluebird',
#    '9.0'       => 'Dolphin',
#    '9.1'       => 'Bamboo',
#    '9.2'       => 'FiveStar',
#    '10.0'      => 'Community and Official',
#    '10.1'      => 'Community',
#    '10.1'      => 'Official',
#    '10.2'      => 'Limited Edition 2005',
#    '2006.0'    => 'Mandriva Linux 2006',
#    '2007'      => 'Mandriva Linux 2007',
#    '2007.1'    => 'Mandriva Linux 2007 Spring',
#    '2008.0'    => 'Mandriva Linux 2008',
#    '2008.1'    => 'Mandriva Linux 2008 Spring',
#    '2009.0'    => 'Mandriva Linux 2009',
#    '2009.1'    => 'Mandriva Linux 2009 Spring',
#    '2010.0'    => 'Mandriva Linux 2010 (Adlie)',
#    '2010.1'    => 'Mandriva Linux 2010 Spring',
#    '2010.2'    => 'Mandriva Linux 2010.2',
#    '2011.0'    => 'Hydrogen',
#);
#
#my %redhat = (
#    '0.8'       => 'Preview',
#    '0.9'       => 'Halloween',
#    '1.0'       => q{Mother's Day},
#    '1.1'       => q{Mother's Day+0.1},
#    '2.0'       => '',
#    '2.1'       => '',
#    '3.0.3'     => 'Picasso',
#    '3.95'      => 'Rembrandt',
#    '4.0'       => 'Colgate',
#    '4.1'       => 'Vanderbilt',
#    '4.2'       => 'Biltmore',
#    '4.95'      => 'Thunderbird',
#    '4.96'      => 'Mustang',
#    '5.0'       => 'Hurricane',
#    '5.1'       => 'Manhattan',
#    '5.2'       => 'Apollo',
#    '5.9'       => 'Starbuck',
#    '6.0'       => 'Hedwig',
#    '6.0.95'    => 'Lorax',
#    '6.1'       => 'Cartman',
#    '6.1.95'    => 'Piglet',
#    '6.2'       => 'Zoot',
#    '6.2.98'    => 'Pinstripe',
#    '7'         => 'Guinness',
#    '7.0.90'    => 'Fisher',
#    '7.0.91'    => 'Wolverine',
#    '7.1'       => 'Seawolf',
#    '7.1.92'    => 'Roswell',
#    '7.2'       => 'Enigma',
#    '7.2.92'    => 'Skipjack',
#    '7.3'       => 'Valhalla',
#    '7.3.92'    => 'Limbo',
#    '7.3.93'    => 'Limbo',
#    '7.3.94'    => 'Null',
#    '8.0'       => 'Psyche',
#    '8.0.93'    => 'Phoebe',
#    '9'         => 'Shrike',
#    '9.0.93'    => 'Severn',
#);
#
#my %rhel = (
#    '2.1 AS'    => 'Pensacola',
#    '2.1'       => 'Pensacola',
#    '2.1.1'     => 'Pensacola',
#    '2.1.2'     => 'Pensacola',
#    '2.1.3'     => 'Pensacola',
#    '2.1.4'     => 'Pensacola',
#    '2.1.5'     => 'Pensacola',
#    '2.1.6'     => 'Pensacola',
#    '2.1.7'     => 'Pensacola',
#    '2.1 ES'    => 'Panama',
#    '3'         => 'Taroon',
#    '3.0'       => 'Taroon',
#    '3.1'       => 'Taroon',
#    '3.2'       => 'Taroon',
#    '3.3'       => 'Taroon',
#    '3.4'       => 'Taroon',
#    '3.5'       => 'Taroon',
#    '3.6'       => 'Taroon',
#    '3.7'       => 'Taroon',
#    '3.8'       => 'Taroon',
#    '3.9'       => 'Taroon',
#    '4'         => 'Nahant',
#    '4.1'       => 'Nahant',
#    '4.2'       => 'Nahant',
#    '4.3'       => 'Nahant',
#    '4.4'       => 'Nahant',
#    '4.5'       => 'Nahant',
#    '4.6'       => 'Nahant',
#    '4.7'       => 'Nahant',
#    '4.8'       => 'Nahant',
#    '4.9'       => 'Nahant',
#    '5'         => 'Tikanga',
#    '5.1'       => 'Tikanga',
#    '5.2'       => 'Tikanga',
#    '5.3'       => 'Tikanga',
#    '5.4'       => 'Tikanga',
#    '5.5'       => 'Tikanga',
#    '5.6'       => 'Tikanga',
#    '5.7'       => 'Tikanga',
#    '5.8'       => 'Tikanga',
#    '6'         => 'Santiago',
#    '6.1'       => 'Santiago',
#    '6.2'       => 'Santiago',
#    '6.3'       => 'Santiago',
#    '6.4'       => 'Santiago',
#    '6.5'       => 'Santiago',
#    '7'         => 'Maipo',
#);
#
#my %scientific = (
#    '3.0.1'     => 'Feynman',
#    '3.0.2'     => 'Feynman',
#    '3.0.3'     => 'Feynman',
#    '3.0.4'     => 'Feynman',
#    '3.0.5'     => 'Feynman',
#    '3.0.6'     => 'Feynman',
#    '3.0.7'     => 'Feynman',
#    '3.0.8'     => 'Feynman',
#    '3.0.9'     => 'Legacy',
#    '4.0'       => 'Beryllium',
#    '4.1'       => 'Beryllium',
#    '4.2'       => 'Beryllium',
#    '4.3'       => 'Beryllium',
#    '4.4'       => 'Beryllium',
#    '4.5'       => 'Beryllium',
#    '4.6'       => 'Beryllium',
#    '4.7'       => 'Beryllium',
#    '4.8'       => 'Beryllium',
#    '4.9'       => 'Beryllium',
#    '5.0'       => 'Boron',
#    '5.1'       => 'Boron',
#    '5.2'       => 'Boron',
#    '5.3'       => 'Boron',
#    '5.4'       => 'Boron',
#    '5.5'       => 'Boron',
#    '5.6'       => 'Boron',
#    '5.7'       => 'Boron',
#    '5.8'       => 'Boron',
#    '5.9'       => 'Boron',
#    '6.0'       => 'Carbon',
#    '6.1'       => 'Carbon',
#    '6.2'       => 'Carbon',
#    '6.3'       => 'Carbon',
#    '6.4'       => 'Carbon',
#    '6.5'       => 'Carbon',
#    '6.6'       => 'Carbon',
#    '6.7'       => 'Carbon',
#    '6.8'       => 'Carbon',
#    '6.9'       => 'Carbon',
#    '6.10'      => 'Carbon',
#    '6.11'      => 'Carbon',
#    '7.0'       => 'Nitrogen',
#    '7.1'       => 'Nitrogen',
#    '7.2'       => 'Nitrogen',
#);
#
#my %ubuntu = (
#    '4.10'      => 'Warty Warthog',
#    '5.04'      => 'Hoary Hedgehog',
#    '5.10'      => 'Breezy Badger',
#    '6.06'      => 'Dapper Drake',
#    '6.10'      => 'Edgy Eft',
#    '7.04'      => 'Feisty Fawn',
#    '7.10'      => 'Gutsy Gibbon',
#    '8.04'      => 'Hardy Heron',
#    '8.10'      => 'Intrepid Ibex',
#    '9.04'      => 'Jaunty Jackalope',
#    '9.10'      => 'Karmic Koala',
#    '10.04'     => 'Lucid Lynx',
#    '10.10'     => 'Maverick Meerkat',
#    '11.04'     => 'Natty Narwhal',
#    '11.10'     => 'Oneiric Ocelot',
#    '12.04'     => 'Precise Pangolin',
#    '12.10'     => 'Quantal Quetzal',
#    '13.04'     => 'Raring Ringtail',
#    '13.10'     => 'Saucy Salamander',
#    '14.04'     => 'Trusty Tahr',
#    '14.10'     => 'Utopic Unicorn',
#    '15.04'     => 'Vivid Vervet',
#    '15.10'     => 'Wily Werewolf',
#    '16.04'     => 'Xenial Xerus',
#);
#
#my %distributions = (
#    'Adamantix'                 => { codenames => \%default,                        files => [ qw( /etc/adamantix_version ) ] },
#    'Annvix'                    => { codenames => \%default,                        files => [ qw( /etc/annvix-release ) ] },
#    'Arch Linux'                => { codenames => \%archlinux,                      files => [ qw( /etc/arch-release ) ] },
#    'Arklinux'                  => { codenames => \%default,                        files => [ qw( /etc/arklinux-release ) ] },
#    'Aurox Linux'               => { codenames => \%default,                        files => [ qw( /etc/aurox-release ) ] },
#    'BlackCat'                  => { codenames => \%default,                        files => [ qw( /etc/blackcat-release ) ] },
#    'Cobalt'                    => { codenames => \%default,                        files => [ qw( /etc/cobalt-release ) ] },
#    'Conectiva'                 => { codenames => \%default,                        files => [ qw( /etc/conectiva-release ) ] },
#    'CrunchBang Linux'          => { codenames => \%crunch,                         files => [ qw( /etc/lsb-release-crunchbang /etc/lsb-release ) ] },
#    'Debian'                    => { codenames => \%debian,     key => 'debian',    files => [ qw( /etc/debian_version /etc/debian_release ) ] },
#    'Fedora Core'               => { codenames => \%fedora,     key => 'fedora',    files => [ qw( /etc/fedora-release ) ] },
#    'Gentoo Linux'              => { codenames => \%default,    key => 'gentoo',    files => [ qw( /etc/gentoo-release ) ] },
#    'Immunix'                   => { codenames => \%default,                        files => [ qw( /etc/immunix-release ) ] },
#    'Knoppix'                   => { codenames => \%default,                        files => [ qw( /etc/knoppix_version ) ] },
#    'Libranet'                  => { codenames => \%default,                        files => [ qw( /etc/libranet_version ) ] },
#    'Linux-From-Scratch'        => { codenames => \%default,                        files => [ qw( /etc/lfs-release ) ] },
#    'Linux-PPC'                 => { codenames => \%default,                        files => [ qw( /etc/linuxppc-release ) ] },
#    'Mandrake'                  => { codenames => \%mandriva,                       files => [ qw( /etc/mandrake-release ) ] },
#    'Mandriva'                  => { codenames => \%mandriva,                       files => [ qw( /etc/mandriva-release /etc/mandrake-release /etc/mandakelinux-release ) ] },
#    'Mandrake Linux'            => { codenames => \%mandriva,                       files => [ qw( /etc/mandriva-release /etc/mandrake-release /etc/mandakelinux-release ) ] },
#    'MkLinux'                   => { codenames => \%default,                        files => [ qw( /etc/mklinux-release ) ] },
#    'Novell Linux Desktop'      => { codenames => \%default,                        files => [ qw( /etc/nld-release ) ] },
#    'Pardus'                    => { codenames => \%default,    key => 'pardus',    files => [ qw( /etc/pardus-release ) ] },
#    'PLD Linux'                 => { codenames => \%default,                        files => [ qw( /etc/pld-release ) ] },
#    'Red Flag'                  => { codenames => \%default,    key => 'redflag',   files => [ qw( /etc/redflag-release ) ] },
#    'Red Hat Enterprise Linux'  => { codenames => \%rhel,       key => 'rhel',      files => [ qw( /etc/redhat-release /etc/redhat_version ) ] },
#    'Red Hat Linux'             => { codenames => \%redhat,     key => 'redhat',    files => [ qw( /etc/redhat-release /etc/redhat_version ) ] },
#    'Scientific Linux'          => { codenames => \%scientific,                     files => [ qw( /etc/lsb-release ) ] },
#    'Slackware'                 => { codenames => \%default,    key => 'slackware', files => [ qw( /etc/slackware-version /etc/slackware-release ) ] },
#    'SME Server'                => { codenames => \%default,                        files => [ qw( /etc/e-smith-release ) ] },
#    'Sun JDS'                   => { codenames => \%default,                        files => [ qw( /etc/sun-release ) ] },
#    'SUSE Linux'                => { codenames => \%default,    key => 'suse',      files => [ qw( /etc/SuSE-release /etc/novell-release ) ] },
#    'SUSE Linux ES9'            => { codenames => \%default,    key => 'suse',      files => [ qw( /etc/sles-release ) ] },
#    'Tiny Sofa'                 => { codenames => \%default,                        files => [ qw( /etc/tinysofa-release ) ] },
#    'Trustix Secure Linux'      => { codenames => \%default,                        files => [ qw( /etc/trustix-release ) ] },
#    'TurboLinux'                => { codenames => \%default,                        files => [ qw( /etc/turbolinux-release ) ] },
#    'Ubuntu Linux'              => { codenames => \%ubuntu,                         files => [ qw( /etc/lsb-release ) ] },
#    'UltraPenguin'              => { codenames => \%default,                        files => [ qw( /etc/ultrapenguin-release ) ] },
#    'UnitedLinux'               => { codenames => \%default,                        files => [ qw( /etc/UnitedLinux-release ) ] },
#    'VA-Linux/RH-VALE'          => { codenames => \%default,                        files => [ qw( /etc/va-release ) ] },
#    'Yellow Dog'                => { codenames => \%default,                        files => [ qw( /etc/yellowdog-release ) ] },
#    'Yoper'                     => { codenames => \%default,                        files => [ qw( /etc/yoper-release ) ] },
#);
#
#my %version_pattern = (
#    'gentoo'    => 'Gentoo Base System version (.*)',
#    'debian'    => '(.+)',
#    'suse'      => 'VERSION = (.*)',
#    'fedora'    => 'Fedora Core release (\d+) \(',
#    'redflag'   => 'Red Flag (?:Desktop|Linux) (?:release |\()(.*?)(?: \(.+)?\)',
#    'redhat'    => 'Red Hat Linux release (.*) \(',
#    'rhel'      => 'Red Hat Enterprise Linux(?: Server)? release (.*) \(',
#    'slackware' => '^Slackware (.+)$',
#    'pardus'    => '^Pardus (.+)$',
#);
#
#my %oslabel_pattern = (
#    'suse'      => '^(\S+)',
#    'rhel'      => '(Red Hat Enterprise Linux(?: Server)?) release (.*) \(',
#);
#
#
#sub new {
#    my ($class) = @_;
#    my $self = {};
#    bless $self, $class;
#
#    return $self;
#}
#
#sub get_info {
#    my $self  = shift;
#
#    for my $cmd (keys %commands) {
#        $self->{cmds}{$cmd} = `$commands{$cmd} 2>/dev/null`;
#        $self->{cmds}{$cmd} =~ s/\s+$//s;
#        $self->{info}{$cmd} = $self->{cmds}{$cmd}   if($cmd !~ /^_/);
#    }
#
#    $self->{info}{osflag}       = $^O;
#    $self->{info}{kernel}       = lc($self->{info}{kname}) . '-' . $self->{info}{kvers};
#
#    $self->{info}{is32bit}      = $self->{info}{archname} !~ /_(64)$/ ? 1 : 0;
#    $self->{info}{is64bit}      = $self->{info}{archname} =~ /_(64)$/ ? 1 : 0;
#
#    if($self->{cmds}{'_lsb'}) {
#        ($self->{info}{oslabel})    = $self->{cmds}{'_lsb'} =~ /Distributor ID:\s*(.*?)\n/si;
#        ($self->{info}{osvers})     = $self->{cmds}{'_lsb'} =~ /Release:\s*(.*?)\n/si;
#        ($self->{info}{codename})   = $self->{cmds}{'_lsb'} =~ /Codename:\s*(.*)\n?/si;
#    } else {
#        $self->_release_version();
#    }
#
#    $self->{info}{source}{$commands{$_}} = $self->{cmds}{$_}    for(keys %commands);
#    return $self->{info};
#}
#
#
#sub _release_version {
#    my $self = shift;
#
#    for my $label (keys %distributions) {
#        for my $file (@{ $distributions{$label}->{files} }) {
#            next    unless(-f $file);
#            my $line = `cat $file 2>/dev/null`;
#
#            my ($version,$oslabel);
#            if($distributions{$label}->{key}) {
#                if($version_pattern{ $distributions{$label}->{key} }) {
#                    ($version) = $line =~ /$version_pattern{ $distributions{$label}->{key} }/si;
#                }
#                if($oslabel_pattern{ $distributions{$label}->{key} }) {
#                    ($oslabel) = $line =~ /$oslabel_pattern{ $distributions{$label}->{key} }/si;
#                }
#            }
#
#            $version = $line    unless($version);
#            $version =~ s/\s*$//;
#
#            unless($oslabel) {
#                if($self->{cmds}{'_issue1'}) {
#                    ($oslabel) = $self->{cmds}{'_issue1'} =~ /^(\S*)/;
#                } elsif($self->{cmds}{'_issue2'}) {
#                    ($oslabel) = $self->{cmds}{'_issue2'} =~ /^(\S*)/;
#                }
#                $oslabel ||= $label;    
#            }
#
#            $self->{info}{oslabel}  = $oslabel;
#            $self->{info}{osvers}   = $version;
#            $commands{'_cat'} = "cat $file";
#            $self->{cmds}{'_cat'}  = $line;
#
#            for my $vers (keys %{ $distributions{$label}->{codenames} }) {
#                if($version =~ /^$vers\b/) {
#                    $self->{info}{codename} = $distributions{$label}->{codenames}{$vers};
#                    return;
#                }
#            }
#
#            return;
#        }
#    }
#}
#
#1;
#
#__END__
#
### Devel/Platform/Info/Mac.pm ###
#package Devel::Platform::Info::Mac;
#
#use strict;
#use warnings;
#
#use vars qw($VERSION);
#$VERSION = '0.16';
#
#
#sub new {
#    my ($class) = @_;
#    my $self = {};
#    bless $self, $class;
#
#    return $self;
#}
#
#
#sub get_info {
#    my $self = shift;
#    $self->{info}{osname} = 'Mac';
#    $self->{info}{osflag} = $^O;
#
#    my $uname_s = $self->_command('uname -s');
#    if ($uname_s =~ /Darwin/i) {
#        $self->{info}{oslabel} = 'OS X';
#
#        my $productversion = $self->_command('sw_vers -productVersion');
#        if ($productversion =~ /((\d+)\.(\d+)(\.(\d+))?)/) {
#            my ($version, $major, $minor) = ($1, $2, $3);
#            my $versions = _macos_versions();
#            if (my $codename = $versions->{"$major.$minor"}) {
#                $self->{info}{codename} = $codename;
#                $self->{info}{osvers}  = $version;
#            }
#        }
#    }
#
#    if (my $arch = $self->_command('uname -p')) {
#        chomp $arch;
#        $self->{info}{archname} = $arch;
#        $self->{info}{is32bit}  = $arch !~ /_(64)$/ ? 1 : 0;
#        $self->{info}{is64bit}  = $arch =~ /_(64)$/ ? 1 : 0;
#    }
#
#    if (my $unamev = $self->_command('uname -v')) {
#        chomp $unamev;
#        $self->{info}{kernel} = $unamev;
#    }
#
#    $self->_command('uname -a');
#
#    return $self->{info};
#}
#
#
#
#sub _command {
#    my $self    = shift;
#    my $command = shift;
#    my $result  = `$command`;
#    chomp $result;
#
#    $self->{info}{source}{$command} = $result;
#
#    return $result;
#}
#
#
#sub _macos_versions {
#    return {
#        '10.0'  => 'Cheetah',
#        '10.1'  => 'Puma',
#        '10.2'  => 'Jaguar',
#        '10.3'  => 'Panther',
#        '10.4'  => 'Tiger',
#        '10.5'  => 'Leopard',
#        '10.6'  => 'Snow Leopard',
#        '10.7'  => 'Lion',
#        '10.8'  => 'Mountain Lion',
#        '10.9'  => 'Mavericks',
#        '10.10' => 'Yosemite',
#        '10.11' => 'El Capitan',
#    };
#}
#
#
#1;
#
#__END__
#
### Devel/Platform/Info/SCO.pm ###
#package Devel::Platform::Info::SCO;
#
#use strict;
#use warnings;
#
#use vars qw($VERSION);
#$VERSION = '0.16';
#
#
#my %commands = (
#    '_uname'    => 'uname -a',
#    '_lsb'      => 'uname -X',
#    'kname'     => 'uname -s',
#    'kvers'     => 'uname -r',
#    'archname'  => 'uname -m',
#);
#
#my %releases = (
#    '3.2.0'     => { oslabel => 'SCO UNIX System V/386',    codename => '' },
#    '3.2.1'     => { oslabel => 'Open Desktop 1.0',         codename => '' },
#    '3.2v2.0'   => { oslabel => 'Open Desktop 1.1',         codename => '' },
#    '3.2v4.0'   => { oslabel => 'SCO UNIX',                 codename => '' },
#    '3.2v4.1'   => { oslabel => 'Open Desktop 2.0',         codename => 'Phoenix' },
#    '3.2v4.2'   => { oslabel => 'Open Desktop/Server 3.0',  codename => 'Tbird' },
#    '3.2v5.0'   => { oslabel => 'OpenServer 5.0',           codename => 'Everest' },
#    '3.2v5.0.2' => { oslabel => 'OpenServer 5.0.2',         codename => '' },
#    '3.2v5.0.4' => { oslabel => 'OpenServer 5.0.4',         codename => 'Comet' },
#    '3.2v5.0.5' => { oslabel => 'OpenServer 5.0.5',         codename => 'Davenport' },
#    '3.2v5.0.6' => { oslabel => 'OpenServer 5.0.6',         codename => 'Freedom' },
#    '3.2v5.0.7' => { oslabel => 'OpenServer 5.0.7',         codename => 'Harvey West' },
#    '5'         => { oslabel => 'OpenServer 6.0',           codename => 'Legend' },
#);
#
#
#sub new {
#    my ($class) = @_;
#    my $self = {};
#    bless $self, $class;
#
#    return $self;
#}
#
#sub get_info {
#    my $self  = shift;
#
#    for my $cmd (keys %commands) {
#        $self->{cmds}{$cmd} = `$commands{$cmd} 2>/dev/null`;
#        $self->{cmds}{$cmd} =~ s/\s+$//s;
#        $self->{info}{$cmd} = $self->{cmds}{$cmd}   if($cmd !~ /^_/);
#    }
#
#    $self->{info}{osflag}       = $^O;
#    $self->{info}{osname}       = 'SCO';
#    $self->{info}{kernel}       = lc($self->{info}{kname}) . '-' . $self->{info}{kvers};
#    ($self->{info}{osvers})     = $self->{cmds}{'_lsb'} =~ /Release\s*=\s*(.*?)\n/s;
#    ($self->{info}{oslabel})    = $releases{ $self->{info}{osvers} }->{oslabel};
#    ($self->{info}{codename})   = $releases{ $self->{info}{osvers} }->{codename};
#
#    $self->{info}{is32bit}      = $self->{info}{archname} !~ /_(64)$/ ? 1 : 0;
#    $self->{info}{is64bit}      = $self->{info}{archname} =~ /_(64)$/ ? 1 : 0;
#
#    $self->{info}{source}{$commands{$_}} = $self->{cmds}{$_}    for(keys %commands);
#    return $self->{info};
#}
#
#1;
#
#__END__
#
### Devel/Platform/Info/Solaris.pm ###
#package Devel::Platform::Info::Solaris;
#
#use strict;
#use warnings;
#
#use vars qw($VERSION);
#$VERSION = '0.16';
#
#
#my %commands = (
#    '_uname1'   => 'uname -a',
#    '_showrev'  => 'showrev -a | grep -v "^Patch"',
#    '_release'  => 'cat /etc/release',
#    '_isainfo'  => '/usr/bin/isainfo -kv',
#    'kname'     => 'uname -s',
#    'kvers'     => 'uname -r',
#    'archname'  => 'uname -m',
#);
#
#
#sub new {
#    my ($class) = @_;
#    my $self = {};
#    bless $self, $class;
#
#    return $self;
#}
#
#sub get_info {
#    my $self  = shift;
#
#    for my $cmd (keys %commands) {
#        $self->{cmds}{$cmd} = `$commands{$cmd} 2>/dev/null`;
#        $self->{cmds}{$cmd} =~ s/\s+$//s;
#        $self->{info}{$cmd} = $self->{cmds}{$cmd}   if($cmd !~ /^_/);
#    }
#
#    $self->{info}{osflag}   = $^O;
#    $self->{info}{kernel}   = lc($self->{info}{kname}) . '-' . $self->{info}{kvers};
#    $self->{info}{is32bit}  = $self->{cmds}{_isainfo} !~ /64-bit/s ? 1 : 0;
#    $self->{info}{is64bit}  = $self->{cmds}{_isainfo} =~ /64-bit/s ? 1 : 0;
#
#    ($self->{info}{osname}) = $self->{cmds}{_release} =~ /((?:Open)?Solaris|SunOS|OpenIndiana)/is;
#    $self->{info}{oslabel}  = $self->{info}{osname};
#    $self->{info}{osvers}   = $self->{info}{kvers};
#
#    if($self->{info}{osname} =~ /Solaris/) {
#        $self->{info}{osvers} =~ s/^5\.([0123456]\b)/2.$1/;
#        $self->{info}{osvers} =~ s/^5\.(\d+)/$1/;
#    }
#
#
#    $self->{info}{source}{$commands{$_}} = $self->{cmds}{$_}    for(keys %commands);
#    return $self->{info};
#}
#
#
#1;
#
#__END__
#
### Devel/Platform/Info/Win32.pm ###
#package Devel::Platform::Info::Win32;
#
#use strict;
#use warnings;
#use POSIX;
#
#use vars qw($VERSION);
#$VERSION = '0.16';
#
#
#sub new {
#    my ($class) = @_;
#    my $self = {};
#    bless $self, $class;
#
#    return $self;
#}
#
#sub get_info {
#    my $self  = shift;
#
#    $self->{info}{osflag}       = $^O;
#    my $inf = $self->_GetArchName();
#    $self->{info}{oslabel} = $inf->{osLabel};
#    $self->{info}{osvers} = $inf->{version};
#    $self->{info}{archname} = $inf->{archname};
#    $self->{info}{is32bit} = $self->{info}{archname} !~ /64/ ? 1 : 0;
#    $self->{info}{is64bit} = $self->{info}{archname} =~ /64/ ? 1 : 0;
#    $self->{info}{source} = $inf->{source};
#    $self->{info}{wow64} = $inf->{wow64};
#
#    return $self->{info};
#}
#
#sub _GetArchName
#{
#    my $self = shift;
#    my @uname = POSIX::uname();
#    my @versions = Win32::GetOSVersion();
#    my $info = $self->_InterpretWin32Info(@versions);
#    $self->_AddPOSIXInfo($info, \@uname);
#    return $info;
#}
#
#sub _AddPOSIXInfo
#{
#    my $self = shift;
#    my $info = shift;
#    my $uname = shift;
#    my $arch = $uname->[4];
#    $info->{archname} = $arch;
#    $info->{source} = {
#        uname => $uname,
#        GetOSVersion => $info->{source},
#    };
#    if($ENV{'PROCESSOR_ARCHITEW6432'})
#    {
#        $info->{wow64} = 1;
#    }
#    else
#    {
#        $info->{wow64} = 0;
#    }
#}
#
#sub _InterpretWin32Info
#{
#    my $self = shift;
#    my @versionInfo = @_;
#    my ($string, $major, $minor, $build, $id, $spmajor, $spminor, $suitemask, $producttype, @extra)  = @versionInfo;
#    my ($osname, $oslabel, $version, $source);
#    my %info;
#    my $NTWORKSTATION = 1;
#    if($major == 5 && $minor == 2 && $producttype == $NTWORKSTATION)
#    {
#        $osname = 'Windows XP Pro 64';
#    } elsif($major == 5 && $minor == 2 && $producttype != $NTWORKSTATION)
#    {
#        $osname = 'Windows Server 2003';
#    } elsif($major == 5 && $minor == 1)
#    {
#        $osname = 'Windows XP';
#    } elsif($major == 5 && $minor == 0)
#    {
#        $osname = 'Windows 2000';
#    } elsif($major == 6 && $minor == 1 && $producttype == $NTWORKSTATION)
#    {
#        $osname = 'Windows 7';
#    } elsif($major == 6 && $minor == 1 && $producttype != $NTWORKSTATION)
#    {
#        $osname = 'Windows Server 2008 R2';
#    } elsif($major == 6 && $minor == 0 && $producttype == $NTWORKSTATION)
#    {
#        $osname = 'Windows Vista';
#    } elsif($major == 6 && $minor == 0 && $producttype != $NTWORKSTATION)
#    {
#        $osname = 'Windows Server 2008';
#    } elsif($major == 4 && $minor == 0 && $id == 1)
#    {
#        $osname = "Windows 95";
#    } elsif($major == 4 && $minor == 10)
#    {
#        $osname = "Windows 98";
#    } elsif($major == 4 && $minor == 90)
#    {
#        $osname = "Windows Me";
#    } elsif($major == 4 && $minor == 0)
#    {
#        $osname = 'Windows NT 4';
#    } elsif($major == 3 && $minor == 51)
#    {
#        $osname = "Windows NT 3.51";
#    } else
#    {
#        $osname = 'Unrecognised - please file an RT case';
#    }
#    my $info =
#    {
#        osName => 'Windows',
#        osLabel => $osname,
#        version => "$major.$minor.$build.$id",
#        source => \@versionInfo,
#    };
#    return $info;
#}
#
#
#1;
#
#__END__
#
### JSON/PP.pm ###
#package JSON::PP;
#
#
#use 5.005;
#use strict;
#
#use Exporter ();
#BEGIN { @JSON::PP::ISA = ('Exporter') }
#
#use overload ();
#use JSON::PP::Boolean;
#
#use Carp ();
#
#$JSON::PP::VERSION = '4.02';
#
#@JSON::PP::EXPORT = qw(encode_json decode_json from_json to_json);
#
#
#use constant P_ASCII                => 0;
#use constant P_LATIN1               => 1;
#use constant P_UTF8                 => 2;
#use constant P_INDENT               => 3;
#use constant P_CANONICAL            => 4;
#use constant P_SPACE_BEFORE         => 5;
#use constant P_SPACE_AFTER          => 6;
#use constant P_ALLOW_NONREF         => 7;
#use constant P_SHRINK               => 8;
#use constant P_ALLOW_BLESSED        => 9;
#use constant P_CONVERT_BLESSED      => 10;
#use constant P_RELAXED              => 11;
#
#use constant P_LOOSE                => 12;
#use constant P_ALLOW_BIGNUM         => 13;
#use constant P_ALLOW_BAREKEY        => 14;
#use constant P_ALLOW_SINGLEQUOTE    => 15;
#use constant P_ESCAPE_SLASH         => 16;
#use constant P_AS_NONBLESSED        => 17;
#
#use constant P_ALLOW_UNKNOWN        => 18;
#use constant P_ALLOW_TAGS           => 19;
#
#use constant OLD_PERL => $] < 5.008 ? 1 : 0;
#use constant USE_B => $ENV{PERL_JSON_PP_USE_B} || 0;
#
#BEGIN {
#    if (USE_B) {
#        require B;
#    }
#}
#
#BEGIN {
#    my @xs_compati_bit_properties = qw(
#            latin1 ascii utf8 indent canonical space_before space_after allow_nonref shrink
#            allow_blessed convert_blessed relaxed allow_unknown
#            allow_tags
#    );
#    my @pp_bit_properties = qw(
#            allow_singlequote allow_bignum loose
#            allow_barekey escape_slash as_nonblessed
#    );
#
#    if ( OLD_PERL ) {
#        my $helper = $] >= 5.006 ? 'JSON::PP::Compat5006' : 'JSON::PP::Compat5005';
#        eval qq| require $helper |;
#        if ($@) { Carp::croak $@; }
#    }
#
#    for my $name (@xs_compati_bit_properties, @pp_bit_properties) {
#        my $property_id = 'P_' . uc($name);
#
#        eval qq/
#            sub $name {
#                my \$enable = defined \$_[1] ? \$_[1] : 1;
#
#                if (\$enable) {
#                    \$_[0]->{PROPS}->[$property_id] = 1;
#                }
#                else {
#                    \$_[0]->{PROPS}->[$property_id] = 0;
#                }
#
#                \$_[0];
#            }
#
#            sub get_$name {
#                \$_[0]->{PROPS}->[$property_id] ? 1 : '';
#            }
#        /;
#    }
#
#}
#
#
#
#
#my $JSON; 
#
#sub encode_json ($) { 
#    ($JSON ||= __PACKAGE__->new->utf8)->encode(@_);
#}
#
#
#sub decode_json { 
#    ($JSON ||= __PACKAGE__->new->utf8)->decode(@_);
#}
#
#
#sub to_json($) {
#   Carp::croak ("JSON::PP::to_json has been renamed to encode_json.");
#}
#
#
#sub from_json($) {
#   Carp::croak ("JSON::PP::from_json has been renamed to decode_json.");
#}
#
#
#
#sub new {
#    my $class = shift;
#    my $self  = {
#        max_depth   => 512,
#        max_size    => 0,
#        indent_length => 3,
#    };
#
#    $self->{PROPS}[P_ALLOW_NONREF] = 1;
#
#    bless $self, $class;
#}
#
#
#sub encode {
#    return $_[0]->PP_encode_json($_[1]);
#}
#
#
#sub decode {
#    return $_[0]->PP_decode_json($_[1], 0x00000000);
#}
#
#
#sub decode_prefix {
#    return $_[0]->PP_decode_json($_[1], 0x00000001);
#}
#
#
#
#
#
#sub pretty {
#    my ($self, $v) = @_;
#    my $enable = defined $v ? $v : 1;
#
#    if ($enable) { 
#        $self->indent(1)->space_before(1)->space_after(1);
#    }
#    else {
#        $self->indent(0)->space_before(0)->space_after(0);
#    }
#
#    $self;
#}
#
#
#sub max_depth {
#    my $max  = defined $_[1] ? $_[1] : 0x80000000;
#    $_[0]->{max_depth} = $max;
#    $_[0];
#}
#
#
#sub get_max_depth { $_[0]->{max_depth}; }
#
#
#sub max_size {
#    my $max  = defined $_[1] ? $_[1] : 0;
#    $_[0]->{max_size} = $max;
#    $_[0];
#}
#
#
#sub get_max_size { $_[0]->{max_size}; }
#
#sub boolean_values {
#    my $self = shift;
#    if (@_) {
#        my ($false, $true) = @_;
#        $self->{false} = $false;
#        $self->{true} = $true;
#        return ($false, $true);
#    } else {
#        delete $self->{false};
#        delete $self->{true};
#        return;
#    }
#}
#
#sub get_boolean_values {
#    my $self = shift;
#    if (exists $self->{true} and exists $self->{false}) {
#        return @$self{qw/false true/};
#    }
#    return;
#}
#
#sub filter_json_object {
#    if (defined $_[1] and ref $_[1] eq 'CODE') {
#        $_[0]->{cb_object} = $_[1];
#    } else {
#        delete $_[0]->{cb_object};
#    }
#    $_[0]->{F_HOOK} = ($_[0]->{cb_object} or $_[0]->{cb_sk_object}) ? 1 : 0;
#    $_[0];
#}
#
#sub filter_json_single_key_object {
#    if (@_ == 1 or @_ > 3) {
#        Carp::croak("Usage: JSON::PP::filter_json_single_key_object(self, key, callback = undef)");
#    }
#    if (defined $_[2] and ref $_[2] eq 'CODE') {
#        $_[0]->{cb_sk_object}->{$_[1]} = $_[2];
#    } else {
#        delete $_[0]->{cb_sk_object}->{$_[1]};
#        delete $_[0]->{cb_sk_object} unless %{$_[0]->{cb_sk_object} || {}};
#    }
#    $_[0]->{F_HOOK} = ($_[0]->{cb_object} or $_[0]->{cb_sk_object}) ? 1 : 0;
#    $_[0];
#}
#
#sub indent_length {
#    if (!defined $_[1] or $_[1] > 15 or $_[1] < 0) {
#        Carp::carp "The acceptable range of indent_length() is 0 to 15.";
#    }
#    else {
#        $_[0]->{indent_length} = $_[1];
#    }
#    $_[0];
#}
#
#sub get_indent_length {
#    $_[0]->{indent_length};
#}
#
#sub sort_by {
#    $_[0]->{sort_by} = defined $_[1] ? $_[1] : 1;
#    $_[0];
#}
#
#sub allow_bigint {
#    Carp::carp("allow_bigint() is obsoleted. use allow_bignum() instead.");
#    $_[0]->allow_bignum;
#}
#
#
#
#
#{ 
#
#    my $max_depth;
#    my $indent;
#    my $ascii;
#    my $latin1;
#    my $utf8;
#    my $space_before;
#    my $space_after;
#    my $canonical;
#    my $allow_blessed;
#    my $convert_blessed;
#
#    my $indent_length;
#    my $escape_slash;
#    my $bignum;
#    my $as_nonblessed;
#    my $allow_tags;
#
#    my $depth;
#    my $indent_count;
#    my $keysort;
#
#
#    sub PP_encode_json {
#        my $self = shift;
#        my $obj  = shift;
#
#        $indent_count = 0;
#        $depth        = 0;
#
#        my $props = $self->{PROPS};
#
#        ($ascii, $latin1, $utf8, $indent, $canonical, $space_before, $space_after, $allow_blessed,
#            $convert_blessed, $escape_slash, $bignum, $as_nonblessed, $allow_tags)
#         = @{$props}[P_ASCII .. P_SPACE_AFTER, P_ALLOW_BLESSED, P_CONVERT_BLESSED,
#                    P_ESCAPE_SLASH, P_ALLOW_BIGNUM, P_AS_NONBLESSED, P_ALLOW_TAGS];
#
#        ($max_depth, $indent_length) = @{$self}{qw/max_depth indent_length/};
#
#        $keysort = $canonical ? sub { $a cmp $b } : undef;
#
#        if ($self->{sort_by}) {
#            $keysort = ref($self->{sort_by}) eq 'CODE' ? $self->{sort_by}
#                     : $self->{sort_by} =~ /\D+/       ? $self->{sort_by}
#                     : sub { $a cmp $b };
#        }
#
#        encode_error("hash- or arrayref expected (not a simple scalar, use allow_nonref to allow this)")
#             if(!ref $obj and !$props->[ P_ALLOW_NONREF ]);
#
#        my $str  = $self->object_to_json($obj);
#
#        $str .= "\n" if ( $indent ); 
#
#        unless ($ascii or $latin1 or $utf8) {
#            utf8::upgrade($str);
#        }
#
#        if ($props->[ P_SHRINK ]) {
#            utf8::downgrade($str, 1);
#        }
#
#        return $str;
#    }
#
#
#    sub object_to_json {
#        my ($self, $obj) = @_;
#        my $type = ref($obj);
#
#        if($type eq 'HASH'){
#            return $self->hash_to_json($obj);
#        }
#        elsif($type eq 'ARRAY'){
#            return $self->array_to_json($obj);
#        }
#        elsif ($type) { 
#            if (blessed($obj)) {
#
#                return $self->value_to_json($obj) if ( $obj->isa('JSON::PP::Boolean') );
#
#                if ( $allow_tags and $obj->can('FREEZE') ) {
#                    my $obj_class = ref $obj || $obj;
#                    $obj = bless $obj, $obj_class;
#                    my @results = $obj->FREEZE('JSON');
#                    if ( @results and ref $results[0] ) {
#                        if ( refaddr( $obj ) eq refaddr( $results[0] ) ) {
#                            encode_error( sprintf(
#                                "%s::FREEZE method returned same object as was passed instead of a new one",
#                                ref $obj
#                            ) );
#                        }
#                    }
#                    return '("'.$obj_class.'")['.join(',', @results).']';
#                }
#
#                if ( $convert_blessed and $obj->can('TO_JSON') ) {
#                    my $result = $obj->TO_JSON();
#                    if ( defined $result and ref( $result ) ) {
#                        if ( refaddr( $obj ) eq refaddr( $result ) ) {
#                            encode_error( sprintf(
#                                "%s::TO_JSON method returned same object as was passed instead of a new one",
#                                ref $obj
#                            ) );
#                        }
#                    }
#
#                    return $self->object_to_json( $result );
#                }
#
#                return "$obj" if ( $bignum and _is_bignum($obj) );
#
#                if ($allow_blessed) {
#                    return $self->blessed_to_json($obj) if ($as_nonblessed); 
#                    return 'null';
#                }
#                encode_error( sprintf("encountered object '%s', but neither allow_blessed, convert_blessed nor allow_tags settings are enabled (or TO_JSON/FREEZE method missing)", $obj)
#                );
#            }
#            else {
#                return $self->value_to_json($obj);
#            }
#        }
#        else{
#            return $self->value_to_json($obj);
#        }
#    }
#
#
#    sub hash_to_json {
#        my ($self, $obj) = @_;
#        my @res;
#
#        encode_error("json text or perl structure exceeds maximum nesting level (max_depth set too low?)")
#                                         if (++$depth > $max_depth);
#
#        my ($pre, $post) = $indent ? $self->_up_indent() : ('', '');
#        my $del = ($space_before ? ' ' : '') . ':' . ($space_after ? ' ' : '');
#
#        for my $k ( _sort( $obj ) ) {
#            if ( OLD_PERL ) { utf8::decode($k) } 
#            push @res, $self->string_to_json( $k )
#                          .  $del
#                          . ( ref $obj->{$k} ? $self->object_to_json( $obj->{$k} ) : $self->value_to_json( $obj->{$k} ) );
#        }
#
#        --$depth;
#        $self->_down_indent() if ($indent);
#
#        return '{}' unless @res;
#        return '{' . $pre . join( ",$pre", @res ) . $post . '}';
#    }
#
#
#    sub array_to_json {
#        my ($self, $obj) = @_;
#        my @res;
#
#        encode_error("json text or perl structure exceeds maximum nesting level (max_depth set too low?)")
#                                         if (++$depth > $max_depth);
#
#        my ($pre, $post) = $indent ? $self->_up_indent() : ('', '');
#
#        for my $v (@$obj){
#            push @res, ref($v) ? $self->object_to_json($v) : $self->value_to_json($v);
#        }
#
#        --$depth;
#        $self->_down_indent() if ($indent);
#
#        return '[]' unless @res;
#        return '[' . $pre . join( ",$pre", @res ) . $post . ']';
#    }
#
#    sub _looks_like_number {
#        my $value = shift;
#        if (USE_B) {
#            my $b_obj = B::svref_2object(\$value);
#            my $flags = $b_obj->FLAGS;
#            return 1 if $flags & ( B::SVp_IOK() | B::SVp_NOK() ) and !( $flags & B::SVp_POK() );
#            return;
#        } else {
#            no warnings 'numeric';
#            return if utf8::is_utf8($value);
#            return unless length((my $dummy = "") & $value);
#            return unless 0 + $value eq $value;
#            return 1 if $value * 0 == 0;
#            return -1; 
#        }
#    }
#
#    sub value_to_json {
#        my ($self, $value) = @_;
#
#        return 'null' if(!defined $value);
#
#        my $type = ref($value);
#
#        if (!$type) {
#            if (_looks_like_number($value)) {
#                return $value;
#            }
#            return $self->string_to_json($value);
#        }
#        elsif( blessed($value) and  $value->isa('JSON::PP::Boolean') ){
#            return $$value == 1 ? 'true' : 'false';
#        }
#        else {
#            if ((overload::StrVal($value) =~ /=(\w+)/)[0]) {
#                return $self->value_to_json("$value");
#            }
#
#            if ($type eq 'SCALAR' and defined $$value) {
#                return   $$value eq '1' ? 'true'
#                       : $$value eq '0' ? 'false'
#                       : $self->{PROPS}->[ P_ALLOW_UNKNOWN ] ? 'null'
#                       : encode_error("cannot encode reference to scalar");
#            }
#
#            if ( $self->{PROPS}->[ P_ALLOW_UNKNOWN ] ) {
#                return 'null';
#            }
#            else {
#                if ( $type eq 'SCALAR' or $type eq 'REF' ) {
#                    encode_error("cannot encode reference to scalar");
#                }
#                else {
#                    encode_error("encountered $value, but JSON can only represent references to arrays or hashes");
#                }
#            }
#
#        }
#    }
#
#
#    my %esc = (
#        "\n" => '\n',
#        "\r" => '\r',
#        "\t" => '\t',
#        "\f" => '\f',
#        "\b" => '\b',
#        "\"" => '\"',
#        "\\" => '\\\\',
#        "\'" => '\\\'',
#    );
#
#
#    sub string_to_json {
#        my ($self, $arg) = @_;
#
#        $arg =~ s/([\x22\x5c\n\r\t\f\b])/$esc{$1}/g;
#        $arg =~ s/\//\\\//g if ($escape_slash);
#        $arg =~ s/([\x00-\x08\x0b\x0e-\x1f])/'\\u00' . unpack('H2', $1)/eg;
#
#        if ($ascii) {
#            $arg = JSON_PP_encode_ascii($arg);
#        }
#
#        if ($latin1) {
#            $arg = JSON_PP_encode_latin1($arg);
#        }
#
#        if ($utf8) {
#            utf8::encode($arg);
#        }
#
#        return '"' . $arg . '"';
#    }
#
#
#    sub blessed_to_json {
#        my $reftype = reftype($_[1]) || '';
#        if ($reftype eq 'HASH') {
#            return $_[0]->hash_to_json($_[1]);
#        }
#        elsif ($reftype eq 'ARRAY') {
#            return $_[0]->array_to_json($_[1]);
#        }
#        else {
#            return 'null';
#        }
#    }
#
#
#    sub encode_error {
#        my $error  = shift;
#        Carp::croak "$error";
#    }
#
#
#    sub _sort {
#        defined $keysort ? (sort $keysort (keys %{$_[0]})) : keys %{$_[0]};
#    }
#
#
#    sub _up_indent {
#        my $self  = shift;
#        my $space = ' ' x $indent_length;
#
#        my ($pre,$post) = ('','');
#
#        $post = "\n" . $space x $indent_count;
#
#        $indent_count++;
#
#        $pre = "\n" . $space x $indent_count;
#
#        return ($pre,$post);
#    }
#
#
#    sub _down_indent { $indent_count--; }
#
#
#    sub PP_encode_box {
#        {
#            depth        => $depth,
#            indent_count => $indent_count,
#        };
#    }
#
#} 
#
#
#sub _encode_ascii {
#    join('',
#        map {
#            $_ <= 127 ?
#                chr($_) :
#            $_ <= 65535 ?
#                sprintf('\u%04x', $_) : sprintf('\u%x\u%x', _encode_surrogates($_));
#        } unpack('U*', $_[0])
#    );
#}
#
#
#sub _encode_latin1 {
#    join('',
#        map {
#            $_ <= 255 ?
#                chr($_) :
#            $_ <= 65535 ?
#                sprintf('\u%04x', $_) : sprintf('\u%x\u%x', _encode_surrogates($_));
#        } unpack('U*', $_[0])
#    );
#}
#
#
#sub _encode_surrogates { 
#    my $uni = $_[0] - 0x10000;
#    return ($uni / 0x400 + 0xD800, $uni % 0x400 + 0xDC00);
#}
#
#
#sub _is_bignum {
#    $_[0]->isa('Math::BigInt') or $_[0]->isa('Math::BigFloat');
#}
#
#
#
#
#my $max_intsize;
#
#BEGIN {
#    my $checkint = 1111;
#    for my $d (5..64) {
#        $checkint .= 1;
#        my $int   = eval qq| $checkint |;
#        if ($int =~ /[eE]/) {
#            $max_intsize = $d - 1;
#            last;
#        }
#    }
#}
#
#{ 
#
#    my %escapes = ( 
#        b    => "\x8",
#        t    => "\x9",
#        n    => "\xA",
#        f    => "\xC",
#        r    => "\xD",
#        '\\' => '\\',
#        '"'  => '"',
#        '/'  => '/',
#    );
#
#    my $text; 
#    my $at;   
#    my $ch;   
#    my $len;  
#    my $depth;          
#    my $encoding;       
#    my $is_valid_utf8;  
#    my $utf8_len;       
#    my $utf8;           
#    my $max_depth;      
#    my $max_size;
#    my $relaxed;
#    my $cb_object;
#    my $cb_sk_object;
#
#    my $F_HOOK;
#
#    my $allow_bignum;   
#    my $singlequote;    
#    my $loose;          
#    my $allow_barekey;  
#    my $allow_tags;
#
#    my $alt_true;
#    my $alt_false;
#
#    sub _detect_utf_encoding {
#        my $text = shift;
#        my @octets = unpack('C4', $text);
#        return 'unknown' unless defined $octets[3];
#        return ( $octets[0] and  $octets[1]) ? 'UTF-8'
#             : (!$octets[0] and  $octets[1]) ? 'UTF-16BE'
#             : (!$octets[0] and !$octets[1]) ? 'UTF-32BE'
#             : ( $octets[2]                ) ? 'UTF-16LE'
#             : (!$octets[2]                ) ? 'UTF-32LE'
#             : 'unknown';
#    }
#
#    sub PP_decode_json {
#        my ($self, $want_offset);
#
#        ($self, $text, $want_offset) = @_;
#
#        ($at, $ch, $depth) = (0, '', 0);
#
#        if ( !defined $text or ref $text ) {
#            decode_error("malformed JSON string, neither array, object, number, string or atom");
#        }
#
#        my $props = $self->{PROPS};
#
#        ($utf8, $relaxed, $loose, $allow_bignum, $allow_barekey, $singlequote, $allow_tags)
#            = @{$props}[P_UTF8, P_RELAXED, P_LOOSE .. P_ALLOW_SINGLEQUOTE, P_ALLOW_TAGS];
#
#        ($alt_true, $alt_false) = @$self{qw/true false/};
#
#        if ( $utf8 ) {
#            $encoding = _detect_utf_encoding($text);
#            if ($encoding ne 'UTF-8' and $encoding ne 'unknown') {
#                require Encode;
#                Encode::from_to($text, $encoding, 'utf-8');
#            } else {
#                utf8::downgrade( $text, 1 ) or Carp::croak("Wide character in subroutine entry");
#            }
#        }
#        else {
#            utf8::upgrade( $text );
#            utf8::encode( $text );
#        }
#
#        $len = length $text;
#
#        ($max_depth, $max_size, $cb_object, $cb_sk_object, $F_HOOK)
#             = @{$self}{qw/max_depth  max_size cb_object cb_sk_object F_HOOK/};
#
#        if ($max_size > 1) {
#            use bytes;
#            my $bytes = length $text;
#            decode_error(
#                sprintf("attempted decode of JSON text of %s bytes size, but max_size is set to %s"
#                    , $bytes, $max_size), 1
#            ) if ($bytes > $max_size);
#        }
#
#        white(); 
#
#        decode_error("malformed JSON string, neither array, object, number, string or atom") unless defined $ch; 
#
#        my $result = value();
#
#        if ( !$props->[ P_ALLOW_NONREF ] and !ref $result ) {
#                decode_error(
#                'JSON text must be an object or array (but found number, string, true, false or null,'
#                       . ' use allow_nonref to allow this)', 1);
#        }
#
#        Carp::croak('something wrong.') if $len < $at; 
#
#        my $consumed = defined $ch ? $at - 1 : $at; 
#
#        white(); 
#
#        return ( $result, $consumed ) if $want_offset; 
#
#        decode_error("garbage after JSON object") if defined $ch;
#
#        $result;
#    }
#
#
#    sub next_chr {
#        return $ch = undef if($at >= $len);
#        $ch = substr($text, $at++, 1);
#    }
#
#
#    sub value {
#        white();
#        return          if(!defined $ch);
#        return object() if($ch eq '{');
#        return array()  if($ch eq '[');
#        return tag()    if($ch eq '(');
#        return string() if($ch eq '"' or ($singlequote and $ch eq "'"));
#        return number() if($ch =~ /[0-9]/ or $ch eq '-');
#        return word();
#    }
#
#    sub string {
#        my $utf16;
#        my $is_utf8;
#
#        ($is_valid_utf8, $utf8_len) = ('', 0);
#
#        my $s = ''; 
#
#        if($ch eq '"' or ($singlequote and $ch eq "'")){
#            my $boundChar = $ch;
#
#            OUTER: while( defined(next_chr()) ){
#
#                if($ch eq $boundChar){
#                    next_chr();
#
#                    if ($utf16) {
#                        decode_error("missing low surrogate character in surrogate pair");
#                    }
#
#                    utf8::decode($s) if($is_utf8);
#
#                    return $s;
#                }
#                elsif($ch eq '\\'){
#                    next_chr();
#                    if(exists $escapes{$ch}){
#                        $s .= $escapes{$ch};
#                    }
#                    elsif($ch eq 'u'){ 
#                        my $u = '';
#
#                        for(1..4){
#                            $ch = next_chr();
#                            last OUTER if($ch !~ /[0-9a-fA-F]/);
#                            $u .= $ch;
#                        }
#
#                        if ($u =~ /^[dD][89abAB][0-9a-fA-F]{2}/) { 
#                            $utf16 = $u;
#                        }
#                        elsif ($u =~ /^[dD][c-fC-F][0-9a-fA-F]{2}/) { 
#                            unless (defined $utf16) {
#                                decode_error("missing high surrogate character in surrogate pair");
#                            }
#                            $is_utf8 = 1;
#                            $s .= JSON_PP_decode_surrogates($utf16, $u) || next;
#                            $utf16 = undef;
#                        }
#                        else {
#                            if (defined $utf16) {
#                                decode_error("surrogate pair expected");
#                            }
#
#                            if ( ( my $hex = hex( $u ) ) > 127 ) {
#                                $is_utf8 = 1;
#                                $s .= JSON_PP_decode_unicode($u) || next;
#                            }
#                            else {
#                                $s .= chr $hex;
#                            }
#                        }
#
#                    }
#                    else{
#                        unless ($loose) {
#                            $at -= 2;
#                            decode_error('illegal backslash escape sequence in string');
#                        }
#                        $s .= $ch;
#                    }
#                }
#                else{
#
#                    if ( ord $ch  > 127 ) {
#                        unless( $ch = is_valid_utf8($ch) ) {
#                            $at -= 1;
#                            decode_error("malformed UTF-8 character in JSON string");
#                        }
#                        else {
#                            $at += $utf8_len - 1;
#                        }
#
#                        $is_utf8 = 1;
#                    }
#
#                    if (!$loose) {
#                        if ($ch =~ /[\x00-\x1f\x22\x5c]/)  { 
#                            if (!$relaxed or $ch ne "\t") {
#                                $at--;
#                                decode_error('invalid character encountered while parsing JSON string');
#                            }
#                        }
#                    }
#
#                    $s .= $ch;
#                }
#            }
#        }
#
#        decode_error("unexpected end of string while parsing JSON string");
#    }
#
#
#    sub white {
#        while( defined $ch  ){
#            if($ch eq '' or $ch =~ /\A[ \t\r\n]\z/){
#                next_chr();
#            }
#            elsif($relaxed and $ch eq '/'){
#                next_chr();
#                if(defined $ch and $ch eq '/'){
#                    1 while(defined(next_chr()) and $ch ne "\n" and $ch ne "\r");
#                }
#                elsif(defined $ch and $ch eq '*'){
#                    next_chr();
#                    while(1){
#                        if(defined $ch){
#                            if($ch eq '*'){
#                                if(defined(next_chr()) and $ch eq '/'){
#                                    next_chr();
#                                    last;
#                                }
#                            }
#                            else{
#                                next_chr();
#                            }
#                        }
#                        else{
#                            decode_error("Unterminated comment");
#                        }
#                    }
#                    next;
#                }
#                else{
#                    $at--;
#                    decode_error("malformed JSON string, neither array, object, number, string or atom");
#                }
#            }
#            else{
#                if ($relaxed and $ch eq '#') { 
#                    pos($text) = $at;
#                    $text =~ /\G([^\n]*(?:\r\n|\r|\n|$))/g;
#                    $at = pos($text);
#                    next_chr;
#                    next;
#                }
#
#                last;
#            }
#        }
#    }
#
#
#    sub array {
#        my $a  = $_[0] || []; 
#
#        decode_error('json text or perl structure exceeds maximum nesting level (max_depth set too low?)')
#                                                    if (++$depth > $max_depth);
#
#        next_chr();
#        white();
#
#        if(defined $ch and $ch eq ']'){
#            --$depth;
#            next_chr();
#            return $a;
#        }
#        else {
#            while(defined($ch)){
#                push @$a, value();
#
#                white();
#
#                if (!defined $ch) {
#                    last;
#                }
#
#                if($ch eq ']'){
#                    --$depth;
#                    next_chr();
#                    return $a;
#                }
#
#                if($ch ne ','){
#                    last;
#                }
#
#                next_chr();
#                white();
#
#                if ($relaxed and $ch eq ']') {
#                    --$depth;
#                    next_chr();
#                    return $a;
#                }
#
#            }
#        }
#
#        $at-- if defined $ch and $ch ne '';
#        decode_error(", or ] expected while parsing array");
#    }
#
#    sub tag {
#        decode_error('malformed JSON string, neither array, object, number, string or atom') unless $allow_tags;
#
#        next_chr();
#        white();
#
#        my $tag = value();
#        return unless defined $tag;
#        decode_error('malformed JSON string, (tag) must be a string') if ref $tag;
#
#        white();
#
#        if (!defined $ch or $ch ne ')') {
#            decode_error(') expected after tag');
#        }
#
#        next_chr();
#        white();
#
#        my $val = value();
#        return unless defined $val;
#        decode_error('malformed JSON string, tag value must be an array') unless ref $val eq 'ARRAY';
#
#        if (!eval { $tag->can('THAW') }) {
#             decode_error('cannot decode perl-object (package does not exist)') if $@;
#             decode_error('cannot decode perl-object (package does not have a THAW method)');
#        }
#        $tag->THAW('JSON', @$val);
#    }
#
#    sub object {
#        my $o = $_[0] || {}; 
#        my $k;
#
#        decode_error('json text or perl structure exceeds maximum nesting level (max_depth set too low?)')
#                                                if (++$depth > $max_depth);
#        next_chr();
#        white();
#
#        if(defined $ch and $ch eq '}'){
#            --$depth;
#            next_chr();
#            if ($F_HOOK) {
#                return _json_object_hook($o);
#            }
#            return $o;
#        }
#        else {
#            while (defined $ch) {
#                $k = ($allow_barekey and $ch ne '"' and $ch ne "'") ? bareKey() : string();
#                white();
#
#                if(!defined $ch or $ch ne ':'){
#                    $at--;
#                    decode_error("':' expected");
#                }
#
#                next_chr();
#                $o->{$k} = value();
#                white();
#
#                last if (!defined $ch);
#
#                if($ch eq '}'){
#                    --$depth;
#                    next_chr();
#                    if ($F_HOOK) {
#                        return _json_object_hook($o);
#                    }
#                    return $o;
#                }
#
#                if($ch ne ','){
#                    last;
#                }
#
#                next_chr();
#                white();
#
#                if ($relaxed and $ch eq '}') {
#                    --$depth;
#                    next_chr();
#                    if ($F_HOOK) {
#                        return _json_object_hook($o);
#                    }
#                    return $o;
#                }
#
#            }
#
#        }
#
#        $at-- if defined $ch and $ch ne '';
#        decode_error(", or } expected while parsing object/hash");
#    }
#
#
#    sub bareKey { 
#        my $key;
#        while($ch =~ /[^\x00-\x23\x25-\x2F\x3A-\x40\x5B-\x5E\x60\x7B-\x7F]/){
#            $key .= $ch;
#            next_chr();
#        }
#        return $key;
#    }
#
#
#    sub word {
#        my $word =  substr($text,$at-1,4);
#
#        if($word eq 'true'){
#            $at += 3;
#            next_chr;
#            return defined $alt_true ? $alt_true : $JSON::PP::true;
#        }
#        elsif($word eq 'null'){
#            $at += 3;
#            next_chr;
#            return undef;
#        }
#        elsif($word eq 'fals'){
#            $at += 3;
#            if(substr($text,$at,1) eq 'e'){
#                $at++;
#                next_chr;
#                return defined $alt_false ? $alt_false : $JSON::PP::false;
#            }
#        }
#
#        $at--; 
#
#        decode_error("'null' expected")  if ($word =~ /^n/);
#        decode_error("'true' expected")  if ($word =~ /^t/);
#        decode_error("'false' expected") if ($word =~ /^f/);
#        decode_error("malformed JSON string, neither array, object, number, string or atom");
#    }
#
#
#    sub number {
#        my $n    = '';
#        my $v;
#        my $is_dec;
#        my $is_exp;
#
#        if($ch eq '-'){
#            $n = '-';
#            next_chr;
#            if (!defined $ch or $ch !~ /\d/) {
#                decode_error("malformed number (no digits after initial minus)");
#            }
#        }
#
#        if($ch eq '0'){
#            my $peek = substr($text,$at,1);
#            if($peek =~ /^[0-9a-dfA-DF]/){ 
#                decode_error("malformed number (leading zero must not be followed by another digit)");
#            }
#            $n .= $ch;
#            next_chr;
#        }
#
#        while(defined $ch and $ch =~ /\d/){
#            $n .= $ch;
#            next_chr;
#        }
#
#        if(defined $ch and $ch eq '.'){
#            $n .= '.';
#            $is_dec = 1;
#
#            next_chr;
#            if (!defined $ch or $ch !~ /\d/) {
#                decode_error("malformed number (no digits after decimal point)");
#            }
#            else {
#                $n .= $ch;
#            }
#
#            while(defined(next_chr) and $ch =~ /\d/){
#                $n .= $ch;
#            }
#        }
#
#        if(defined $ch and ($ch eq 'e' or $ch eq 'E')){
#            $n .= $ch;
#            $is_exp = 1;
#            next_chr;
#
#            if(defined($ch) and ($ch eq '+' or $ch eq '-')){
#                $n .= $ch;
#                next_chr;
#                if (!defined $ch or $ch =~ /\D/) {
#                    decode_error("malformed number (no digits after exp sign)");
#                }
#                $n .= $ch;
#            }
#            elsif(defined($ch) and $ch =~ /\d/){
#                $n .= $ch;
#            }
#            else {
#                decode_error("malformed number (no digits after exp sign)");
#            }
#
#            while(defined(next_chr) and $ch =~ /\d/){
#                $n .= $ch;
#            }
#
#        }
#
#        $v .= $n;
#
#        if ($is_dec or $is_exp) {
#            if ($allow_bignum) {
#                require Math::BigFloat;
#                return Math::BigFloat->new($v);
#            }
#        } else {
#            if (length $v > $max_intsize) {
#                if ($allow_bignum) { 
#                    require Math::BigInt;
#                    return Math::BigInt->new($v);
#                }
#                else {
#                    return "$v";
#                }
#            }
#        }
#
#        return $is_dec ? $v/1.0 : 0+$v;
#    }
#
#
#    sub is_valid_utf8 {
#
#        $utf8_len = $_[0] =~ /[\x00-\x7F]/  ? 1
#                  : $_[0] =~ /[\xC2-\xDF]/  ? 2
#                  : $_[0] =~ /[\xE0-\xEF]/  ? 3
#                  : $_[0] =~ /[\xF0-\xF4]/  ? 4
#                  : 0
#                  ;
#
#        return unless $utf8_len;
#
#        my $is_valid_utf8 = substr($text, $at - 1, $utf8_len);
#
#        return ( $is_valid_utf8 =~ /^(?:
#             [\x00-\x7F]
#            |[\xC2-\xDF][\x80-\xBF]
#            |[\xE0][\xA0-\xBF][\x80-\xBF]
#            |[\xE1-\xEC][\x80-\xBF][\x80-\xBF]
#            |[\xED][\x80-\x9F][\x80-\xBF]
#            |[\xEE-\xEF][\x80-\xBF][\x80-\xBF]
#            |[\xF0][\x90-\xBF][\x80-\xBF][\x80-\xBF]
#            |[\xF1-\xF3][\x80-\xBF][\x80-\xBF][\x80-\xBF]
#            |[\xF4][\x80-\x8F][\x80-\xBF][\x80-\xBF]
#        )$/x )  ? $is_valid_utf8 : '';
#    }
#
#
#    sub decode_error {
#        my $error  = shift;
#        my $no_rep = shift;
#        my $str    = defined $text ? substr($text, $at) : '';
#        my $mess   = '';
#        my $type   = 'U*';
#
#        if ( OLD_PERL ) {
#            my $type   =  $] <  5.006           ? 'C*'
#                        : utf8::is_utf8( $str ) ? 'U*' 
#                        : 'C*'
#                        ;
#        }
#
#        for my $c ( unpack( $type, $str ) ) { 
#            $mess .=  $c == 0x07 ? '\a'
#                    : $c == 0x09 ? '\t'
#                    : $c == 0x0a ? '\n'
#                    : $c == 0x0d ? '\r'
#                    : $c == 0x0c ? '\f'
#                    : $c <  0x20 ? sprintf('\x{%x}', $c)
#                    : $c == 0x5c ? '\\\\'
#                    : $c <  0x80 ? chr($c)
#                    : sprintf('\x{%x}', $c)
#                    ;
#            if ( length $mess >= 20 ) {
#                $mess .= '...';
#                last;
#            }
#        }
#
#        unless ( length $mess ) {
#            $mess = '(end of string)';
#        }
#
#        Carp::croak (
#            $no_rep ? "$error" : "$error, at character offset $at (before \"$mess\")"
#        );
#
#    }
#
#
#    sub _json_object_hook {
#        my $o    = $_[0];
#        my @ks = keys %{$o};
#
#        if ( $cb_sk_object and @ks == 1 and exists $cb_sk_object->{ $ks[0] } and ref $cb_sk_object->{ $ks[0] } ) {
#            my @val = $cb_sk_object->{ $ks[0] }->( $o->{$ks[0]} );
#            if (@val == 0) {
#                return $o;
#            }
#            elsif (@val == 1) {
#                return $val[0];
#            }
#            else {
#                Carp::croak("filter_json_single_key_object callbacks must not return more than one scalar");
#            }
#        }
#
#        my @val = $cb_object->($o) if ($cb_object);
#        if (@val == 0) {
#            return $o;
#        }
#        elsif (@val == 1) {
#            return $val[0];
#        }
#        else {
#            Carp::croak("filter_json_object callbacks must not return more than one scalar");
#        }
#    }
#
#
#    sub PP_decode_box {
#        {
#            text    => $text,
#            at      => $at,
#            ch      => $ch,
#            len     => $len,
#            depth   => $depth,
#            encoding      => $encoding,
#            is_valid_utf8 => $is_valid_utf8,
#        };
#    }
#
#} 
#
#
#sub _decode_surrogates { 
#    my $uni = 0x10000 + (hex($_[0]) - 0xD800) * 0x400 + (hex($_[1]) - 0xDC00);
#    my $un  = pack('U*', $uni);
#    utf8::encode( $un );
#    return $un;
#}
#
#
#sub _decode_unicode {
#    my $un = pack('U', hex shift);
#    utf8::encode( $un );
#    return $un;
#}
#
#
#BEGIN {
#
#    unless ( defined &utf8::is_utf8 ) {
#       require Encode;
#       *utf8::is_utf8 = *Encode::is_utf8;
#    }
#
#    if ( !OLD_PERL ) {
#        *JSON::PP::JSON_PP_encode_ascii      = \&_encode_ascii;
#        *JSON::PP::JSON_PP_encode_latin1     = \&_encode_latin1;
#        *JSON::PP::JSON_PP_decode_surrogates = \&_decode_surrogates;
#        *JSON::PP::JSON_PP_decode_unicode    = \&_decode_unicode;
#
#        if ($] < 5.008003) { 
#            package JSON::PP;
#            require subs;
#            subs->import('join');
#            eval q|
#                sub join {
#                    return '' if (@_ < 2);
#                    my $j   = shift;
#                    my $str = shift;
#                    for (@_) { $str .= $j . $_; }
#                    return $str;
#                }
#            |;
#        }
#    }
#
#
#    sub JSON::PP::incr_parse {
#        local $Carp::CarpLevel = 1;
#        ( $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new )->incr_parse( @_ );
#    }
#
#
#    sub JSON::PP::incr_skip {
#        ( $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new )->incr_skip;
#    }
#
#
#    sub JSON::PP::incr_reset {
#        ( $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new )->incr_reset;
#    }
#
#    eval q{
#        sub JSON::PP::incr_text : lvalue {
#            $_[0]->{_incr_parser} ||= JSON::PP::IncrParser->new;
#
#            if ( $_[0]->{_incr_parser}->{incr_pos} ) {
#                Carp::croak("incr_text cannot be called when the incremental parser already started parsing");
#            }
#            $_[0]->{_incr_parser}->{incr_text};
#        }
#    } if ( $] >= 5.006 );
#
#} 
#
#
#
#BEGIN {
#    eval 'require Scalar::Util';
#    unless($@){
#        *JSON::PP::blessed = \&Scalar::Util::blessed;
#        *JSON::PP::reftype = \&Scalar::Util::reftype;
#        *JSON::PP::refaddr = \&Scalar::Util::refaddr;
#    }
#    else{ 
#        eval 'sub UNIVERSAL::a_sub_not_likely_to_be_here { ref($_[0]) }';
#        *JSON::PP::blessed = sub {
#            local($@, $SIG{__DIE__}, $SIG{__WARN__});
#            ref($_[0]) ? eval { $_[0]->a_sub_not_likely_to_be_here } : undef;
#        };
#        require B;
#        my %tmap = qw(
#            B::NULL   SCALAR
#            B::HV     HASH
#            B::AV     ARRAY
#            B::CV     CODE
#            B::IO     IO
#            B::GV     GLOB
#            B::REGEXP REGEXP
#        );
#        *JSON::PP::reftype = sub {
#            my $r = shift;
#
#            return undef unless length(ref($r));
#
#            my $t = ref(B::svref_2object($r));
#
#            return
#                exists $tmap{$t} ? $tmap{$t}
#              : length(ref($$r)) ? 'REF'
#              :                    'SCALAR';
#        };
#        *JSON::PP::refaddr = sub {
#          return undef unless length(ref($_[0]));
#
#          my $addr;
#          if(defined(my $pkg = blessed($_[0]))) {
#            $addr .= bless $_[0], 'Scalar::Util::Fake';
#            bless $_[0], $pkg;
#          }
#          else {
#            $addr .= $_[0]
#          }
#
#          $addr =~ /0x(\w+)/;
#          local $^W;
#          hex($1);
#        }
#    }
#}
#
#
#
#$JSON::PP::true  = do { bless \(my $dummy = 1), "JSON::PP::Boolean" };
#$JSON::PP::false = do { bless \(my $dummy = 0), "JSON::PP::Boolean" };
#
#sub is_bool { blessed $_[0] and ( $_[0]->isa("JSON::PP::Boolean") or $_[0]->isa("Types::Serialiser::BooleanBase") or $_[0]->isa("JSON::XS::Boolean") ); }
#
#sub true  { $JSON::PP::true  }
#sub false { $JSON::PP::false }
#sub null  { undef; }
#
#
#package JSON::PP::IncrParser;
#
#use strict;
#
#use constant INCR_M_WS   => 0; 
#use constant INCR_M_STR  => 1; 
#use constant INCR_M_BS   => 2; 
#use constant INCR_M_JSON => 3; 
#use constant INCR_M_C0   => 4;
#use constant INCR_M_C1   => 5;
#use constant INCR_M_TFN  => 6;
#use constant INCR_M_NUM  => 7;
#
#$JSON::PP::IncrParser::VERSION = '1.01';
#
#sub new {
#    my ( $class ) = @_;
#
#    bless {
#        incr_nest    => 0,
#        incr_text    => undef,
#        incr_pos     => 0,
#        incr_mode    => 0,
#    }, $class;
#}
#
#
#sub incr_parse {
#    my ( $self, $coder, $text ) = @_;
#
#    $self->{incr_text} = '' unless ( defined $self->{incr_text} );
#
#    if ( defined $text ) {
#        if ( utf8::is_utf8( $text ) and !utf8::is_utf8( $self->{incr_text} ) ) {
#            utf8::upgrade( $self->{incr_text} ) ;
#            utf8::decode( $self->{incr_text} ) ;
#        }
#        $self->{incr_text} .= $text;
#    }
#
#    if ( defined wantarray ) {
#        my $max_size = $coder->get_max_size;
#        my $p = $self->{incr_pos};
#        my @ret;
#        {
#            do {
#                unless ( $self->{incr_nest} <= 0 and $self->{incr_mode} == INCR_M_JSON ) {
#                    $self->_incr_parse( $coder );
#
#                    if ( $max_size and $self->{incr_pos} > $max_size ) {
#                        Carp::croak("attempted decode of JSON text of $self->{incr_pos} bytes size, but max_size is set to $max_size");
#                    }
#                    unless ( $self->{incr_nest} <= 0 and $self->{incr_mode} == INCR_M_JSON ) {
#                        if ( $self->{incr_mode} == INCR_M_WS and $self->{incr_pos} ) {
#                            $self->{incr_pos} = 0;
#                            $self->{incr_text} = '';
#                        }
#                        last;
#                    }
#                }
#
#                my ($obj, $offset) = $coder->PP_decode_json( $self->{incr_text}, 0x00000001 );
#                push @ret, $obj;
#                use bytes;
#                $self->{incr_text} = substr( $self->{incr_text}, $offset || 0 );
#                $self->{incr_pos} = 0;
#                $self->{incr_nest} = 0;
#                $self->{incr_mode} = 0;
#                last unless wantarray;
#            } while ( wantarray );
#        }
#
#        if ( wantarray ) {
#            return @ret;
#        }
#        else { 
#            return defined $ret[0] ? $ret[0] : undef;
#        }
#    }
#}
#
#
#sub _incr_parse {
#    my ($self, $coder) = @_;
#    my $text = $self->{incr_text};
#    my $len = length $text;
#    my $p = $self->{incr_pos};
#
#INCR_PARSE:
#    while ( $len > $p ) {
#        my $s = substr( $text, $p, 1 );
#        last INCR_PARSE unless defined $s;
#        my $mode = $self->{incr_mode};
#
#        if ( $mode == INCR_M_WS ) {
#            while ( $len > $p ) {
#                $s = substr( $text, $p, 1 );
#                last INCR_PARSE unless defined $s;
#                if ( ord($s) > 0x20 ) {
#                    if ( $s eq '#' ) {
#                        $self->{incr_mode} = INCR_M_C0;
#                        redo INCR_PARSE;
#                    } else {
#                        $self->{incr_mode} = INCR_M_JSON;
#                        redo INCR_PARSE;
#                    }
#                }
#                $p++;
#            }
#        } elsif ( $mode == INCR_M_BS ) {
#            $p++;
#            $self->{incr_mode} = INCR_M_STR;
#            redo INCR_PARSE;
#        } elsif ( $mode == INCR_M_C0 or $mode == INCR_M_C1 ) {
#            while ( $len > $p ) {
#                $s = substr( $text, $p, 1 );
#                last INCR_PARSE unless defined $s;
#                if ( $s eq "\n" ) {
#                    $self->{incr_mode} = $self->{incr_mode} == INCR_M_C0 ? INCR_M_WS : INCR_M_JSON;
#                    last;
#                }
#                $p++;
#            }
#            next;
#        } elsif ( $mode == INCR_M_TFN ) {
#            while ( $len > $p ) {
#                $s = substr( $text, $p++, 1 );
#                next if defined $s and $s =~ /[rueals]/;
#                last;
#            }
#            $p--;
#            $self->{incr_mode} = INCR_M_JSON;
#
#            last INCR_PARSE unless $self->{incr_nest};
#            redo INCR_PARSE;
#        } elsif ( $mode == INCR_M_NUM ) {
#            while ( $len > $p ) {
#                $s = substr( $text, $p++, 1 );
#                next if defined $s and $s =~ /[0-9eE.+\-]/;
#                last;
#            }
#            $p--;
#            $self->{incr_mode} = INCR_M_JSON;
#
#            last INCR_PARSE unless $self->{incr_nest};
#            redo INCR_PARSE;
#        } elsif ( $mode == INCR_M_STR ) {
#            while ( $len > $p ) {
#                $s = substr( $text, $p, 1 );
#                last INCR_PARSE unless defined $s;
#                if ( $s eq '"' ) {
#                    $p++;
#                    $self->{incr_mode} = INCR_M_JSON;
#
#                    last INCR_PARSE unless $self->{incr_nest};
#                    redo INCR_PARSE;
#                }
#                elsif ( $s eq '\\' ) {
#                    $p++;
#                    if ( !defined substr($text, $p, 1) ) {
#                        $self->{incr_mode} = INCR_M_BS;
#                        last INCR_PARSE;
#                    }
#                }
#                $p++;
#            }
#        } elsif ( $mode == INCR_M_JSON ) {
#            while ( $len > $p ) {
#                $s = substr( $text, $p++, 1 );
#                if ( $s eq "\x00" ) {
#                    $p--;
#                    last INCR_PARSE;
#                } elsif ( $s eq "\x09" or $s eq "\x0a" or $s eq "\x0d" or $s eq "\x20" ) {
#                    if ( !$self->{incr_nest} ) {
#                        $p--; 
#                        last INCR_PARSE;
#                    }
#                    next;
#                } elsif ( $s eq 't' or $s eq 'f' or $s eq 'n' ) {
#                    $self->{incr_mode} = INCR_M_TFN;
#                    redo INCR_PARSE;
#                } elsif ( $s =~ /^[0-9\-]$/ ) {
#                    $self->{incr_mode} = INCR_M_NUM;
#                    redo INCR_PARSE;
#                } elsif ( $s eq '"' ) {
#                    $self->{incr_mode} = INCR_M_STR;
#                    redo INCR_PARSE;
#                } elsif ( $s eq '[' or $s eq '{' ) {
#                    if ( ++$self->{incr_nest} > $coder->get_max_depth ) {
#                        Carp::croak('json text or perl structure exceeds maximum nesting level (max_depth set too low?)');
#                    }
#                    next;
#                } elsif ( $s eq ']' or $s eq '}' ) {
#                    if ( --$self->{incr_nest} <= 0 ) {
#                        last INCR_PARSE;
#                    }
#                } elsif ( $s eq '#' ) {
#                    $self->{incr_mode} = INCR_M_C1;
#                    redo INCR_PARSE;
#                }
#            }
#        }
#    }
#
#    $self->{incr_pos} = $p;
#    $self->{incr_parsing} = $p ? 1 : 0; 
#}
#
#
#sub incr_text {
#    if ( $_[0]->{incr_pos} ) {
#        Carp::croak("incr_text cannot be called when the incremental parser already started parsing");
#    }
#    $_[0]->{incr_text};
#}
#
#
#sub incr_skip {
#    my $self  = shift;
#    $self->{incr_text} = substr( $self->{incr_text}, $self->{incr_pos} );
#    $self->{incr_pos}     = 0;
#    $self->{incr_mode}    = 0;
#    $self->{incr_nest}    = 0;
#}
#
#
#sub incr_reset {
#    my $self = shift;
#    $self->{incr_text}    = undef;
#    $self->{incr_pos}     = 0;
#    $self->{incr_mode}    = 0;
#    $self->{incr_nest}    = 0;
#}
#
#
#
#1;
#__END__
### JSON/PP/Boolean.pm ###
#package JSON::PP::Boolean;
#
#use strict;
#require overload;
#local $^W;
#overload::import('overload',
#    "0+"     => sub { ${$_[0]} },
#    "++"     => sub { $_[0] = ${$_[0]} + 1 },
#    "--"     => sub { $_[0] = ${$_[0]} - 1 },
#    fallback => 1,
#);
#
#$JSON::PP::Boolean::VERSION = '4.02';
#
#1;
#
#__END__
#
#
