I'm trying to learn perl by writing a custom base64 encoding function, unfortunately I've had no success by now. What I've come to is the following, which doesn't work and I unfortunately don't have any clue about how to proceed.
sub base64($) {
# Split string into single bits
my $bitstring = unpack("B*", $_[0]);
# Pack bits in pieces of six bits at a time
my @splitsixs = unpack("(A6)*", $bitstring);
my @enc = ("A".."Z", "a".."z", "0".."9", "+", "/");
# For each piece of six bits, convert them to integer, and take the corresponding place in @enc.
my @s = map { $enc[pack("B6", $_)] } @splitsixs;
join "", @s;
}
Can someone explain to me what am I doing wrong in this conversion? (Please leave aside for now the fact that I'm not considering padding)
I finally made it! I was erroneously trying to indexing elements in $enc
directly via packed bytes, while I should convert them first into integers.
You can see this in the lines below.
I copy the entire function, padding included, in the hope that it might be useful to others.
sub base64($) {
# Split string into single bits
my $bitstring = unpack("B*", $_[0]);
# Pack bits in pieces of six bits at a time
my @sixs = unpack("(A6)*", $bitstring);
# Compute the amount of zero padding necessary to obtain a 6-aligned bitstring
my $padding = ((6 - (length $sixs[-1]) % 6) % 6);
$sixs[-1] = join "", ($sixs[-1], "0" x $padding);
# Array of mapping from pieces to encodings
my @enc = ("A".."Z", "a".."z", "0".."9", "+", "/");
# Unpack bit strings into integers
@sixs = map { unpack("c", pack("b6", join "", reverse(split "", $_))) } @sixs;
# For each integer take the corresponding place in @enc.
my @s = map { $enc[$_] } @sixs;
# Concatenate string adding necessary padding
join "", (@s, "=" x ($padding / 2));
}