Skip to content

Instantly share code, notes, and snippets.

@odzhan
Last active August 19, 2022 01:56
Show Gist options
  • Select an option

  • Save odzhan/52dceb2f7893868c43b65140ee6a14ef to your computer and use it in GitHub Desktop.

Select an option

Save odzhan/52dceb2f7893868c43b65140ee6a14ef to your computer and use it in GitHub Desktop.
Base64 Encode
//
// Base-N encoding based on assembly code by Qkumba
//
#include <stdint.h>
#define ROTR32(v,n)(((v)>>(n))|((v)<<(32-(n))))
#define ROTL32(v,n)(((v)<<(n))|((v)>>(32-(n))))
#define ROTR64(v,n)(((v)>>(n))|((v)<<(64-(n))))
#define ROTL64(v,n)(((v)<<(n))|((v)>>(64-(n))))
void
base64_encode1(void *inbuf, int inlen, char *outbuf) {
uint8_t *in = (uint8_t*)inbuf;
char *out = outbuf;
int i;
while (inlen) {
uint32_t x = 0;
for (i=0; i<3; i++) {
x |= ((i < inlen) ? *in++ : 0);
x <<= 8;
}
inlen++;
for (i=4; inlen && i>0; i--) {
x = ROTL32(x, 6);
uint8_t c = x % 64;
if (c < 26) c += 'A';
else if (c < 52) c = (c - 26) + 'a';
else if (c < 62) c = (c - 52) + '0';
else if (c == 63) c = '+';
else c = '/';
*out++ = c;
--inlen;
}
}
while (i) { *out++ = '='; i--; }
*out = 0;
}
void
base64_encode2(void *inbuf, int inlen, char *outbuf) {
uint8_t *in = (uint8_t*)inbuf;
char *out = outbuf;
int i;
uint32_t len;
while (inlen) {
uint32_t x = 0;
uint8_t c;
// read 3 or less bytes. if required, pad with zeros
for (len=i=0; i<3; i++) {
c = (i < inlen) ? in[len++] : 0;
x = (x << 8) | c;
}
// encode 4 bytes.
for (i=4; i>0; i--) {
c = x % 64; // get remainder
x /= 64; // divide by base
if (c < 26) c += 'A';
else if (c < 52) c = (c - 26) + 'a';
else if (c < 62) c = (c - 52) + '0';
else if (c == 63) c = '+';
else c = '/';
out[i-1] = c;
}
in += len;
inlen -= len;
out += len+1;
}
// if required, add padding.
while (len++ < 3) *out++ = '=';
*out = 0;
}
void
base32_encode(void *inbuf, uint32_t inlen, char *outbuf) {
uint8_t *in = (uint8_t*)inbuf;
char *out = outbuf;
int i;
uint32_t len;
while ((int)inlen>0) {
uint64_t x = 0;
uint8_t c;
// read 5 or less bytes. if required, pad with zeros
for (len=i=0; i<5; i++) {
c = (i < inlen) ? in[len++] : 0;
x = (x << 8) | c;
}
//
// Base32 needs to be a multiple of 40 bits.
//
in += len;
inlen -= len;
len = (len * 8 + 4) / 5;
x = ROTL64(x, 24);
// encode 8 bytes
for (i=0; i<len; i++) {
x = ROTL64(x, 5);
c = x % 32;
if (c < 26) c += 'A';
else c = (c - 26) + '2';
*out++ = c;
}
}
// if required, add padding.
while (len++ < 8) *out++ = '=';
*out = 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment