refactor: split up the utilities file into smaller modules

This commit is contained in:
lisk77 2025-09-19 03:48:08 +02:00
parent abaa6e12fc
commit ff71a92249
13 changed files with 572 additions and 488 deletions

View file

@ -1,108 +1,5 @@
#include "utilities.h"
List* list_new(size_t item_size) {
List* list = calloc(1, sizeof(List));
if (!list) { perror("ERROR: memory allocation in new_list failed!"); return NULL; }
list->items = calloc(LIST_INIT_CAPACITY, item_size);
if (!list->items) { perror("ERROR: memory allocation in new_list failed!"); free(list); return NULL; }
list->len = 0;
list->capacity = LIST_INIT_CAPACITY;
list->item_size = item_size;
return list;
}
int list_push(List* list, void* item) {
if (!list || !item) return 0;
if (list->len == list->capacity) {
size_t new_capacity = list->capacity * 2;
void* new_items = realloc(list->items, new_capacity * list->item_size);
if (!new_items) { perror("ERROR: memory reallocation failed in list_push!"); return 0; }
list->items = new_items;
list->capacity = new_capacity;
}
char* dest = (char*)list->items + (list->len * list->item_size);
memcpy(dest, item, list->item_size);
list->len++;
return 1;
}
int list_remove(List* list, const void* key, int (*compare)(const void*, const void*)) {
if (!list || !key || !compare || list->len == 0) {
return 0;
}
for (size_t i = 0; i < list->len; i++) {
char* current_item = (char*)list->items + (i * list->item_size);
if (compare(key, current_item) == 0) {
for (size_t j = i; j < list->len - 1; j++) {
char* dest = (char*)list->items + (j * list->item_size);
char* src = (char*)list->items + ((j + 1) * list->item_size);
memcpy(dest, src, list->item_size);
}
list->len--;
return 1;
}
}
return 0;
}
void list_free(List* buffer) {
if (buffer) {
for (size_t i = 0; i < buffer->len; i++) {
free(buffer->items[i]);
}
free(buffer->items);
free(buffer);
}
}
void* binary_search(const void* key, const void* base, size_t num_elements, size_t element_size, int (*compare)(const void*, const void*)) {
if (!key || !base || !compare || num_elements == 0) {
return NULL;
}
size_t left = 0;
size_t right = num_elements - 1;
while (left <= right) {
size_t mid = left + (right - left) / 2;
const char* mid_element = (const char*)base + (mid * element_size);
int cmp = compare(key, mid_element);
if (cmp == 0) {
return (void*)mid_element;
}
else if (cmp < 0) {
if (mid == 0) break;
right = mid - 1;
}
else {
left = mid + 1;
}
}
return NULL;
}
void* list_binary_search(List* list, const void* key, int (*compare)(const void*, const void*)) {
if (!list || !key || !compare) {
return NULL;
}
return binary_search(key, list->items, list->len, list->item_size, compare);
}
StringBuffer* string_buffer_new() {
return list_new(sizeof(char*));
}
@ -135,44 +32,6 @@ char* string_buffer_search(StringBuffer* buffer, char* path) {
return (char*)list_binary_search(buffer, path, compare_strings);
}
FileInfoBuffer* file_info_buffer_new() {
return list_new(sizeof(FileInfo));
}
int file_info_buffer_push(FileInfoBuffer* buffer, FileInfo info) {
return list_push(buffer, &info);
}
void file_info_buffer_free(List* buffer) {
if (buffer) {
free(buffer->items);
free(buffer);
}
}
int compare_file_info(const void* a, const void* b) {
const FileInfo* info1 = (const FileInfo*)a;
const FileInfo* info2 = (const FileInfo*)b;
return strcmp(info1->name, info2->name);
}
void file_info_buffer_sort(FileInfoBuffer* buffer) {
if (!buffer || buffer->len <= 1) {
return;
}
qsort(buffer->items, buffer->len, sizeof(FileInfo), compare_file_info);
}
FileInfo* file_info_buffer_search(FileInfoBuffer* buffer, const char* filename) {
if (!buffer || !filename) return NULL;
FileInfo search_key = {.mode = 0, .name = (char*)filename};
return (FileInfo*)list_binary_search(buffer, &search_key, compare_file_info);
}
static int is_dot_or_dotdot(const char* s) {
return (s[0] == '.' && (s[1] == '\0' || (s[1] == '.' && s[2] == '\0')));
}
@ -697,319 +556,119 @@ int save_diff(ActionList* diff, char* path, char* root, size_t diff_id, char* ba
return 1;
}
int read_diff(char* path, char* root, size_t diff_id, char* basefile_hash, ActionList* diff_out) {
size_t compressed_size;
unsigned char* compressed_data = (unsigned char*)get_file_content_with_size(path, &compressed_size);
if (!compressed_data || compressed_size == 0) {
free(compressed_data);
return 1;
int read_diff(char* content, char* basefile_hash, ActionList* diff_out) {
if (!content || !basefile_hash || !diff_out) {
return 0;
}
size_t idx = 0;
while (idx < compressed_size && IS_DIGIT(compressed_data[idx])) {
idx++;
}
if (idx == 0) {
perror("ERROR: no length found at start of base file list!");
free(compressed_data);
return 0;
}
char* size_str = calloc(idx + 1, sizeof(char));
if (!size_str) {
free(compressed_data);
return 0;
}
memcpy(size_str, compressed_data, idx);
size_str[idx] = '\0';
char* end;
long original_size = strtol(size_str, &end, 10);
if (end == size_str || *end != '\0') {
perror("ERROR: invalid length in read_diff!");
free(size_str);
free(compressed_data);
return 0;
}
free(size_str);
if (idx < compressed_size && compressed_data[idx] == ' ') {
idx++;
}
char* diff_list = calloc(original_size + 1, sizeof(char));
if (!diff_list) {
free(compressed_data);
return 0;
}
uLongf dest_len = (uLongf)original_size;
int result = uncompress((unsigned char*)diff_list, &dest_len, compressed_data + idx, compressed_size - idx);
free(compressed_data);
if (result != Z_OK) {
perror("ERROR: decompression of the diff failed!");
free(diff_list);
return 0;
}
diff_list[dest_len] = '\0';
printf("Decompressed diff content: %s\n", diff_list);
idx = 0;
strncpy(basefile_hash, diff_list, 40);
strncpy(basefile_hash, content, 40);
basefile_hash[40] = '\0';
idx += 41;
while (idx < dest_len && IS_DIGIT(diff_list[idx])) {
while (content[idx] && IS_DIGIT(content[idx])) {
idx++;
}
if (idx == 41) {
perror("ERROR: no length found at start of diff!");
free(diff_list);
return 0;
}
char* number_of_actions = calloc(idx + 1, sizeof(char));
char* number_of_actions = calloc(idx - 41 + 1, sizeof(char));
if (!number_of_actions) {
free(diff_list);
return 0;
}
memcpy(number_of_actions, diff_list + 41, idx-41);
number_of_actions[idx] = '\0';
memcpy(number_of_actions, content + 41, idx - 41);
number_of_actions[idx - 41] = '\0';
char* end;
long actions = strtol(number_of_actions, &end, 10);
if (end == number_of_actions || *end != '\0') {
perror("ERROR: invalid length in read_diff!");
free(number_of_actions);
free(diff_list);
return 0;
}
free(number_of_actions);
if (actions <= 0) {
free(diff_list);
return 1;
if (end == number_of_actions || *end != '\0' || actions <= 0) {
perror("ERROR: invalid number of actions in read_diff!");
return 0;
}
size_t action_idx = 0;
while (idx < dest_len && action_idx < (size_t)actions) {
while (content[idx] && action_idx < (size_t)actions) {
idx++;
if (diff_list[idx] == '0') {
Action action = {0};
if (content[idx] == '0') {
idx++;
if (diff_list[idx] == ' ') idx++;
else {
if (content[idx] != ' ') {
perror("ERROR: expected space after opbit in read_diff!");
free(diff_list);
return 0;
}
size_t start_idx = idx;
while (idx < dest_len && IS_DIGIT(diff_list[idx])) {
idx++;
}
if (idx == dest_len) {
perror("ERROR: unexpected end of diff in read_diff!");
free(diff_list);
return 0;
}
char* line_original_str = calloc(idx + 1, sizeof(char));
if (!line_original_str) {
free(diff_list);
return 0;
}
memcpy(line_original_str, diff_list + start_idx, idx - start_idx);
line_original_str[idx - start_idx] = '\0';
char* end2;
long line_original = strtol(line_original_str, &end2, 10);
if (end2 == line_original_str || *end2 != '\0') {
perror("ERROR: invalid line number in read_diff!");
free(line_original_str);
free(diff_list);
return 0;
}
free(line_original_str);
if (diff_list[idx] == ' ') idx++;
else {
perror("ERROR: expected space after line original in read_diff!");
free(diff_list);
return 0;
}
start_idx = idx;
while (idx < dest_len && IS_DIGIT(diff_list[idx])) {
idx++;
}
if (idx == dest_len) {
perror("ERROR: unexpected end of diff in read_diff!");
free(diff_list);
return 0;
}
char* line_changed_str = calloc(idx + 1, sizeof(char));
if (!line_changed_str) {
free(diff_list);
return 0;
}
memcpy(line_changed_str, diff_list + start_idx, idx - start_idx);
line_changed_str[idx - start_idx] = '\0';
long line_changed = strtol(line_changed_str, &end2, 10);
if (end2 == line_changed_str || *end2 != '\0') {
perror("ERROR: invalid line number in read_diff!");
free(line_changed_str);
free(diff_list);
return 0;
}
free(line_changed_str);
Action action = {.type=DELETE, .line_original=line_original, .line_changed=line_changed, .content=NULL};
add_action(diff_out, action);
action_idx++;
}
else if (diff_list[idx] == '1') {
idx++;
if (diff_list[idx] == ' ') idx++;
else {
char* endptr;
action.line_original = strtol(content + idx, &endptr, 10);
if (endptr == content + idx || *endptr != ' ') {
perror("ERROR: failed to parse line_original in read_diff!");
return 0;
}
idx = endptr - content + 1;
action.line_changed = strtol(content + idx, &endptr, 10);
if (endptr == content + idx || (*endptr != ' ' && *endptr != '\0')) {
perror("ERROR: failed to parse line_changed in read_diff!");
return 0;
}
idx = endptr - content;
} else if (content[idx] == '1') {
idx++;
if (content[idx] != ' ') {
perror("ERROR: expected space after opbit in read_diff!");
free(diff_list);
return 0;
}
size_t start_idx = idx;
idx++;
while (idx < dest_len && IS_DIGIT(diff_list[idx])) {
idx++;
}
if (idx == dest_len) {
perror("ERROR: unexpected end of diff in read_diff!");
free(diff_list);
return 0;
}
char* line_original_str = calloc(idx + 1, sizeof(char));
if (!line_original_str) {
free(diff_list);
return 0;
}
memcpy(line_original_str, diff_list + start_idx, idx - start_idx);
line_original_str[idx - start_idx] = '\0';
char* end2;
long line_original = strtol(line_original_str, &end2, 10);
if (end2 == line_original_str || *end2 != '\0') {
perror("ERROR: invalid line number in read_diff!");
free(line_original_str);
free(diff_list);
return 0;
}
free(line_original_str);
if (diff_list[idx] == ' ') idx++;
else {
perror("ERROR: expected space after line original in read_diff!");
free(diff_list);
return 0;
}
start_idx = idx;
while (idx < dest_len && IS_DIGIT(diff_list[idx])) {
idx++;
}
if (idx == dest_len) {
perror("ERROR: unexpected end of diff in read_diff!");
free(diff_list);
return 0;
}
char* line_changed_str = calloc(idx + 1, sizeof(char));
if (!line_changed_str) {
free(diff_list);
return 0;
}
memcpy(line_changed_str, diff_list + start_idx, idx - start_idx);
line_changed_str[idx - start_idx] = '\0';
long line_changed = strtol(line_changed_str, &end2, 10);
if (end2 == line_changed_str || *end2 != '\0') {
perror("ERROR: invalid line number in read_diff!");
free(line_changed_str);
free(diff_list);
return 0;
}
free(line_changed_str);
if (diff_list[idx] == ' ') idx++;
else {
perror("ERROR: expected space after line changed in read_diff!");
free(diff_list);
char* endptr;
action.line_original = strtol(content + idx, &endptr, 10);
if (endptr == content + idx || *endptr != ' ') {
perror("ERROR: failed to parse line_original in read_diff!");
return 0;
}
idx = endptr - content + 1;
start_idx = idx;
while (idx < dest_len && IS_DIGIT(diff_list[idx])) {
idx++;
}
if (idx == dest_len) {
perror("ERROR: unexpected end of diff in read_diff!");
free(diff_list);
return 0;
}
char* content_len_str = calloc(idx + 1, sizeof(char));
if (!content_len_str) {
free(diff_list);
return 0;
}
memcpy(content_len_str, diff_list + start_idx, idx - start_idx);
content_len_str[idx - start_idx] = '\0';
long content_len = strtol(content_len_str, &end2, 10);
if (end2 == content_len_str || *end2 != '\0') {
perror("ERROR: invalid line number in read_diff!");
free(content_len_str);
free(diff_list);
return 0;
}
free(content_len_str);
if (diff_list[idx] == ' ') idx++;
else {
perror("ERROR: expected space after line original in read_diff!");
free(diff_list);
action.line_changed = strtol(content + idx, &endptr, 10);
if (endptr == content + idx || *endptr != ' ') {
perror("ERROR: failed to parse line_changed in read_diff!");
return 0;
}
idx = endptr - content + 1;
if (idx + content_len > dest_len) {
perror("ERROR: content length exceeds diff length in read_diff!");
free(diff_list);
size_t content_length = strtol(content + idx, &endptr, 10);
if (endptr == content + idx || *endptr != ' ') {
perror("ERROR: failed to parse content length in read_diff!");
return 0;
}
idx = endptr - content + 1;
char* content = calloc(content_len + 1, sizeof(char));
if (!content) {
free(diff_list);
action.content = strndup(content + idx, content_length);
if (!action.content) {
perror("ERROR: failed to allocate memory for action content in read_diff!");
return 0;
}
memcpy(content, diff_list + idx, content_len);
content[content_len] = '\0';
idx += content_len;
Action action = {.type=INSERT, .line_original=line_original, .line_changed=line_changed, .content=content};
add_action(diff_out, action);
action_idx++;
}
else {
perror("ERROR: invalid opbit in read_diff!");
free(diff_list);
idx += content_length;
} else {
perror("ERROR: unknown action type in read_diff!");
return 0;
}
add_action(diff_out, action);
action_idx++;
}
return 1;
}
int save_file_diff(char* path, char* root, size_t diff_id, char* basefile_hash, Changes* changes) {
char basefile_location[2+strlen(root)+strlen("/.merk/objects/")+strlen(basefile_hash)];
snprintf(basefile_location, sizeof(basefile_location), "%s/.merk/objects/%.2s/%s", root, basefile_hash, basefile_hash+2);
@ -1135,30 +794,4 @@ File* apply_diff(File* basefile, ActionList* diff) {
}
return copy;
}
int compare_actions(const void* a, const void* b) {
const Action* action1 = (const Action*)a;
const Action* action2 = (const Action*)b;
if (action1->type != action2->type) {
return (action1->type == DELETE) ? -1 : 1;
}
if (action1->type == DELETE) {
if (action1->line_original < action2->line_original) return 1;
if (action1->line_original > action2->line_original) return -1;
return 0;
} else {
if (action1->line_changed < action2->line_changed) return -1;
if (action1->line_changed > action2->line_changed) return 1;
return 0;
}
}
void sort_action_list(ActionList* actions) {
if (!actions || actions->len <= 1) return;
qsort(actions->actions, actions->len, sizeof(Action), compare_actions);
}