diff --git a/src/base/info.c b/src/base/info.c index 5ee86a47..3f6d90a6 100644 --- a/src/base/info.c +++ b/src/base/info.c @@ -3,7 +3,7 @@ #include "../coding/coding.h" #include "mixing.h" #include "../util/channel_mappings.h" - +#include "../util/sf_utils.h" /*******************************************************************************/ /* TEXT */ diff --git a/src/base/render.c b/src/base/render.c index f5480efa..a7cc29de 100644 --- a/src/base/render.c +++ b/src/base/render.c @@ -285,7 +285,6 @@ int render_layout(sample_t* buf, int32_t sample_count, VGMSTREAM* vgmstream) { case layout_blocked_ivaud: case layout_blocked_ea_swvr: case layout_blocked_adm: - case layout_blocked_bdsp: case layout_blocked_ps2_iab: case layout_blocked_vs_str: case layout_blocked_rws: diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 3cbec036..8484a505 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -185,6 +185,7 @@ + @@ -745,6 +746,7 @@ + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index 7984edc6..7bfe3e72 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -380,6 +380,9 @@ util\Header Files + + util\Header Files + util\Header Files @@ -2056,6 +2059,9 @@ util\Source Files + + util\Source Files + util\Source Files diff --git a/src/meta/meta.h b/src/meta/meta.h index ba3bbb40..18cae8af 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -4,6 +4,7 @@ #include "../vgmstream.h" #include "../util/reader_sf.h" #include "../util/reader_text.h" +#include "../util/sf_utils.h" typedef VGMSTREAM* (*init_vgmstream_t)(STREAMFILE* sf); diff --git a/src/streamfile.c b/src/streamfile.c index ef1c5e70..8566febf 100644 --- a/src/streamfile.c +++ b/src/streamfile.c @@ -1,8 +1,8 @@ #include "streamfile.h" #include "util.h" #include "vgmstream.h" -#include "util/reader_sf.h" #include "util/paths.h" +#include "util/sf_utils.h" #include /* for dup/fdopen in some systems */ @@ -985,92 +985,10 @@ STREAMFILE* open_multifile_streamfile_f(STREAMFILE** sfs, size_t sfs_size) { /* **************************************************** */ -/* change pathname's extension to another (or add it if extensionless) */ -static void swap_extension(char* pathname, /*size_t*/ int pathname_len, const char* swap) { - char* extension = (char*)filename_extension(pathname); - //todo safeops - if (extension[0] == '\0') { - strcat(pathname, "."); - strcat(pathname, swap); - } - else { - strcpy(extension, swap); - } -} - STREAMFILE* open_streamfile(STREAMFILE* sf, const char* pathname) { return sf->open(sf, pathname, STREAMFILE_DEFAULT_BUFFER_SIZE); } -STREAMFILE* open_streamfile_by_ext(STREAMFILE* sf, const char* ext) { - char filename[PATH_LIMIT]; - - get_streamfile_name(sf, filename, sizeof(filename)); - - swap_extension(filename, sizeof(filename), ext); - - return open_streamfile(sf, filename); -} - -STREAMFILE* open_streamfile_by_filename(STREAMFILE* sf, const char* filename) { - char fullname[PATH_LIMIT]; - char partname[PATH_LIMIT]; - char *path, *name, *otherpath; - - if (!sf || !filename || !filename[0]) return NULL; - - get_streamfile_name(sf, fullname, sizeof(fullname)); - - //todo normalize separators in a better way, safeops, improve copying - - /* check for non-normalized paths first (ex. txth) */ - path = strrchr(fullname, '/'); - otherpath = strrchr(fullname, '\\'); - if (otherpath > path) { //todo cast to ptr? - /* foobar makes paths like "(fake protocol)://(windows path with \)". - * Hack to work around both separators, though probably foo_streamfile - * should just return and handle normalized paths without protocol. */ - path = otherpath; - } - - if (path) { - path[1] = '\0'; /* remove name after separator */ - - strcpy(partname, filename); - fix_dir_separators(partname); /* normalize to DIR_SEPARATOR */ - - /* normalize relative paths as don't work ok in some plugins */ - if (partname[0] == '.' && partname[1] == DIR_SEPARATOR) { /* './name' */ - name = partname + 2; /* ignore './' */ - } - else if (partname[0] == '.' && partname[1] == '.' && partname[2] == DIR_SEPARATOR) { /* '../name' */ - char* pathprev; - - path[0] = '\0'; /* remove last separator so next call works */ - pathprev = strrchr(fullname,DIR_SEPARATOR); - if (pathprev) { - pathprev[1] = '\0'; /* remove prev dir after separator */ - name = partname + 3; /* ignore '../' */ - } - else { /* let plugin handle? */ - path[0] = DIR_SEPARATOR; - name = partname; - } - /* could work with more relative paths but whatevs */ - } - else { - name = partname; - } - - strcat(fullname, name); - } - else { - strcpy(fullname, filename); - } - - return open_streamfile(sf, fullname); -} - STREAMFILE* reopen_streamfile(STREAMFILE* sf, size_t buffer_size) { char pathname[PATH_LIMIT]; @@ -1084,111 +1002,6 @@ STREAMFILE* reopen_streamfile(STREAMFILE* sf, size_t buffer_size) { /* ************************************************************************* */ -int check_extensions(STREAMFILE* sf, const char* cmp_exts) { - char filename[PATH_LIMIT]; - const char* ext = NULL; - const char* cmp_ext = NULL; - const char* ststr_res = NULL; - size_t ext_len, cmp_len; - - sf->get_name(sf, filename, sizeof(filename)); - ext = filename_extension(filename); - ext_len = strlen(ext); - - cmp_ext = cmp_exts; - do { - ststr_res = strstr(cmp_ext, ","); - cmp_len = ststr_res == NULL - ? strlen(cmp_ext) /* total length if more not found */ - : (intptr_t)ststr_res - (intptr_t)cmp_ext; /* find next ext; ststr_res should always be greater than cmp_ext, resulting in a positive cmp_len */ - - if (ext_len == cmp_len && strncasecmp(ext,cmp_ext, ext_len) == 0) - return 1; - - cmp_ext = ststr_res; - if (cmp_ext != NULL) - cmp_ext = cmp_ext + 1; /* skip comma */ - - } while (cmp_ext != NULL); - - return 0; -} - -/* ************************************************************************* */ - -/* copies name as-is (may include full path included) */ -void get_streamfile_name(STREAMFILE* sf, char* buffer, size_t size) { - sf->get_name(sf, buffer, size); -} - -/* copies the filename without path */ -void get_streamfile_filename(STREAMFILE* sf, char* buffer, size_t size) { - char foldername[PATH_LIMIT]; - const char* path; - - - get_streamfile_name(sf, foldername, sizeof(foldername)); - - //todo Windows CMD accepts both \\ and /, better way to handle this? - path = strrchr(foldername,'\\'); - if (!path) - path = strrchr(foldername,'/'); - if (path != NULL) - path = path+1; - - //todo validate sizes and copy sensible max - if (path) { - strcpy(buffer, path); - } else { - strcpy(buffer, foldername); - } -} - -/* copies the filename without path or extension */ -void get_streamfile_basename(STREAMFILE* sf, char* buffer, size_t size) { - char* ext; - - get_streamfile_filename(sf, buffer, size); - - ext = strrchr(buffer,'.'); - if (ext) { - ext[0] = '\0'; /* remove .ext from buffer */ - } -} - -/* copies path removing name (NULL when if filename has no path) */ -void get_streamfile_path(STREAMFILE* sf, char* buffer, size_t size) { - const char* path; - - get_streamfile_name(sf, buffer, size); - - path = strrchr(buffer,DIR_SEPARATOR); - if (path!=NULL) path = path+1; /* includes "/" */ - - if (path) { - buffer[path - buffer] = '\0'; - } else { - buffer[0] = '\0'; - } -} - -/* copies extension only */ -void get_streamfile_ext(STREAMFILE* sf, char* buffer, size_t size) { - char filename[PATH_LIMIT]; - const char* extension = NULL; - - get_streamfile_name(sf, filename, sizeof(filename)); - extension = filename_extension(filename); - if (!extension) { - buffer[0] = '\n'; - } - else { - strncpy(buffer, extension, size); //todo use something better - } -} - -/* ************************************************************************* */ - /* debug util, mainly for custom IO testing */ void dump_streamfile(STREAMFILE* sf, int num) { #ifdef VGM_DEBUG_OUTPUT diff --git a/src/streamfile.h b/src/streamfile.h index 476372c3..d3e89091 100644 --- a/src/streamfile.h +++ b/src/streamfile.h @@ -130,15 +130,6 @@ STREAMFILE* open_multifile_streamfile_f(STREAMFILE** sfs, size_t sfs_size); * Just a wrapper, to avoid having to access the STREAMFILE's callbacks directly. */ STREAMFILE* open_streamfile(STREAMFILE* sf, const char* pathname); -/* Opens a STREAMFILE from a base pathname + new extension - * Can be used to get companion headers. */ -STREAMFILE* open_streamfile_by_ext(STREAMFILE* sf, const char* ext); - -/* Opens a STREAMFILE from a base path + new filename. - * Can be used to get companion files. Relative paths like - * './filename', '../filename', 'dir/filename' also work. */ -STREAMFILE* open_streamfile_by_filename(STREAMFILE* sf, const char* filename); - /* Reopen a STREAMFILE with a different buffer size, for fine-tuned bigfile parsing. * Uses default buffer size when buffer_size is 0 */ STREAMFILE* reopen_streamfile(STREAMFILE* sf, size_t buffer_size); @@ -161,18 +152,6 @@ static inline size_t get_streamfile_size(STREAMFILE* sf) { } -/* various STREAMFILE helpers functions */ - -/* Checks if the stream filename is one of the extensions (comma-separated, ex. "adx" or "adx,aix"). - * Empty is ok to accept files without extension ("", "adx,,aix"). Returns 0 on failure */ -int check_extensions(STREAMFILE* sf, const char* cmp_exts); - -/* filename helpers */ -void get_streamfile_name(STREAMFILE* sf, char* buf, size_t size); -void get_streamfile_filename(STREAMFILE* sf, char* buf, size_t size); -void get_streamfile_basename(STREAMFILE* sf, char* buf, size_t size); -void get_streamfile_path(STREAMFILE* sf, char* buf, size_t size); -void get_streamfile_ext(STREAMFILE* sf, char* buf, size_t size); - void dump_streamfile(STREAMFILE* sf, int num); + #endif diff --git a/src/util/companion_files.c b/src/util/companion_files.c index 253b18e3..b126a49e 100644 --- a/src/util/companion_files.c +++ b/src/util/companion_files.c @@ -1,7 +1,8 @@ #include "companion_files.h" #include "paths.h" #include "../vgmstream.h" -#include "../util/reader_text.h" +#include "reader_text.h" +#include "sf_utils.h" size_t read_key_file(uint8_t* buf, size_t buf_size, STREAMFILE* sf) { diff --git a/src/util/sf_utils.c b/src/util/sf_utils.c new file mode 100644 index 00000000..d0cd061e --- /dev/null +++ b/src/util/sf_utils.c @@ -0,0 +1,192 @@ +#include "sf_utils.h" +#include "../vgmstream.h" +#include "reader_sf.h" +#include "paths.h" + + +/* change pathname's extension to another (or add it if extensionless) */ +static void swap_extension(char* pathname, /*size_t*/ int pathname_len, const char* swap) { + char* extension = (char*)filename_extension(pathname); + //todo safeops + if (extension[0] == '\0') { + strcat(pathname, "."); + strcat(pathname, swap); + } + else { + strcpy(extension, swap); + } +} + +STREAMFILE* open_streamfile_by_ext(STREAMFILE* sf, const char* ext) { + char filename[PATH_LIMIT]; + + get_streamfile_name(sf, filename, sizeof(filename)); + + swap_extension(filename, sizeof(filename), ext); + + return open_streamfile(sf, filename); +} + +STREAMFILE* open_streamfile_by_filename(STREAMFILE* sf, const char* filename) { + char fullname[PATH_LIMIT]; + char partname[PATH_LIMIT]; + char *path, *name, *otherpath; + + if (!sf || !filename || !filename[0]) return NULL; + + get_streamfile_name(sf, fullname, sizeof(fullname)); + + //todo normalize separators in a better way, safeops, improve copying + + /* check for non-normalized paths first (ex. txth) */ + path = strrchr(fullname, '/'); + otherpath = strrchr(fullname, '\\'); + if (otherpath > path) { //todo cast to ptr? + /* foobar makes paths like "(fake protocol)://(windows path with \)". + * Hack to work around both separators, though probably foo_streamfile + * should just return and handle normalized paths without protocol. */ + path = otherpath; + } + + if (path) { + path[1] = '\0'; /* remove name after separator */ + + strcpy(partname, filename); + fix_dir_separators(partname); /* normalize to DIR_SEPARATOR */ + + /* normalize relative paths as don't work ok in some plugins */ + if (partname[0] == '.' && partname[1] == DIR_SEPARATOR) { /* './name' */ + name = partname + 2; /* ignore './' */ + } + else if (partname[0] == '.' && partname[1] == '.' && partname[2] == DIR_SEPARATOR) { /* '../name' */ + char* pathprev; + + path[0] = '\0'; /* remove last separator so next call works */ + pathprev = strrchr(fullname,DIR_SEPARATOR); + if (pathprev) { + pathprev[1] = '\0'; /* remove prev dir after separator */ + name = partname + 3; /* ignore '../' */ + } + else { /* let plugin handle? */ + path[0] = DIR_SEPARATOR; + name = partname; + } + /* could work with more relative paths but whatevs */ + } + else { + name = partname; + } + + strcat(fullname, name); + } + else { + strcpy(fullname, filename); + } + + return open_streamfile(sf, fullname); +} + +/* ************************************************************************* */ + +int check_extensions(STREAMFILE* sf, const char* cmp_exts) { + char filename[PATH_LIMIT]; + const char* ext = NULL; + const char* cmp_ext = NULL; + const char* ststr_res = NULL; + size_t ext_len, cmp_len; + + sf->get_name(sf, filename, sizeof(filename)); + ext = filename_extension(filename); + ext_len = strlen(ext); + + cmp_ext = cmp_exts; + do { + ststr_res = strstr(cmp_ext, ","); + cmp_len = ststr_res == NULL + ? strlen(cmp_ext) /* total length if more not found */ + : (intptr_t)ststr_res - (intptr_t)cmp_ext; /* find next ext; ststr_res should always be greater than cmp_ext, resulting in a positive cmp_len */ + + if (ext_len == cmp_len && strncasecmp(ext,cmp_ext, ext_len) == 0) + return 1; + + cmp_ext = ststr_res; + if (cmp_ext != NULL) + cmp_ext = cmp_ext + 1; /* skip comma */ + + } while (cmp_ext != NULL); + + return 0; +} + +/* ************************************************************************* */ + +/* copies name as-is (may include full path included) */ +void get_streamfile_name(STREAMFILE* sf, char* buffer, size_t size) { + sf->get_name(sf, buffer, size); +} + +/* copies the filename without path */ +void get_streamfile_filename(STREAMFILE* sf, char* buffer, size_t size) { + char foldername[PATH_LIMIT]; + const char* path; + + + get_streamfile_name(sf, foldername, sizeof(foldername)); + + //todo Windows CMD accepts both \\ and /, better way to handle this? + path = strrchr(foldername,'\\'); + if (!path) + path = strrchr(foldername,'/'); + if (path != NULL) + path = path+1; + + //todo validate sizes and copy sensible max + if (path) { + strcpy(buffer, path); + } else { + strcpy(buffer, foldername); + } +} + +/* copies the filename without path or extension */ +void get_streamfile_basename(STREAMFILE* sf, char* buffer, size_t size) { + char* ext; + + get_streamfile_filename(sf, buffer, size); + + ext = strrchr(buffer,'.'); + if (ext) { + ext[0] = '\0'; /* remove .ext from buffer */ + } +} + +/* copies path removing name (NULL when if filename has no path) */ +void get_streamfile_path(STREAMFILE* sf, char* buffer, size_t size) { + const char* path; + + get_streamfile_name(sf, buffer, size); + + path = strrchr(buffer,DIR_SEPARATOR); + if (path!=NULL) path = path+1; /* includes "/" */ + + if (path) { + buffer[path - buffer] = '\0'; + } else { + buffer[0] = '\0'; + } +} + +/* copies extension only */ +void get_streamfile_ext(STREAMFILE* sf, char* buffer, size_t size) { + char filename[PATH_LIMIT]; + const char* extension = NULL; + + get_streamfile_name(sf, filename, sizeof(filename)); + extension = filename_extension(filename); + if (!extension) { + buffer[0] = '\n'; + } + else { + strncpy(buffer, extension, size); //todo use something better + } +} diff --git a/src/util/sf_utils.h b/src/util/sf_utils.h new file mode 100644 index 00000000..c1260bfe --- /dev/null +++ b/src/util/sf_utils.h @@ -0,0 +1,29 @@ +#ifndef _SF_UTILS_H +#define _SF_UTILS_H +#include "../streamfile.h" + + + +/* Opens a STREAMFILE from a base pathname + new extension + * Can be used to get companion headers. */ +STREAMFILE* open_streamfile_by_ext(STREAMFILE* sf, const char* ext); + +/* Opens a STREAMFILE from a base path + new filename. + * Can be used to get companion files. Relative paths like + * './filename', '../filename', 'dir/filename' also work. */ +STREAMFILE* open_streamfile_by_filename(STREAMFILE* sf, const char* filename); + +/* various STREAMFILE helpers functions */ + +/* Checks if the stream filename is one of the extensions (comma-separated, ex. "adx" or "adx,aix"). + * Empty is ok to accept files without extension ("", "adx,,aix"). Returns 0 on failure */ +int check_extensions(STREAMFILE* sf, const char* cmp_exts); + +/* filename helpers */ +void get_streamfile_name(STREAMFILE* sf, char* buf, size_t size); +void get_streamfile_filename(STREAMFILE* sf, char* buf, size_t size); +void get_streamfile_basename(STREAMFILE* sf, char* buf, size_t size); +void get_streamfile_path(STREAMFILE* sf, char* buf, size_t size); +void get_streamfile_ext(STREAMFILE* sf, char* buf, size_t size); + +#endif diff --git a/src/vgmstream.c b/src/vgmstream.c index c2b61e78..68deec24 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -12,6 +12,7 @@ #include "base/decode.h" #include "base/render.h" #include "base/mixing.h" +#include "util/sf_utils.h" typedef VGMSTREAM* (*init_vgmstream_t)(STREAMFILE*);