1
0
Fork 0
src/Wip/runlength.c

108 lines
2.3 KiB
C

#include <ctype.h> /* isdigit(3) */
#include <stdio.h> /* fprintf(3), getc(3), putc(3) */
#include <stdlib.h> /* stdin, stderr, stdout */
#include <sysexits.h> /* EX_DATAERR, EX_OK */
/* Unicode compatibility coming someday */
#define GETC getc
#define PUTC putc
#define NUMBER_TERMINATOR '*'
/* syntax error if a decoding file ends with [char][char] */
/* if(STRICT) just print it out */
#define STRICT 0
static int decode(FILE *input, FILE *output){
int c[2];
unsigned int num;
enum{NUMBER_PARSING = 1} state;
c[0] = EOF;
/* reading -> (current char == prev char)> number parsing -> reading */
while((c[1] = GETC(input)) != EOF)
if(state == NUMBER_PARSING){
if(isdigit(c[1]))
num = num * 10 + c[1] - '0';
else if(c[1] == NUMBER_TERMINATOR){
for(; num > 0; --num)
PUTC(c[0], output);
c[0] = EOF; c[1] = EOF;
state = 0;
}else
return EX_DATAERR;
}else if(c[1] == c[0]){
num = 0;
state = NUMBER_PARSING;
}else{
if(c[0] != EOF)
PUTC(c[0], output);
c[0] = c[1];
}
if(state == NUMBER_PARSING && !STRICT)
/* it doesn't make sense to put this in a loop */
{ PUTC(c[0], output); PUTC(c[0], output); }
else if(state == NUMBER_PARSING)
return EX_DATAERR;
else if(c[0] != EOF)
PUTC(c[0], output);
return EX_OK;
}
static int encode(FILE *input, FILE *output){
int c[2];
unsigned int num;
enum{COUNTING = 1} state;
/* It was more fun to use gotos than to use sane structure. */
for(c[0] = EOF, num = 2, state = 0; ;)
if((c[1] = GETC(input)) == EOF){
if(state == COUNTING)
goto dump;
else
goto place;
}else if(state == COUNTING){
if(c[1] != c[0]){
dump: PUTC(c[0], output);
fprintf(output,
"%d%c",
num, NUMBER_TERMINATOR
);
num = 2;
state = 0;
goto next;
}else
++num;
}else if(c[1] == c[0])
state = COUNTING;
else{ /* c[1] != c[0] */
if(c[0] != EOF) /* c[0] will be EOF at first */
place: PUTC(c[0], output);
next: if(c[1] == EOF)
return EX_OK;
c[0] = c[1];
}
}
int main(int argc, char *argv[]){
int r;
if(argc != 1){
fprintf(stderr,
"Usage: %s\n",
argv[0] == NULL ?
(f == decode ? "decode" : "encode")
: argv[0]
);
return EX_USAGE;
}
if((r = f(stdin, stdout)) == EX_DATAERR)
fprintf(stderr, "%s: syntax error.\n", argv[0]);
return r;
}