1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
|
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#define extract(c,i) (3 & (c >> 2*i))
typedef uint8_t (*code_len_function)(int c);
static uint8_t code_to_length(int c) {
/* 0,1,2,3 codes-> 1,2,3,4 bytes */
return c + 1;
}
static uint8_t code_to_length_0124(int c) {
switch (c) {
case 0: // 0 bytes
return 0;
case 1: // 1 byte
return 1;
case 2: // 2 bytes
return 2;
default: // 4 bytes
return 4;
}
}
// Initializes the lengths tables. Meant to be called before
// decoder_permutation/encoder_permutation functions.
static void lengths_init(uint8_t *lengths, code_len_function code_len) {
for(int code = 0; code < 256; code++) {
lengths[code] = 0;
for(int i = 0; i < 4; i++ ) {
int c = extract(code, i);
lengths[code] += code_len(c);
}
}
}
// produces the decoder permutation tables
// as well as the "length" tables. The length table
// is the same for encoding and decoding.
// table should point at 256*16 bytes
// length should point at 256 bytes
static void decoder_permutation(uint8_t *table) {
uint8_t *p = table;
for(int code = 0; code < 256; code++) {
int byte = 0;
for(int i = 0; i < 4; i++ ) {
int c = extract(code, i);
int j;
for( j = 0; j <= c; j++ )
*p++ = byte++;
for( ; j < 4; j++ )
*p++ = -1;
}
}
}
// produces the encoder permutation tables
// table should point at 256*16 bytes
// length should point at 256 bytes initialized with init_lengths
static void encoder_permutation(uint8_t *table, uint8_t *lengths) {
uint8_t *p = table;
for(int code = 0; code < 256; code++) {
for(int i = 0; i < 4; i++ ) {
int c = extract(code, i);
int j;
for( j = 0; j <= c; j++ )
*p++ = 4*i + j;
}
for( int i = lengths[code]; i < 16; i++ )
*p++ = -1;
}
}
// produces the decoder permutation tables
// table should point at 256*16 bytes
static void decoder_permutation_0124(uint8_t *table) {
uint8_t *p = table;
for(int code = 0; code < 256; code++) {
int byte = 0;
for(int i = 0; i < 4; i++ ) {
int c = extract(code, i);
if (c < 3) {
// Here c stands for a number of bytes to copy, i.e. 0,1,2
int j;
for( j = 0; j < c; j++ )
*p++ = byte++;
for( ; j < 4; j++ )
*p++ = -1;
} else {
// Otherwise always copy all 4 bytes
for(int j = 0; j < 4; j++ )
*p++ = byte++;
}
}
}
}
// produces the encoder permutation tables
// table should point at 256*16 bytes
// length should point at 256 bytes initialized
// with lengths_init
static void encoder_permutation_0124(uint8_t *table, uint8_t *lengths) {
uint8_t *p = table;
for(int code = 0; code < 256; code++) {
for(int i = 0; i < 4; i++ ) {
int c = extract(code, i);
if (c < 3) {
for( int j = 1; j <= c; j++ )
*p++ = 4*i + j - 1;
} else {
for( int j = 0; j <= c; j++ )
*p++ = 4*i + j;
}
}
for( int i = lengths[code]; i < 16; i++ )
*p++ = -1;
}
}
// to be used after calling either decoder_permutation or encoder_permutation
// table should point at 256*16 bytes
static void print_permutation(uint8_t *table) {
for(int code = 0; code < 256; code++) {
int x;
printf(" {");
for(int i = 0; i < 15; i++)
printf(" %2d,", x = (int8_t) table[code*16 + i]);
printf( " %2d", x = (int8_t) table[code*16 + 15]);
printf(" }, // %d%d%d%d\n",
extract(code,0),
extract(code,1),
extract(code,2),
extract(code,3));
}
}
// to be used after calling either decoder_permutation or encoder_permutation
// length should point at 256 bytes
static void print_lengths(uint8_t *length) {
printf("{");
printf("\n");
for(int code = 0; code < 256; ) {
for(int k = 0; k < 16 ; k++) {
printf(" %2d,", length[code]);
code++;
}
printf("\n");
}
printf(" }");
}
int main(int argc, char **argv) {
uint8_t *encoder_table = (uint8_t *) malloc( sizeof(uint8_t[256][16]));
uint8_t *decoder_table = (uint8_t *) malloc( sizeof(uint8_t[256][16]));
uint8_t lengths[256];
if (argc == 2 && 0 == strcmp(argv[1], "0124")) {
printf("// using 0,1,2,4 bytes per value\n");
lengths_init(lengths, code_to_length_0124);
encoder_permutation_0124(encoder_table, lengths);
decoder_permutation_0124(decoder_table);
} else if (argc == 2 && 0 == strcmp(argv[1], "1234")) {
printf("// using 1,2,3,4 bytes per value\n");
lengths_init(lengths, code_to_length);
encoder_permutation(encoder_table, lengths);
decoder_permutation(decoder_table);
} else {
fprintf(stderr, "Usage: shuffle_tables <0124|1234> > src/streamvbyte_shuffle_tables.h\n");
exit(EXIT_FAILURE);
}
printf("static uint8_t lengthTable[256] =");
print_lengths(lengths);
printf(";\n\n");
printf("// decoding:\n");
printf("static uint8_t shuffleTable[256][16] = {\n");
print_permutation(decoder_table);
printf("};\n\n");
printf("// encoding:\n");
printf("static uint8_t encodingShuffleTable[256][16] = {\n");
print_permutation(encoder_table);
printf("};\n");
return 0;
}
|