Skip to content

Instantly share code, notes, and snippets.

@apsun
Created December 10, 2015 00:42
Show Gist options
  • Select an option

  • Save apsun/d37752962d25c51a0540 to your computer and use it in GitHub Desktop.

Select an option

Save apsun/d37752962d25c51a0540 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int read_stdin_ignore_nl(char *output_buf, int size) {
int i = 0, c;
while (i < size) {
c = getchar();
if (c == EOF) {
fprintf(stderr, "Reached EOF, expected %d chars, got %d\n", i, size);
return -1;
}
if (c != '\n' && c != '\r')
output_buf[i++] = (char)c;
}
return 0;
}
int bin2dec(const char *bin_str, int bin_str_length) {
int i, dec = 0;
for (i = 0; i < bin_str_length; ++i) {
dec = (dec << 1) | (bin_str[i] - '0');
}
return dec;
}
int all_bits_set(int num, int n) {
while (--n >= 0) {
if ((num & 1) == 0) {
return 0;
}
num >>= 1;
}
return 1;
}
int main_index(int n) {
int sum = 0;
while (--n >= 0) {
sum += (1 << n) - 1;
}
return sum;
}
char key_to_char(const char *header, const char *key, int key_length) {
int index, sub_index = bin2dec(key, key_length);
if (all_bits_set(sub_index, key_length)) {
return '\0';
}
index = main_index(key_length) + sub_index;
return header[index];
}
int read_header(char *out_header, int buffer_size) {
int header_length;
if (fgets(out_header, buffer_size, stdin) == NULL) {
/* fprintf(stderr, "Could not read message header\n"); */
return -1;
}
header_length = strlen(out_header) - 1;
out_header[header_length] = '\0';
/* fprintf(stderr, "Got message header: %s\n", out_header); */
return header_length;
}
int read_key_length() {
int key_length;
char bits[3];
if (read_stdin_ignore_nl(bits, sizeof(bits)) < 0) {
fprintf(stderr, "Could not read key length\n");
return -1;
}
key_length = bin2dec(bits, sizeof(bits));
/* fprintf(stderr, "Got key length: %d\n", key_length); */
return key_length;
}
int read_and_print_segment(const char *header, int key_length) {
char mapped_char;
char *key = malloc(sizeof(char) * key_length);
if (key == NULL) {
fprintf(stderr, "Could not allocate space for key\n");
return -1;
}
do {
if (read_stdin_ignore_nl(key, key_length) < 0) {
fprintf(stderr, "Could not read segment key\n");
free(key);
return -1;
}
mapped_char = key_to_char(header, key, key_length);
if (mapped_char == '\0')
break;
putchar(mapped_char);
} while (1);
free(key);
return 0;
}
int read_and_print_segments(const char *header) {
int key_length;
do {
key_length = read_key_length();
if (key_length < 0)
return -1;
if (key_length == 0)
break;
if (read_and_print_segment(header, key_length) < 0)
return -1;
} while (1);
putchar('\n');
return 0;
}
int main(int argc, char **argv) {
int header_length;
char header[1024];
do {
header_length = read_header(header, sizeof(header));
if (header_length < 0)
return 0;
if (read_and_print_segments(header) < 0)
return -1;
if (getchar() == EOF)
break;
} while (1);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment