/**
* \file
*
* MODP_B36 - High performance base36 encoder/decoder
* https://github.com/client9/stringencoders
*
* Copyright © 2006-2016 Nick Galbreath
* All rights reserved.
*
* Released under MIT license. See LICENSE for details.
*
*/
/* exported public header */
#include "modp_b36.h"
#include "modp_stdint.h"
/* private header */
#include "modp_b36_data.h"
/*
* Might need changing depending on platform
* we need htonl, and ntohl
*/
#include
/**
* you can decode IN PLACE!
* no memory allocated
*/
size_t modp_b36_decode(char* out, const char* data, size_t len)
{
size_t i;
int j;
const size_t buckets = len / 7;
const uint8_t* d2 = (const uint8_t*)data;
if (len % 7 != 0) {
return (size_t)-1;
}
uint32_t* o2 = (uint32_t*)out;
for (i = 0; i < buckets; ++i) {
uint32_t tmp = 0;
for (j = 0; j < 7; ++j) {
uint32_t digit = gsCharToInt[(uint32_t)*d2++];
if (digit >= 36) {
return (size_t)-1;
}
tmp = tmp * 36 + digit;
}
*o2++ = htonl(tmp);
}
return 4 * buckets;
}
/**
* src != out
*/
size_t modp_b36_encode(char* out, const char* src, size_t len)
{
const uint32_t* sary = (const uint32_t*)src;
const size_t buckets = len / 4;
if (len % 4 != 0) {
return (size_t)-1;
}
size_t i;
for (i = 0; i < buckets; ++i) {
uint32_t tmp = *sary++;
tmp = htonl(tmp);
/* this crazy function */
#if 0
*out++ = (char)gsIntToChar[(tmp / 52200625)]; // don't need % 36 here, always < 36
*out++ = (char)gsIntToChar[(tmp / 614125) % 36];
*out++ = (char)gsIntToChar[(tmp / 7225) % 36];
*out++ = (char)gsIntToChar[(tmp / 36) % 36];
*out++ = (char)gsIntToChar[tmp % 36];
#else
/* is really this */
*(out + 6) = gsIntToChar[tmp % 36];
tmp /= 36;
*(out + 5) = gsIntToChar[tmp % 36];
tmp /= 36;
*(out + 4) = gsIntToChar[tmp % 36];
tmp /= 36;
*(out + 3) = gsIntToChar[tmp % 36];
tmp /= 36;
*(out + 2) = gsIntToChar[tmp % 36];
tmp /= 36;
*(out + 1) = gsIntToChar[tmp % 36];
tmp /= 36;
*out = gsIntToChar[tmp];
out += 7;
#endif
// NOTES
// Version 1 under -O3 is about 10-20 PERCENT faster than version 2
// BUT Version 1 is 10 TIMES SLOWER when used with -Os !!!
// Reason: gcc does a lot of tricks to remove the divisions
// op with multiplies and shift.
// In V1 with -O3 this works. Under -Os it reverts to very
// slow division.
// In V2 -O3 it does the same thing, but under Os, it's smart
// enough to know we want the quotient and remainder and only
// one div call per line.
}
*out = 0; // final null
return buckets * 7;
}