Mercurial > repos > blastem
diff util.c @ 1692:5dacaef602a7 segacd
Merge from default
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 05 Jan 2019 00:58:08 -0800 |
parents | c362f2c7766a |
children | ba3fb7a3be6b |
line wrap: on
line diff
--- a/util.c Tue Dec 19 00:49:13 2017 -0800 +++ b/util.c Sat Jan 05 00:58:08 2019 -0800 @@ -204,6 +204,85 @@ *(output++) = 0; } +char *utf16be_to_utf8(uint8_t *buf, uint32_t max_size) +{ + uint8_t *cur = buf; + uint32_t converted_size = 0; + for (uint32_t i = 0; i < max_size; i++, cur+=2) + { + uint16_t code = *cur << 16 | cur[1]; + if (!code) { + break; + } + if (code < 0x80) { + converted_size++; + } else if (code < 0x800) { + converted_size += 2; + } else { + //TODO: Deal with surrogate pairs + converted_size += 3; + } + } + char *out = malloc(converted_size + 1); + char *cur_out = out; + cur = buf; + for (uint32_t i = 0; i < max_size; i++, cur+=2) + { + uint16_t code = *cur << 16 | cur[1]; + if (!code) { + break; + } + if (code < 0x80) { + *(cur_out++) = code; + } else if (code < 0x800) { + *(cur_out++) = 0xC0 | code >> 6; + *(cur_out++) = 0x80 | (code & 0x3F); + } else { + //TODO: Deal with surrogate pairs + *(cur_out++) = 0xF0 | code >> 12; + *(cur_out++) = 0x80 | (code >> 6 & 0x3F); + *(cur_out++) = 0x80 | (code & 0x3F); + } + } + *cur_out = 0; + return out; +} + +int utf8_codepoint(const char **text) +{ + uint8_t initial = **text; + (*text)++; + if (initial < 0x80) { + return initial; + } + int base = 0; + uint8_t extended_bytes = 0; + if ((initial & 0xE0) == 0xC0) { + base = 0x80; + initial &= 0x1F; + extended_bytes = 1; + } else if ((initial & 0xF0) == 0xE0) { + base = 0x800; + initial &= 0xF; + extended_bytes = 2; + } else if ((initial & 0xF8) == 0xF0) { + base = 0x10000; + initial &= 0x7; + extended_bytes = 3; + } + int value = initial; + for (uint8_t i = 0; i < extended_bytes; i++) + { + if ((**text & 0xC0) != 0x80) { + return -1; + } + value = value << 6; + value |= (**text) & 0x3F; + (*text)++; + } + return value + base; +} + char is_path_sep(char c) { #ifdef _WIN32 @@ -224,11 +303,11 @@ return is_path_sep(path[0]); } -char * basename_no_extension(char *path) +char * basename_no_extension(const char *path) { - char *lastdot = NULL; - char *lastslash = NULL; - char *cur; + const char *lastdot = NULL; + const char *lastslash = NULL; + const char *cur; for (cur = path; *cur; cur++) { if (*cur == '.') { @@ -250,11 +329,11 @@ return barename; } -char *path_extension(char *path) +char *path_extension(char const *path) { - char *lastdot = NULL; - char *lastslash = NULL; - char *cur; + char const *lastdot = NULL; + char const *lastslash = NULL; + char const *cur; for (cur = path; *cur; cur++) { if (*cur == '.') { @@ -270,10 +349,28 @@ return strdup(lastdot+1); } -char * path_dirname(char *path) +uint8_t path_matches_extensions(char *path, char **ext_list, uint32_t num_exts) { - char *lastslash = NULL; - char *cur; + char *ext = path_extension(path); + if (!ext) { + return 0; + } + uint32_t extidx; + for (extidx = 0; extidx < num_exts; extidx++) + { + if (!strcasecmp(ext, ext_list[extidx])) { + free(ext); + return 1; + } + } + free(ext); + return 0; +} + +char * path_dirname(const char *path) +{ + const char *lastslash = NULL; + const char *cur; for (cur = path; *cur; cur++) { if (is_path_sep(*cur)) { @@ -440,34 +537,70 @@ dir_entry *get_dir_list(char *path, size_t *numret) { - HANDLE dir; - WIN32_FIND_DATA file; - char *pattern = alloc_concat(path, "/*.*"); - dir = FindFirstFile(pattern, &file); - free(pattern); - if (dir == INVALID_HANDLE_VALUE) { + dir_entry *ret; + if (path[0] == PATH_SEP[0] && !path[1]) { + int drives = GetLogicalDrives(); + size_t count = 0; + for (int i = 0; i < 26; i++) + { + if (drives & (1 << i)) { + count++; + } + } + ret = calloc(count, sizeof(dir_entry)); + dir_entry *cur = ret; + for (int i = 0; i < 26; i++) + { + if (drives & (1 << i)) { + cur->name = malloc(4); + cur->name[0] = 'A' + i; + cur->name[1] = ':'; + cur->name[2] = PATH_SEP[0]; + cur->name[3] = 0; + cur->is_dir = 1; + cur++; + } + } if (numret) { - *numret = 0; + *numret = count; } - return NULL; - } - - size_t storage = 64; - dir_entry *ret = malloc(sizeof(dir_entry) * storage); - size_t pos = 0; - - do { - if (pos == storage) { - storage = storage * 2; - ret = realloc(ret, sizeof(dir_entry) * storage); + } else { + HANDLE dir; + WIN32_FIND_DATA file; + char *pattern = alloc_concat(path, "/*.*"); + dir = FindFirstFile(pattern, &file); + free(pattern); + if (dir == INVALID_HANDLE_VALUE) { + if (numret) { + *numret = 0; + } + return NULL; } - ret[pos].name = strdup(file.cFileName); - ret[pos++].is_dir = (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; - } while (FindNextFile(dir, &file)); - - FindClose(dir); - if (numret) { - *numret = pos; + + size_t storage = 64; + ret = malloc(sizeof(dir_entry) * storage); + size_t pos = 0; + + if (path[1] == ':' && (!path[2] || (path[2] == PATH_SEP[0] && !path[3]))) { + //we are in the root of a drive, add a virtual .. entry + //for navigating to the virtual root directory + ret[pos].name = strdup(".."); + ret[pos++].is_dir = 1; + } + + do { + if (pos == storage) { + storage = storage * 2; + ret = realloc(ret, sizeof(dir_entry) * storage); + } + ret[pos].name = strdup(file.cFileName); + ret[pos++].is_dir = (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; + } while (FindNextFile(dir, &file)); + + FindClose(dir); + if (numret) { + *numret = pos; + } } return ret; } @@ -489,7 +622,7 @@ return (time_t)wintime; } -int ensure_dir_exists(char *path) +int ensure_dir_exists(const char *path) { if (CreateDirectory(path, NULL)) { return 1; @@ -626,6 +759,7 @@ if (numret) { *numret = pos; } + closedir(d); return ret; } @@ -643,7 +777,7 @@ #endif } -int ensure_dir_exists(char *path) +int ensure_dir_exists(const char *path) { struct stat st; if (stat(path, &st)) { @@ -680,6 +814,22 @@ free(list); } +static int sort_dir_alpha(const void *a, const void *b) +{ + const dir_entry *da, *db; + da = a; + db = b; + if (da->is_dir != db->is_dir) { + return db->is_dir - da->is_dir; + } + return strcasecmp(((dir_entry *)a)->name, ((dir_entry *)b)->name); +} + +void sort_dir_list(dir_entry *list, size_t num_entries) +{ + qsort(list, num_entries, sizeof(dir_entry), sort_dir_alpha); +} + #ifdef __ANDROID__ #include <SDL.h> @@ -759,6 +909,7 @@ } else { ret = NULL; } + fclose(f); return ret; } @@ -776,7 +927,14 @@ char const *get_config_dir() { - return get_userdata_dir(); + static char* confdir; + if (!confdir) { + char const *base = get_userdata_dir(); + if (base) { + confdir = alloc_concat(base, PATH_SEP "blastem"); + } + } + return confdir; } #define CONFIG_PREFIX "" #define SAVE_PREFIX ""