diff --git a/.github/workflows/build-checks.yaml b/.github/workflows/build-checks.yaml index e6c1565..4d899cb 100644 --- a/.github/workflows/build-checks.yaml +++ b/.github/workflows/build-checks.yaml @@ -1,6 +1,9 @@ name: Cross-platform Build Checks -on: [push, pull_request] +on: + push: + branches: [main] + pull_request: jobs: build: @@ -68,8 +71,9 @@ jobs: - name: Try compiling run: cmake --build out + # It should work anyway I'm pretty sure build-freebsd: - # if: false + if: false strategy: fail-fast: false matrix: diff --git a/.gitignore b/.gitignore index 6b1a43b..3a25eeb 100644 --- a/.gitignore +++ b/.gitignore @@ -134,3 +134,5 @@ CMakeUserPresets.json *-prefix/ # End of https://www.toptal.com/developers/gitignore/api/cmake,clion + +.tmp_dir_path \ No newline at end of file diff --git a/.idea/NoteViewer.iml b/.idea/NoteViewer.iml index f08604b..220714a 100644 --- a/.idea/NoteViewer.iml +++ b/.idea/NoteViewer.iml @@ -1,2 +1,8 @@ - \ No newline at end of file + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 0b76fe5..684040f 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,5 +1,8 @@ + + diff --git a/.idea/runConfigurations/NoteViewer.xml b/.idea/runConfigurations/NoteViewer.xml new file mode 100644 index 0000000..b69b83b --- /dev/null +++ b/.idea/runConfigurations/NoteViewer.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations/setup_test_env.xml b/.idea/runConfigurations/setup_test_env.xml new file mode 100644 index 0000000..65b4b13 --- /dev/null +++ b/.idea/runConfigurations/setup_test_env.xml @@ -0,0 +1,24 @@ + + + + + \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 9b49bbb..f0b22ca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,4 +7,9 @@ add_executable(NoteViewer main.c sequence.h types.h sequence.c - consts.h) + consts.h + utils.h + parse.c + parse.h + utils.c +) diff --git a/main.c b/main.c index a782048..74319c9 100644 --- a/main.c +++ b/main.c @@ -4,120 +4,36 @@ #include #include "consts.h" +#include "parse.h" #include "sequence.h" #include "types.h" + + int main(int argc, char **argv) { // TODO: Read each files in the current directory with idk what criteria yet FILE *file = fopen("test.txt", "r"); - const str word_to_base_output_on = alloca(sizeof(wchar_t)*strlen(argv[1])); - mbtowc(word_to_base_output_on, argv[1], strlen(argv[1])); - // TODO: Replace by wchar_t later on - int curr_char = fgetc(file); - - while (curr_char != '[' && curr_char != EOF) - curr_char = fgetc(file); - - int line_counter = 1; - - str string_to_save = NULL; - int string_size = 0; - - sequence_t start_of_sequence; - start_of_sequence.elem = string_to_save; - start_of_sequence.next = NULL; - - sequence_t *current_seq_elem = &start_of_sequence; - - enum reading_state_t { - UNDEFINED, - READING_TITLE, - SKIP, - SAVE - }; + const char *arg2 = argv[1]; + wchar_t *word_to_base_output_on = alloca(sizeof(wchar_t)*strlen(arg2)); // allocated on the stack because speed + mbstowcs(word_to_base_output_on, arg2, strlen(arg2)); - enum reading_state_t reading_state = UNDEFINED; - wchar_t reading_chars[wcslen(word_to_base_output_on) + 1]; - int reading_chars_index = 0; - - // Chunk of bytes to consume from the file everytime - wchar_t current_chunk[CHUNK_SIZE / sizeof(wchar_t)]; - sequence_t *stack_of_chunks; - - // TODO: Send to threads and queues - while (fgetws(current_chunk, CHUNK_SIZE / sizeof(wchar_t), file) != NULL) { - for (int i = 0; i < CHUNK_SIZE / sizeof(wchar_t); i++) { - curr_char = current_chunk[i]; - if (curr_char == '\n') { - line_counter++; - } - - switch (reading_state) { - case SKIP: - case SAVE: - case UNDEFINED: - if (curr_char == '[') { - if (reading_state == SAVE) { - wchar_t chars_saved_so_far[CHUNK_SIZE / sizeof(wchar_t)]; - wcslcpy(chars_saved_so_far, current_chunk, i); - const str new_string = assemble_str(stack_of_chunks, chars_saved_so_far); - attach(current_seq_elem, new_string); - } - - reading_state = READING_TITLE; - stack_of_chunks = malloc(sizeof(sequence_t)); - string_size = 0; - } else if (reading_state == SAVE) string_size++; // this basically becomes the evil twin chunk index - break; - case READING_TITLE: - if (curr_char == ']') { - // Error handling - if (string_size == 0) { - fprintf(stderr, "Empty tag at %i", line_counter); - exit(EXIT_FAILURE); - } - - if (wcslen(word_to_base_output_on) != string_size - || wcpcpy(word_to_base_output_on, reading_chars) != 0) { - reading_state = SKIP; - } else { - reading_state = SAVE; - } - } else { - string_size++; - if (string_size <= wcslen(word_to_base_output_on)) { - reading_chars[reading_chars_index] = curr_char; - reading_chars_index++; - } else { - reading_state = SKIP; - // bzero(reading_chars, strlen(word_to_base_output_on)); /// no need - - reading_chars[reading_chars_index] = 0; - // resetting this index will be enough since it will overwrite the earlier string - // plus, this string is only compared to its right length - } - } - break; - } - } - - if (reading_state == SAVE) { - attach(stack_of_chunks, current_chunk); // if it's null deal with it - string_size = 0; - } - } + sequence_t main_sequence_of_chars; // Also the start of sequence + sequence_t *seq_ptr = &main_sequence_of_chars; // movable pointer, start at the thing above + parse_file_content(file, word_to_base_output_on, &seq_ptr); + fclose(file); // TODO: Formatting - while (start_of_sequence.next != NULL) { - printf("%ls", (*start_of_sequence.next).elem); + while (main_sequence_of_chars.next != NULL) { + seq_ptr = &main_sequence_of_chars; + wprintf(L"%ls", seq_ptr->elem); // no time to free anything - start_of_sequence = *start_of_sequence.next; + seq_ptr = seq_ptr->next; } return 0; -} +} \ No newline at end of file diff --git a/parse.c b/parse.c new file mode 100644 index 0000000..b701bd1 --- /dev/null +++ b/parse.c @@ -0,0 +1,142 @@ +// +// Created by mayachen on 2025-09-20. +// + +#include "parse.h" + +#include +#include +#include + +#include "sequence.h" + +// not global functions to give the compiler for dinner // + +void advance_file_ptr_or_fail(FILE **file); + +// Insane I finally used pointers of pointers +void save_chars(wchar_t current_chunk[CHUNK_SIZE / sizeof(wchar_t)], + int string_size, + sequence_t *stack_of_chunks, + sequence_t **seq_ptr +); + +enum reading_state_t { + UNDEFINED, + READING_TITLE, + SKIP, + SAVE +}; + +// File reading state. (Please use the pointer instead for ARM's sake) +enum reading_state_t reading_statee; + +// ARM cpus will thank me for putting this variable nearby +// +// If it's even put nearby +enum reading_state_t __attribute__((section(".text"))) *const reading_state_ptr = &reading_statee; + +void save_chars(wchar_t current_chunk[CHUNK_SIZE / sizeof(wchar_t)], + const int string_size, + sequence_t *stack_of_chunks, + sequence_t **seq_ptr +) { + wchar_t chars_saved_so_far[CHUNK_SIZE / sizeof(wchar_t)]; + wcslcpy(chars_saved_so_far, current_chunk, string_size); + const str new_string = assemble_str(stack_of_chunks, chars_saved_so_far); + *seq_ptr = attach(*seq_ptr, new_string); +} + +void advance_file_ptr_or_fail(FILE **file) { + wchar_t curr_char; + + while ((curr_char = fgetc(*file) != '[')) + if (curr_char == EOF) + perror("File format error. No tags found!"); + + *reading_state_ptr = READING_TITLE; +} + +void parse_file_content(FILE *file, const wchar_t *word_to_base_output_on, sequence_t **curr_seq_ptr) { + advance_file_ptr_or_fail(&file); + + int line_counter = 1; + + int string_size = 0; + + sequence_t start_of_sequence; + start_of_sequence.elem = NULL; + start_of_sequence.next = NULL; + + sequence_t *current_seq_elem = &start_of_sequence; + + + wchar_t reading_chars[wcslen(word_to_base_output_on) + 1]; + int reading_chars_index = 0; + + // Chunk of bytes to consume from the file everytime + wchar_t current_chunk[CHUNK_SIZE / sizeof(wchar_t)]; + sequence_t *stack_of_chunks; + + // TODO: Send to threads and queues + while (fgetws(current_chunk, CHUNK_SIZE / sizeof(wchar_t), file) != NULL) { + wchar_t *curr_char_ptr = alloca(sizeof(wchar_t)); + for (int i = 0; i < CHUNK_SIZE / sizeof(wchar_t); i++) { + wchar_t curr_char = *curr_char_ptr; + if (curr_char == '\n') { + line_counter++; + } + + switch (*reading_state_ptr) { + case SKIP: + case SAVE: + case UNDEFINED: + if (curr_char == '[') { + if (*reading_state_ptr == SAVE) { + save_chars(current_chunk, string_size, stack_of_chunks, curr_seq_ptr); + } + + *reading_state_ptr = READING_TITLE; + stack_of_chunks = malloc(sizeof(sequence_t)); + string_size = 0; + } else if (*reading_state_ptr == SAVE) string_size++; + // this basically becomes the evil twin chunk index + break; + case READING_TITLE: + if (curr_char == ']') { + // Error handling + if (string_size == 0) { + fprintf(stderr, "Empty tag at %i", line_counter); + exit(EXIT_FAILURE); + } + + if (wcslen(word_to_base_output_on) != string_size + || wcscmp(word_to_base_output_on, reading_chars) != 0) { + *reading_state_ptr = SKIP; + } else { + *reading_state_ptr = SAVE; + } + } else { + string_size++; + if (string_size <= wcslen(word_to_base_output_on)) { + reading_chars[reading_chars_index] = curr_char; + reading_chars_index++; + } else { + *reading_state_ptr = SKIP; + // bzero(reading_chars, strlen(word_to_base_output_on)); /// no need + + reading_chars[reading_chars_index] = 0; + // resetting this index will be enough since it will overwrite the earlier string + // plus, this string is only compared to its right length + } + } + break; + } + } + + if (*reading_state_ptr == SAVE) { + attach(stack_of_chunks, current_chunk); // if it's null deal with it + string_size = 0; + } + } +} diff --git a/parse.h b/parse.h new file mode 100644 index 0000000..494b180 --- /dev/null +++ b/parse.h @@ -0,0 +1,12 @@ +// +// Created by mayachen on 2025-09-20. +// + +#ifndef NOTEVIEWER_PARSE_H +#define NOTEVIEWER_PARSE_H +#include + +#include "sequence.h" + +void parse_file_content(FILE *file, const wchar_t *word_to_base_output_on, sequence_t **curr_seq_ptr); +#endif //NOTEVIEWER_PARSE_H \ No newline at end of file diff --git a/sequence.c b/sequence.c index 164a108..b372e59 100644 --- a/sequence.c +++ b/sequence.c @@ -9,6 +9,7 @@ #include "types.h" +// Returns a pointer to the `next` element. sequence_t *attach(sequence_t *curr_seq_ptr, const str new_elem) { sequence_t *new_seq_ptr = malloc(sizeof(sequence_t)); new_seq_ptr->elem = new_elem; @@ -17,9 +18,10 @@ sequence_t *attach(sequence_t *curr_seq_ptr, const str new_elem) { return new_seq_ptr; } +// The seq should be NULL at the end str assemble_str(sequence_t *seq, const wchar_t rest_of_the_chars[CHUNK_SIZE / sizeof(wchar_t)]) { - void* backup = seq; - str s; + void *backup = seq; // Save starting addresses + wchar_t *ret_str; // I'm sure the compiler will be glad to optimize this "scope" :clueless: { @@ -30,25 +32,25 @@ str assemble_str(sequence_t *seq, const wchar_t rest_of_the_chars[CHUNK_SIZE / s seq = seq->next; // truly the peakest type of loops } - s = malloc((len + 1) * sizeof(wchar_t)); + ret_str = malloc((len + 1) * sizeof(wchar_t)); } - seq = (sequence_t*)backup; - backup = s; + seq = (sequence_t *) backup; + backup = ret_str; while (seq->elem != NULL) { - wcscpy(s, seq->elem); - s += wcslen(seq->elem); + wcscpy(ret_str, seq->elem); + ret_str += wcslen(seq->elem); sequence_t *old_seq = seq; seq = seq->next; free(old_seq); // it has served its purpose - // it can now enjoy crystal stasis + // it can now enjoy crystal stasis } free(seq); - wcscpy(s, rest_of_the_chars); // it fits well its name + wcscpy(ret_str, rest_of_the_chars); // it fits well its name - s = backup; + ret_str = backup; - return s; + return ret_str; } diff --git a/setup_test-env.py b/setup_test-env.py new file mode 100755 index 0000000..6185d4c --- /dev/null +++ b/setup_test-env.py @@ -0,0 +1,17 @@ +#!/usr/bin/python + +import os +import tempfile + +global tempdir +pathExist: bool = os.path.exists(os.path.join(os.curdir, ".tmp_dir_path")) + +with open(".tmp_dir_path", 'r+t') as f: + if pathExist: + tempdir = f.readline() + else: + tempdir = tempfile.mkdtemp() + f.write(tempdir) + f.write("\n") + +os.chdir(tempdir) \ No newline at end of file diff --git a/utils.c b/utils.c new file mode 100644 index 0000000..bb7a585 --- /dev/null +++ b/utils.c @@ -0,0 +1,24 @@ +// +// Created by mayachen on 2025-09-20. +// + +// +// Created by mayachen on 2025-09-20. +// + +#include "utils.h" + +#include +#include + + +// "Throw with error code" +void throww_errcode(const char *err_msg, const int err_code) { + perror(err_msg); + exit(err_code); +} + +// Throw an error like it was a high level language (okay it doesn't print the stack trace) +inline void throw(const char *err_msg) { + throww_errcode(err_msg, 1); +} diff --git a/utils.h b/utils.h new file mode 100644 index 0000000..20832f1 --- /dev/null +++ b/utils.h @@ -0,0 +1,11 @@ +// +// Created by mayachen on 2025-09-20. +// + +#ifndef NOTEVIEWER_UTILS_H +#define NOTEVIEWER_UTILS_H + +inline void throw(const char* err_msg); +void throww_errcode(const char* err_msg, int err_code); + +#endif //NOTEVIEWER_UTILS_H \ No newline at end of file