path_ops.c (4078B)
1// This is free and unencumbered software released into the public domain. 2// For more information, please refer to <https://unlicense.org> 3// bbbbbr 2020 4 5#include <stdio.h> 6#include <string.h> 7#include <stdbool.h> 8#include "common.h" 9#include "path_ops.h" 10 11const char kExtensionSeparator = '.'; 12const char kPathSeparator = 13 14#ifdef _WIN32 15 #ifndef _WIN32 16 #define __WIN32__ 17 #endif 18#endif 19 20#ifdef __WIN32__ 21 '\\'; 22#else 23 '/'; 24#endif 25 26const char kPathSeparator_unix = '/'; 27 28 29void filename_replace_extension(char * filename, char * new_ext, size_t maxlen) { 30 31 // Use a temp work string in case out and in filename are the same pointer 32 char temp[MAX_FILE_STR]; 33 char ext_sep[2] = {'\0'}; // default to empty string 34 35 // Add leading . to path if needed 36 if (new_ext[0] != kExtensionSeparator) { 37 ext_sep[0] = kExtensionSeparator; 38 ext_sep[1] = '\0'; 39 } 40 41 // Strip extension from filename, append new extension 42 filename_remove_extension(filename); 43 snprintf(temp, maxlen, "%s%s%s", filename, ext_sep, new_ext); 44 snprintf(filename, maxlen, "%s", temp); 45} 46 47 48void filename_replace_path(char * filename, char * new_path, size_t maxlen) { 49 50 // Use a temp work string in case out and in filename are the same pointer 51 char temp[MAX_FILE_STR]; 52 char path_sep[2] = {'\0'}; // default to empty string 53 54 // Add trailing slash to path if needed (Windows needs both for when running under linix like env) 55#ifdef __WIN32__ 56 if (((new_path[(strlen(new_path)-1)] != kPathSeparator)) && 57 ((new_path[(strlen(new_path)-1)] != kPathSeparator_unix))) 58#else 59 if ((new_path[(strlen(new_path)-1)] != kPathSeparator)) 60#endif 61 { 62 path_sep[0] = kPathSeparator; 63 path_sep[1] = '\0'; 64 } 65 66 // Strip path from path+filename, pre-pend new path 67 snprintf(temp, maxlen, "%s%s%s", new_path, path_sep, get_filename_from_path(filename)); 68 snprintf(filename, maxlen, "%s", temp); 69} 70 71 72const char * get_filename_from_path(const char * path) 73{ 74 size_t i; 75 76 // Returns string starting at last occurrance of path separator char 77 for(i = strlen(path) - 1; i; i--) { 78 79 // Add trailing slash to path if needed (Windows needs both for when running under linix like env) 80 #ifdef __WIN32__ 81 if ((path[i] == kPathSeparator) || (path[i] == kPathSeparator_unix)) 82 #else 83 if (path[i] == kPathSeparator) 84 #endif 85 { 86 return &path[i+1]; 87 } 88 } 89 return path; 90} 91 92 93void filename_remove_extension(char * path) 94{ 95 char * last_ext; 96 char * last_slash; 97 98 // Find the last path separator if present 99 // Starting from here ensures that no path ".." characters 100 // get mistaken as extension delimiters. 101 last_slash = strrchr (path, kExtensionSeparator); 102 if (!last_slash) 103 last_slash = path; 104 105 // Then check to see if there is an extension (starting with the last occurance of '.') 106 // (tries to remove *all* trailing extensions backward until the last slash) 107 last_ext = strrchr (last_slash, kExtensionSeparator); 108 while (last_ext) { 109 if (last_ext != NULL) { 110 // If an extension is found then overwrite it with a string terminator 111 *last_ext = '\0'; 112 } 113 last_ext = strrchr (last_slash, kExtensionSeparator); 114 } 115} 116 117 118bool get_path_without_filename(const char * path, char * path_only, uint32_t str_max) 119{ 120 size_t i; 121 122 if (strlen(path) + 1 > str_max) 123 return false; 124 125 for(i = strlen(path) - 1; i; i--) { 126 127 // Add trailing slash to path if needed (Windows needs both for when running under linix like env) 128 #ifdef __WIN32__ 129 if ((path[i] == kPathSeparator) || (path[i] == kPathSeparator_unix)) 130 #else 131 if (path[i] == kPathSeparator) 132 #endif 133 { 134 memcpy(path_only, path, i+1 ); 135 path_only[i+1] = '\0'; 136 return true; 137 } 138 } 139 140 // memcpy(path_only, path, strlen(path)); 141 // No separater found, so no path 142 path_only[0] = '\0'; 143 return true; 144} 145