refactor(utilities)!: renamed PathBuffer to StringBuffer

This commit is contained in:
lisk77 2025-08-28 03:48:44 +02:00
parent 983c6d4ca4
commit 52e740fab0
2 changed files with 185 additions and 58 deletions

View file

@ -1,18 +1,19 @@
#ifndef UTILITIES_H #ifndef UTILITIES_H
#define UTILITIES_H #define UTILITIES_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h> #include <errno.h>
#include <dirent.h> #include <dirent.h>
#include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include "file.h" #include "file.h"
#include "action_list.h" #include "action_list.h"
#define IS_ALPHA(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
#define IS_DIGIT(c) (c >= '0' && c <= '9')
#define IS_ALNUM(c) (IS_ALPHA(c) || IS_DIGIT(c))
#define IS_PUNCT(c) ((c >= 33 && c <= 47) || (c >= 58 && c <= 64) || (c >= 91 && c <= 96) || (c >= 123 && c <= 126))
#define RESET "\033[0m" #define RESET "\033[0m"
#define RED_BG "\033[41m" #define RED_BG "\033[41m"
#define GREEN_BG "\033[42m" #define GREEN_BG "\033[42m"
@ -35,21 +36,31 @@ typedef struct {
size_t item_size; size_t item_size;
} List; } List;
typedef List PathBuffer; typedef List StringBuffer;
typedef List FileInfoBuffer;
List* list_new(size_t); List* list_new(size_t);
int list_push(List*, void*); int list_push(List*, void*);
PathType get_path_type(const char*); void list_free(List*);
PathBuffer* path_buffer_new(); void* binary_search(const void*, const void*, size_t, size_t, int (*compare)(const void*, const void*));
void path_buffer_push(PathBuffer*, char*); void* list_binary_search(List*, const void*, int (*compare)(const void*, const void*));
void path_buffer_sort(PathBuffer*); StringBuffer* string_buffer_new();
void path_buffer_free(PathBuffer*); int string_buffer_push(StringBuffer*, char*);
void string_buffer_sort(StringBuffer*);
char* string_buffer_search(StringBuffer*, char*);
FileInfoBuffer* file_info_buffer_new();
int file_info_buffer_push(FileInfoBuffer*, FileInfo);
void file_info_buffer_free(FileInfoBuffer*);
void file_info_buffer_sort(FileInfoBuffer*);
FileInfo* file_info_buffer_search(FileInfoBuffer*, const char*);
char* find_root(char*); char* find_root(char*);
void walk(char*, char*, char*, PathBuffer*, int, char*); void walk(char*, char*, char*, FileInfoBuffer*, int, char*);
char* get_repo_path(char*, char*); char* get_repo_path(char*, char*);
int is_in_repo(char*, char*); int is_in_repo(char*, char*);
void visualize_diff(File*, File*, ActionList*); void visualize_diff(File*, File*, ActionList*);
void cut_path(char* base, char* path); int cut_path(char*, char*);
void combine_path(char* base, char* path); void combine_path(char*, char*);
PathType get_path_type(const char*);
char* get_file_content(char*);
#endif // UTILITIES_H #endif // UTILITIES_H

View file

