Skip to content

Instantly share code, notes, and snippets.

@kmlx
Last active December 11, 2015 21:38
Show Gist options
  • Save kmlx/4663311 to your computer and use it in GitHub Desktop.
Save kmlx/4663311 to your computer and use it in GitHub Desktop.
/*
Author: Radu Apostoleanu
E-mail: radu.apostoleanu@gmail.com
Description:
This is a nodeJs module for fast base64 encoding based on this link:
http://www.experts-exchange.com/Programming/System/Windows__Programming/A_3216-Fast-Base64-Encode-and-Decode.html
The code was made for Linux environment from Windows example.
*/
#include <node.h>
#include <v8.h>
#include <assert.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
//Defining some common windows' types. They must match the byte length for this to be effective.
typedef short int WORD;
typedef unsigned int DWORD;
using namespace v8;
//Defining static information tables
static char Base64Digits[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static WORD* Base64Digits8192 = (WORD*) "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cIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZcacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczc0c1c2c3c4c5c6c7c8c9c+c/dAdBdCdDdEdFdGdHdIdJdKdLdMdNdOdPdQdRdSdTdUdVdWdXdYdZdadbdcdddedfdgdhdidjdkdldmdndodpdqdrdsdtdudvdwdxdydzd0d1d2d3d4d5d6d7d8d9d+d/eAeBeCeDeEeFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZeaebecedeeefegeheiejekelemeneoepeqereseteuevewexeyeze0e1e2e3e4e5e6e7e8e9e+e/fAfBfCfDfEfFfGfHfIfJfKfLfMfNfOfPfQfRfSfTfUfVfWfXfYfZfafbfcfdfefffgfhfifjfkflfmfnfofpfqfrfsftfufvfwfxfyfzf0f1f2f3f4f5f6f7f8f9f+f/gAgBgCgDgEgFgGgHgIgJgKgLgMgNgOgPgQgRgSgTgUgVgWgXgYgZgagbgcgdgegfggghgigjgkglgmgngogpgqgrgsgtgugvgwgxgygzg0g1g2g3g4g5g6g7g8g9g+g/hAhBhChDhEhFhGhHhIhJhKhLhMhNhOhPhQhRhShThUhVhWhXhYhZhahbhchdhehfhghhhihjhkhlhmhnhohphqhrhshthuhvhwhxhyhzh0h1h2h3h4h5h6h7h8h9h+h/iAiBiCiDiEiFiGiHiIiJiKiLiMiNiOiPiQiRiSiTiUiViWiXiYiZiaibicidieifigihiiijikiliminioipiqirisitiuiviwixiyizi0i1i2i3i4i5i6i7i8i9i+i/jAjBjCjDjEjFjGjHjIjJjKjLjMjNjOjPjQjRjSjTjUjVjWjXjYjZjajbjcjdjejfjgjhjijjjkjljmjnjojpjqjrjsjtjujvjwjxjyjzj0j1j2j3j4j5j6j7j8j9j+j/kAkBkCkDkEkFkGkHkIkJkKkLkMkNkOkPkQkRkSkTkUkVkWkXkYkZkakbkckdkekfkgkhkikjkkklkmknkokpkqkrksktkukvkwkxkykzk0k1k2k3k4k5k6k7k8k9k+k/lAlBlClDlElFlGlHlIlJlKlLlMlNlOlPlQlRlSlTlUlVlWlXlYlZlalblcldlelflglhliljlklllmlnlolplqlrlsltlulvlwlxlylzl0l1l2l3l4l5l6l7l8l9l+l/mAmBmCmDmEmFmGmHmImJmKmLmMmNmOmPmQmRmSmTmUmVmWmXmYmZmambmcmdmemfmgmhmimjmkmlmmmnmompmqmrmsmtmumvmwmxmymzm0m1m2m3m4m5m6m7m8m9m+m/nAnBnCnDnEnFnGnHnInJnKnLnMnNnOnPnQnRnSnTnUnVnWnXnYnZnanbncndnenfngnhninjnknlnmnnnonpnqnrnsntnunvnwnxnynzn0n1n2n3n4n5n6n7n8n9n+n/oAoBoCoDoEoFoGoHoIoJoKoLoMoNoOoPoQoRoSoToUoVoWoXoYoZoaobocodoeofogohoiojokolomonooopoqorosotouovowoxoyozo0o1o2o3o4o5o6o7o8o9o+o/pApBpCpDpEpFpGpHpIpJpKpLpMpNpOpPpQpRpSpTpUpVpWpXpYpZpapbpcpdpepfpgphpipjpkplpmpnpopppqprpsptpupvpwpxpypzp0p1p2p3p4p5p6p7p8p9p+p/qAqBqCqDqEqFqGqHqIqJqKqLqMqNqOqPqQqRqSqTqUqVqWqXqYqZqaqbqcqdqeqfqgqhqiqjqkqlqmqnqoqpqqqrqsqtquqvqwqxqyqzq0q1q2q3q4q5q6q7q8q9q+q/rArBrCrDrErFrGrHrIrJrKrLrMrNrOrPrQrRrSrTrUrVrWrXrYrZrarbrcrdrerfrgrhrirjrkrlrmrnrorprqrrrsrtrurvrwrxryrzr0r1r2r3r4r5r6r7r8r9r+r/sAsBsCsDsEsFsGsHsIsJsKsLsMsNsOsPsQsRsSsTsUsVsWsXsYsZsasbscsdsesfsgshsisjskslsmsnsospsqsrssstsusvswsxsyszs0s1s2s3s4s5s6s7s8s9s+s/tAtBtCtDtEtFtGtHtItJtKtLtMtNtOtPtQtRtStTtUtVtWtXtYtZtatbtctdtetftgthtitjtktltmtntotptqtrtstttutvtwtxtytzt0t1t2t3t4t5t6t7t8t9t+t/uAuBuCuDuEuFuGuHuIuJuKuLuMuNuOuPuQuRuSuTuUuVuWuXuYuZuaubucudueufuguhuiujukulumunuoupuqurusutuuuvuwuxuyuzu0u1u2u3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";
char* ToCString( v8::String::Utf8Value& value) {
return *value ;
}
Handle<Value > Method(const Arguments& args){
HandleScope scope;
//CONVERT VALUES
v8::String::Utf8Value str(args[0]);
char* pSrc = ToCString(str);
int nLenSrc = strlen(pSrc);
//Calculation of output length
int nLenOut= ((nLenSrc+2)/3)*4+1; // 4 out for every 3 in, rounded up
//memory allocation and initialization
char* pDst = (char*) malloc(nLenOut*sizeof(WORD));
char* p = pDst;
memset(p,0,nLenOut*2);
//the algorithm in the paper mentioned at the begining
while( nLenSrc > 2 ) {
DWORD n= pSrc[0]; // xxx1
n <<= 8; // xx1x
n |= pSrc[1]; // xx12
n <<= 8; // x12x
n |= pSrc[2]; // x123
((WORD*)pDst)[0]= Base64Digits8192[ n >> 12 ]; //A little trick to write 2 bytes at a time
((WORD*)pDst)[1]= Base64Digits8192[ n & 0x00000fff ];
nLenSrc -= 3;
pDst += 4; //jump 2*2bytes at a time
pSrc += 3;
}
if ( nLenSrc > 0 ) { // some left after last triple
int n1= (*pSrc & 0xfc) >> 2;
int n2= (*pSrc & 0x03) << 4;
if (nLenSrc > 1 ) { // corrected. Thanks to jprichey
pSrc++;
n2 |= (*pSrc & 0xf0) >> 4;
}
*pDst++ = Base64Digits[n1]; // encode at least 2 outputs
*pDst++ = Base64Digits[n2];
if (nLenSrc == 2) { // 2 src bytes left to encode, output xxx=
int n3= (*pSrc & 0x0f) << 2;
pSrc++;
n3 |= (*pSrc & 0xc0) >> 6;
*pDst++ = Base64Digits[n3];
}
if (nLenSrc == 1) { // 1 src byte left to encode, output xx==
*pDst++ = '=';
}
*pDst++ = '=';
}
//Create the resulting object and free the memory
//further memory allocation should be caught by nodejs context
Local<v8::String> result =v8::String::New(p);
free(p);
//free(pDst);
return scope.Close(result );
}
void init(Handle<Object> target){
target->Set(String::NewSymbol("toBase64Fast"),
FunctionTemplate::New(Method)->GetFunction());
}
NODE_MODULE(base64, init)
{
"targets":[
{
"target_name":"base64",
"sources": [ "base64.cc" ]
}
]
}
int ToBase64Fast( const BYTE* pSrc, int nLenSrc, char* pDst, int nLenDst )
{
int nLenOut= ((nLenSrc+2)/3)*4; // 4 out for every 3 in, rounded up
if ( nLenOut+1 > nLenDst ) {
return( 0 ); // fail!
}
WORD* pwDst= (WORD*)pDst;
while( nLenSrc > 2 ) {
DWORD n= pSrc[0]; // xxx1
n <<= 8; // xx1x
n |= pSrc[1]; // xx12
n <<= 8; // x12x
n |= pSrc[2]; // x123
pwDst[0]= Base64Digits8192[ n >> 12 ];
pwDst[1]= Base64Digits8192[ n & 0x00000fff ];
nLenSrc -= 3;
pwDst += 2;
pSrc += 3;
}
// -------------- end of buffer special handling (see text)
pDst= (char*)pdwDst;
if ( nLenSrc > 0 ) { // some left after last triple
int n1= (*pSrc & 0xfc) >> 2;
int n2= (*pSrc & 0x03) << 4;
if (nLenSrc > 1 ) { // corrected. Thanks to jprichey
pSrc++;
n2 |= (*pSrc & 0xf0) >> 4;
}
*pDst++ = Base64Digits[n1]; // encode at least 2 outputs
*pDst++ = Base64Digits[n2];
if (nLenSrc == 2) { // 2 src bytes left to encode, output xxx=
int n3= (*pSrc & 0x0f) << 2;
pSrc++;
n3 |= (*pSrc & 0xc0) >> 6;
*pDst++ = Base64Digits[n3];
}
if (nLenSrc == 1) { // 1 src byte left to encode, output xx==
*pDst++ = '=';
}
*pDst++ = '=';
}
// *pDst= 0; nLenOut++ // could terminate with NULL, here
return( nLenOut );
}
WORD Base64Digits8192[ 4096 ];
void SetupTable8192()
{
for ( int j=0; j<64; j++ ) {
for ( int k=0; k<64; k++ ) {
WORD w;
w = Base64Digits[k] << 8;
w |= Base64Digits[j];
Base64Digits8192[(j*64)+k]= w;
}
}
}
@ceco70
Copy link

ceco70 commented Aug 16, 2015

There is a little bug when encoding 3k+2 buffer length and the next char is not NULL.
The correct code should be as following:

int ToBase64Fast( const BYTE* pSrc, int nLenSrc, char* pDst, int nLenDst )
{
int nLenOut= ((nLenSrc+2)/3)4; // 4 out for every 3 in, rounded up
if ( nLenOut+1 > nLenDst ) {
return( 0 ); // fail!
}
WORD
pwDst= (WORD*)pDst;
while( nLenSrc > 2 ) {
DWORD n= pSrc[0]; // xxx1
n <<= 8; // xx1x
n |= pSrc[1]; // xx12
n <<= 8; // x12x
n |= pSrc[2]; // x123

  pwDst[0]= Base64Digits8192[ n >> 12 ]; 
  pwDst[1]= Base64Digits8192[ n & 0x00000fff ]; 

  nLenSrc -= 3;
  pwDst += 2;
  pSrc += 3;

}
// -------------- end of buffer special handling (see text)
pDst= (char_)pdwDst;
if ( nLenSrc > 0 ) { // some left after last triple
int n1= (_pSrc & 0xfc) >> 2;
int n2= (_pSrc & 0x03) << 4;
if (nLenSrc > 1 ) { // corrected. Thanks to jprichey
pSrc++; // this is already the last character in case of 3k+2 buffer length
n2 |= (_pSrc & 0xf0) >> 4;
}
_pDst++ = Base64Digits[n1]; // encode at least 2 outputs
*pDst++ = Base64Digits[n2];
if (nLenSrc == 2) { // 2 src bytes left to encode, output xxx=
int n3= (_pSrc & 0x0f) << 2;
// pSrc++; // no increment necessary as it would be outside the buffer and if it is not NULL then a bad encoding result is produced
// n3 |= (*pSrc & 0xc0) >> 6; // not necessary as the next element is considered NULL
*pDst++ = Base64Digits[n3];
}
if (nLenSrc == 1) { // 1 src byte left to encode, output xx==
*pDst++ = '=';
}
*pDst++ = '=';
}
// *pDst= 0; nLenOut++ // could terminate with NULL, here
return( nLenOut );
}

WORD Base64Digits8192[ 4096 ];
void SetupTable8192()
{
for ( int j=0; j<64; j++ ) {
for ( int k=0; k<64; k++ ) {
WORD w;
w = Base64Digits[k] << 8;
w |= Base64Digits[j];
Base64Digits8192[(j*64)+k]= w;
}
}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment