move wip stuff to wip
This commit is contained in:
107
wip/runlength.c
Normal file
107
wip/runlength.c
Normal file
@@ -0,0 +1,107 @@
|
||||
#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;
|
||||
}
|
||||
Reference in New Issue
Block a user