12#ifdef MXIO_MINFO_MFILE
13#define ASSIGN_M_FILE(X) m_info.hmmio = (HMMIO) (X)
14#define M_FILE (HFILE)(m_info.hmmio)
15#define RAW_M_FILE m_info.hmmio
17#define ASSIGN_M_FILE(X) m_file = (X)
18#define M_FILE (m_file)
19#define RAW_M_FILE m_file
41 MxU16 result = MMSYSERR_NOERROR;
49 if (
M_FILE != HFILE_ERROR) {
51 if (
m_info.dwFlags & MMIO_ALLOCBUF) {
59 char* buf =
new char[len];
62 m_info.dwFlags &= ~MMIO_ALLOCBUF;
65 result = MMIOERR_OUTOFMEMORY;
69 m_info.pchBuffer = (HPSTR) buf;
77 result = MMIOERR_CANNOTOPEN;
87 MxU16 result = MMSYSERR_NOERROR;
94 if (
m_info.dwFlags & MMIO_ALLOCBUF) {
117 if (p_len < bytesLeft) {
121 memcpy(p_buf,
m_info.pchNext, bytesLeft);
123 m_info.pchNext += bytesLeft;
124 bytesRead += bytesLeft;
134 if (bytesLeft <= 0) {
142 bytesRead = _hread(
M_FILE, p_buf, p_len);
144 if (bytesRead == -1) {
149 m_info.lDiskOffset += bytesRead;
167 if (p_len < bytesLeft) {
171 memcpy(
m_info.pchNext, p_buf, bytesLeft);
172 m_info.dwFlags |= MMIO_DIRTY;
174 m_info.pchNext += bytesLeft;
175 bytesWritten += bytesLeft;
186 if (bytesLeft <= 0) {
195 bytesWritten = _hwrite(
M_FILE, (
const char*) p_buf, p_len);
197 if (bytesWritten == -1) {
202 m_info.lDiskOffset += bytesWritten;
222 if (p_origin == SEEK_CUR) {
233 else if (p_origin == SEEK_END) {
242 if (p_offset >=
m_info.lBufOffset && p_offset <
m_info.lBufOffset +
m_info.cchBuffer) {
249 m_info.lDiskOffset = _llseek(
M_FILE, p_offset, p_origin);
251 if (
m_info.lDiskOffset == -1) {
257 m_info.lBufOffset = p_offset - (p_offset %
m_info.cchBuffer);
261 if (p_offset !=
m_info.lBufOffset) {
264 if (
m_info.lDiskOffset == -1) {
271 if ((
m_info.dwFlags & MMIO_RWMODE) == 0 || (
m_info.dwFlags & MMIO_RWMODE) == MMIO_READWRITE) {
275 if (bytesRead == -1) {
279 m_info.lDiskOffset += bytesRead;
300 if (p_origin == SEEK_CUR && p_offset == 0) {
301 return m_info.lDiskOffset;
304 m_info.lDiskOffset = _llseek(
M_FILE, p_offset, p_origin);
306 result =
m_info.lDiskOffset;
320 MxU16 result = MMSYSERR_NOERROR;
323 if (
m_info.dwFlags & MMIO_ALLOCBUF) {
324 m_info.dwFlags &= ~MMIO_ALLOCBUF;
325 delete[]
m_info.pchBuffer;
340 MxU16 result = MMSYSERR_NOERROR;
344 if (
m_info.dwFlags & MMIO_DIRTY) {
358 result = MMIOERR_CANNOTSEEK;
362 bytesWritten = _hwrite(
M_FILE,
m_info.pchBuffer, cchBuffer);
364 if (bytesWritten == -1 || bytesWritten != cchBuffer) {
365 result = MMIOERR_CANNOTWRITE;
369 m_info.lDiskOffset += bytesWritten;
371 m_info.dwFlags &= ~MMIO_DIRTY;
377 result = MMIOERR_CANNOTWRITE;
381 result = MMIOERR_UNBUFFERED;
392 MxU16 result = MMSYSERR_NOERROR;
402 if ((rwmode == MMIO_WRITE || rwmode == MMIO_READWRITE) && (
m_info.dwFlags & MMIO_DIRTY) &&
403 ((p_option & MMIO_WRITE) || (rwmode == MMIO_READWRITE)) && cch > 0) {
410 result = MMIOERR_CANNOTSEEK;
416 if (bytesCounter == -1 || bytesCounter != cch) {
417 result = MMIOERR_CANNOTWRITE;
421 m_info.lDiskOffset += bytesCounter;
424 m_info.dwFlags &= ~MMIO_DIRTY;
430 if ((!rwmode || rwmode == MMIO_READWRITE) && cch > 0) {
437 result = MMIOERR_CANNOTSEEK;
443 if (bytesCounter == -1) {
444 result = MMIOERR_CANNOTREAD;
448 m_info.lDiskOffset += bytesCounter;
456 result = MMIOERR_UNBUFFERED;
466 MxU16 result = MMSYSERR_NOERROR;
475 p_chunkInfo->dwFlags = 0;
476 if (
Read(p_chunkInfo, 8) != 8) {
477 result = MMIOERR_CANNOTREAD;
484 p_chunkInfo->dwDataOffset =
m_info.lDiskOffset;
487 if ((p_chunkInfo->ckid == FOURCC_RIFF || p_chunkInfo->ckid == FOURCC_LIST) &&
488 Read(&p_chunkInfo->fccType, 4) != 4) {
489 result = MMIOERR_CANNOTREAD;
497 ofs = p_parentInfo->cksize + p_parentInfo->dwDataOffset;
506 if (
Read(&tmp, 8) != 8) {
508 result = readOk ? MMIOERR_CHUNKNOTFOUND : MMIOERR_CANNOTREAD;
517 tmp.dwDataOffset =
m_info.lDiskOffset;
520 if (ofs < tmp.dwDataOffset) {
521 result = MMIOERR_CHUNKNOTFOUND;
524 else if ((p_descend == MMIO_FINDLIST && tmp.ckid == FOURCC_LIST) || (p_descend == MMIO_FINDRIFF && tmp.ckid == FOURCC_RIFF)) {
525 if (
Read(&tmp.fccType, 4) != 4) {
526 result = MMIOERR_CANNOTREAD;
529 else if (p_chunkInfo->fccType == tmp.fccType) {
533 else if (p_chunkInfo->ckid == tmp.ckid) {
536 else if (
Seek((tmp.cksize & 1) + tmp.cksize, SEEK_CUR) == -1) {
537 result = MMIOERR_CANNOTSEEK;
557 MxU16 result = MMSYSERR_NOERROR;
559 if (p_chunkInfo ==
NULL) {
563 if (
m_info.dwFlags & MMIO_RWMODE) {
568 size =
m_info.lDiskOffset - p_chunkInfo->dwDataOffset;
576 if ((p_chunkInfo->dwFlags & MMIO_DIRTY) && p_chunkInfo->cksize != size) {
577 ofs = p_chunkInfo->dwDataOffset - 4;
579 p_chunkInfo->cksize = size;
580 p_chunkInfo->dwFlags &= ~MMIO_DIRTY;
584 memcpy(
m_info.pchBuffer + (ofs -
m_info.lBufOffset), (
char*) &size, 4);
585 m_info.dwFlags |= MMIO_DIRTY;
590 if (
m_info.lDiskOffset == ofs) {
591 if (_lwrite(
M_FILE, (
char*) &size, 4) != 4) {
593 result = MMIOERR_CANNOTWRITE;
601 result = MMIOERR_CANNOTSEEK;
608 if (result == MMSYSERR_NOERROR &&
609 Seek((p_chunkInfo->cksize & 1) + p_chunkInfo->cksize + p_chunkInfo->dwDataOffset, SEEK_SET) == -1) {
610 result = MMIOERR_CANNOTSEEK;
619 MxU16 result = MMSYSERR_NOERROR;
621 if (p_chunkInfo ==
NULL) {
625 if (p_create == MMIO_CREATERIFF) {
626 p_chunkInfo->ckid = FOURCC_RIFF;
628 if (p_create == MMIO_CREATELIST) {
629 p_chunkInfo->ckid = FOURCC_LIST;
632 p_chunkInfo->dwDataOffset =
Seek(0, SEEK_CUR);
633 if (p_chunkInfo->dwDataOffset == -1) {
634 result = MMIOERR_CANNOTSEEK;
637 p_chunkInfo->dwDataOffset += 8;
641 if (p_chunkInfo->ckid == FOURCC_RIFF || p_chunkInfo->ckid == FOURCC_LIST) {
648 if (
Write(p_chunkInfo, size) != size) {
649 result = MMIOERR_CANNOTWRITE;
652 p_chunkInfo->dwFlags = MMIO_DIRTY;
[AI] A wrapper for low-level file I/O, abstracting MMIOINFO functionality, and providing additional b...
MxU16 Descend(MMCKINFO *p_chunkInfo, const MMCKINFO *p_parentInfo, MxU16 p_descend)
[AI] Descends into a specific RIFF or LIST chunk in a hierarchical file, reading chunk headers and up...
MxLong Seek(MxLong p_offset, MxLong p_origin)
[AI] Seeks to a specific position in the file (or file buffer).
MxU16 Advance(MxU16 p_option)
[AI] Advances the buffer state for reading/writing the next block, committing dirty writes and loadin...
~MXIOINFO()
[AI] Destructor, closes the file and releases all memory associated with buffers if necessary.
MxU16 SetBuffer(char *p_buf, MxLong p_len, MxLong p_unused)
[AI] Changes the buffer used for internal I/O (applies and releases old buffer if owned).
MxU16 Ascend(MMCKINFO *p_chunkInfo, MxU16 p_ascend)
[AI] Ascends from a chunk in a hierarchical file, correcting chunk size and finishing the chunk corre...
MxLong Read(void *p_buf, MxLong p_len)
[AI] Reads a number of bytes from the file or buffer into the destination buffer.
MXIOINFO()
[AI] Constructs a new MXIOINFO instance and initializes all struct members to zero.
MxLong Write(void *p_buf, MxLong p_len)
[AI] Writes data to the file or internal buffer.
MxU16 CreateChunk(MMCKINFO *p_chunkInfo, MxU16 p_create)
[AI] Creates a new hierarchical chunk (RIFF or LIST or other type), writing initial chunk header.
MxU16 Open(const char *p_filename, MxULong p_flags)
[AI] Opens a file for buffered/unbuffered I/O, initializing MMIOINFO and (optionally) internal buffer...
MMIOINFO m_info
[AI] Underlying MMIOINFO structure used for buffered and low-level file I/O.
MxU16 Flush(MxU16 p_unused)
[AI] Flushes contents of the buffer to disk if necessary (e.g., if data is dirty).
MxU16 Close(MxLong p_unused)
[AI] Closes the file and releases its resources, including buffer memory if owned.
#define DECOMP_SIZE_ASSERT(T, S)
#define NULL
[AI] Null pointer value (C/C++ semantics).