|
#ifndef TIKKER_DECODE_H
|
|
#define TIKKER_DECODE_H
|
|
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
static inline char tikker_get_shifted_char(char c) {
|
|
switch (c) {
|
|
case '1': return '!';
|
|
case '2': return '@';
|
|
case '3': return '#';
|
|
case '4': return '$';
|
|
case '5': return '%';
|
|
case '6': return '^';
|
|
case '7': return '&';
|
|
case '8': return '*';
|
|
case '9': return '(';
|
|
case '0': return ')';
|
|
case '-': return '_';
|
|
case '=': return '+';
|
|
case '[': return '{';
|
|
case ']': return '}';
|
|
case '\\': return '|';
|
|
case ';': return ':';
|
|
case '\'': return '"';
|
|
case ',': return '<';
|
|
case '.': return '>';
|
|
case '/': return '?';
|
|
case '`': return '~';
|
|
default: return c;
|
|
}
|
|
}
|
|
|
|
static inline int tikker_decode_buffer(const char *input, char *output, size_t output_size) {
|
|
size_t out_pos = 0;
|
|
int shift_active = 0;
|
|
const char *p = input;
|
|
|
|
while (*p && out_pos < output_size - 1) {
|
|
if (*p == '[') {
|
|
const char *end = strchr(p, ']');
|
|
if (!end) {
|
|
p++;
|
|
continue;
|
|
}
|
|
|
|
size_t token_len = end - p - 1;
|
|
char token[64];
|
|
if (token_len >= sizeof(token)) token_len = sizeof(token) - 1;
|
|
strncpy(token, p + 1, token_len);
|
|
token[token_len] = '\0';
|
|
|
|
if (strcmp(token, "LEFT_SHIFT") == 0 || strcmp(token, "RIGHT_SHIFT") == 0) {
|
|
shift_active = 1;
|
|
} else if (strcmp(token, "BACKSPACE") == 0) {
|
|
if (out_pos > 0) out_pos--;
|
|
} else if (strcmp(token, "ENTER") == 0) {
|
|
output[out_pos++] = '\n';
|
|
} else if (strcmp(token, "TAB") == 0) {
|
|
output[out_pos++] = '\t';
|
|
} else if (token_len == 1) {
|
|
char c = token[0];
|
|
if (shift_active) {
|
|
if (c >= 'A' && c <= 'Z') {
|
|
output[out_pos++] = c;
|
|
} else if (c >= 'a' && c <= 'z') {
|
|
output[out_pos++] = c - 32;
|
|
} else {
|
|
output[out_pos++] = tikker_get_shifted_char(c);
|
|
}
|
|
shift_active = 0;
|
|
} else {
|
|
if (c >= 'A' && c <= 'Z') {
|
|
output[out_pos++] = c + 32;
|
|
} else {
|
|
output[out_pos++] = c;
|
|
}
|
|
}
|
|
}
|
|
|
|
p = end + 1;
|
|
} else if (*p == ' ' || *p == '\n' || *p == '\t') {
|
|
output[out_pos++] = *p;
|
|
p++;
|
|
} else if ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') ||
|
|
(*p >= '0' && *p <= '9') || *p == '.' || *p == ',' ||
|
|
*p == '-' || *p == '_' || *p == '\'' || *p == '"') {
|
|
char c = *p;
|
|
if (shift_active) {
|
|
if (c >= 'a' && c <= 'z') {
|
|
output[out_pos++] = c - 32;
|
|
} else {
|
|
output[out_pos++] = tikker_get_shifted_char(c);
|
|
}
|
|
shift_active = 0;
|
|
} else {
|
|
if (c >= 'A' && c <= 'Z') {
|
|
output[out_pos++] = c + 32;
|
|
} else {
|
|
output[out_pos++] = c;
|
|
}
|
|
}
|
|
p++;
|
|
} else {
|
|
p++;
|
|
}
|
|
}
|
|
|
|
output[out_pos] = '\0';
|
|
return (int)out_pos;
|
|
}
|
|
|
|
static inline int tikker_decode_file(const char *filename) {
|
|
FILE *f = fopen(filename, "r");
|
|
if (!f) {
|
|
fprintf(stderr, "Error: Cannot open file '%s'\n", filename);
|
|
return 1;
|
|
}
|
|
|
|
fseek(f, 0, SEEK_END);
|
|
long file_size = ftell(f);
|
|
fseek(f, 0, SEEK_SET);
|
|
|
|
char *input = malloc(file_size + 1);
|
|
if (!input) {
|
|
fclose(f);
|
|
fprintf(stderr, "Error: Memory allocation failed\n");
|
|
return 1;
|
|
}
|
|
|
|
size_t bytes_read = fread(input, 1, file_size, f);
|
|
input[bytes_read] = '\0';
|
|
fclose(f);
|
|
|
|
char *output = malloc(file_size + 1);
|
|
if (!output) {
|
|
free(input);
|
|
fprintf(stderr, "Error: Memory allocation failed\n");
|
|
return 1;
|
|
}
|
|
|
|
tikker_decode_buffer(input, output, file_size + 1);
|
|
printf("%s", output);
|
|
|
|
free(input);
|
|
free(output);
|
|
return 0;
|
|
}
|
|
|
|
#endif
|