@ -32,45 +32,7 @@ int list_push(List* list, void* item) {
return 1; return 1;
} }
PathType get_path_type(const char* path) { void list_free(List* buffer) {
struct stat st;
int rc = stat(path, &st);
if (rc != 0) {
return (errno == ENOENT) ? PT_NOEXIST : PT_ERROR;
}
if (S_ISREG(st.st_mode)) return PT_FILE;
if (S_ISDIR(st.st_mode)) return PT_DIR;
return PT_OTHER;
}
PathBuffer* path_buffer_new() {
return list_new(sizeof(char*));
}
void path_buffer_push(PathBuffer* buffer, char* path) {
char* path_copy = strdup(path);
if (!path_copy) {
perror("ERROR: strdup failed in add_path");
return;
}
list_push(buffer, &path_copy);
}
int compare_paths(const void* a, const void* b) {
const char* s1 = *(const char**)a;
const char* s2 = *(const char**)b;
return strcmp(s1,s2);
}
void path_buffer_sort(PathBuffer* buffer) {
if (!buffer || buffer->len <= 1) {
return;
}
qsort(buffer->items, buffer->len, sizeof(char*), compare_paths);
}
void path_buffer_free(PathBuffer* buffer) {
if (buffer) { if (buffer) {
for (size_t i = 0; i < buffer->len; i++) { for (size_t i = 0; i < buffer->len; i++) {
free(buffer->items[i]); free(buffer->items[i]);
@ -80,6 +42,114 @@ void path_buffer_free(PathBuffer* 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*));
}
int string_buffer_push(StringBuffer* buffer, char* path) {
char* path_copy = strdup(path);
if (!path_copy) {
perror("ERROR: strdup failed in string_buffer_push!");
return 0;
}
return list_push(buffer, &path_copy);
}
int compare_strings(const void* a, const void* b) {
const char* s1 = *(const char**)a;
const char* s2 = *(const char**)b;
return strcmp(s1,s2);
}
void string_buffer_sort(StringBuffer* buffer) {
if (!buffer || buffer->len <= 1) {
return;
}
qsort(buffer->items, buffer->len, sizeof(char*), compare_strings);
}
char* string_buffer_search(StringBuffer* buffer, char* path) {
if (!buffer || !path) return NULL;
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) { static int is_dot_or_dotdot(const char* s) {
return (s[0] == '.' && (s[1] == '\0' || (s[1] == '.' && s[2] == '\0'))); return (s[0] == '.' && (s[1] == '\0' || (s[1] == '.' && s[2] == '\0')));
} }
@ -196,7 +266,7 @@ char* find_root(char* relative) {
return NULL; return NULL;
} }
void walk(char* base, char* base_rel, char* rel, PathBuffer* paths, int full_repo_path, char* repo_root_path) { void walk(char* base, char* base_rel, char* rel, FileInfoBuffer* file_infos, int full_repo_path, char* repo_root_path) {
DIR* dir = opendir(base); DIR* dir = opendir(base);
if (!dir) { if (!dir) {
return; return;
@ -235,7 +305,7 @@ void walk(char* base, char* base_rel, char* rel, PathBuffer* paths, int full_rep
exit(1); exit(1);
} }
walk(child_full, base_rel, new_rel, paths, full_repo_path, repo_root_path); walk(child_full, base_rel, new_rel, file_infos, full_repo_path, repo_root_path);
free(new_rel); free(new_rel);
} else { } else {
char* relative_path; char* relative_path;
@ -254,12 +324,14 @@ void walk(char* base, char* base_rel, char* rel, PathBuffer* paths, int full_rep
if (!full_repo_path) { if (!full_repo_path) {
normalize_path(relative_path, base_rel); normalize_path(relative_path, base_rel);
path_buffer_push(paths, relative_path); FileInfo info = (FileInfo){.mode=st.st_mode, .name=strdup(relative_path)};
file_info_buffer_push(file_infos, info);
free(relative_path); free(relative_path);
} }
else { else {
char* repo_path = get_repo_path(repo_root_path, relative_path); char* repo_path = get_repo_path(repo_root_path, relative_path);
path_buffer_push(paths, repo_path); FileInfo info = (FileInfo){.mode=st.st_mode, .name=strdup(repo_path)};
file_info_buffer_push(file_infos, info);
free(relative_path); free(relative_path);
free(repo_path); free(repo_path);
} }
@ -278,6 +350,18 @@ char* get_repo_path(char* repo_root_path, char* path) {
return real_path; return real_path;
} }
int is_in_repo(char* repo_root_path, char* path) {
size_t root_len = strlen(repo_root_path);
char* path_base = strdup(path);
path_base[root_len] = '\0';
int cmp = strcmp(path_base, repo_root_path);
free(path_base);
return cmp;
}
void visualize_diff(File* old_version, File* new_version, ActionList* actions) { void visualize_diff(File* old_version, File* new_version, ActionList* actions) {
int* deleted_lines = calloc(old_version->lines, sizeof(int)); int* deleted_lines = calloc(old_version->lines, sizeof(int));
int* inserted_lines = calloc(new_version->lines, sizeof(int)); int* inserted_lines = calloc(new_version->lines, sizeof(int));
@ -333,9 +417,9 @@ void visualize_diff(File* old_version, File* new_version, ActionList* actions) {
// In this function we assume that base is a prefix of path // In this function we assume that base is a prefix of path
// Thus we just need the length of the base to jump ahead in the path // Thus we just need the length of the base to jump ahead in the path
void cut_path(char* base, char* path) { int cut_path(char* base, char* path) {
size_t base_len = strlen(base); size_t base_len = strlen(base);
if (strlen(path) < base_len) perror("ERROR: the provided path is smaller than the base path!"); if (strlen(path) < base_len) return 0;
int add = strlen(path) != base_len ? 1 : 0; int add = strlen(path) != base_len ? 1 : 0;
strcpy(path, path+base_len+add); strcpy(path, path+base_len+add);
@ -345,6 +429,8 @@ void cut_path(char* base, char* path) {
snprintf(tmp, sizeof(tmp), "%s/", path); snprintf(tmp, sizeof(tmp), "%s/", path);
strcpy(path, tmp); strcpy(path, tmp);
} }
return 1;
} }
// In this function we assume that the end of the base and the beginning of the // In this function we assume that the end of the base and the beginning of the
@ -365,4 +451,34 @@ void combine_path(char* base, char* path) {
strcpy(path, tmp); strcpy(path, tmp);
} }
PathType get_path_type(const char* path) {
struct stat st;
int rc = stat(path, &st);
if (rc != 0) {
return (errno == ENOENT) ? PT_NOEXIST : PT_ERROR;
}
if (S_ISREG(st.st_mode)) return PT_FILE;
if (S_ISDIR(st.st_mode)) return PT_DIR;
return PT_OTHER;
}
char* get_file_content(char* path) {
if (!path) return NULL;
FILE* file = fopen(path, "rb");
if (!file) { perror("ERROR: could not open file in get_file_content!"); return NULL; }
if (fseek(file, 0, SEEK_END) != 0) { fclose(file); return NULL; }
long file_size = ftell(file);
if (file_size < 0) { perror("ERROR: file size is negative in get_file_content!"); fclose(file); return NULL; }
if (fseek(file, 0, SEEK_SET) != 0) { fclose(file); return NULL; }
size_t n = (size_t)file_size;
char* buf = (char*)calloc(n + 1, 1);
if (!buf) { fclose(file); return NULL; }
size_t got = fread(buf, 1, n, file);
fclose(file);
buf[got] = '\0';
return buf;
}