1 byte: 0..127
2 bytes: 128..etc
3 bytes: 16_384
4 bytes: 2_097_152
5 bytes: 268_435_456
6 bytes: 34_359_738_368
7 bytes: 4_398_046_511_104
8 bytes: 562_949_953_421_312
9 bytes: 72_057_594_037_927_936
####
sub compress_uint {
my ($uint) = @_;
my $compressed = '';
while ($uint >= 128) {
$compressed .= chr(($uint & 127) | 128);
$uint >>= 7;
}
$compressed .= chr($uint);
}
for (100, 1000, 100000) {
print $fh compress_uint($_);
}
####
sub decompress_uint {
our $compressed; local *compressed = \($_[0]);
my $bytes_read = 0;
my $uint = 0;
for (;;) {
die if length($compressed) == $bytes_read;
my $byte = ord(substr($compressed, $bytes_read++, 1));
$uint = ($uint << 7) | ($byte & 127);
last if $byte & 128;
}
$compressed = substr($compressed, $bytes_read);
}
my $raw = do { local $/; <$fh> };
my @nums;
while (length($raw)) {
push @nums, decompress_uint($raw);
}