core :: CString :: decode_base64
self
from base64assert "c3RyaW5n".decode_base64.to_s == "string"
assert "c3Rya\nW5n".decode_base64.to_s == "string"
assert "c3RyaW5nCg==".decode_base64.to_s == "string\n"
assert "c3RyaW5nCg".decode_base64.to_s == "string\n"
assert "c3RyaW5neQo=".decode_base64.to_s == "stringy\n"
assert "c3RyaW5neQo".decode_base64.to_s == "stringy\n"
# Decodes `self` from base64
#
# assert "c3RyaW5n".decode_base64.to_s == "string"
# assert "c3Rya\nW5n".decode_base64.to_s == "string"
# assert "c3RyaW5nCg==".decode_base64.to_s == "string\n"
# assert "c3RyaW5nCg".decode_base64.to_s == "string\n"
# assert "c3RyaW5neQo=".decode_base64.to_s == "stringy\n"
# assert "c3RyaW5neQo".decode_base64.to_s == "stringy\n"
#
private fun decode_base64(length: Int): Bytes do
if length == 0 then return new Bytes.empty
# Avoids constant unboxing
var pad = '='
var result = new Bytes.with_capacity((length / 4 + 1) * 3)
var curr = 0
var cnt = 0
var endpos = -1
for i in [0 .. length[ do
var b = self[i]
if b == pad then
endpos = i
break
end
# Ignore whitespaces
if b <= 0x20 then continue
if not b.is_base64_char then continue
curr <<= 6
curr += b.to_base64_char.to_i
cnt += 1
if cnt == 4 then
result.add ((curr & 0xFF0000) >> 16)
result.add ((curr & 0xFF00) >> 8)
result.add (curr & 0xFF)
curr = 0
cnt = 0
end
end
if endpos != -1 or cnt != 0 then
var pads = 0
for i in [endpos .. length[ do
var b = self[i]
if b <= 0x20 then continue
pads += 1
end
if cnt == 2 then
curr >>= 4
result.add(curr)
else if cnt == 3 then
curr >>= 2
result.add ((curr & 0xFF00) >> 8)
result.add (curr & 0xFF)
end
end
return result
end
lib/base64/base64.nit:106,2--163,4