Replace char * with Str8 in cpath dirup
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
#include "cpath.h"
|
||||
#include "aliases.h"
|
||||
#include "mem_allocator.h"
|
||||
#include "mem_arena_allocator.h"
|
||||
#include "misc_utils.h"
|
||||
#include "str8.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
@@ -59,56 +62,76 @@ u32 wapp_cpath_join_path(Str8 *dst, const Str8List *parts) {
|
||||
return CPATH_JOIN_SUCCESS;
|
||||
}
|
||||
|
||||
void dirup(char *dst, u64 levels, const char *path) {
|
||||
Str8 *dirup(const Allocator *allocator, Str8RO *path, u64 levels) {
|
||||
Str8 *output = NULL;
|
||||
if (!allocator || !path) {
|
||||
goto RETURN_DIRUP;
|
||||
}
|
||||
|
||||
bool absolute = wapp_str8_get(path, 0) == PATH_SEP;
|
||||
Str8 separator = wapp_str8_buf(4);
|
||||
wapp_str8_push_back(&separator, PATH_SEP);
|
||||
|
||||
if (path->size == 0) {
|
||||
output = wapp_str8_alloc_buf(allocator, 16);
|
||||
if (!output) {
|
||||
goto RETURN_DIRUP;
|
||||
}
|
||||
|
||||
wapp_str8_push_back(output, absolute ? PATH_SEP : '.');
|
||||
goto RETURN_DIRUP;
|
||||
}
|
||||
|
||||
if (levels < 1) {
|
||||
return;
|
||||
output = wapp_str8_alloc_str8(allocator, path);
|
||||
goto RETURN_DIRUP;
|
||||
}
|
||||
|
||||
u64 copy_count = 0;
|
||||
u64 sep_count = 0;
|
||||
|
||||
u64 full_length;
|
||||
u64 length;
|
||||
length = full_length = strlen(path);
|
||||
|
||||
if (length > 1 && path[length - 1] == PATH_SEP) {
|
||||
--length;
|
||||
Allocator tmp_arena = wapp_mem_arena_allocator_init(MB(8));
|
||||
if (wapp_mem_allocator_invalid(&tmp_arena)) {
|
||||
goto RETURN_DIRUP;
|
||||
}
|
||||
|
||||
for (i64 i = length - 1; i >= 0; --i) {
|
||||
if (path[i] == PATH_SEP) {
|
||||
++sep_count;
|
||||
copy_count = i + 1;
|
||||
Str8List *parts = wapp_str8_split(&tmp_arena, path, &separator);
|
||||
if (!parts) {
|
||||
goto RETURN_DIRUP;
|
||||
}
|
||||
|
||||
if (sep_count == levels) {
|
||||
break;
|
||||
if (levels >= parts->node_count) {
|
||||
output = wapp_str8_alloc_buf(allocator, 16);
|
||||
if (!output) {
|
||||
goto LIST_CLEANUP_DIRUP;
|
||||
}
|
||||
|
||||
wapp_str8_push_back(output, absolute ? PATH_SEP : '.');
|
||||
} else {
|
||||
for (u64 i = 0; i < levels; ++i) {
|
||||
wapp_str8_list_pop_back(parts);
|
||||
}
|
||||
|
||||
u64 alignment = sizeof(void *) * 2;
|
||||
u64 alloc_size = parts->total_size + parts->node_count * separator.size;
|
||||
u64 modulo = alloc_size & (alignment - 1);
|
||||
alloc_size += alignment - modulo;
|
||||
|
||||
output = wapp_str8_alloc_buf(allocator, alloc_size);
|
||||
if (output) {
|
||||
if (absolute) {
|
||||
wapp_str8_push_back(output, PATH_SEP);
|
||||
}
|
||||
|
||||
Str8 *joined = wapp_str8_join(&tmp_arena, parts, &separator);
|
||||
if (joined) {
|
||||
wapp_str8_concat_capped(output, joined);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char tmp[256];
|
||||
snprintf(tmp, 2, "%c", PATH_SEP);
|
||||
// NOTE (Abdelrahman): Conditions stored in variables to silence MSVC warning C5045
|
||||
bool insufficient_levels = sep_count < levels;
|
||||
bool path_to_copy_is_separator = strncmp(path, tmp, copy_count) != 0;
|
||||
if (insufficient_levels && path_to_copy_is_separator) {
|
||||
copy_count = 0;
|
||||
}
|
||||
LIST_CLEANUP_DIRUP:
|
||||
wapp_mem_arena_allocator_destroy(&tmp_arena);
|
||||
|
||||
if (dst == path) {
|
||||
memset(&dst[copy_count], 0, full_length - copy_count);
|
||||
} else {
|
||||
u64 dst_length = strlen(dst);
|
||||
memset(dst, 0, dst_length);
|
||||
strncpy(dst, path, copy_count);
|
||||
}
|
||||
|
||||
u64 final_length = strlen(dst);
|
||||
if (final_length > 1) {
|
||||
dst[final_length - 1] = '\0';
|
||||
} else if (final_length == 0) {
|
||||
dst[0] = '.';
|
||||
}
|
||||
RETURN_DIRUP:
|
||||
return output;
|
||||
}
|
||||
|
||||
void join_root_and_leaf(const char *root, const char *leaf, char *dst) {
|
||||
|
@@ -2,6 +2,7 @@
|
||||
#define CPATH_H
|
||||
|
||||
#include "aliases.h"
|
||||
#include "mem_allocator.h"
|
||||
#include "platform.h"
|
||||
#include "str8.h"
|
||||
|
||||
@@ -17,8 +18,8 @@ BEGIN_C_LINKAGE
|
||||
#error "Unrecognised platform"
|
||||
#endif
|
||||
|
||||
#define wapp_cpath_dirname(DST, PATH) dirup(DST, 1, PATH)
|
||||
#define wapp_cpath_dirup(DST, COUNT, PATH) dirup(DST, COUNT, PATH)
|
||||
#define wapp_cpath_dirname(ALLOCATOR, PATH) dirup(ALLOCATOR, PATH, 1)
|
||||
#define wapp_cpath_dirup(ALLOCATOR, PATH, COUNT) dirup(ALLOCATOR, PATH, COUNT)
|
||||
|
||||
enum {
|
||||
CPATH_JOIN_SUCCESS = 0,
|
||||
@@ -28,7 +29,7 @@ enum {
|
||||
};
|
||||
|
||||
u32 wapp_cpath_join_path(Str8 *dst, const Str8List *parts);
|
||||
void dirup(char *dst, u64 levels, const char *path);
|
||||
Str8 *dirup(const Allocator *allocator, Str8RO *path, u64 levels);
|
||||
|
||||
#ifdef __cplusplus
|
||||
END_C_LINKAGE
|
||||
|
Reference in New Issue
Block a user