Skip to content

Instantly share code, notes, and snippets.

@vi
Created September 16, 2012 16:02
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save vi/3732972 to your computer and use it in GitHub Desktop.
Save vi/3732972 to your computer and use it in GitHub Desktop.
Simple command-line Reed-Solomon encoding and decoding tool
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ecc.h"
/* Reed-solomon command-line tool by Vitaly "_Vi" Shukela; 2012 */
/*
Usage:
1. Download http://sourceforge.net/projects/rscode/
2. Tune NPAR in ecc.h to the value you want
3. Build rscode, put this source file to it's directory;
3. gcc -o reedsolomon reedsolomon.c -L. -lecc
Encoding:
Start "reedsolomon encode" and feed it lines to encode.
It should write hex-encoded bytes to stdout (your input + NPAR bytes)
If "reedsolomon encode --hex" it will read hex strings instead of raw data
$ reedsolomon encode
ABC
414243234EB33A
ABCD
4142434420877B3B
$ reedsolomon encode --hex
FF00FF
FF00FF885F7DD5
Decoding:
Start "reedsolomon decode" and feed the hex lines (minimum 2*NPAR+2 hex characters per line)
Use "__" instead of a byte for erasures.
The tool wil output "G ", "C ", "B " (good, corrected, uncorrected respectively) followed by your data
"reedsolomon decode --hex" will print hex strings
$ reedsolomon decode
4142434420877B3B
G ABCD
41FF434420877B3B
C ABCD
41FF434420877FFF
B A?CD
41FF43442087____
C ABCD
$ reedsolomon decode --hex
41FF43442087____
C 41424344
There are pre-built versions of the tool for static i386 and for Android ARM at
http://vi-server.org/pub/
*/
unsigned char codeword[256];
unsigned char msg[256-NPAR];
int erasures[256];
int nerasures;
int n;
int readhex(unsigned char* out, int maxn) {
char buf[516];
int i;
char* ret = fgets(buf, maxn*2, stdin);
if (!ret) return 0;
const char* eos = strchr(buf, '\n');
if (eos) n = (eos - buf)/2; else n=maxn;
nerasures = 0;
for (i=0; i<n; ++i) {
char tmp = buf[i*2+2];
buf[i*2+2]=0;
if(buf[i*2]=='_') {
erasures[nerasures++]=i;
out[i] = 0;
} else {
out[i] = strtol(buf+i*2, NULL, 16);
}
buf[i*2+2]=tmp;
}
return n;
}
void writehex(unsigned char* out, int n) {
int i;
for (i=0; i<n; ++i) {
fprintf(stdout, "%02X", out[i]);
}
fprintf(stdout, "\n");
}
int main(int argc, char* argv[]) {
if (argc < 2) {
fprintf(stderr, "Usage: reedsolomon {encode|decode} [--hex]\n");
fprintf(stderr, "/* Reed Solomon Coding for glyphs\n"
" * Copyright Henry Minsky (hqm@alum.mit.edu) 1991-2009\n"
" * This software library is licensed under terms of the GNU GENERAL\n"
" * PUBLIC LICENSE v3+ */\n");
fprintf(stdout, "NPAR=%d\n", NPAR);
return 1;
}
int hexmode = 0;
if (argc >= 3 && !strcmp(argv[2], "--hex")) hexmode = 1;
if(getenv("DEBUG")) DEBUG=1;
initialize_ecc ();
int i;
if (!strcmp(argv[1], "encode")) {
for (;;) {
if (!hexmode) {
char* ret = fgets((char*)msg, sizeof(msg), stdin);
if (!ret) break;
const unsigned char* eos = (unsigned char*) strchr((char*)msg, '\n');
if (eos) n = eos - msg; else n=sizeof(msg)-1;
} else {
n = readhex(msg, sizeof(msg));
if (!n) break;
}
encode_data(msg, n, codeword);
writehex(codeword, n+NPAR);
fflush(stdout);
}
} else
if (!strcmp(argv[1], "decode")) {
for(;;) {
n = readhex(codeword, sizeof(codeword)) - NPAR;
if (n==-NPAR) return 0;
if (n<0) { fprintf(stdout, "B \n"); continue; }
for(i=0; i<nerasures; ++i) {
erasures[i] = n+NPAR - erasures[i]-1;
}
decode_data(codeword, n+NPAR);
int s = check_syndrome();
if (s) {
int r = correct_errors_erasures(codeword, n+NPAR, nerasures, erasures);
if (r) {
fprintf(stdout, "C ");
} else {
fprintf(stdout, "B ");
}
} else {
fprintf(stdout, "G ");
}
if (hexmode) {
writehex(codeword, n);
} else {
fwrite(codeword, 1, n, stdout);
fprintf(stdout, "\n");
}
fflush(stdout);
}
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment