diff options
Diffstat (limited to 'Base64/Base64.lua')
-rw-r--r-- | Base64/Base64.lua | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/Base64/Base64.lua b/Base64/Base64.lua new file mode 100644 index 0000000..33e78bd --- /dev/null +++ b/Base64/Base64.lua @@ -0,0 +1,178 @@ +--------------------------------------------------------------------------------------------------- +-- -= Base64 =- +--------------------------------------------------------------------------------------------------- + +-- Make some functions easier to write +local floor = math.floor +local sub = string.sub +local gsub = string.gsub +local rem = table.remove + +--------------------------------------------------------------------------------------------------- +-- Our base64 value table +local base64 = { ['A']=0,['B']=1,['C']=2,['D']=3,['E']=4,['F']=5,['G']=6,['H']=7,['I']=8, + ['J']=9,['K']=10,['L']=11,['M']=12,['N']=13,['O']=14,['P']=15,['Q']=16, + ['R']=17,['S']=18,['T']=19,['U']=20,['V']=21,['W']=22,['X']=23,['Y']=24, + ['Z']=25,['a']=26,['b']=27,['c']=28,['d']=29,['e']=30,['f']=31,['g']=32, + ['h']=33,['i']=34,['j']=35,['k']=36,['l']=37,['m']=38,['n']=39,['o']=40, + ['p']=41,['q']=42,['r']=43,['s']=44,['t']=45,['u']=46,['v']=47,['w']=48, + ['x']=49,['y']=50,['z']=51,['0']=52,['1']=53,['2']=54,['3']=55,['4']=56, + ['5']=57,['6']=58,['7']=59,['8']=60,['9']=61,['+']=62,['/']=63,['=']=nil} + +--------------------------------------------------------------------------------------------------- +-- Decimal values for binary digits +local bin ={} +local mult = 1 +for i = 1,40 do + bin[i] = mult + mult = mult*2 +end + +--------------------------------------------------------------------------------------------------- +-- A buffer we will use to process the bits +local buffer = 0 +local pos = 0 +local function clearBuffer() + buffer = 0 + pos = 1 +end + +--------------------------------------------------------------------------------------------------- +-- Shift all of the bits up in the buffer and put the base64 number on the bottom +local function pushBase64(n) + if base64[n] == nil then return end + buffer = buffer * bin[7] + base64[n] + pos = pos + 6 +end + +--------------------------------------------------------------------------------------------------- +-- Get an int out of the buffer. This is tricky. The byte order is in little endian so we're going +-- to have to isolate and cut the bytes out and then move them around. +local function getInt() + -- If our buffer isn't filled all the way then fill it with zeros + while pos < 33 do + buffer = buffer * bin[2] + pos = pos + 1 + end + -- Move the buffer position to just below the integer. + pos = pos - 32 + + -- Swap the first and forth byte and then the second and third. + local tmp = floor((buffer%bin[33+pos-1])/bin[25+pos-1]) + + floor((buffer%bin[25+pos-1])/bin[17+pos-1])*bin[9] + + floor((buffer%bin[17+pos-1])/bin[9+pos-1])*bin[17] + + floor((buffer%bin[9+pos-1])/bin[pos])*bin[25] + + -- We've got our integer so let's cut that portion out of the buffer + buffer = buffer % bin[pos] + -- Return the int + return tmp +end + +--------------------------------------------------------------------------------------------------- +-- Get a byte out of the buffer +local function getByte() + -- If our buffer isn't filled all the way then fill it with zeros + while pos < 9 do + buffer = buffer * bin[2] + pos = pos + 1 + end + -- Move the buffer position to just below the byte. + pos = pos - 8 + -- Cut out the byte + local tmp = floor((buffer%bin[9+pos-1])/bin[pos]) + -- Delete the byte from the buffer + buffer = buffer % bin[pos] + -- Return the byte + return tmp +end + +--------------------------------------------------------------------------------------------------- +-- Glues together an integer from four bytes. Little endian +local function glueInt(b1, b2, b3, b4) + return b1%bin[9] + b2%bin[9]*bin[9] + b3%bin[9]*bin[17] + b4%bin[9]*bin[25] +end + +--------------------------------------------------------------------------------------------------- +-- A Lua set that will filter out characters that aren't in the base64 table +local set = "[^%a%d%+%/%=]" + +--------------------------------------------------------------------------------------------------- +-- Decodes a base64 string into the given type +local function decode(mode, raw) + + -- Make sure the mode is supported + assert(mode=="string" or mode=="int" or mode=="byte", "Base64 decode - Invalid mode: " .. mode) + + -- Clear the buffer + clearBuffer() + + -- Filters undefined characters out of the string + raw = gsub(raw, set, "") + + local size = 0 -- Size of the returned type in bits + local val = {} -- A table containing the data to be returned + local raw_pos = 1 -- The position of the progress through the raw base64 string + local raw_size = #raw -- The size of the base64 string + local char = "" -- The current base64 character to be processed + + -- If we're expected to return an int then the bit size is 32, otherwise it's 8 + if mode == "int" then size = 32 else size = 8 end + + -- While we still have input + while raw_pos <= raw_size do + -- Fill the buffer until we have enough bits + while pos <= size and raw_pos <= raw_size do + char = sub(raw,raw_pos,raw_pos) + pushBase64( char ) + raw_pos = raw_pos + 1 + end + -- If a nil character is encountered the end the loop + if char == "=" then break end + -- Get data from the buffer depending on the type + if mode == "string" then val[#val+1] = string.char( getByte() ) end + if mode == "byte" then val[#val+1] = getByte() end + if mode == "int" then val[#val+1] = getInt() end + end + + if mode == "string" then return table.concat(val) end + return val +end + +--------------------------------------------------------------------------------------------------- +-- Encodes a table of ints into a base64 string. +local function encode(ints) + + -- Clear the buffer + clearBuffer() + + local size = 0 -- Size of the returned type in bits + local val = {} -- A table containing the data to be returned + local char = "" -- The current base64 character to be processed + + -- If we're expected to return an int then the bit size is 32, otherwise it's 8 + if mode == "int" then size = 32 else size = 8 end + + -- While we still have input + while raw_pos <= raw_size do + -- Fill the buffer until we have enough bits + while pos <= size and raw_pos <= raw_size do + char = sub(raw,raw_pos,raw_pos) + pushBase64( char ) + raw_pos = raw_pos + 1 + end + -- If a nil character is encountered the end the loop + if char == "=" then break end + -- Get data from the buffer depending on the type + if mode == "string" then val[#val+1] = string.char( getByte() ) end + if mode == "byte" then val[#val+1] = getByte() end + if mode == "int" then val[#val+1] = getInt() end + end + + if mode == "string" then return table.concat(val) end + return val +end + +--------------------------------------------------------------------------------------------------- +-- Returns the functions +return {decode = decode, glueInt = glueInt, base64 = base64}
\ No newline at end of file |