From 5d9fc7d18d6aa0b5fcbfa08cdc333fead4eb7e61 Mon Sep 17 00:00:00 2001 From: bronku Date: Tue, 21 Oct 2025 18:50:21 +0200 Subject: [PATCH] refactor --- README.md | 21 +++++ buffer.c | 43 ++++++++++ buffer.h | 12 +++ config.c | 52 ++++++++++++ config.h | 23 +++++ main.c | 221 ++++++++++++++++--------------------------------- makefile | 29 ++++--- record.h | 4 +- status_codes.h | 5 ++ tape.c | 108 ------------------------ tape.h | 26 ------ 11 files changed, 247 insertions(+), 297 deletions(-) create mode 100644 README.md create mode 100644 buffer.c create mode 100644 buffer.h create mode 100644 config.c create mode 100644 config.h create mode 100644 status_codes.h delete mode 100644 tape.c delete mode 100644 tape.h diff --git a/README.md b/README.md new file mode 100644 index 0000000..2b3305a --- /dev/null +++ b/README.md @@ -0,0 +1,21 @@ +``` +// Generates a random.txt file with parameters specified, and exits +// parameters besides N, are only used internally to specify how big are the chunks written +
-g -N 100000 -b 10 -n 101 -o + +// Sort the input file, using the temporary dir, and the parameters specified, save to the output file +
-i -o -d -N 100000 -b 10 -n 101 + +// If no option is specified, system will prompt for parameters, and use the input data from stdin +
+``` + +- option `-i` implies the program is supposed to sort something, and thus is incompatible with `-g` +- when a parameter is not specified the default values are used: + - i = "1.in" + - o = "1.out" + - d = "tmp" + - g isn't set (false) + - N = 100000 + - b = 10 + - n = 101 diff --git a/buffer.c b/buffer.c new file mode 100644 index 0000000..4d46105 --- /dev/null +++ b/buffer.c @@ -0,0 +1,43 @@ +#include "buffer.h" +#include "record.h" +#include "status_codes.h" + +buffer create_buffer(int capacity) +{ + buffer out; + out.length = 0; + out.capacity = capacity; + out.location = malloc(sizeof(record) * capacity); + return out; +} + +int read_buffer(buffer* buff, FILE* in) +{ + int status; + record* current = buff->location; + buff->length = 0; + for (int i = 0; i < buff->capacity; i++) { + status = read_record(in, current); + if (status != SUCCESS) { + return status; + } + buff->length++; + current++; + } + return SUCCESS; +} + +int write_buffer(buffer* buff, FILE* out) +{ + int status; + record* current = buff->location; + for (int i = 0; i < buff->length; i++) { + status = print_record(out, current); + if (status < 0) { + return status; + } + fprintf(out, "\n"); + current++; + } + return SUCCESS; +} diff --git a/buffer.h b/buffer.h new file mode 100644 index 0000000..d713160 --- /dev/null +++ b/buffer.h @@ -0,0 +1,12 @@ +#pragma once +#include "record.h" + +typedef struct { + record* location; + int length; + int capacity; +} buffer; + +buffer create_buffer(int capacity); +int read_buffer(buffer* buff, FILE* in); +int write_buffer(buffer* buff, FILE* in); diff --git a/config.c b/config.c new file mode 100644 index 0000000..9dedf89 --- /dev/null +++ b/config.c @@ -0,0 +1,52 @@ +#include "config.h" +#include +#include +#include +#include + +int process_args(int argc, char** argv, Configuration* opts) +{ + opts->input_file = DEFAULT_IN; + opts->output_file = DEFAULT_OUT; + opts->directory = DEFAULT_DIR; + opts->generate_data = false; + opts->N = DEFAULT_NN; + opts->n = DEFAULT_N; + opts->b = DEFAULT_B; + int opt; + bool input_set = false; + while ((opt = getopt(argc, argv, "i:o:d:gN:n:b:")) != -1) { + switch (opt) { + case 'i': + opts->input_file = optarg; + input_set = true; + break; + case 'o': + opts->output_file = optarg; + break; + case 'd': + opts->directory = optarg; + break; + case 'g': + opts->generate_data = true; + break; + case 'N': + opts->N = atoi(optarg); + break; + case 'n': + opts->n = atoi(optarg); + break; + case 'b': + opts->b = atoi(optarg); + break; + case '?': + printf("wrong argument\n"); + return ERROR; + } + } + if (opts->generate_data && input_set) { + printf("incompatible arguments\n"); + return ERROR; + } + return SUCCESS; +} diff --git a/config.h b/config.h new file mode 100644 index 0000000..d6aa562 --- /dev/null +++ b/config.h @@ -0,0 +1,23 @@ +#pragma once +#include "status_codes.h" +#include + +#define DEFAULT_IN "1.in" +#define DEFAULT_OUT "1.in" +#define DEFAULT_DIR "tmp" +#define DEFAULT_NN 100000 +#define DEFAULT_N 101 +#define DEFAULT_B 10 + +typedef struct +{ + const char* input_file; + const char* output_file; + const char* directory; + bool generate_data; + int N; // number of records in a file + int b; // blocking factor + int n; // number of buffers +} Configuration; + +int process_args(int argc, char** argv, Configuration* opts); diff --git a/main.c b/main.c index 63c3ef7..7cc7059 100644 --- a/main.c +++ b/main.c @@ -1,167 +1,62 @@ +#include "buffer.h" +#include "config.h" #include "record.h" -#include "tape.h" -#include -#include -#include +#include "status_codes.h" #include #include #include #include -#define DEFAULT_FILE "tests/1.in" -#define DEFAULT_DIR "tmp" -#define DEFAULT_NN 100000 -#define DEFAULT_N 101 -#define DEFAULT_B 10 -#define END_PROGRAM -1 -#define SUCCESS 0 -#define ERROR -2 - -void print_usage() +int generate_file(int N, const char* filename) { - printf("Options:\n"); - printf(" -f [filename]\tRead/Generate records from [filename], default %s\n", DEFAULT_FILE); - printf(" -d [dirname]\tSet the directory used for temporary files, default %s\n", DEFAULT_DIR); - printf(" -N [count]\tSet total number of records, default %d\n", DEFAULT_NN); - printf(" -n [count]\tSet blocking factor, default %d\n", DEFAULT_N); - printf(" -b [count]\tSet number of buffers, default %d\n", DEFAULT_B); - printf(" -r\t randomly generate N records\n"); - printf(" -h\tShow this help message\n"); -} + srand(time(0)); + FILE* f = fopen(filename, "w"); + record rec; -typedef struct -{ - FILE* input; - char* filename; - char* dirname; - bool generate_data; - bool manual_input; - int N; // number of records in a file - int b; // blocking factor - int n; // number of buffers -} options; - -// reads args into opts -int process_args(int argc, char** argv, options* opts) -{ - if (opts == NULL) { - return ERROR; - } - opts->input = stdin; - opts->filename = DEFAULT_FILE; - opts->dirname = DEFAULT_DIR; - opts->generate_data = false; - opts->manual_input = false; - opts->N = DEFAULT_NN; - opts->n = DEFAULT_N; - opts->b = DEFAULT_B; - int opt; - while ((opt = getopt(argc, argv, "f:d:N:n:b:rhm")) != -1) { - switch (opt) { - case 'f': - opts->filename = optarg; - break; - case 'd': - opts->dirname = optarg; - break; - case 'r': - opts->generate_data = true; - break; - case 'N': - opts->N = atoi(optarg); - break; - case 'n': - opts->n = atoi(optarg); - break; - case 'b': - opts->b = atoi(optarg); - break; - case 'm': - opts->manual_input = true; - break; - case 'h': - print_usage(); - return END_PROGRAM; - case '?': - fprintf(stderr, "invalid option, terminating\n"); - return ERROR; - } - } - if (opts->manual_input == true && opts->generate_data == true) { - fprintf(stderr, "Incompatible arguments: mr, aborting\n"); - return ERROR; - } - opts->input = fopen(opts->filename, "r+"); - if (!opts->input) { - opts->input = fopen(opts->filename, "w+"); - } - if (!opts->input) { - fprintf(stderr, "Error: Cannot open file '%s'\n", opts->filename); - return ERROR; - } - struct stat st = { 0 }; - if (stat(opts->dirname, &st) == -1) { - mkdir(opts->dirname, 0777); + for (int i = 0; i < N; i++) { + random_record(&rec); + print_record(f, &rec); + fprintf(f, "\n"); } return SUCCESS; } -void generate_file(options* opts) +int sort_file(Configuration* opts) { - srand(time(0)); - record rec; - for (int i = 0; i < opts->N; i++) { - random_record(&rec); - print_record(opts->input, &rec); - fprintf(opts->input, "\n"); - } - fseek(opts->input, 0, SEEK_SET); -} + // create buffer + buffer buff = create_buffer(opts->b * opts->n); + // open file + FILE* in = fopen(opts->input_file, "r"); + // + // while !eof: + for (int i = 0; true; i++) { + // read buffer + int status = read_buffer(&buff, in); + printf("buffer i:%d, status: %d\n", i, status); + // sort buffer -void write_file(options* opts) -{ -} - -int sort_block(tape* t, buffer* buff) -{ - static int counter = 0; - int status = read_buffer(buff, t); - if (status != SUCCESS && status != EOF) { - fprintf(stderr, "Error reading file: %d\n", status); - return status; - } - - sort_buffer(buff); - printf("sorted the buffer %d, the results:\n", counter); - print_buffer(buff); - counter++; - return status; -} - -int sort_file(options* opts) -{ - tape a = { 0, 0, opts->input }; - buffer buff; - buff.capacity = opts->b * opts->n; - buff.location = malloc(sizeof(record) * buff.capacity); - int status = 0; - while (status == SUCCESS) { - status = sort_block(&a, &buff); - } - if (status != EOF) { - free(buff.location); - fclose(a.file); - return status; + // write run + write_buffer(&buff, stdout); + if (status != SUCCESS) { + break; + } } + // + // while tmp: + // merge b-1 runs + // + // close file + // free buffer + fclose(in); free(buff.location); - fclose(a.file); return SUCCESS; } int main(int argc, char** argv) { - options opts; + Configuration opts; if (argc <= 1) { + // #todo: stdin input fprintf(stderr, "please specify input args\n"); return ERROR; } @@ -170,12 +65,42 @@ int main(int argc, char** argv) return result; } if (opts.generate_data) { - generate_file(&opts); - return SUCCESS; - } - if (opts.manual_input) { - write_file(&opts); + return generate_file(opts.N, opts.output_file); } sort_file(&opts); - fclose(opts.input); } +// int sort_block(tape* t, buffer* buff) +// { +// static int counter = 0; +// int status = read_buffer(buff, t); +// if (status != SUCCESS && status != EOF) { +// fprintf(stderr, "Error reading file: %d\n", status); +// return status; +// } + +// sort_buffer(buff); +// printf("sorted the buffer %d, the results:\n", counter); +// print_buffer(buff); +// counter++; +// return status; +// } + +// int sort_file(options* opts) +// { +// tape a = { 0, 0, opts->input }; +// buffer buff; +// buff.capacity = opts->b * opts->n; +// buff.location = malloc(sizeof(record) * buff.capacity); +// int status = 0; +// while (status == SUCCESS) { +// status = sort_block(&a, &buff); +// } +// if (status != EOF) { +// free(buff.location); +// fclose(a.file); +// return status; +// } +// free(buff.location); +// fclose(a.file); +// return SUCCESS; +// } diff --git a/makefile b/makefile index 481378c..6196c62 100644 --- a/makefile +++ b/makefile @@ -1,30 +1,33 @@ CFLAGS = -g -build/main: build/main.o build/tape.o build - clang $(CFLAGS) build/main.o build/tape.o -o build/main +build/main: build/main.o build/config.o build/buffer.o + clang $(CFLAGS) build/main.o build/config.o build/buffer.o -o build/main build/main.o: main.c build clang $(CFLAGS) -c main.c -o build/main.o -build/tape.o: tape.c build - clang $(CFLAGS) -c tape.c -o build/tape.o +build/config.o: config.c build + clang $(CFLAGS) -c config.c -o build/config.o + +build/buffer.o: buffer.c build + clang $(CFLAGS) -c buffer.c -o build/buffer.o build: mkdir -p build -tests: - mkdir -p tests +build/run: build + mkdir -p build/run clean: - rm -rf build tests tmp + rm -rf build -run: build/main tests/1.in - build/main -f tests/1.in | less +build/run/1.in: build/run build/main + build/main -g -o build/run/1.in + +run: build/main build/run/1.in + build/main -i build/run/1.in | less debug: build/main tests/1.in - lldb -- build/main -f tests/1.in - -tests/1.in: build/main tests - build/main -f tests/1.in -r + lldb -- build/main .PHONY: clean run debug diff --git a/record.h b/record.h index bbd1d11..265b2c5 100644 --- a/record.h +++ b/record.h @@ -28,9 +28,9 @@ static inline int compare_records(const void* a, const void* b) return result; } -static inline void print_record(FILE* stream, const record* out) +static inline int print_record(FILE* stream, const record* out) { - fprintf(stream, "%d %d %d %d %d %d", + return fprintf(stream, "%d %d %d %d %d %d", out->a[0], out->a[1], out->a[2], out->a[3], out->a[4], out->x); } diff --git a/status_codes.h b/status_codes.h new file mode 100644 index 0000000..2a38140 --- /dev/null +++ b/status_codes.h @@ -0,0 +1,5 @@ +#pragma once + +#define END_PROGRAM -1 +#define SUCCESS 0 +#define ERROR -2 diff --git a/tape.c b/tape.c deleted file mode 100644 index d9b304a..0000000 --- a/tape.c +++ /dev/null @@ -1,108 +0,0 @@ -#include "record.h" -#include "tape.h" - -int partition(record* arr, int start, int end) -{ - int i = start; - record* pivot = arr; - pivot += end; - for (int j = start; j < end; j++) { - record* current = arr; - current += j; - if (compare_records(current, pivot) > 0) { - continue; - } - record* i_rec = arr; - i_rec += i; - record tmp = *i_rec; - *i_rec = *current; - *current = tmp; - i++; - } - record* i_rec = arr; - i_rec += i; - record tmp = *i_rec; - *i_rec = *pivot; - *pivot = tmp; - return i; -} - -void quicksort(record* arr, int start, int end, int depth) -{ - if (start >= end || start < 0) { - return; - } - - int p = partition(arr, start, end); - quicksort(arr, start, p - 1, depth + 1); - quicksort(arr, p + 1, end, depth + 1); -} - -void sort_buffer(buffer* buff) -{ - quicksort(buff->location, 0, buff->length - 1, 0); -} - -int read_buffer(buffer* buff, tape* tape) -{ - int status; - record* destination = buff->location; - buff->length = 0; - while (buff->capacity > buff->length) { - status = read_record(tape->file, destination); - if (status != 0) { - return status; - } - destination++; - buff->length++; - tape->reads++; - } - return 0; -} - -void print_full_buffer(buffer* buff) -{ - for (int i = 0; i < buff->length; i++) { - record* current = buff->location; - current += i; - printf("i: %d\tg: %d\t", i, g(current)); - print_record(stdout, current); - printf("\n"); - } -} - -void print_buffer(buffer* buff) -{ - if (buff->length <= 10) { - print_full_buffer(buff); - return; - } - for (int i = 0; i < 5; i++) { - record* current = buff->location; - current += i; - printf("i: %d\tg: %d\t", i, g(current)); - print_record(stdout, current); - printf("\n"); - } - for (int i = buff->length - 5; i < buff->length; i++) { - record* current = buff->location; - current += i; - printf("i: %d\tg: %d\t", i, g(current)); - print_record(stdout, current); - printf("\n"); - } -} - -int write_buffer(buffer* buff, tape* tape) -{ - record* current = buff->location; - record* last = current; - last += buff->length; - while (current < last) { - print_record(tape->file, current); - fprintf(tape->file, "\n"); - current++; - tape->reads++; - } - return 0; -} diff --git a/tape.h b/tape.h deleted file mode 100644 index b201ac5..0000000 --- a/tape.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once -#include - -typedef struct { - int reads; - int writes; - FILE* file; -} tape; - -typedef struct { - void* location; - int length; - int capacity; -} buffer; - -// sorts the entire buffer -void sort_buffer(buffer* buff); - -// reads [capacity] records -int read_buffer(buffer* buff, tape* tape); -// writes everything -int write_buffer(buffer* buff, tape* tape); -// for debugging -void print_buffer(buffer* buff); - -void clear_tape(tape* tape);