def self.decode(str)
input = str.to_s
begin
regex = "<~(.*?)?~>"
if regex.methods.include?(:encode)
regex = regex.encode(input.encoding)
end
regex = Regexp.compile(regex, Regexp::MULTILINE)
input = input.match(regex)
rescue EncodingError
raise ArgumentError, "Incompatible input encoding: #{str.encoding.inspect}"
end
return '' if input.nil?
input = input.captures.first
result = []
count = 0
word = 0
input.each_byte do |c|
case c.chr
when /[ \t\r\n\f\0]/
next
when 'z'
if count == 0
result << 0
else
raise(Ascii85::DecodingError, "Found 'z' inside Ascii85 5-tuple")
end
when '!'..'u'
word += (c - 33) * 85**(4 - count)
count += 1
if count == 5
if word > 0xffffffff
raise(Ascii85::DecodingError,
"Invalid Ascii85 5-tuple (#{word} >= 2**32)")
end
result << word
word = 0
count = 0
end
else
raise(Ascii85::DecodingError,
"Illegal character inside Ascii85: #{c.chr.dump}")
end
end
result = result.pack('N*')
if count > 0
if count == 1
raise(Ascii85::DecodingError,
"Last 5-tuple consists of single character")
end
count -= 1
word += 85**(4 - count)
result << ((word >> 24) & 255).chr if count >= 1
result << ((word >> 16) & 255).chr if count >= 2
result << ((word >> 8) & 255).chr if count == 3
end
return result
end