feat(basefiles): added the BaseFileBuffer with BaseFileInfo and its core functionality to track files in the repo

This commit is contained in:
lisk77 2025-08-28 16:15:16 +02:00
parent a3ee042758
commit 1606f479db
2 changed files with 244 additions and 0 deletions

View file

@ -0,0 +1,24 @@
#ifndef BASE_FILE_BUFFER_H
#define BASE_FILE_BUFFER_H
#include <zlib.h>
#include "utilities.h"
typedef struct {
size_t base_num;
size_t diff_num;
char* name;
} BaseFileInfo;
typedef List BaseFileBuffer;
BaseFileBuffer* base_file_buffer_new();
int base_file_buffer_push(BaseFileBuffer*, BaseFileInfo);
void base_file_buffer_free(BaseFileBuffer*);
void base_file_buffer_sort(BaseFileBuffer*);
BaseFileInfo* base_file_buffer_search(BaseFileBuffer*, char*);
int read_base_file_list(BaseFileBuffer*, char*);
int write_base_file_list(BaseFileBuffer*, char*);
#endif // BASE_FILE_BUFFER_H

220
src/base_file_buffer.c Normal file
View file

@ -0,0 +1,220 @@
#include "base_file_buffer.h"
BaseFileBuffer* base_file_buffer_new() {
return list_new(sizeof(BaseFileInfo));
}
int base_file_buffer_push(BaseFileBuffer* buffer, BaseFileInfo info) {
return list_push(buffer, &info);
}
void base_file_buffer_free(BaseFileBuffer* buffer) {
if (buffer) {
for (int i = 0; i < buffer->len; i++) {
free(((BaseFileInfo*)buffer->items+i)->name);
}
free(buffer->items);
free(buffer);
}
}
int compare_base_file_info(const void* a, const void* b) {
const BaseFileInfo* info1 = (const BaseFileInfo*)a;
const BaseFileInfo* info2 = (const BaseFileInfo*)b;
return strcmp(info1->name, info2->name);
}
void base_file_buffer_sort(BaseFileBuffer* buffer) {
if (!buffer || buffer->len <= 1) {
return;
}
qsort(buffer->items, buffer->len, sizeof(BaseFileInfo), compare_base_file_info);
}
BaseFileInfo* base_file_buffer_search(BaseFileBuffer* buffer, char* filename) {
if (!buffer || !filename) return NULL;
BaseFileInfo search_key = (BaseFileInfo){.base_num = 0, .diff_num=0, .name = filename};
return (BaseFileInfo*)list_binary_search(buffer, &search_key, compare_base_file_info);
}
int read_base_file_list(BaseFileBuffer* buffer, char* base_file_list_path) {
size_t compressed_size;
unsigned char* compressed_data = (unsigned char*)get_file_content_with_size(base_file_list_path, &compressed_size);
if (!compressed_data || compressed_size == 0) {
free(compressed_data);
return 1;
}
char base_file_list[4096];
uLongf dest_len = sizeof(base_file_list) - 1;
int result = uncompress((unsigned char*)base_file_list, &dest_len, compressed_data, compressed_size);
free(compressed_data);
if (result != Z_OK) {
perror("ERROR: decompression of the base file list failed!");
return 0;
}
base_file_list[dest_len] = '\0';
size_t list_len = strlen(base_file_list);
if (list_len == 0) return 1;
size_t idx = 0;
char current;
while (idx < list_len && IS_DIGIT(base_file_list[idx])) {
idx++;
}
if (idx == 0) {
perror("ERROR: no length found at start of base_file_list!");
return 0;
}
char* len_str = calloc(idx + 1, sizeof(char));
memcpy(len_str, base_file_list, idx);
len_str[idx] = '\0';
char* end;
long len = strtol(len_str, &end, 10);
if (end == len_str || *end != '\0') {
perror("ERROR: invalid length in read_base_file_list!");
free(len_str);
return 0;
}
free(len_str);
if (idx < list_len && base_file_list[idx] == ' ') {
idx++;
}
for (int i = 0; i < len; i++) {
BaseFileInfo info;
size_t name_start = idx;
while (idx < list_len && base_file_list[idx] != ' ') {
idx++;
}
if (idx == name_start) {
perror("ERROR: empty filename in base_file_list!");
return 0;
}
size_t name_len = idx - name_start;
char* file_name = calloc(name_len + 1, sizeof(char));
memcpy(file_name, base_file_list + name_start, name_len);
file_name[name_len] = '\0';
info.name = file_name;
if (idx < list_len && base_file_list[idx] == ' ') {
idx++;
}
size_t base_start = idx;
while (idx < list_len && IS_DIGIT(base_file_list[idx])) {
idx++;
}
if (idx == base_start) {
perror("ERROR: no base_num found in base_file_list!");
free(file_name);
return 0;
}
size_t base_len = idx - base_start;
char* base_num_str = calloc(base_len + 1, sizeof(char));
memcpy(base_num_str, base_file_list + base_start, base_len);
base_num_str[base_len] = '\0';
long base_num = strtol(base_num_str, &end, 10);
if (end == base_num_str || *end != '\0') {
perror("ERROR: invalid base_num in base_file_list!");
free(file_name);
free(base_num_str);
return 0;
}
info.base_num = base_num;
free(base_num_str);
if (idx < list_len && base_file_list[idx] == ' ') {
idx++;
}
size_t diff_start = idx;
while (idx < list_len && IS_DIGIT(base_file_list[idx])) {
idx++;
}
if (idx == diff_start) {
perror("ERROR: no diff_num found in base_file_list!");
free(file_name);
return 0;
}
size_t diff_len = idx - diff_start;
char* diff_num_str = calloc(diff_len + 1, sizeof(char));
memcpy(diff_num_str, base_file_list + diff_start, diff_len);
diff_num_str[diff_len] = '\0';
long diff_num = strtol(diff_num_str, &end, 10);
if (end == diff_num_str || *end != '\0') {
perror("ERROR: invalid diff_num in base_file_list!");
free(file_name);
free(diff_num_str);
return 0;
}
info.diff_num = diff_num;
free(diff_num_str);
if (i < len - 1 && idx < list_len && base_file_list[idx] == ' ') {
idx++;
}
base_file_buffer_push(buffer, info);
}
return 1;
}
int write_base_file_list(BaseFileBuffer* buffer, char* info_file) {
base_file_buffer_sort(buffer);
char tmp[1024];
size_t offset = 0;
offset += snprintf(tmp + offset, sizeof(tmp) - offset, "%d ", buffer->len);
for (size_t idx = 0; idx < buffer->len; idx++) {
size_t remaining = sizeof(tmp) - offset;
BaseFileInfo* info = (BaseFileInfo*)buffer->items + idx;
offset += snprintf(tmp + offset, remaining, "%s %zu %zu ",
info->name, info->base_num, info->diff_num);
}
printf("%s\n", tmp);
FILE* fp = fopen(info_file, "wb");
if (!fp) { perror("ERROR: cannot open path in snapshot_tree!\n"); return 0; }
uLong originalLen = strlen(tmp) + 1;
uLong compressedLen = compressBound(originalLen);
Bytef compressed[compressedLen];
if (compress(compressed, &compressedLen, (const Bytef*)tmp, originalLen) != Z_OK) {
perror("ERROR: compression failed in snapshot_tree!");
return 0;
}
fwrite(compressed, sizeof(Bytef), compressedLen, fp);
fclose(fp);
return 1;
}