cleanup: separate functions

move common functions to its own .h so it's clearer where are they used and don't get copied in all headers
This commit is contained in:
bnnm 2023-05-14 21:20:29 +02:00
parent ff34edfa91
commit bf218c08b4
26 changed files with 219 additions and 193 deletions

View File

@ -1,5 +1,6 @@
#include "../vgmstream.h"
#include "../util/log.h"
#include "../util/reader_sf.h"
#include "plugins.h"
#include "mixing.h"

View File

@ -2,6 +2,7 @@
#define _CODING_H
#include "../vgmstream.h"
#include "../util/reader_sf.h"
#include "../util/reader_get_nibbles.h"
//todo remove
#include "hca_decoder_clhca.h"

View File

@ -61,7 +61,7 @@
#include <stdlib.h>
#include "nwa_decoder.h"
#include "../util/reader_sf.h"
//NWAInfo::UseRunLength
static int is_use_runlength(NWAData* nwa) {

View File

@ -3,6 +3,7 @@
#include "../streamtypes.h"
#include "../vgmstream.h"
#include "../util/reader_sf.h"
/* blocked layouts */
void render_vgmstream_blocked(sample_t* buffer, int32_t sample_count, VGMSTREAM* vgmstream);

View File

@ -1,5 +1,7 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util/endianness.h"
/* .BAF - Bizarre Creations bank file [Blur (PS3), Project Gotham Racing 4 (X360), Geometry Wars (PC)] */
VGMSTREAM * init_vgmstream_baf(STREAMFILE *sf) {
@ -8,7 +10,7 @@ VGMSTREAM * init_vgmstream_baf(STREAMFILE *sf) {
size_t stream_size;
uint32_t channel_count, sample_rate, num_samples, version, codec, tracks;
int loop_flag, total_subsongs, target_subsong = sf->stream_index;
uint32_t (*read_u32)(off_t,STREAMFILE*);
read_u32_t read_u32;
/* checks */
if (!is_id32be(0x00, sf, "BANK"))
@ -18,7 +20,7 @@ VGMSTREAM * init_vgmstream_baf(STREAMFILE *sf) {
goto fail;
/* use BANK size to check endianness */
if (guess_endianness32bit(0x04,sf)) {
if (guess_endian32(0x04,sf)) {
read_u32 = read_u32be;
} else {
read_u32 = read_u32le;

View File

@ -1,6 +1,7 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util/chunks.h"
#include "../util/endianness.h"
/* BKHD - Wwise soundbank container */
@ -10,8 +11,8 @@ VGMSTREAM* init_vgmstream_bkhd(STREAMFILE* sf) {
uint32_t subfile_offset, subfile_size, base_offset = 0;
uint32_t subfile_id, version;
int big_endian, is_dummy = 0, is_wmid = 0;
uint32_t (*read_u32)(off_t,STREAMFILE*);
float (*read_f32)(off_t,STREAMFILE*);
read_u32_t read_u32;
read_f32_t read_f32;
int total_subsongs, target_subsong = sf->stream_index;
int prefetch = 0;
@ -24,7 +25,7 @@ VGMSTREAM* init_vgmstream_bkhd(STREAMFILE* sf) {
base_offset = 0x0c;
if (!is_id32be(base_offset + 0x00, sf, "BKHD"))
goto fail;
big_endian = guess_endianness32bit(base_offset + 0x04, sf);
big_endian = guess_endian32(base_offset + 0x04, sf);
read_u32 = big_endian ? read_u32be : read_u32le;
read_f32 = big_endian ? read_f32be : read_f32le;
@ -200,7 +201,7 @@ VGMSTREAM* init_vgmstream_bkhd_fx(STREAMFILE* sf) {
/* .wem: used when (rarely) external */
if (!check_extensions(sf,"wem,bnk"))
goto fail;
big_endian = guess_endianness32bit(0x00, sf);
big_endian = guess_endian32(0x00, sf);
read_u32 = big_endian ? read_u32be : read_u32le;
/* Not an actual stream but typically convolution reverb models and other FX plugin helpers.

View File

@ -2,6 +2,7 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../coding/coding.h"
#include "../util/endianness.h"
#include "ea_eaac_streamfile.h"
/* EAAudioCore (aka SND10) formats, EA's current audio middleware */
@ -85,7 +86,7 @@ VGMSTREAM* init_vgmstream_ea_snu(STREAMFILE* sf) {
* 0x0c(4): some sub-offset? (0x20, found when @0x01 is set) */
/* use start_offset as endianness flag */
if (guess_endianness32bit(0x08,sf)) {
if (guess_endian32(0x08,sf)) {
read_32bit = read_32bitBE;
} else {
read_32bit = read_32bitLE;
@ -125,7 +126,7 @@ VGMSTREAM* init_vgmstream_ea_abk_eaac(STREAMFILE* sf) {
goto fail;
/* use table offset to check endianness */
if (guess_endianness32bit(0x1C, sf)) {
if (guess_endian32(0x1C, sf)) {
read_32bit = read_32bitBE;
read_16bit = read_16bitBE;
} else {

View File

@ -1,6 +1,7 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../coding/coding.h"
#include "../util/endianness.h"
#include "ea_schl_streamfile.h"
/* header version */
@ -222,7 +223,7 @@ VGMSTREAM* init_vgmstream_ea_schl_video(STREAMFILE* sf) {
}
/* use block size to check endianness */
if (guess_endianness32bit(0x04, sf)) {
if (guess_endian32(0x04, sf)) {
read_32bit = read_32bitBE;
} else {
read_32bit = read_32bitLE;
@ -329,7 +330,7 @@ VGMSTREAM* init_vgmstream_ea_abk(STREAMFILE* sf) {
goto fail;
/* use table offset to check endianness */
if (guess_endianness32bit(0x1C, sf)) {
if (guess_endian32(0x1C, sf)) {
read_32bit = read_32bitBE;
read_16bit = read_16bitBE;
} else {
@ -1142,7 +1143,7 @@ static VGMSTREAM* parse_schl_block(STREAMFILE* sf, off_t offset) {
ea.codec_config |= (header_id & 0xFFFF) << 16;
}
if (guess_endianness32bit(offset + 0x04, sf)) { /* size is always LE, except in early SS/MAC */
if (guess_endian32(offset + 0x04, sf)) { /* size is always LE, except in early SS/MAC */
header_size = read_32bitBE(offset + 0x04, sf);
ea.codec_config |= 0x02;
}

View File

@ -1,6 +1,7 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../layout/layout.h"
#include "../util/endianness.h"
/* EA WVE (Ad10) - from early Electronic Arts movies [Wing Commander 3/4 (PS1), Madden NHL 97 (PC)-w95] */
VGMSTREAM* init_vgmstream_ea_wve_ad10(STREAMFILE* sf) {
@ -22,7 +23,7 @@ VGMSTREAM* init_vgmstream_ea_wve_ad10(STREAMFILE* sf) {
!is_id32be(0x00, sf, "Ad11")) /* last audio block, but could be first */
goto fail;
big_endian = guess_endianness32bit(0x04, sf);
big_endian = guess_endian32(0x04, sf);
if (is_id32be(0x00, sf, "AABB"))
start_offset += big_endian ? read_u32be(0x04, sf) : read_u32le(0x04, sf);

View File

@ -1,5 +1,6 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util/endianness.h"
typedef enum { PCM16, MSADPCM, DSP_HEAD, DSP_BODY, AT9, MSF_APEX, XMA2 } kwb_codec;
@ -594,7 +595,7 @@ static int parse_kwb(kwb_header* kwb, STREAMFILE* sf_h, STREAMFILE* sf_b) {
head_offset = 0x00;
body_offset = 0x00;
kwb->big_endian = guess_endianness32bit(head_offset + 0x08, sf_h);
kwb->big_endian = guess_endian32(head_offset + 0x08, sf_h);
read_u32 = kwb->big_endian ? read_u32be : read_u32le;
}

View File

@ -2,6 +2,7 @@
#define _META_H
#include "../vgmstream.h"
#include "../util/reader_sf.h"
typedef VGMSTREAM* (*init_vgmstream_t)(STREAMFILE* sf);

View File

@ -33,7 +33,7 @@ VGMSTREAM* init_vgmstream_mul(STREAMFILE* sf) {
read_u32be(0x1c,sf) != 0)
goto fail;
big_endian = guess_endianness32bit(0x00, sf);
big_endian = guess_endian32(0x00, sf);
read_u32 = big_endian ? read_u32be : read_u32le;
read_f32 = big_endian ? read_f32be : read_f32le;

View File

@ -1,5 +1,6 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util/endianness.h"
static void load_name(char* name, size_t name_size, STREAMFILE* sf, int big_endian, int total_subsongs, int target_subsong);
@ -33,7 +34,7 @@ VGMSTREAM* init_vgmstream_nub(STREAMFILE* sf) {
goto fail;
/* sometimes LE [Soul Calibur: Broken Destiny (PSP), Tales of Vesperia (PS4) */
big_endian = guess_endianness32bit(0x18, sf);
big_endian = guess_endian32(0x18, sf);
if (big_endian) {
read_32bit = read_32bitBE;
} else{
@ -249,7 +250,7 @@ VGMSTREAM* init_vgmstream_nub_wav(STREAMFILE* sf) {
if (read_32bitBE(0x00,sf) != 0x77617600) /* "wav\0" "*/
goto fail;
if (guess_endianness32bit(0x1c, sf)) {
if (guess_endian32(0x1c, sf)) {
read_32bit = read_32bitBE;
read_16bit = read_16bitBE;
} else {
@ -313,7 +314,7 @@ VGMSTREAM* init_vgmstream_nub_vag(STREAMFILE* sf) {
if (read_32bitBE(0x00,sf) != 0x76616700) /* "vag\0" */
goto fail;
if (guess_endianness32bit(0x1c, sf)) {
if (guess_endian32(0x1c, sf)) {
read_32bit = read_32bitBE;
} else {
read_32bit = read_32bitLE;
@ -598,7 +599,7 @@ VGMSTREAM* init_vgmstream_nub_is14(STREAMFILE* sf) {
if (read_32bitBE(0x00,sf) != 0x69733134) /* "is14" */
goto fail;
if (guess_endianness32bit(0x1c, sf)) {
if (guess_endian32(0x1c, sf)) {
read_32bit = read_32bitBE;
} else{
read_32bit = read_32bitLE;

View File

@ -1,5 +1,7 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util/endianness.h"
/* SEG - from Stormfront games [Eragon (multi), Forgotten Realms: Demon Stone (multi) */
VGMSTREAM* init_vgmstream_seg(STREAMFILE* sf) {
@ -19,7 +21,7 @@ VGMSTREAM* init_vgmstream_seg(STREAMFILE* sf) {
codec = read_32bitBE(0x04,sf);
/* 0x08: version? (2: Eragon, Spiderwick Chronicles Wii / 3: Spiderwick Chronicles X360 / 4: Spiderwick Chronicles PC) */
if (guess_endianness32bit(0x08,sf)) {
if (guess_endian32(0x08,sf)) {
read_32bit = read_32bitBE;
} else {
read_32bit = read_32bitLE;

View File

@ -1,6 +1,7 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../coding/coding.h"
#include "../util/endianness.h"
/* also see init_vgmstream_dsp_sps_n1 and init_vgmstream_opus_sps_n1 */
@ -21,7 +22,7 @@ VGMSTREAM* init_vgmstream_sps_n1(STREAMFILE* sf) {
if (!check_extensions(sf,"sps"))
goto fail;
if (guess_endianness32bit(0x00, sf)) { /* PS3 */
if (guess_endian32(0x00, sf)) { /* PS3 */
read_u32 = read_u32be;
read_u16 = read_u16be;
}

View File

@ -1,5 +1,6 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util/endianness.h"
/* SSPR - Capcom container [Sengoku Basara 4 (PS3/PS4), Mega Man Zero ZX Legacy Collection (PS4)] */
VGMSTREAM* init_vgmstream_sspr(STREAMFILE* sf) {
@ -21,7 +22,7 @@ VGMSTREAM* init_vgmstream_sspr(STREAMFILE* sf) {
/* Simple (audio only) container used some Capcom games (common engine?).
* Some files come with a .stqr with unknown data (cues?). */
big_endian = guess_endianness32bit(0x04, sf); /* 0x01 (version?) */
big_endian = guess_endian32(0x04, sf); /* 0x01 (version?) */
read_u32 = big_endian ? read_u32be : read_u32le;
total_subsongs = read_u32(0x08,sf);

View File

@ -1,6 +1,7 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../coding/coding.h"
#include "../util/endianness.h"
#include "ubi_bao_streamfile.h"
#define BAO_MIN_VERSION 0x1B
@ -1570,7 +1571,7 @@ static void config_bao_endian(ubi_bao_header* bao, off_t offset, STREAMFILE* sf)
* This could be done once as all BAOs share endianness */
/* negate as fields looks like LE (0xN0000000) */
bao->big_endian = !guess_endianness32bit(offset+bao->cfg.bao_class, sf);
bao->big_endian = !guess_endian32(offset+bao->cfg.bao_class, sf);
}
@ -1714,7 +1715,7 @@ static int config_bao_version(ubi_bao_header* bao, STREAMFILE* sf) {
/* next BAO uses machine endianness, entry should always exist
* (maybe should use project BAO to detect?) */
if (guess_endianness32bit(header_size + 0x04, sf)) {
if (guess_endian32(header_size + 0x04, sf)) {
version |= 0xFF00; /* signal Wii=BE, but don't modify original */
}
}

View File

@ -1,6 +1,6 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../coding/coding.h"
#include "../util/endianness.h"
typedef enum { MSADPCM, DSP, MP3, XMA2 } ckd_codec;
@ -30,7 +30,7 @@ VGMSTREAM* init_vgmstream_ubi_ckd(STREAMFILE* sf) {
if (!is_id32be(0x0c,sf, "fmt "))
goto fail;
big_endian = guess_endianness32bit(0x04, sf);
big_endian = guess_endian32(0x04, sf);
read_u32 = big_endian ? read_u32be : read_u32le;
read_u16 = big_endian ? read_u16be : read_u16le;

View File

@ -1,6 +1,7 @@
#include "streamfile.h"
#include "util.h"
#include "vgmstream.h"
#include "util/reader_sf.h"
#include <string.h>
/* for dup/fdopen in some systems */

View File

@ -161,169 +161,6 @@ static inline size_t get_streamfile_size(STREAMFILE* sf) {
}
/* Sometimes you just need an int, and we're doing the buffering.
* Note, however, that if these fail to read they'll return -1,
* so that should not be a valid value or there should be some backup. */
static inline int16_t read_16bitLE(off_t offset, STREAMFILE* sf) {
uint8_t buf[2];
if (read_streamfile(buf,offset,2,sf)!=2) return -1;
return get_16bitLE(buf);
}
static inline int16_t read_16bitBE(off_t offset, STREAMFILE* sf) {
uint8_t buf[2];
if (read_streamfile(buf,offset,2,sf)!=2) return -1;
return get_16bitBE(buf);
}
static inline int32_t read_32bitLE(off_t offset, STREAMFILE* sf) {
uint8_t buf[4];
if (read_streamfile(buf,offset,4,sf)!=4) return -1;
return get_32bitLE(buf);
}
static inline int32_t read_32bitBE(off_t offset, STREAMFILE* sf) {
uint8_t buf[4];
if (read_streamfile(buf,offset,4,sf)!=4) return -1;
return get_32bitBE(buf);
}
static inline int64_t read_64bitLE(off_t offset, STREAMFILE* sf) {
uint8_t buf[8];
if (read_streamfile(buf,offset,8,sf)!=8) return -1;
return get_64bitLE(buf);
}
static inline int64_t read_64bitBE(off_t offset, STREAMFILE* sf) {
uint8_t buf[8];
if (read_streamfile(buf,offset,8,sf)!=8) return -1;
return get_64bitBE(buf);
}
static inline int8_t read_8bit(off_t offset, STREAMFILE* sf) {
uint8_t buf[1];
if (read_streamfile(buf,offset,1,sf)!=1) return -1;
return buf[0];
}
/* alias of the above */
static inline int8_t read_s8 (off_t offset, STREAMFILE* sf) { return read_8bit(offset, sf); }
static inline uint8_t read_u8 (off_t offset, STREAMFILE* sf) { return (uint8_t) read_8bit(offset, sf); }
static inline int16_t read_s16le(off_t offset, STREAMFILE* sf) { return read_16bitLE(offset, sf); }
static inline uint16_t read_u16le(off_t offset, STREAMFILE* sf) { return (uint16_t)read_16bitLE(offset, sf); }
static inline int16_t read_s16be(off_t offset, STREAMFILE* sf) { return read_16bitBE(offset, sf); }
static inline uint16_t read_u16be(off_t offset, STREAMFILE* sf) { return (uint16_t)read_16bitBE(offset, sf); }
static inline int32_t read_s32le(off_t offset, STREAMFILE* sf) { return read_32bitLE(offset, sf); }
static inline uint32_t read_u32le(off_t offset, STREAMFILE* sf) { return (uint32_t)read_32bitLE(offset, sf); }
static inline int32_t read_s32be(off_t offset, STREAMFILE* sf) { return read_32bitBE(offset, sf); }
static inline uint32_t read_u32be(off_t offset, STREAMFILE* sf) { return (uint32_t)read_32bitBE(offset, sf); }
static inline int64_t read_s64be(off_t offset, STREAMFILE* sf) { return read_64bitBE(offset, sf); }
static inline uint64_t read_u64be(off_t offset, STREAMFILE* sf) { return (uint64_t)read_64bitBE(offset, sf); }
static inline int64_t read_s64le(off_t offset, STREAMFILE* sf) { return read_64bitLE(offset, sf); }
static inline uint64_t read_u64le(off_t offset, STREAMFILE* sf) { return (uint64_t)read_64bitLE(offset, sf); }
static inline float read_f32be(off_t offset, STREAMFILE* sf) {
uint8_t buf[4];
if (read_streamfile(buf, offset, sizeof(buf), sf) != sizeof(buf))
return -1;
return get_f32be(buf);
}
static inline float read_f32le(off_t offset, STREAMFILE* sf) {
uint8_t buf[4];
if (read_streamfile(buf, offset, sizeof(buf), sf) != sizeof(buf))
return -1;
return get_f32le(buf);
}
#if 0
// on GCC, this reader will be correctly optimized out (as long as it's static/inline), would be same as declaring:
// uintXX_t (*read_uXX)(off_t,uint8_t*) = be ? get_uXXbe : get_uXXle;
// only for the functions actually used in code, and inlined if possible (like big_endian param being a constant).
// on MSVC seems all read_X in sf_reader are compiled and included in the translation unit, plus ignores constants
// so may result on bloatness?
// (from godbolt tests, test more real cases)
/* collection of callbacks for quick access */
typedef struct sf_reader {
int32_t (*read_s32)(off_t,STREAMFILE*); //maybe r.s32
float (*read_f32)(off_t,STREAMFILE*);
/* ... */
} sf_reader;
static inline void sf_reader_init(sf_reader* r, int big_endian) {
memset(r, 0, sizeof(sf_reader));
if (big_endian) {
r->read_s32 = read_s32be;
r->read_f32 = read_f32be;
}
else {
r->read_s32 = read_s32le;
r->read_f32 = read_f32le;
}
}
/* sf_reader r;
* ...
* sf_reader_init(&r, big_endian);
* val = r.read_s32; //maybe r.s32?
*/
#endif
#if 0 //todo improve + test + simplify code (maybe not inline?)
static inline int read_s4h(off_t offset, STREAMFILE* sf) {
uint8_t byte = read_u8(offset, streamfile);
return get_nibble_signed(byte, 1);
}
static inline int read_u4h(off_t offset, STREAMFILE* sf) {
uint8_t byte = read_u8(offset, streamfile);
return (byte >> 4) & 0x0f;
}
static inline int read_s4l(off_t offset, STREAMFILE* sf) {
...
}
static inline int read_u4l(off_t offset, STREAMFILE* sf) {
...
}
static inline int max_s32(int32_t a, int32_t b) { return a > b ? a : b; }
static inline int min_s32(int32_t a, int32_t b) { return a < b ? a : b; }
//align32, align16, clamp16, etc
#endif
/* fastest to compare would be read_u32x == (uint32), but should be pre-optimized (see get_id32x) */
static inline /*const*/ int is_id32be(off_t offset, STREAMFILE* sf, const char* s) {
return read_u32be(offset, sf) == get_id32be(s);
}
static inline /*const*/ int is_id32le(off_t offset, STREAMFILE* sf, const char* s) {
return read_u32le(offset, sf) == get_id32be(s);
}
static inline /*const*/ int is_id64be(off_t offset, STREAMFILE* sf, const char* s) {
return read_u64be(offset, sf) == get_id64be(s);
}
//TODO: maybe move to streamfile.c
/* guess byte endianness from a given value, return true if big endian and false if little endian */
static inline int guess_endianness16bit(off_t offset, STREAMFILE* sf) {
uint8_t buf[0x02];
if (read_streamfile(buf, offset, 0x02, sf) != 0x02) return -1; /* ? */
return get_u16le(buf) > get_u16be(buf) ? 1 : 0;
}
static inline int guess_endianness32bit(off_t offset, STREAMFILE* sf) {
uint8_t buf[0x04];
if (read_streamfile(buf, offset, 0x04, sf) != 0x04) return -1; /* ? */
return get_u32le(buf) > get_u32be(buf) ? 1 : 0;
}
static inline size_t align_size_to_block(size_t value, size_t block_align) {
size_t extra_size = value % block_align;
if (extra_size == 0) return value;
return (value + block_align - extra_size);
}
/* various STREAMFILE helpers functions */
/* Read into dst a line delimited by CRLF (Windows) / LF (Unux) / CR (Mac) / EOF, null-terminated

View File

@ -42,3 +42,12 @@ void concatn(int length, char * dst, const char * src) {
dst[i]=src[j];
dst[i]='\0';
}
size_t align_size_to_block(size_t value, size_t block_align) {
if (!block_align)
return 0;
size_t extra_size = value % block_align;
if (extra_size == 0) return value;
return (value + block_align - extra_size);
}

View File

@ -51,4 +51,6 @@ const char* filename_extension(const char* pathname);
void concatn(int length, char * dst, const char * src);
size_t align_size_to_block(size_t value, size_t block_align);
#endif

View File

@ -1,5 +1,5 @@
#include "chunks.h"
//#include "log.h"
#include "reader_sf.h"
int next_chunk(chunk_t* chunk, STREAMFILE* sf) {

View File

@ -1,5 +1,6 @@
#include "cri_utf.h"
#include "log.h"
#include "reader_sf.h"
#define UTF_MAX_SCHEMA_SIZE 0x8000 /* arbitrary max */
#define COLUMN_BITMASK_FLAG 0xf0

View File

@ -2,6 +2,7 @@
#define _UTIL_ENDIAN_H
#include "../streamfile.h"
#include "reader_get.h"
typedef uint32_t (*read_u32_t)(off_t, STREAMFILE*);
typedef int32_t (*read_s32_t)(off_t, STREAMFILE*);
@ -11,8 +12,17 @@ typedef float (*read_f32_t)(off_t, STREAMFILE*);
typedef int16_t (*get_s16_t)(const uint8_t*);
//todo move here
#define guess_endian32 guess_endianness32bit
#define guess_endian16 guess_endianness16bit
/* guess byte endianness from a given value, return true if big endian and false if little endian */
static inline int guess_endian16(off_t offset, STREAMFILE* sf) {
uint8_t buf[0x02];
if (read_streamfile(buf, offset, 0x02, sf) != 0x02) return -1; /* ? */
return get_u16le(buf) > get_u16be(buf) ? 1 : 0;
}
static inline int guess_endian32(off_t offset, STREAMFILE* sf) {
uint8_t buf[0x04];
if (read_streamfile(buf, offset, 0x04, sf) != 0x04) return -1; /* ? */
return get_u32le(buf) > get_u32be(buf) ? 1 : 0;
}
#endif

149
src/util/reader_sf.h Normal file
View File

@ -0,0 +1,149 @@
#ifndef _READER_SF_H
#define _READER_SF_H
#include "../streamfile.h"
/* Sometimes you just need an int, and we're doing the buffering.
* Note, however, that if these fail to read they'll return -1,
* so that should not be a valid value or there should be some backup. */
static inline int16_t read_16bitLE(off_t offset, STREAMFILE* sf) {
uint8_t buf[2];
if (read_streamfile(buf,offset,2,sf)!=2) return -1;
return get_16bitLE(buf);
}
static inline int16_t read_16bitBE(off_t offset, STREAMFILE* sf) {
uint8_t buf[2];
if (read_streamfile(buf,offset,2,sf)!=2) return -1;
return get_16bitBE(buf);
}
static inline int32_t read_32bitLE(off_t offset, STREAMFILE* sf) {
uint8_t buf[4];
if (read_streamfile(buf,offset,4,sf)!=4) return -1;
return get_32bitLE(buf);
}
static inline int32_t read_32bitBE(off_t offset, STREAMFILE* sf) {
uint8_t buf[4];
if (read_streamfile(buf,offset,4,sf)!=4) return -1;
return get_32bitBE(buf);
}
static inline int64_t read_64bitLE(off_t offset, STREAMFILE* sf) {
uint8_t buf[8];
if (read_streamfile(buf,offset,8,sf)!=8) return -1;
return get_64bitLE(buf);
}
static inline int64_t read_64bitBE(off_t offset, STREAMFILE* sf) {
uint8_t buf[8];
if (read_streamfile(buf,offset,8,sf)!=8) return -1;
return get_64bitBE(buf);
}
static inline int8_t read_8bit(off_t offset, STREAMFILE* sf) {
uint8_t buf[1];
if (read_streamfile(buf,offset,1,sf)!=1) return -1;
return buf[0];
}
/* alias of the above */
static inline int8_t read_s8 (off_t offset, STREAMFILE* sf) { return read_8bit(offset, sf); }
static inline uint8_t read_u8 (off_t offset, STREAMFILE* sf) { return (uint8_t) read_8bit(offset, sf); }
static inline int16_t read_s16le(off_t offset, STREAMFILE* sf) { return read_16bitLE(offset, sf); }
static inline uint16_t read_u16le(off_t offset, STREAMFILE* sf) { return (uint16_t)read_16bitLE(offset, sf); }
static inline int16_t read_s16be(off_t offset, STREAMFILE* sf) { return read_16bitBE(offset, sf); }
static inline uint16_t read_u16be(off_t offset, STREAMFILE* sf) { return (uint16_t)read_16bitBE(offset, sf); }
static inline int32_t read_s32le(off_t offset, STREAMFILE* sf) { return read_32bitLE(offset, sf); }
static inline uint32_t read_u32le(off_t offset, STREAMFILE* sf) { return (uint32_t)read_32bitLE(offset, sf); }
static inline int32_t read_s32be(off_t offset, STREAMFILE* sf) { return read_32bitBE(offset, sf); }
static inline uint32_t read_u32be(off_t offset, STREAMFILE* sf) { return (uint32_t)read_32bitBE(offset, sf); }
static inline int64_t read_s64be(off_t offset, STREAMFILE* sf) { return read_64bitBE(offset, sf); }
static inline uint64_t read_u64be(off_t offset, STREAMFILE* sf) { return (uint64_t)read_64bitBE(offset, sf); }
static inline int64_t read_s64le(off_t offset, STREAMFILE* sf) { return read_64bitLE(offset, sf); }
static inline uint64_t read_u64le(off_t offset, STREAMFILE* sf) { return (uint64_t)read_64bitLE(offset, sf); }
static inline float read_f32be(off_t offset, STREAMFILE* sf) {
uint8_t buf[4];
if (read_streamfile(buf, offset, sizeof(buf), sf) != sizeof(buf))
return -1;
return get_f32be(buf);
}
static inline float read_f32le(off_t offset, STREAMFILE* sf) {
uint8_t buf[4];
if (read_streamfile(buf, offset, sizeof(buf), sf) != sizeof(buf))
return -1;
return get_f32le(buf);
}
#if 0
// on GCC, this reader will be correctly optimized out (as long as it's static/inline), would be same as declaring:
// uintXX_t (*read_uXX)(off_t,uint8_t*) = be ? get_uXXbe : get_uXXle;
// only for the functions actually used in code, and inlined if possible (like big_endian param being a constant).
// on MSVC seems all read_X in sf_reader are compiled and included in the translation unit, plus ignores constants
// so may result on bloatness?
// (from godbolt tests, test more real cases)
/* collection of callbacks for quick access */
typedef struct sf_reader {
int32_t (*read_s32)(off_t,STREAMFILE*); //maybe r.s32
float (*read_f32)(off_t,STREAMFILE*);
/* ... */
} sf_reader;
static inline void sf_reader_init(sf_reader* r, int big_endian) {
memset(r, 0, sizeof(sf_reader));
if (big_endian) {
r->read_s32 = read_s32be;
r->read_f32 = read_f32be;
}
else {
r->read_s32 = read_s32le;
r->read_f32 = read_f32le;
}
}
/* sf_reader r;
* ...
* sf_reader_init(&r, big_endian);
* val = r.read_s32; //maybe r.s32?
*/
#endif
#if 0 //todo improve + test + simplify code (maybe not inline?)
static inline int read_s4h(off_t offset, STREAMFILE* sf) {
uint8_t byte = read_u8(offset, streamfile);
return get_nibble_signed(byte, 1);
}
static inline int read_u4h(off_t offset, STREAMFILE* sf) {
uint8_t byte = read_u8(offset, streamfile);
return (byte >> 4) & 0x0f;
}
static inline int read_s4l(off_t offset, STREAMFILE* sf) {
...
}
static inline int read_u4l(off_t offset, STREAMFILE* sf) {
...
}
static inline int max_s32(int32_t a, int32_t b) { return a > b ? a : b; }
static inline int min_s32(int32_t a, int32_t b) { return a < b ? a : b; }
//align32, align16, clamp16, etc
#endif
/* fastest to compare would be read_u32x == (uint32), but should be pre-optimized (see get_id32x) */
static inline /*const*/ int is_id32be(off_t offset, STREAMFILE* sf, const char* s) {
return read_u32be(offset, sf) == get_id32be(s);
}
static inline /*const*/ int is_id32le(off_t offset, STREAMFILE* sf, const char* s) {
return read_u32le(offset, sf) == get_id32be(s);
}
static inline /*const*/ int is_id64be(off_t offset, STREAMFILE* sf, const char* s) {
return read_u64be(offset, sf) == get_id64be(s);
}
#endif