#define WIN32_LEAN_AND_MEAN #include #include #include #include #include #include #include struct fx_path { struct fx_dsref base; struct fx_string *pathstr; }; static void path_release(struct fx_dsref *obj); static void path_to_string(struct fx_dsref *obj, struct fx_stringstream *out); static struct fx_dsref_type path_type = { .t_name = "corelib::path", .t_flags = FX_DSREF_FUNDAMENTAL, .t_id = FX_DSREF_TYPE_PATH, .t_instance_size = sizeof(struct fx_path), .t_release = path_release, .t_to_string = path_to_string, }; struct fx_path *fx_path_create() { struct fx_path *path = (struct fx_path *)fx_dsref_type_instantiate(&path_type); if (!path) { return NULL; } path->pathstr = fx_string_create(); if (!path->pathstr) { fx_path_release(path); return NULL; } return path; } struct fx_path *fx_path_create_root() { const char *system_drive = getenv("SystemDrive"); if (!system_drive) { /* take an educated guess. */ system_drive = "C:"; } size_t system_drive_len = strlen(system_drive); struct fx_path *path = fx_path_create(); if (!path) { return NULL; } fx_string_append_cstr(path->pathstr, system_drive); if (system_drive[system_drive_len - 1] != '\\') { fx_string_append_cstr(path->pathstr, "\\"); } return path; } struct fx_path *fx_path_create_cwd() { DWORD cwd_len = GetCurrentDirectory(0, NULL); if (cwd_len == 0) { return NULL; } TCHAR *cwd_buf = malloc(cwd_len + 1); if (!cwd_buf) { return NULL; } cwd_len = GetCurrentDirectory(cwd_len + 1, cwd_buf); if (cwd_len == 0) { free(cwd_buf); return NULL; } struct fx_path *path = fx_path_create(); if (!path) { return NULL; } for (DWORD i = 0; i < cwd_len; i++) { TCHAR c = cwd_buf[i]; char s[] = {(c >= 128 ? '?' : (char)c), 0}; fx_string_append_cstr(path->pathstr, s); } free(cwd_buf); return path; } struct fx_path *fx_path_create_from_cstr(const char *cstr) { struct fx_path *path = fx_path_create(); if (!path) { return NULL; } char prev = 0; for (size_t i = 0; cstr[i]; i++) { char c = cstr[i]; if (c == '\\') { c = '/'; } if (prev == '/' && c == '/') { continue; } char s[] = {c, 0}; fx_string_append_cstr(path->pathstr, s); prev = c; } while (fx_string_back(path->pathstr) == '/') { fx_string_pop_back(path->pathstr); } return path; } static void append_path(struct fx_path *dest, const struct fx_path *src) { if (fx_path_is_absolute(src)) { fx_string_clear(dest->pathstr); fx_string_append_s(dest->pathstr, src->pathstr); return; } if (fx_string_back(dest->pathstr) != '/' && fx_string_front(src->pathstr) != '/') { char s[] = {'/', 0}; fx_string_append_cstr(dest->pathstr, s); } fx_string_append_s(dest->pathstr, src->pathstr); } struct fx_path *fx_path_join( const fx_path *paths[], size_t nr_paths) { struct fx_path *result = fx_path_create(); if (!result) { return NULL; } for (size_t i = 0; i < nr_paths; i++) { if (paths[i]) { append_path(result, paths[i]); } } return result; } struct fx_path *fx_path_make_absolute(const struct fx_path *in) { return NULL; } struct fx_path *fx_path_make_relative(const struct fx_path *in) { return NULL; } struct fx_path *fx_path_make_canonical(const struct fx_path *in) { return NULL; } bool fx_path_is_absolute(const struct fx_path *path) { const char *s = fx_string_ptr(path->pathstr); size_t i; for (i = 0; s[i]; i++) { char c = s[i]; if (!isalpha(c)) { break; } } if (s[i++] != ':') { return false; } if (s[i++] != '/') { return false; } return true; } bool fx_path_exists(const struct fx_path *path) { DWORD attrib = GetFileAttributesA(fx_path_ptr(path)); return attrib != INVALID_FILE_ATTRIBUTES; } bool fx_path_is_file(const struct fx_path *path) { DWORD attrib = GetFileAttributesA(fx_path_ptr(path)); if (attrib == INVALID_FILE_ATTRIBUTES) { return false; } return (attrib & FILE_ATTRIBUTE_NORMAL) != 0; } bool fx_path_is_directory(const struct fx_path *path) { DWORD attrib = GetFileAttributesA(fx_path_ptr(path)); if (attrib == INVALID_FILE_ATTRIBUTES) { return false; } return (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0; } const char *fx_path_ptr(const struct fx_path *path) { return fx_string_ptr(path->pathstr); } void path_release(struct fx_dsref* obj) { struct fx_path *path = FX_PATH(obj); fx_string_release(path->pathstr); } void path_to_string(struct fx_dsref* obj, struct fx_stringstream* out) { struct fx_path *path = (struct fx_path *)obj; fx_stringstream_add(out, fx_string_ptr(path->pathstr)); }