file-handling · advanced · ~15 min
Parse real-world binary multimedia containers with magic byte verification and bounds checking.
The RIFF WAV format is a ubiquitous binary container. The header specifies sample rate, audio channels, bit depth, and data chunk lengths encoded in Little-Endian format.
Given the parsed WAV header structure:
typedef struct {
uint16_t num_channels; // 1 for mono, 2 for stereo
uint32_t sample_rate; // e.g. 44100
uint16_t bits_per_sample;// e.g. 16
uint32_t data_bytes; // audio payload size
} WavHeaderInfo;
Implement:
int parse_wav_header(const uint8_t *raw, size_t len, WavHeaderInfo *out);
"RIFF""WAVE""fmt "num_channels (Little Endian)sample_rate (Little Endian)bits_per_sample (Little Endian)"data"data_bytes (Little Endian)raw == NULL, out == NULL, or len < 44, return -1."RIFF", bytes 8..11 == "WAVE", bytes 12..15 == "fmt ", bytes 36..39 == "data". If any mismatch, return -1.1.44 + (size_t)data_bytes <= len. If payload exceeds file, return -1.out and return 0.WavHeaderInfo info;
parse_wav_header(wav_bytes, 44 + 1000, &info); // returns 0, info.sample_rate == 44100
raw: pointer to binary WAV header; len: total buffer length; out: output struct.
Returns 0 on valid PCM WAV header, or -1 on invalid format/truncation.
Zero heap allocations. Little-endian integer decoding.
#include <stddef.h>
#include <stdint.h>
typedef struct {
uint16_t num_channels;
uint32_t sample_rate;
uint16_t bits_per_sample;
uint32_t data_bytes;
} WavHeaderInfo;
int parse_wav_header(const uint8_t *raw, size_t len, WavHeaderInfo *out) {
(void)raw; (void)len; (void)out;
return -1;
}
Decoding integers as big-endian instead of little-endian; ignoring audio format check.
len < 44 returns -1; audio format != 1 returns -1; data_bytes exceeding len returns -1.
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.