summaryrefslogtreecommitdiff
path: root/Base64/Base64.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Base64/Base64.lua')
-rw-r--r--Base64/Base64.lua178
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