refactor(utilities)!: renamed PathBuffer to StringBuffer
This commit is contained in:
parent
983c6d4ca4
commit
52e740fab0
2 changed files with 185 additions and 58 deletions
|
|
@ -1,18 +1,19 @@
|
|||
#ifndef UTILITIES_H
|
||||
#define UTILITIES_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "file.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 RED_BG "\033[41m"
|
||||
#define GREEN_BG "\033[42m"
|
||||
|
|
@ -35,21 +36,31 @@ typedef struct {
|
|||
size_t item_size;
|
||||
} List;
|
||||
|
||||
typedef List PathBuffer;
|
||||
typedef List StringBuffer;
|
||||
typedef List FileInfoBuffer;
|
||||
|
||||
List* list_new(size_t);
|
||||
int list_push(List*, void*);
|
||||
PathType get_path_type(const char*);
|
||||
PathBuffer* path_buffer_new();
|
||||
void path_buffer_push(PathBuffer*, char*);
|
||||
void path_buffer_sort(PathBuffer*);
|
||||
void path_buffer_free(PathBuffer*);
|
||||
void list_free(List*);
|
||||
void* binary_search(const void*, const void*, size_t, size_t, int (*compare)(const void*, const void*));
|
||||
void* list_binary_search(List*, const void*, int (*compare)(const void*, const void*));
|
||||
StringBuffer* string_buffer_new();
|
||||
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*);
|
||||
void walk(char*, char*, char*, PathBuffer*, int, char*);
|
||||
void walk(char*, char*, char*, FileInfoBuffer*, int, char*);
|
||||
char* get_repo_path(char*, char*);
|
||||
int is_in_repo(char*, char*);
|
||||
void visualize_diff(File*, File*, ActionList*);
|
||||
void cut_path(char* base, char* path);
|
||||
void combine_path(char* base, char* path);
|
||||
int cut_path(char*, char*);
|
||||
void combine_path(char*, char*);
|
||||
PathType get_path_type(const char*);
|
||||
char* get_file_content(char*);
|
||||
|
||||
#endif // UTILITIES_H
|
||||
|
|
|
|||
206
src/utilities.c
206
src/utilities.c
|
|
@ -32,45 +32,7 @@ int list_push(List* list, void* item) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
void list_free(List* buffer) {
|
||||
if (buffer) {
|
||||
for (size_t i = 0; i < buffer->len; 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) {
|
||||
return (s[0] == '.' && (s[1] == '\0' || (s[1] == '.' && s[2] == '\0')));
|
||||
}
|
||||
|
|
@ -196,7 +266,7 @@ char* find_root(char* relative) {
|
|||
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);
|
||||
if (!dir) {
|
||||
return;
|
||||
|
|
@ -235,7 +305,7 @@ void walk(char* base, char* base_rel, char* rel, PathBuffer* paths, int full_rep
|
|||
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);
|
||||
} else {
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
else {
|
||||
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(repo_path);
|
||||
}
|
||||
|
|
@ -278,6 +350,18 @@ char* get_repo_path(char* repo_root_path, char* 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) {
|
||||
int* deleted_lines = calloc(old_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
|
||||
// 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);
|
||||
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;
|
||||
|
||||
strcpy(path, path+base_len+add);
|
||||
|
|
@ -345,6 +429,8 @@ void cut_path(char* base, char* path) {
|
|||
snprintf(tmp, sizeof(tmp), "%s/", path);
|
||||
strcpy(path, tmp);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue