Skip to content

Instantly share code, notes, and snippets.

@tron1point0
Created October 10, 2012 00:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tron1point0/3862455 to your computer and use it in GitHub Desktop.
Save tron1point0/3862455 to your computer and use it in GitHub Desktop.
NBT parser
#!/usr/bin/env perl
package NBT;
use strict;
use warnings;
sub parse {
my ($fh) = @_;
my @types = qw(
end byte short int long float double
byte_array string list compound int_array
);
my %types;
my $read = sub { my $buf; read $fh, $buf, $_[0] or return; $buf };
my $_scalar = sub {
my ($bytes,$packing) = @_;
sub { scalar unpack $packing, ($read->($bytes) or return) }
};
my $_list = sub {
my ($ltype) = @_;
sub {
my $type = ref $ltype ? $ltype->() : $ltype;
[map {$types{$type}->()} 0..$types{int}->()-1]
}
};
my $next = sub {
my $itype = $types{byte}->() or return;
return $types[$itype],
$types[$itype] eq 'end' ? '' : $types{string}->() || '(unnamed)'
};
%types = (
end => sub { 'END' },
byte => $_scalar->(1,'c'),
short => $_scalar->(2,'s>'),
int => $_scalar->(4,'l>'),
long => $_scalar->(8,'q>'),
float => $_scalar->(4,'f'),
double => $_scalar->(8,'d'),
byte_array => $_list->('byte'),
string => sub { $read->($types{short}->()) },
list => $_list->(sub {$types[$types{byte}->()]}),
compound => sub {
my ($type,$name,%elems);
$elems{$name} = $types{$type}->()
while ($type,$name) = $next->() and $type ne 'end';
\%elems
},
int_array => $_list->('int'),
);
$types{compound}->();
}
1;
__END__
=head1 NAME
C<NBT> - parse L<Minecraft's NBT format|http://www.minecraftwiki.net/wiki/NBT>
into a perl hash
=head1 SYNOPSIS
use PerlIO::gzip;
use YAML qw(Dump);
open my $fh, '<:gzip', \do {local $/;<>};
print Dump NBT::parse $fh;
Or, in a shell:
$ perl -MNBT -MYAML -MPerlIO::gzip \
> -E 'open my $fh, "<:gzip", \do {local $/;<>};
> print Dump NBT::parse $fh' level.dat
=head1 FUNCTIONS
C<NBT> exports only one function: C<parse>.
=head2 C<parse>
C<parse> takes exactly one argument - a filehandle to an B<uncompressed> NBT
stream and returns a hashref containing the data in the stream.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment