#!/usr/bin/perl -w # Expand the output of encode.pl such that it fits a certain length. # # 2017-12-16 use strict; use constant NEWLINE => 33; use constant MIN_CHAR => 35; use constant MIN_SPACE => 93; unless( $#ARGV >= 0 ) { die "$0 \n"; } my $target = shift @ARGV; die unless $target =~ /^\d+$/; # Load input my $input = join '', <>; chomp $input; # Drop encoded newline, since puts() will insert an extra newline $input =~ s/!*$//; if( length($input) > $target ) { die "Input length (" . length($input) . ") is already longer than desired length ($target)\n"; } # Select random indices to expand my @index = (); push @index, $_ foreach 0 .. (length($input) - 1); for(my $i = @index; --$i;) { my $j = int(rand($i + 1)); @index[$i, $j] = @index[$j, $i]; } # Convert single character pieces to two character fragments my @pieces = map {chr} unpack 'C*', $input; my $pad = $target - length($input); foreach my $i (@index) { # Skip over unexpandable characters my $d = ord($pieces[$i]); next if $d == NEWLINE || $d == MIN_CHAR || $d == MIN_SPACE; # Stop when we have padded enough bytes last if $pad-- <= 0; if( $d < MIN_SPACE ) { $d = $d - MIN_CHAR + 1; my $partition = int(rand($d - 1)) + 1; $pieces[$i] = chr(MIN_CHAR + $partition - 1) . chr(MIN_CHAR + $d - $partition - 1); } else { $d = $d - MIN_SPACE + 1; my $partition = int(rand($d - 1)) + 1; $pieces[$i] = chr(MIN_SPACE + $partition - 1) . chr(MIN_SPACE + $d - $partition - 1); } } print((join '', @pieces), "\n");