# pack a 'binary protocol list' sub pack_list { my $list = ref($_[0]) ? $_[0] : \@_; my $packed = ''; for my $item (@$list) { my $len; if (not defined $item) { $len = 0xFF; # escape code for undef } else { $len = length $item; if ($len >= 0xFE) { # we need to escape and send a 4-byte length... $item = (pack 'N', $len) . $item; $len = 0xFE; # escape code } } $packed .= (pack 'C', $len) . (defined $item ? $item : ''); } $packed = (pack 'n', scalar @$list) . $packed; return $packed; } # unpack a 'binary protocol' list # this will return () / undef if there is a protocol error - which suggests not to use it in list context afterall! sub unpack_list { my $packed = shift; my $n = unpack 'n', substr $packed, 0, 2, ''; return unless defined $n; my @list = (); while ($packed) { my $len = unpack 'C', substr $packed, 0, 1, ''; my $item; if ($len == 0xFF) { # $item = undef; } else { if ($len == 0xFE) { $len = unpack 'N', substr $packed, 0, 4, ''; } return unless defined $len and $len <= length($packed); $item = substr $packed, 0, $len, ''; } push @list, $item; } return unless $n == @list; return wantarray ? @list : \@list; } sub unpack_list { my $packed = shift; my $pos = 0; my $len_packed = length $packed; my $n = unpack 'N', substr $packed, $pos, 4; $pos += 4; return unless defined $n; my @list = (); while ($pos < $len_packed) { my $len = unpack 'N', substr $packed, $pos, 4; $pos += 4; if ($len == 0xFFFFFFFF) { push @list, undef; } else { push @list, substr $packed, $pos, $len; $pos += $len; } } return unless $n == @list; return unless $pos == $len_packed; return wantarray ? @list : \@list; }