Created
December 10, 2015 00:42
-
-
Save apsun/d37752962d25c51a0540 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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