#include "iron_path.h" #include #include #include "iron_array.h" #include "iron_file.h" #include "iron_alloc.h" #include "iron_map.h" #include "iron_string.h" #ifdef IRON_LINUX bool path_is_protected_linux = false; #endif string_array_t *_path_mesh_formats = NULL; string_array_t *_path_texture_formats = NULL; string_array_t *_path_sound_formats = NULL; string_array_t *_path_text_formats = NULL; static string_array_t *_path_base_color_ext = NULL; static string_array_t *_path_opacity_ext = NULL; static string_array_t *_path_normal_map_ext = NULL; static string_array_t *_path_occlusion_ext = NULL; static string_array_t *_path_roughness_ext = NULL; static string_array_t *_path_metallic_ext = NULL; static string_array_t *_path_displacement_ext = NULL; string_array_t *path_mesh_formats(void) { if (_path_mesh_formats == NULL) { _path_mesh_formats = string_array_create(0); string_array_push(_path_mesh_formats, "obj"); string_array_push(_path_mesh_formats, "blend"); } return _path_mesh_formats; } string_array_t *path_texture_formats(void) { if (_path_texture_formats == NULL) { _path_texture_formats = string_array_create(0); string_array_push(_path_texture_formats, "jpg"); string_array_push(_path_texture_formats, "jpeg"); string_array_push(_path_texture_formats, "png"); string_array_push(_path_texture_formats, "tga"); string_array_push(_path_texture_formats, "bmp"); string_array_push(_path_texture_formats, "psd"); string_array_push(_path_texture_formats, "gif"); string_array_push(_path_texture_formats, "hdr"); string_array_push(_path_texture_formats, "k"); } return _path_texture_formats; } string_array_t *path_sound_formats(void) { if (_path_sound_formats == NULL) { _path_sound_formats = string_array_create(0); string_array_push(_path_sound_formats, "wav"); string_array_push(_path_sound_formats, "ogg"); } return _path_sound_formats; } string_array_t *path_text_formats(void) { if (_path_text_formats == NULL) { _path_text_formats = string_array_create(0); string_array_push(_path_text_formats, "txt"); string_array_push(_path_text_formats, "json"); } return _path_text_formats; } string_array_t *path_base_color_ext(void) { if (_path_base_color_ext == NULL) { _path_base_color_ext = string_array_create(0); string_array_push(_path_base_color_ext, "albedo"); string_array_push(_path_base_color_ext, "alb"); string_array_push(_path_base_color_ext, "basecol"); string_array_push(_path_base_color_ext, "basecolor"); string_array_push(_path_base_color_ext, "diffuse"); string_array_push(_path_base_color_ext, "diff"); string_array_push(_path_base_color_ext, "base"); string_array_push(_path_base_color_ext, "bc"); string_array_push(_path_base_color_ext, "d"); string_array_push(_path_base_color_ext, "color"); string_array_push(_path_base_color_ext, "col"); } return _path_base_color_ext; } string_array_t *path_opacity_ext(void) { if (_path_opacity_ext == NULL) { _path_opacity_ext = string_array_create(0); string_array_push(_path_opacity_ext, "opac"); string_array_push(_path_opacity_ext, "opacity"); string_array_push(_path_opacity_ext, "alpha"); } return _path_opacity_ext; } string_array_t *path_normal_map_ext(void) { if (_path_normal_map_ext == NULL) { _path_normal_map_ext = string_array_create(0); string_array_push(_path_normal_map_ext, "normal"); string_array_push(_path_normal_map_ext, "normals"); string_array_push(_path_normal_map_ext, "nor"); string_array_push(_path_normal_map_ext, "n"); string_array_push(_path_normal_map_ext, "nrm"); string_array_push(_path_normal_map_ext, "normalgl"); } return _path_normal_map_ext; } string_array_t *path_occlusion_ext(void) { if (_path_occlusion_ext == NULL) { _path_occlusion_ext = string_array_create(0); string_array_push(_path_occlusion_ext, "ao"); string_array_push(_path_occlusion_ext, "occlusion"); string_array_push(_path_occlusion_ext, "ambientOcclusion"); string_array_push(_path_occlusion_ext, "o"); string_array_push(_path_occlusion_ext, "occ"); } return _path_occlusion_ext; } string_array_t *path_roughness_ext(void) { if (_path_roughness_ext == NULL) { _path_roughness_ext = string_array_create(0); string_array_push(_path_roughness_ext, "roughness"); string_array_push(_path_roughness_ext, "rough"); string_array_push(_path_roughness_ext, "r"); string_array_push(_path_roughness_ext, "rgh"); } return _path_roughness_ext; } string_array_t *path_metallic_ext(void) { if (_path_metallic_ext == NULL) { _path_metallic_ext = string_array_create(0); string_array_push(_path_metallic_ext, "metallic"); string_array_push(_path_metallic_ext, "metal"); string_array_push(_path_metallic_ext, "metalness"); string_array_push(_path_metallic_ext, "m"); string_array_push(_path_metallic_ext, "met"); } return _path_metallic_ext; } string_array_t *path_displacement_ext(void) { if (_path_displacement_ext == NULL) { _path_displacement_ext = string_array_create(0); string_array_push(_path_displacement_ext, "displacement"); string_array_push(_path_displacement_ext, "height"); string_array_push(_path_displacement_ext, "h"); string_array_push(_path_displacement_ext, "disp"); } return _path_displacement_ext; } static bool has_ext(char *path, char *ext) { size_t len_path = strlen(path); size_t len_ext = strlen(ext); if (len_path < len_ext + 1 || path[len_path - len_ext - 1] != '.') { return false; } char *tail = path + len_path - len_ext; for (size_t i = 0; i < len_ext; ++i) { if (tolower((unsigned char)tail[i]) != tolower((unsigned char)ext[i])) { return false; } } return true; } static char *data_path(void) { #ifdef IRON_ANDROID return "data" PATH_SEP; #else return "." PATH_SEP "data" PATH_SEP; #endif } char *path_data(void) { return string("%s%s%s", iron_internal_files_location(), PATH_SEP, data_path()); } char *path_to_relative(char *from, char *to) { any_array_t *a = string_split(from, PATH_SEP); any_array_t *b = string_split(to, PATH_SEP); if (a->length > 0 && !path_is_folder(from)) { free(array_pop(a)); } while (a->length > 0 && b->length > 0) { char *a0 = a->buffer[0]; char *b0 = b->buffer[0]; if (string_equals(a0, b0)) { array_shift(a); array_shift(b); free(a0); free(b0); } else { break; } } buffer_t sb; string_buffer_init(&sb); for (uint32_t i = 0; i < a->length; ++i) { string_buffer_append(&sb, ".." PATH_SEP); } char *joined = string_array_join(b, PATH_SEP); string_buffer_append(&sb, joined); free(joined); char *p = string_copy(string_buffer_get(&sb)); string_buffer_free(&sb); string_split_free(a); string_split_free(b); return p; } char *path_normalize(char *path) { size_t path_len = strlen(path); char *trimmed = NULL; if (path_len > 0 && ends_with(path, PATH_SEP)) { trimmed = substring(path, 0, path_len - 1); path = trimmed; } any_array_t *ar = string_split(path, PATH_SEP); uint32_t i = 0; while (i < ar->length) { if (i > 0) { char *ar_i = ar->buffer[i]; char *ar_i_1 = ar->buffer[i - 1]; if (string_equals(ar_i, "..") && !string_equals(ar_i_1, "..")) { free(ar_i); free(ar_i_1); array_splice(ar, i - 1, 2); i--; } else { i++; } } else { i++; } } char *r = string_array_join(ar, PATH_SEP); string_split_free(ar); free(trimmed); return r; } char *path_base_dir(char *path) { int32_t last = string_last_index_of(path, PATH_SEP); return substring(path, 0, last + 1); } char *path_base_name(char *path) { int32_t last_sep = string_last_index_of(path, PATH_SEP); int32_t last_dot = string_last_index_of(path, "."); return substring(path, last_sep + 1, last_dot); } static bool path_has_format(char *path, string_array_t *formats) { for (uint32_t i = 0; i < formats->length; ++i) { if (has_ext(path, formats->buffer[i])) { return true; } } return false; } bool path_is_mesh(char *path) { return path_has_format(path, path_mesh_formats()); } bool path_is_texture(char *path) { return path_has_format(path, path_texture_formats()); } bool path_is_sound(char *path) { return path_has_format(path, path_sound_formats()); } bool path_is_font(char *path) { return has_ext(path, "ttf") || has_ext(path, "ttc") || has_ext(path, "otf"); } bool path_is_project(char *path) { return has_ext(path, "arm"); } bool path_is_plugin(char *path) { return has_ext(path, "c"); } bool path_is_json(char *path) { return has_ext(path, "json"); } bool path_is_text(char *path) { return path_has_format(path, path_text_formats()); } bool path_is_ext_format(char *path) { return has_ext(path, "stl") || has_ext(path, "svg"); } bool path_is_lut(char *path) { return has_ext(path, "cube"); } bool path_is_known(char *path) { return path_is_mesh(path) || path_is_texture(path) || path_is_sound(path) || path_is_font(path) || path_is_project(path) || path_is_plugin(path) || path_is_text(path) || path_is_ext_format(path) || path_is_lut(path); } static char tag_char(char c) { return c == '-' ? '_' : c; } static bool ends_with_tag(char *p, char *tag) { size_t len_p = strlen(p); size_t len_tag = strlen(tag); if (len_p < len_tag + 1) { return false; } char *tail = p + len_p - len_tag; if (tag_char(tail[-1]) != '_') { return false; } for (size_t i = 0; i < len_tag; ++i) { if (tag_char(tail[i]) != tag[i]) { return false; } } return true; } static bool contains_tag(char *p, char *tag) { size_t len_tag = strlen(tag); for (char *s = p; *s != '\0'; ++s) { if (tag_char(*s) != '_') { continue; } size_t i = 0; while (i < len_tag && tag_char(s[1 + i]) == tag[i]) { ++i; } if (i == len_tag && tag_char(s[1 + len_tag]) == '_') { return true; } } return false; } bool path_check_ext(char *p, string_array_t *exts) { for (uint32_t i = 0; i < exts->length; ++i) { char *ext = exts->buffer[i]; if (ends_with_tag(p, ext)) { return true; } if (contains_tag(p, ext) && !ends_with_tag(p, "preview") && !ends_with_tag(p, "icon")) { return true; } } return false; } bool path_is_base_color_tex(char *p) { return path_check_ext(p, path_base_color_ext()); } bool path_is_opacity_tex(char *p) { return path_check_ext(p, path_opacity_ext()); } bool path_is_normal_map_tex(char *p) { return path_check_ext(p, path_normal_map_ext()); } bool path_is_occlusion_tex(char *p) { return path_check_ext(p, path_occlusion_ext()); } bool path_is_roughness_tex(char *p) { return path_check_ext(p, path_roughness_ext()); } bool path_is_metallic_tex(char *p) { return path_check_ext(p, path_metallic_ext()); } bool path_is_displacement_tex(char *p) { return path_check_ext(p, path_displacement_ext()); } bool path_is_folder(char *p) { char *last = p; for (char *s = p; *s != '\0'; ++s) { if (*s == '/' || *s == '\\') { last = s + 1; } } return strchr(last, '.') == NULL; } bool path_is_protected(void) { #ifdef IRON_WINDOWS return string_index_of(iron_internal_files_location(), "Program Files") >= 0; #elif defined(IRON_LINUX) return path_is_protected_linux; #elif defined(IRON_ANDROID) return true; #elif defined(IRON_IOS) return true; #else return false; #endif } char *path_join(char *a, char *b) { if (ends_with(a, PATH_SEP)) { return string("%s%s", a, b); } return string("%s" PATH_SEP "%s", a, b); }