poly-1-fw/ascii85.c

109 lines
2.2 KiB
C

// intellectual property is bullshit bgdc
#include "ascii85.h"
#include <stdbool.h>
#include <stddef.h>
#include <inttypes.h>
#define ASCII85_BASE 33
static inline uint8_t divmod85(uint32_t * x)
{
uint8_t mod = *x % 85;
*x /= 85;
return mod;
}
size_t ascii85_encode(uint8_t * dest, uint8_t const * src, size_t len)
{
size_t total = 0;
while (len >= 4)
{
uint32_t n = (
((uint32_t) src[0] << 24uL) |
((uint32_t) src[1] << 16uL) |
((uint32_t) src[2] << 8uL) |
((uint32_t) src[3] << 0uL));
dest[4] = divmod85(&n) + ASCII85_BASE;
dest[3] = divmod85(&n) + ASCII85_BASE;
dest[2] = divmod85(&n) + ASCII85_BASE;
dest[1] = divmod85(&n) + ASCII85_BASE;
dest[0] = n + ASCII85_BASE; // Guaranteed < 85
src += 4;
dest += 5;
len -= 4;
total += 5;
}
if (len)
{
uint32_t n = 0;
n = (uint32_t) src[0] << 24uL;
if (len > 1) n |= ((uint32_t) src[1] << 16uL);
if (len > 2) n |= ((uint32_t) src[2] << 8uL);
if (len > 3) n |= ((uint32_t) src[3] << 0uL);
char a85[5];
a85[4] = divmod85(&n) + ASCII85_BASE;
a85[3] = divmod85(&n) + ASCII85_BASE;
a85[2] = divmod85(&n) + ASCII85_BASE;
a85[1] = divmod85(&n) + ASCII85_BASE;
a85[0] = n + ASCII85_BASE; // As above
dest[0] = a85[0];
dest[1] = a85[1];
dest[2] = (len > 1) ? a85[2] : 0;
dest[3] = (len > 2) ? a85[3] : 0;
dest[4] = 0; // if we get here we're dropping at least one
total += len + 1;
}
return total;
}
size_t ascii85_decode(uint8_t * dest, uint8_t const * src, size_t len)
{
size_t total = 0;
while (len >= 5)
{
uint32_t n = src[0] - ASCII85_BASE;
n = 85 * n + src[1] - ASCII85_BASE;
n = 85 * n + src[2] - ASCII85_BASE;
n = 85 * n + src[3] - ASCII85_BASE;
n = 85 * n + src[4] - ASCII85_BASE;
dest[0] = (n >> 24uL) & 0xFF;
dest[1] = (n >> 16uL) & 0xFF;
dest[2] = (n >> 8uL) & 0xFF;
dest[3] = (n >> 0uL) & 0xFF;
src += 5;
dest += 4;
len -= 5;
total += 4;
}
if (len > 1)
{
uint32_t n = src[0] - ASCII85_BASE;
n = 85 * n + src[1] - ASCII85_BASE;
n = 85 * n + (len > 2 ? src[2] : 'u') - ASCII85_BASE;
n = 85 * n + (len > 3 ? src[3] : 'u') - ASCII85_BASE;
n = 85 * n;
dest[0] = (n >> 24uL) & 0xFF;
if (len > 2) dest[1] = (n >> 16uL) & 0xFF;
if (len > 3) dest[2] = (n >> 8uL) & 0xFF;
total += len - 1;
}
return total;
}