Home

Awesome

reedsolomon-c

C compatible version for golang-klauspost-reedsolomon.

It can run in platform of MIPS/ARM/i386/x64 of linux, especially for some embedded projects.

It's really simple, with a little change, it can run in other platform.

Installation

Copy rs.c and rs.h to your projects and make it.

Usage

This section assumes you know the basics of Reed-Solomon encoding. A good start is this Backblaze blog post.

To create an encoder/decoder with 10 data shards (where your data goes) and 3 parity shards (calculated):

    reed_solomon* rs = reed_solomon_new(10, 3);

Destroy:

    reed_solomon_relelase(rs);

Encode:

Look at test_create_encoding

int test_create_encoding(
        reed_solomon *rs,
        unsigned char *data,
        int data_size,
        int block_size
        ) {
    unsigned char **data_blocks;
    int data_shards, parity_shards;
    int i, n, nr_shards, nr_blocks, nr_fec_blocks;

    data_shards = rs->data_shards;
    parity_shards = rs->parity_shards;
    nr_blocks = (data_size+block_size-1)/block_size;
    nr_blocks = ((nr_blocks+data_shards-1)/data_shards) * data_shards;
    n = nr_blocks / data_shards;
    nr_fec_blocks = n * parity_shards;
    nr_shards = nr_blocks + nr_fec_blocks;

    data_blocks = (unsigned char**)malloc(nr_shards * sizeof(unsigned char*));
    for(i = 0; i < nr_shards; i++) {
        data_blocks[i] = data + i*block_size;
    }

    n = reed_solomon_encode2(rs, data_blocks, nr_shards, block_size);
    free(data_blocks);

    return n;
}

Decode:

Look at test_data_decode

int test_data_decode(
        reed_solomon *rs,
        unsigned char *data,
        int data_size,
        int block_size,
        int *erases,
        int erase_count) {
    unsigned char **data_blocks;
    unsigned char *zilch;
    int data_shards, parity_shards;
    int i, j, n, nr_shards, nr_blocks, nr_fec_blocks;

    data_shards = rs->data_shards;
    parity_shards = rs->parity_shards;
    nr_blocks = (data_size+block_size-1)/block_size;
    nr_blocks = ((nr_blocks+data_shards-1)/data_shards) * data_shards;
    n = nr_blocks / data_shards;
    nr_fec_blocks = n * parity_shards;
    nr_shards = nr_blocks + nr_fec_blocks;

    data_blocks = (unsigned char**)malloc(nr_shards * sizeof(unsigned char*));
    for(i = 0; i < nr_shards; i++) {
        data_blocks[i] = data + i*block_size;
    }

    zilch = (unsigned char*)calloc(1, nr_shards);
    for(i = 0; i < erase_count; i++) {
        j = erases[i];
        memset(data + j*block_size, 137, block_size);
        zilch[j] = 1; //mark as erased
    }

    n = reed_solomon_reconstruct(rs, data_blocks, zilch, nr_shards, block_size);
    free(data_blocks);
    free(zilch);

    return n;
}

Performance

I have implemented a benchmarkEncode in test_rs.c. but is this implement right ? it's so quick, I think there maybe some mistake in benchmark test.

Compatible Test

Implement a tool to test C and golang version.

simple-encoder.c VS simple-encoder.go

go build -o go-simple-encoder ../simple-encoder.go
./go-simple-encoder --data 12 --par 6 --out o input.txt
./simple-encoder -d 12 -p 6  -o o2 -f input.txt
meld o o2

License

published under an MIT license. See LICENSE file for more information.