#include "utf8hack.h" #include #include #include #include int get_index_of_utf8_char(utf8_char *utf8_string, size_t string_length, utf8_char search_char); void transcode(long offset, char *charset_str, char *message_str); #define HELP_MESSAGE \ "ACaesar - Caesar Cipher transcoder version 0.1\n\ Usage: acaesar [options] message\n\ Options:\n\ --help Print this help message\n\ -o Set the integer offset used in transcoding\n\ -c Set the character set\n\ --xyz Set the character set to the lowercase alphabet (default)\n" int main(int argc, char *argv[]) { bool charset_set = false; bool message_set = false; bool offset_set = false; bool alloc_charset = false; long offset; char *charset; char *message; // Argument parsing for (int i = 1; i < argc; i++) { char *current_arg = argv[i]; // Help flag if (strcmp(current_arg, "--help") == 0) { printf(HELP_MESSAGE); return 0; } // Charset flag if (strcmp(current_arg, "-c") == 0) { if (i == argc - 1) { fprintf(stderr, "Error, charset (-c) flag found without following charset.\n"); return 1; } if (charset_set) { fprintf(stderr, "Error, character set specified twice.\n"); return 1; } char *next_arg = argv[i + 1]; size_t size = strlen(next_arg); charset = malloc(size * sizeof(char) + 1); strcpy(charset, next_arg); charset_set = true; i++; continue; } // Offset flag if (strcmp(current_arg, "-o") == 0) { if (i == argc - 1) { fprintf(stderr, "Error, offset (-o) flag found without following offset.\n"); return 1; } if (offset_set) { fprintf(stderr, "Error, offset (-o) specified twice.\n"); return 1; } char *next_arg = argv[i + 1]; offset = strtol(next_arg, NULL, 10); offset_set = true; i++; continue; } // alphabetical charset flag. (default anyways). Only exists for completeness. if (strcmp(current_arg, "--xyz") == 0) { if (charset_set) { fprintf(stderr, "Error, character set specified twice.\n"); return 1; } charset = "abcdefghijklmnopqrstuvwxyz"; charset_set = true; alloc_charset = true; continue; } if (i != argc - 1) { // Unrecognized flag fprintf(stderr, "Error, unknown argument found: '%s'\n", current_arg); return 1; } else { // Message to be transcoded. // Last argument is assumed to be message. size_t size = strlen(current_arg); message = malloc(size * sizeof(char) + 1); strcpy(message, current_arg); message_set = true; } } if (!charset_set) { // Default to a...z when no charset is found. charset = "abcdefghijklmnopqrstuvwxyz"; charset_set = true; } if (!offset_set) { fprintf(stderr, "Error, no offset found. Use '-o' to set one.\n"); return 1; } if (!message_set) { fprintf(stderr, "Error, no message found to transcode.\n"); return 1; } transcode(offset, charset, message); // Clean up free(message); // In some cases, charset is malloc'd and in others it is set to be a string literal. // String literals can not bee freed so `alloc_charset` is used to determine when charset should be freed if (alloc_charset) free(charset); return 0; } int get_index_of_utf8_char(utf8_char *utf8_string, size_t string_length, utf8_char search_char) { for (size_t i = 0; i < string_length; i++) { if (utf8_char_eq(&utf8_string[i], &search_char)) { return i; } } return -1; } // Error handling would be nice for this function. void transcode(long offset, char *charset_str, char *message_str) { size_t charset_length; utf8_char *charset; parse_to_utf8(charset_str, &charset, &charset_length); size_t message_length; utf8_char *message; parse_to_utf8(message_str, &message, &message_length); utf8_char *transcoded_message = malloc(message_length * sizeof(utf8_char)); for (size_t i = 0; i < message_length; i++) { // A hashmap would likely be more efficient for larger messages, but would introduce much complexity. int a = get_index_of_utf8_char(charset, charset_length, message[i]); if (a != -1) { transcoded_message[i] = copy_utf8_char(&charset[(a + offset) % charset_length]); } else { // If character is not in character set, copy it over unchanged. transcoded_message[i] = copy_utf8_char(&message[i]); } } print_utf8_str(transcoded_message, message_length); printf("\n"); free_utf8_str(charset, charset_length); free_utf8_str(message, message_length); free_utf8_str(transcoded_message, message_length); }