mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-24 15:00:11 +01:00
cleanup: separte sf code
This commit is contained in:
parent
442084cc85
commit
5d9b4ed827
@ -3,7 +3,7 @@
|
|||||||
#include "../coding/coding.h"
|
#include "../coding/coding.h"
|
||||||
#include "mixing.h"
|
#include "mixing.h"
|
||||||
#include "../util/channel_mappings.h"
|
#include "../util/channel_mappings.h"
|
||||||
|
#include "../util/sf_utils.h"
|
||||||
|
|
||||||
/*******************************************************************************/
|
/*******************************************************************************/
|
||||||
/* TEXT */
|
/* TEXT */
|
||||||
|
@ -285,7 +285,6 @@ int render_layout(sample_t* buf, int32_t sample_count, VGMSTREAM* vgmstream) {
|
|||||||
case layout_blocked_ivaud:
|
case layout_blocked_ivaud:
|
||||||
case layout_blocked_ea_swvr:
|
case layout_blocked_ea_swvr:
|
||||||
case layout_blocked_adm:
|
case layout_blocked_adm:
|
||||||
case layout_blocked_bdsp:
|
|
||||||
case layout_blocked_ps2_iab:
|
case layout_blocked_ps2_iab:
|
||||||
case layout_blocked_vs_str:
|
case layout_blocked_vs_str:
|
||||||
case layout_blocked_rws:
|
case layout_blocked_rws:
|
||||||
|
@ -185,6 +185,7 @@
|
|||||||
<ClInclude Include="util\reader_sf.h" />
|
<ClInclude Include="util\reader_sf.h" />
|
||||||
<ClInclude Include="util\reader_text.h" />
|
<ClInclude Include="util\reader_text.h" />
|
||||||
<ClInclude Include="util\samples_ops.h" />
|
<ClInclude Include="util\samples_ops.h" />
|
||||||
|
<ClInclude Include="util\sf_utils.h" />
|
||||||
<ClInclude Include="util\text_reader.h" />
|
<ClInclude Include="util\text_reader.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -745,6 +746,7 @@
|
|||||||
<ClCompile Include="util\paths.c" />
|
<ClCompile Include="util\paths.c" />
|
||||||
<ClCompile Include="util\reader.c" />
|
<ClCompile Include="util\reader.c" />
|
||||||
<ClCompile Include="util\samples_ops.c" />
|
<ClCompile Include="util\samples_ops.c" />
|
||||||
|
<ClCompile Include="util\sf_utils.c" />
|
||||||
<ClCompile Include="util\text_reader.c" />
|
<ClCompile Include="util\text_reader.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
@ -380,6 +380,9 @@
|
|||||||
<ClInclude Include="util\samples_ops.h">
|
<ClInclude Include="util\samples_ops.h">
|
||||||
<Filter>util\Header Files</Filter>
|
<Filter>util\Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="util\sf_utils.h">
|
||||||
|
<Filter>util\Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="util\text_reader.h">
|
<ClInclude Include="util\text_reader.h">
|
||||||
<Filter>util\Header Files</Filter>
|
<Filter>util\Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@ -2056,6 +2059,9 @@
|
|||||||
<ClCompile Include="util\samples_ops.c">
|
<ClCompile Include="util\samples_ops.c">
|
||||||
<Filter>util\Source Files</Filter>
|
<Filter>util\Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="util\sf_utils.c">
|
||||||
|
<Filter>util\Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="util\text_reader.c">
|
<ClCompile Include="util\text_reader.c">
|
||||||
<Filter>util\Source Files</Filter>
|
<Filter>util\Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "../vgmstream.h"
|
#include "../vgmstream.h"
|
||||||
#include "../util/reader_sf.h"
|
#include "../util/reader_sf.h"
|
||||||
#include "../util/reader_text.h"
|
#include "../util/reader_text.h"
|
||||||
|
#include "../util/sf_utils.h"
|
||||||
|
|
||||||
typedef VGMSTREAM* (*init_vgmstream_t)(STREAMFILE* sf);
|
typedef VGMSTREAM* (*init_vgmstream_t)(STREAMFILE* sf);
|
||||||
|
|
||||||
|
189
src/streamfile.c
189
src/streamfile.c
@ -1,8 +1,8 @@
|
|||||||
#include "streamfile.h"
|
#include "streamfile.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "vgmstream.h"
|
#include "vgmstream.h"
|
||||||
#include "util/reader_sf.h"
|
|
||||||
#include "util/paths.h"
|
#include "util/paths.h"
|
||||||
|
#include "util/sf_utils.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
/* for dup/fdopen in some systems */
|
/* 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) {
|
STREAMFILE* open_streamfile(STREAMFILE* sf, const char* pathname) {
|
||||||
return sf->open(sf, pathname, STREAMFILE_DEFAULT_BUFFER_SIZE);
|
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) {
|
STREAMFILE* reopen_streamfile(STREAMFILE* sf, size_t buffer_size) {
|
||||||
char pathname[PATH_LIMIT];
|
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 */
|
/* debug util, mainly for custom IO testing */
|
||||||
void dump_streamfile(STREAMFILE* sf, int num) {
|
void dump_streamfile(STREAMFILE* sf, int num) {
|
||||||
#ifdef VGM_DEBUG_OUTPUT
|
#ifdef VGM_DEBUG_OUTPUT
|
||||||
|
@ -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. */
|
* Just a wrapper, to avoid having to access the STREAMFILE's callbacks directly. */
|
||||||
STREAMFILE* open_streamfile(STREAMFILE* sf, const char* pathname);
|
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.
|
/* Reopen a STREAMFILE with a different buffer size, for fine-tuned bigfile parsing.
|
||||||
* Uses default buffer size when buffer_size is 0 */
|
* Uses default buffer size when buffer_size is 0 */
|
||||||
STREAMFILE* reopen_streamfile(STREAMFILE* sf, size_t buffer_size);
|
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);
|
void dump_streamfile(STREAMFILE* sf, int num);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
#include "companion_files.h"
|
#include "companion_files.h"
|
||||||
#include "paths.h"
|
#include "paths.h"
|
||||||
#include "../vgmstream.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) {
|
size_t read_key_file(uint8_t* buf, size_t buf_size, STREAMFILE* sf) {
|
||||||
|
192
src/util/sf_utils.c
Normal file
192
src/util/sf_utils.c
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
29
src/util/sf_utils.h
Normal file
29
src/util/sf_utils.h
Normal file
@ -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
|
@ -12,6 +12,7 @@
|
|||||||
#include "base/decode.h"
|
#include "base/decode.h"
|
||||||
#include "base/render.h"
|
#include "base/render.h"
|
||||||
#include "base/mixing.h"
|
#include "base/mixing.h"
|
||||||
|
#include "util/sf_utils.h"
|
||||||
|
|
||||||
typedef VGMSTREAM* (*init_vgmstream_t)(STREAMFILE*);
|
typedef VGMSTREAM* (*init_vgmstream_t)(STREAMFILE*);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user