lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Might be worthwhile to put up on the wiki, a more appropriate place even.
Thijs

> -----Original Message-----
> From: lua-l-bounces@lists.lua.org [mailto:lua-l-bounces@lists.lua.org] On
> Behalf Of Ico Doornekamp
> Sent: dinsdag 4 november 2014 14:39
> To: lua-l
> Subject: Speed optimized base64 encoder for Lua 5.3
> 
> I wrote the snippet below today to speed up the base64 encoding in my
> application using the new binary operators in Lua5.3, it might be of use for
> others.  I think the algorithm is pretty much optimal, but I'm open to any
> suggestions and improvements.
> 
> Every three input bytes are mapped to four output bytes using the binary
> operations below:
> 
>          a                   b                   c
>   +-----------------+-----------------+-----------------+
>   | 0 0 0 0 0 0 1 1 | 1 1 1 1 2 2 2 2 | 2 2 3 3 3 3 3 3 |
>   +|- - - - - -|- - + - - - -|- - - - + - -|- - - - - -|+
>   /           /              |              \           \
>  /           /               |               \           \
>      a>>2     (a&3)<<4|b>>4    (b&15)<<2|c>>6      c&63
> 
> The input is padded to always be a multiple of three bytes, the output
> padding
> with '='s is fixed up after calculating the base64 of the padded input
> string.
> 
> 
> local bs = { [0] =
>    'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
>    'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
>    'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
>    'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/',
> }
> 
> local function base64(s)
>    local byte, rep = string.byte, string.rep
>    local pad = 2 - ((#s-1) % 3)
>    s = (s..rep('\0', pad)):gsub("...", function(cs)
>       local a, b, c = byte(cs, 1, 3)
>       return bs[a>>2] .. bs[(a&3)<<4|b>>4] .. bs[(b&15)<<2|c>>6] .. bs[c&63]
>    end)
>    return s:sub(1, #s-pad) .. rep('=', pad)
> end
> 
> 
> assert(base64("") == "")
> assert(base64("f") == "Zg==")
> assert(base64("fo") == "Zm8=")
> assert(base64("foo") == "Zm9v")
> assert(base64("foob") == "Zm9vYg==")
> assert(base64("fooba") == "Zm9vYmE=")
> assert(base64("foobar") == "Zm9vYmFy")
> 
> --
> :wq
> ^X^Cy^K^X^C^C^C^C