diff --git a/src/base/plugins.c b/src/base/plugins.c index 27d9193d..22b62a4f 100644 --- a/src/base/plugins.c +++ b/src/base/plugins.c @@ -1,6 +1,7 @@ #include "../vgmstream.h" #include "../util/log.h" #include "../util/reader_sf.h" +#include "../util/reader_text.h" #include "plugins.h" #include "mixing.h" diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 2a977e14..ff8be911 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -183,6 +183,7 @@ + @@ -746,7 +747,7 @@ - + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index e9aa66ba..493d257a 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -374,6 +374,9 @@ util\Header Files + + util\Header Files + util\Header Files @@ -2059,7 +2062,7 @@ util\Source Files - + util\Source Files diff --git a/src/meta/meta.h b/src/meta/meta.h index 2df93035..c0d9c08c 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -3,6 +3,7 @@ #include "../vgmstream.h" #include "../util/reader_sf.h" +#include "../util/reader_text.h" typedef VGMSTREAM* (*init_vgmstream_t)(STREAMFILE* sf); diff --git a/src/streamfile.c b/src/streamfile.c index 7fb25eff..77ec2bf8 100644 --- a/src/streamfile.c +++ b/src/streamfile.c @@ -1078,123 +1078,6 @@ STREAMFILE* reopen_streamfile(STREAMFILE* sf, size_t buffer_size) { return sf->open(sf, pathname, buffer_size); } -/* **************************************************** */ - -size_t read_line(char* buf, int buf_size, off_t offset, STREAMFILE* sf, int* p_line_ok) { - int i; - off_t file_size = get_streamfile_size(sf); - int extra_bytes = 0; /* how many bytes over those put in the buffer were read */ - - if (p_line_ok) *p_line_ok = 0; - - for (i = 0; i < buf_size-1 && offset+i < file_size; i++) { - char in_char = read_8bit(offset+i, sf); - /* check for end of line */ - if (in_char == 0x0d && read_8bit(offset+i+1, sf) == 0x0a) { /* CRLF */ - extra_bytes = 2; - if (p_line_ok) *p_line_ok = 1; - break; - } - else if (in_char == 0x0d || in_char == 0x0a) { /* CR or LF */ - extra_bytes = 1; - if (p_line_ok) *p_line_ok = 1; - break; - } - - buf[i] = in_char; - } - - buf[i] = '\0'; - - /* did we fill the buffer? */ - if (i == buf_size) { - char in_char = read_8bit(offset+i, sf); - /* did the bytes we missed just happen to be the end of the line? */ - if (in_char == 0x0d && read_8bit(offset+i+1, sf) == 0x0a) { /* CRLF */ - extra_bytes = 2; - if (p_line_ok) *p_line_ok = 1; - } - else if (in_char == 0x0d || in_char == 0x0a) { /* CR or LF */ - extra_bytes = 1; - if (p_line_ok) *p_line_ok = 1; - } - } - - /* did we hit the file end? */ - if (offset+i == file_size) { - /* then we did in fact finish reading the last line */ - if (p_line_ok) *p_line_ok = 1; - } - - return i + extra_bytes; -} - -size_t read_bom(STREAMFILE* sf) { - if (read_u16le(0x00, sf) == 0xFFFE || - read_u16le(0x00, sf) == 0xFEFF) { - return 0x02; - } - - if ((read_u32be(0x00, sf) & 0xFFFFFF00) == 0xEFBBBF00) { - return 0x03; - } - - return 0x00; -} - -size_t read_string(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf) { - size_t pos; - - for (pos = 0; pos < buf_size; pos++) { - uint8_t byte = read_u8(offset + pos, sf); - char c = (char)byte; - if (buf) buf[pos] = c; - if (c == '\0') - return pos; - if (pos+1 == buf_size) { /* null at maxsize and don't validate (expected to be garbage) */ - if (buf) buf[pos] = '\0'; - return buf_size; - } - /* UTF-8 only goes to 0x7F, but allow a bunch of Windows-1252 codes that some games use */ - if (byte < 0x20 || byte > 0xF0) - goto fail; - } - -fail: - if (buf) buf[0] = '\0'; - return 0; -} - -size_t read_string_utf16(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf, int big_endian) { - size_t pos, offpos; - uint16_t (*read_u16)(off_t,STREAMFILE*) = big_endian ? read_u16be : read_u16le; - - - for (pos = 0, offpos = 0; pos < buf_size; pos++, offpos += 2) { - char c = read_u16(offset + offpos, sf) & 0xFF; /* lower byte for now */ - if (buf) buf[pos] = c; - if (c == '\0') - return pos; - if (pos+1 == buf_size) { /* null at maxsize and don't validate (expected to be garbage) */ - if (buf) buf[pos] = '\0'; - return buf_size; - } - if (c < 0x20 || (uint8_t)c > 0xA5) - goto fail; - } - -fail: - if (buf) buf[0] = '\0'; - return 0; -} - -size_t read_string_utf16le(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf) { - return read_string_utf16(buf, buf_size, offset, sf, 0); -} -size_t read_string_utf16be(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf) { - return read_string_utf16(buf, buf_size, offset, sf, 1); -} - /* ************************************************************************* */ int check_extensions(STREAMFILE* sf, const char* cmp_exts) { diff --git a/src/streamfile.h b/src/streamfile.h index 119bea94..476372c3 100644 --- a/src/streamfile.h +++ b/src/streamfile.h @@ -163,22 +163,6 @@ static inline size_t get_streamfile_size(STREAMFILE* sf) { /* various STREAMFILE helpers functions */ -/* Read into dst a line delimited by CRLF (Windows) / LF (Unux) / CR (Mac) / EOF, null-terminated - * and without line feeds. Returns bytes read (including CR/LF), *not* the same as string length. - * p_line_ok is set to 1 if the complete line was read; pass NULL to ignore. */ -size_t read_line(char* buf, int buf_size, off_t offset, STREAMFILE* sf, int* p_line_ok); - -/* skip BOM if needed */ -size_t read_bom(STREAMFILE* sf); - -/* reads a c-string (ANSI only), up to bufsize or NULL, returning size. buf is optional (works as get_string_size). */ -size_t read_string(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf); -/* reads a UTF16 string... but actually only as ANSI (discards the upper byte) */ -size_t read_string_utf16(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf, int big_endian); -size_t read_string_utf16le(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf); -size_t read_string_utf16be(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf); - - /* 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); diff --git a/src/util/companion_files.c b/src/util/companion_files.c index 9a3d02a4..253b18e3 100644 --- a/src/util/companion_files.c +++ b/src/util/companion_files.c @@ -1,6 +1,7 @@ #include "companion_files.h" #include "paths.h" #include "../vgmstream.h" +#include "../util/reader_text.h" size_t read_key_file(uint8_t* buf, size_t buf_size, STREAMFILE* sf) { diff --git a/src/util/reader.c b/src/util/reader.c new file mode 100644 index 00000000..8b4a2fe8 --- /dev/null +++ b/src/util/reader.c @@ -0,0 +1,149 @@ +#include "reader_put.h" +#include "reader_text.h" +#include "reader_sf.h" +#include "endianness.h" + +void put_8bit(uint8_t* buf, int8_t i) { + buf[0] = i; +} + +void put_16bitLE(uint8_t* buf, int16_t i) { + buf[0] = (i & 0xFF); + buf[1] = i >> 8; +} + +void put_32bitLE(uint8_t* buf, int32_t i) { + buf[0] = (uint8_t)(i & 0xFF); + buf[1] = (uint8_t)((i >> 8) & 0xFF); + buf[2] = (uint8_t)((i >> 16) & 0xFF); + buf[3] = (uint8_t)((i >> 24) & 0xFF); +} + +void put_16bitBE(uint8_t* buf, int16_t i) { + buf[0] = i >> 8; + buf[1] = (i & 0xFF); +} + +void put_32bitBE(uint8_t* buf, int32_t i) { + buf[0] = (uint8_t)((i >> 24) & 0xFF); + buf[1] = (uint8_t)((i >> 16) & 0xFF); + buf[2] = (uint8_t)((i >> 8) & 0xFF); + buf[3] = (uint8_t)(i & 0xFF); +} + +/* **************************************************** */ + +size_t read_line(char* buf, int buf_size, off_t offset, STREAMFILE* sf, int* p_line_ok) { + int i; + off_t file_size = get_streamfile_size(sf); + int extra_bytes = 0; /* how many bytes over those put in the buffer were read */ + + if (p_line_ok) *p_line_ok = 0; + + for (i = 0; i < buf_size-1 && offset+i < file_size; i++) { + char in_char = read_8bit(offset+i, sf); + /* check for end of line */ + if (in_char == 0x0d && read_8bit(offset+i+1, sf) == 0x0a) { /* CRLF */ + extra_bytes = 2; + if (p_line_ok) *p_line_ok = 1; + break; + } + else if (in_char == 0x0d || in_char == 0x0a) { /* CR or LF */ + extra_bytes = 1; + if (p_line_ok) *p_line_ok = 1; + break; + } + + buf[i] = in_char; + } + + buf[i] = '\0'; + + /* did we fill the buffer? */ + if (i == buf_size) { + char in_char = read_8bit(offset+i, sf); + /* did the bytes we missed just happen to be the end of the line? */ + if (in_char == 0x0d && read_8bit(offset+i+1, sf) == 0x0a) { /* CRLF */ + extra_bytes = 2; + if (p_line_ok) *p_line_ok = 1; + } + else if (in_char == 0x0d || in_char == 0x0a) { /* CR or LF */ + extra_bytes = 1; + if (p_line_ok) *p_line_ok = 1; + } + } + + /* did we hit the file end? */ + if (offset+i == file_size) { + /* then we did in fact finish reading the last line */ + if (p_line_ok) *p_line_ok = 1; + } + + return i + extra_bytes; +} + +size_t read_bom(STREAMFILE* sf) { + if (read_u16le(0x00, sf) == 0xFFFE || + read_u16le(0x00, sf) == 0xFEFF) { + return 0x02; + } + + if ((read_u32be(0x00, sf) & 0xFFFFFF00) == 0xEFBBBF00) { + return 0x03; + } + + return 0x00; +} + +size_t read_string(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf) { + size_t pos; + + for (pos = 0; pos < buf_size; pos++) { + uint8_t byte = read_u8(offset + pos, sf); + char c = (char)byte; + if (buf) buf[pos] = c; + if (c == '\0') + return pos; + if (pos+1 == buf_size) { /* null at maxsize and don't validate (expected to be garbage) */ + if (buf) buf[pos] = '\0'; + return buf_size; + } + /* UTF-8 only goes to 0x7F, but allow a bunch of Windows-1252 codes that some games use */ + if (byte < 0x20 || byte > 0xF0) + goto fail; + } + +fail: + if (buf) buf[0] = '\0'; + return 0; +} + +size_t read_string_utf16(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf, int big_endian) { + size_t pos, offpos; + read_u16_t read_u16 = big_endian ? read_u16be : read_u16le; + + + for (pos = 0, offpos = 0; pos < buf_size; pos++, offpos += 2) { + char c = read_u16(offset + offpos, sf) & 0xFF; /* lower byte for now */ + if (buf) buf[pos] = c; + if (c == '\0') + return pos; + if (pos+1 == buf_size) { /* null at maxsize and don't validate (expected to be garbage) */ + if (buf) buf[pos] = '\0'; + return buf_size; + } + if (c < 0x20 || (uint8_t)c > 0xA5) + goto fail; + } + +fail: + if (buf) buf[0] = '\0'; + return 0; +} + +size_t read_string_utf16le(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf) { + return read_string_utf16(buf, buf_size, offset, sf, 0); +} +size_t read_string_utf16be(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf) { + return read_string_utf16(buf, buf_size, offset, sf, 1); +} diff --git a/src/util/reader_put.c b/src/util/reader_put.c deleted file mode 100644 index ed04f154..00000000 --- a/src/util/reader_put.c +++ /dev/null @@ -1,29 +0,0 @@ -#include "reader_put.h" - -void put_8bit(uint8_t * buf, int8_t i) { - buf[0] = i; -} - -void put_16bitLE(uint8_t * buf, int16_t i) { - buf[0] = (i & 0xFF); - buf[1] = i >> 8; -} - -void put_32bitLE(uint8_t * buf, int32_t i) { - buf[0] = (uint8_t)(i & 0xFF); - buf[1] = (uint8_t)((i >> 8) & 0xFF); - buf[2] = (uint8_t)((i >> 16) & 0xFF); - buf[3] = (uint8_t)((i >> 24) & 0xFF); -} - -void put_16bitBE(uint8_t * buf, int16_t i) { - buf[0] = i >> 8; - buf[1] = (i & 0xFF); -} - -void put_32bitBE(uint8_t * buf, int32_t i) { - buf[0] = (uint8_t)((i >> 24) & 0xFF); - buf[1] = (uint8_t)((i >> 16) & 0xFF); - buf[2] = (uint8_t)((i >> 8) & 0xFF); - buf[3] = (uint8_t)(i & 0xFF); -} diff --git a/src/util/reader_text.h b/src/util/reader_text.h new file mode 100644 index 00000000..f18b2092 --- /dev/null +++ b/src/util/reader_text.h @@ -0,0 +1,21 @@ +#ifndef _READER_TEXT_H +#define _READER_TEXT_H +#include "../streamfile.h" + + +/* Read into dst a line delimited by CRLF (Windows) / LF (Unux) / CR (Mac) / EOF, null-terminated + * and without line feeds. Returns bytes read (including CR/LF), *not* the same as string length. + * p_line_ok is set to 1 if the complete line was read; pass NULL to ignore. */ +size_t read_line(char* buf, int buf_size, off_t offset, STREAMFILE* sf, int* p_line_ok); + +/* skip BOM if needed */ +size_t read_bom(STREAMFILE* sf); + +/* reads a c-string (ANSI only), up to bufsize or NULL, returning size. buf is optional (works as get_string_size). */ +size_t read_string(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf); +/* reads a UTF16 string... but actually only as ANSI (discards the upper byte) */ +size_t read_string_utf16(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf, int big_endian); +size_t read_string_utf16le(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf); +size_t read_string_utf16be(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf); + +#endif