path.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. #include "path.h"
  2. #include <stddef.h>
  3. void path_extract_filename_no_ext(const char* path, FuriString* filename) {
  4. furi_string_set(filename, path);
  5. size_t start_position = furi_string_search_rchar(filename, '/');
  6. size_t end_position = furi_string_search_rchar(filename, '.');
  7. if(start_position == FURI_STRING_FAILURE) {
  8. start_position = 0;
  9. } else {
  10. start_position += 1;
  11. }
  12. if(end_position == FURI_STRING_FAILURE) {
  13. end_position = furi_string_size(filename);
  14. }
  15. furi_string_mid(filename, start_position, end_position - start_position);
  16. }
  17. void path_extract_filename(FuriString* path, FuriString* name, bool trim_ext) {
  18. size_t filename_start = furi_string_search_rchar(path, '/');
  19. if(filename_start > 0) {
  20. filename_start++;
  21. furi_string_set_n(name, path, filename_start, furi_string_size(path) - filename_start);
  22. }
  23. if(trim_ext) {
  24. size_t dot = furi_string_search_rchar(name, '.');
  25. if(dot > 0) {
  26. furi_string_left(name, dot);
  27. }
  28. }
  29. }
  30. void path_extract_extension(FuriString* path, char* ext, size_t ext_len_max) {
  31. size_t dot = furi_string_search_rchar(path, '.');
  32. size_t filename_start = furi_string_search_rchar(path, '/');
  33. if((dot != FURI_STRING_FAILURE) && (filename_start < dot)) {
  34. strlcpy(ext, &(furi_string_get_cstr(path))[dot], ext_len_max);
  35. }
  36. }
  37. static inline void path_cleanup(FuriString* path) {
  38. furi_string_trim(path);
  39. while(furi_string_end_with(path, "/")) {
  40. furi_string_left(path, furi_string_size(path) - 1);
  41. }
  42. }
  43. void path_extract_basename(const char* path, FuriString* basename) {
  44. furi_string_set(basename, path);
  45. path_cleanup(basename);
  46. size_t pos = furi_string_search_rchar(basename, '/');
  47. if(pos != FURI_STRING_FAILURE) {
  48. furi_string_right(basename, pos + 1);
  49. }
  50. }
  51. void path_extract_dirname(const char* path, FuriString* dirname) {
  52. furi_string_set(dirname, path);
  53. path_cleanup(dirname);
  54. size_t pos = furi_string_search_rchar(dirname, '/');
  55. if(pos != FURI_STRING_FAILURE) {
  56. furi_string_left(dirname, pos);
  57. }
  58. }
  59. void path_append(FuriString* path, const char* suffix) {
  60. path_cleanup(path);
  61. FuriString* suffix_str;
  62. suffix_str = furi_string_alloc_set(suffix);
  63. furi_string_trim(suffix_str);
  64. furi_string_trim(suffix_str, "/");
  65. furi_string_cat_printf(path, "/%s", furi_string_get_cstr(suffix_str));
  66. furi_string_free(suffix_str);
  67. }
  68. void path_concat(const char* path, const char* suffix, FuriString* out_path) {
  69. furi_string_set(out_path, path);
  70. path_append(out_path, suffix);
  71. }
  72. bool path_contains_only_ascii(const char* path) {
  73. if(!path) {
  74. return false;
  75. }
  76. const char* name_pos = strrchr(path, '/');
  77. if(name_pos == NULL) {
  78. name_pos = path;
  79. } else {
  80. name_pos++;
  81. }
  82. for(; *name_pos; ++name_pos) {
  83. const char c = *name_pos;
  84. // Regular ASCII characters from 0x20 to 0x7e
  85. const bool is_out_of_range = (c < ' ') || (c > '~');
  86. // Cross-platform forbidden character set
  87. const bool is_forbidden = strchr("\\<>*|\":?", c);
  88. if(is_out_of_range || is_forbidden) {
  89. return false;
  90. }
  91. }
  92. return true;
  93. }