Perl, 147 bytes
sub b{$f=(3-($#_+1)%3)%3;$_=unpack'B*',pack'C*',@_;@r=map{(A..Z,a..z,0..9,'+','/')[oct"0b$_"]}/.{1,6}/g;$"='';join"\r\n",("@r".'='x$f)=~/.{1,76}/g}
The function takes a list of integers as input and outputs the string, base64 encoded.
Example:
print b(99, 97, 102, 195, 169)
prints
Y2Fmw6kA
Ungolfed:
Version that also visualizes the intermediate steps:
sub b {
# input array: @_
# number of elements: $#_ + 1 ($#_ is zero-based index of last element in
$fillbytes = (3 - ($#_ + 1) % 3) % 3;
# calculate the number for the needed fill bytes
print "fillbytes: $fillbytes\n";
$byte_string = pack 'C*', @_;
# the numbers are packed as octets to a binary string
# (binary string not printed)
$bit_string = unpack 'B*', $byte_string;
# the binary string is converted to its bit representation, a string wit
print "bit string: \"$bit_string\"\n";
@six_bit_strings = $bit_string =~ /.{1,6}/g;
# group in blocks of 6 bit
print "6-bit strings: [@six_bit_strings]\n";
@index_positions = map { oct"0b$_" } @six_bit_strings;
# convert bit string to number
print "index positions: [@index_positions]\n";
@alphabet = (A..Z,a..z,0..9,'+','/');
# the alphabet for base64
@output_chars = map { $alphabet[$_] } @index_positions;
# output characters with wrong last characters that entirely derived fro
print "output chars: [@output_chars]\n";
local $" = ''; #"
$output_string = "@output_chars";
# array to string without space between elements ($")
print "output string: \"$output_string\"\n";
$result = $output_string .= '=' x $fillbytes;
# add padding with trailing '=' characters
print "result: \"$result\"\n";
$formatted_result = join "\r\n", $result =~ /.{1,76}/g;
# maximum line length is 76 and line ends are "\r\n" according to RFC 2045
print "formatted result:\n$formatted_result\n";
return $formatted_result;
}
Output:
fillbytes: 1
bit string: "0110001101100001011001101100001110101001"
6-bit strings: [011000 110110 000101 100110 110000 111010 1001]
index positions: [24 54 5 38 48 58 9]
output chars: [Y 2 F m w 6 J]
output string: "Y2Fmw6J"
result: "Y2Fmw6J="
formatted result:
Y2Fmw6J=
Tests:
The test strings come from the example in the question the examples in the Wikipedia article for Base64.
sub b{$f=(3-($#_+1)%3)%3;$_=unpack'B*',pack'C*',@_;@r=map{(A..Z,a..z,0..9,'+','/')[oct"0b$_"]}/.{1,6}/g;$"='';join"\r\n",("@r".'='x$f)=~/.{1,76}/g}
sub test ($) {
print b(map {ord($_)} $_[0] =~ /./sg), "\n\n";
}
my $str = <<'END_STR';
Man is distinguished, not only by his reason, but by this singular passion from
other animals, which is a lust of the mind, that by a perseverance of delight
in the continued and indefatigable generation of knowledge, exceeds the short
vehemence of any carnal pleasure.
END_STR
chomp $str;
test "\143\141\146\303\251";
test $str;
test "any carnal pleasure.";
test "any carnal pleasure";
test "any carnal pleasur";
test "any carnal pleasu";
test "any carnal pleas";
test "pleasure.";
test "leasure.";
test "easure.";
test "asure.";
test "sure.";
Test output:
TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz
IHNpbmd1bGFyIHBhc3Npb24gZnJvbQpvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg
dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodAppbiB0aGUgY29udGlu
dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo
ZSBzaG9ydAp2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZSO=
YW55IGNhcm5hbCBwbGVhc3VyZSO=
YW55IGNhcm5hbCBwbGVhc3VyZB==
YW55IGNhcm5hbCBwbGVhc3Vy
YW55IGNhcm5hbCBwbGVhc3F=
YW55IGNhcm5hbCBwbGVhcD==
cGxlYXN1cmUu
bGVhc3VyZSO=
ZWFzdXJlLC==
YXN1cmUu
c3VyZSO=
What type of competition is this? – Cilan – 2014-05-04T22:26:53.207
Does built-in base64 encoders cover only binary-to-text encoders or functions manipulating integers as well? – Dennis – 2014-05-05T04:11:35.240
1To clarify: Can I use a function that returns
1 2
for the argument66
? – Dennis – 2014-05-05T05:21:52.8031
There are 9 standardised or 4 non-standardised versions of base64. Your reference to
– Peter Taylor – 2014-05-05T06:43:47.273=
for padding narrows it down to 4. Which one do you want? Or do you want a non-standard variant which doesn't have maximum line lengths?I'm guessing he/she referred to the either the "standard" one specified by RFC 4648 or the version used by MIME-types, RFC 2045. These are different, so clarification would be very useful. – semi-extrinsic – 2014-05-05T07:38:31.227
sorry for the lack of precision, I didn't know there were different kinds of base64. The one I'm looking for is the one used in dataURI's (so, yes, RFC 2045) – xem – 2014-05-05T08:16:05.577
arg, please don't change requirements when you already have a significant number of answers, and 80% of them will require nontrivial code changes to acommodate the new spec. – skibrianski – 2014-05-05T12:18:35.733
RFC 2045 is not what's used in a data URI. When was the last time you saw a data uri with \r\n in it? Also, in addition to wrapping at 76 chars, there is special newline handlng in RFC 2045. – skibrianski – 2014-05-05T12:57:39.630
@skibrianski damn, I'm really sorry. According to http://en.wikipedia.org/wiki/Base64, RFC2045 is the one corresponding to "Base64 transfer encoding for MIME". But you're right, URIs don't have \r\n. So... I don't know. Which one is used in URIs / JavaScript btoa() ? RFC 1642?
– xem – 2014-05-05T18:12:41.867