#include #include #include "array.h" #include "prompt_utils.h" char const *relative_path(char const *const from_dir, char const *const to_dir) { // easiest cases first { if (strcmp(from_dir, to_dir) == 0) { char *return_value = malloc(2); strcpy(return_value, "."); return return_value; } } { if (strcmp("/", from_dir) == 0) { char *return_value = malloc(strlen(to_dir) + 2); return_value[0] = '.'; memcpy(return_value + 1, to_dir, strlen(to_dir) + 1); return return_value; } } // splitting path into pieces so we can do strcmp on each of them size_t const *const from_dir_indices = get_separator_indices(from_dir, '/'); size_t const *const to_dir_indices = get_separator_indices(to_dir, '/'); size_t from_dir_len = arrayLen(from_dir_indices); size_t to_dir_len = arrayLen(to_dir_indices); // finding the longest common substring size_t array_len = from_dir_len < to_dir_len ? from_dir_len : to_dir_len; size_t i = 0; size_t common_position = 0; for (; i < array_len - 1; ++i) { if (from_dir_indices[i + 1] != to_dir_indices[i + 1]) { break; } size_t index = from_dir_indices[i]; size_t count = from_dir_indices[i + 1] - from_dir_indices[i]; if (strncmp(from_dir + index, to_dir + index, count) != 0) { break; } common_position = from_dir_indices[i + 1]; } size_t levels_up = from_dir_len - i - 1; char *return_value; if (levels_up == 0) { // equal dirs for whole length of path and not equal => subdir size_t length = strlen(to_dir + common_position) + strlen("./") + 1; return_value = malloc(length * sizeof(char)); strcpy(return_value, "."); strcat(return_value, to_dir + common_position); } else { char const *const go_up = "/.."; size_t length = strlen(to_dir + common_position) + strlen("..") + strlen(go_up) * (levels_up - 1) + 1; return_value = malloc(length * sizeof(char)); strcpy(return_value, ".."); for (size_t j = 0; j < levels_up - 1; ++j) { strcat(return_value, go_up); } if (strcmp("/", to_dir) != 0) { strcat(return_value, to_dir + common_position); } } arrayRelease((void *)from_dir_indices); arrayRelease((void *)to_dir_indices); return return_value; } size_t *get_separator_indices(char const *const text, char seperator) { size_t *indices; arrayInit(indices); char const *current = text; if (strchr(current, seperator) == NULL) { arrayRelease(indices); return NULL; } while ((current = strchr(current, seperator)) != NULL) { arrayPush(indices) = (size_t) (current - text); ++current; } arrayPush(indices) = strlen(text); return indices; }