Skip to content

Instantly share code, notes, and snippets.

@remi6397
Created October 9, 2017 15:08
Show Gist options
  • Save remi6397/410a3491549df4ea4c9356ab412db5f5 to your computer and use it in GitHub Desktop.
Save remi6397/410a3491549df4ea4c9356ab412db5f5 to your computer and use it in GitHub Desktop.
Ascii85
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <getopt.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
unsigned int AllocMax;
char* Data;
unsigned int Index;
unsigned int IIndex;
void append_char(int c)
{
printf("%i\n", Index);
if (Index > 0 && (Index % AllocMax) == 0)
{
realloc(Data, (AllocMax *= 2));
}
Data[Index++] = c;
printf("%02X +\n", c, Data[Index-1]);
}
int get_char(char* ptr)
{
printf("%02X /\n", ptr[IIndex]);
return ptr[IIndex++];
}
int unget_char(char c, char* ptr)
{
printf("%02X -\n", c);
return (Data[--IIndex] = c);
}
#define putchar(c) append_char(c)
#define getc(ptr) get_char(ptr)
#define ungetc(c, ptr) unget_char(c, ptr)
int powers[5] = {85*85*85*85, 85*85*85, 85*85, 85, 1};
int getc_nospace(char* f) {
int c;
while (isspace(c = getc(f)));
return c;
}
void putc_wrap(char c, int wrap, int *len) {
if (wrap && *len >= wrap) {
putchar('\n');
*len = 0;
}
putchar(c);
(*len)++;
}
void encode_tuple(uint32_t tuple, int count, int wrap, int *plen, int y_abbr) {
int i, lim;
char out[5];
if (tuple == 0 && count == 4) {
putc_wrap('z', wrap, plen);
}
else if (tuple == 0x20202020 && count == 4 && y_abbr) {
putc_wrap('y', wrap, plen);
}
else {
for (i = 0; i < 5; i++) {
out[i] = tuple % 85 + '!';
tuple /= 85;
}
lim = 4 - count;
for (i = 4; i >= lim; i--) {
putc_wrap(out[i], wrap, plen);
}
}
}
void decode_tuple(uint32_t tuple, int count) {
int i;
for (i = 1; i < count; i++) {
putchar(tuple >> ((4 - i) * 8));
}
}
int ascii85_encode(char* input, char* output, int delims, int wrap, int y_abbr) {
int c, count = 0, len = 0;
uint32_t tuple = 0;
AllocMax = 16;
Data = (char*)malloc(AllocMax);
Index = 0;
if (delims) {
putc_wrap('<', wrap, &len);
putc_wrap('~', wrap, &len);
}
for (;;) {
c = getc(input);
if (c != '\0') {
tuple |= ((unsigned int)c) << ((3 - count++) * 8);
if (count < 4) continue;
}
else if (count == 0) break;
encode_tuple(tuple, count, wrap, &len, y_abbr);
if (c == '\0') break;
tuple = 0;
count = 0;
}
if (delims) {
putc_wrap('~', wrap, &len);
putc_wrap('>', wrap, &len);
}
output = (char*)malloc(Index+1);
memcpy(output, Data, Index+1);
return 0;
}
int ascii85_decode(char* input, char* output, int delims, int ignore_garbage) {
int c, count = 0, end = 0;
uint32_t tuple = 0;
AllocMax = 16;
Data = (char*)malloc(AllocMax);
Index = 0;
while (delims) {
c = getc_nospace(input);
if (c == '<') {
c = getc_nospace(input);
if (c == '~') break;
ungetc(c, input);
}
else if (c == '\0') {
return 1;
}
}
for (;;) {
c = getc_nospace(input);
if (c == 'z' && count == 0) {
decode_tuple(0, 5);
continue;
}
if (c == 'y' && count == 0) {
decode_tuple(0x20202020, 5);
continue;
}
if (c == '~' && delims) {
c = getc_nospace(input);
if (c != '>') {
exit(1);
}
c = '\0';
end = 1;
}
if (c == '\0') {
if (delims && !end) {
return 1;
}
if (count > 0) {
tuple += powers[count-1];
decode_tuple(tuple, count);
}
break;
}
if (c < '!' || c > 'u') {
if (ignore_garbage) continue;
return 1;
}
tuple += (c - '!') * powers[count++];
if (count == 5) {
decode_tuple(tuple, count);
tuple = 0;
count = 0;
}
}
output = (char*)malloc(Index+1);
memcpy(output, Data, Index+1);
return 0;
}
#include <stdio.h>
#include "ascii85.c"
void printraw(uint8_t* ptr, size_t ln)
{
for (size_t i = 0; i < ln; ++i)
{
if (((i+1)%8)-1 == 0)
{
printf("\n");
}
printf("%02X ", ptr[i]);
}
printf("\n");
printf("\n");
}
int main()
{
char* in = "Koty lubią mleko";
char* out;
char* dec;
printf("m: %s", in);
printraw((uint*)in, 10);
ascii85_encode(in, out, 1, 1, 1);
printf("FIN%02X +\n", out[2]);
printraw((uint*)out, 10);
ascii85_decode(out, dec, 1, 1);
printraw((uint*)dec, 10);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment