Javascript version of JUCE's (non-standard) base64 decode

Hiya,

I thought I'd share some code I developed for server-side handling of JUCE's special base64 data.  It's really just a translation of C++ into JS.  The end result of the decoded b64 string is an array of integers that you can use to load into Node's buffer object.  It's untested, but I believe you should be able to load it into an ArrayBuffer in a browser as well.

var encodingTable = ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+";

function setBitRange (size, data, bitRangeStart, numBits,  bitsToSet) {

  var bite = bitRangeStart >> 3;

  var offsetInByte = parseInt( bitRangeStart & 7 )

  var mask = ~(((  0xffffffff) << (32 - numBits)) >> (32 - numBits));


  while (numBits > 0 && bite < size)

    {

      var bitsThisTime = Math.min ( numBits, 8 - offsetInByte);


      var tempMask = (mask << offsetInByte) | ~(((0xffffffff) >> offsetInByte) << offsetInByte);

      var tempBits = bitsToSet << offsetInByte;


      data[bite] = ((data[bite] & tempMask) | tempBits);


      ++bite;

      numBits -= bitsThisTime;

      bitsToSet >>= bitsThisTime;

      mask >>= bitsThisTime;

      offsetInByte = 0;

    }

}



function fromBase64Encoding ( s) {

  var size = parseInt(s.slice(0, s.indexOf(".")))

  var b64str = s.slice(s.indexOf(".")+1, s.length)

  var pos = 0;

  var data = []


  for (var i = 0; i < b64str.length; ++i) {

      var c = b64str[i];

      for (var j = 0; j < 64; ++j)

      {

          if (encodingTable[j] == c)

          {

              setBitRange (size, data, pos, 6, j);

              pos += 6;

              break;

          }

      }

  }

 

Using that in node, for example, you can decode the base64 string and unzip using node's zlib

var uza = fromBase64Encoding( codeGZ64 );

var buffer = new Buffer(uza, 'bin');

var data= zlib.unzipSync(buffer)

 

1 Like

I was in the middle of reinventing the wheel just now when I discovered your post here, this is very useful.

Thank you so much sharing this!

Here’s the other size of the puzzle:

function getBitRange (size, data, bitRangeStart, numBits)
{
    let res = 0;

    let byte = bitRangeStart >> 3;
    let offsetInByte = bitRangeStart & 7;
    let bitsSoFar = 0;

    while (numBits > 0 && byte < size)
    {
        let bitsThisTime = Math.min(numBits, 8 - offsetInByte);
        let mask = (0xff >> (8 - bitsThisTime)) << offsetInByte;

        res |= (((data[byte] & mask) >> offsetInByte) << bitsSoFar);

        bitsSoFar += bitsThisTime;
        numBits -= bitsThisTime;
        ++byte;
        offsetInByte = 0;
    }

    return res;
}

function toBase64Encoding(bytes)
{
  if (!bytes) return null;
    const numChars = ((bytes.length << 3) + 5) / 6;

    let s = bytes.length + '.'

    for (let i = 0; i < numChars-1; i++) {
        s += encodingTable[getBitRange(bytes.length, bytes, i * 6, 6)]
    }
    return s;
}