aboutsummaryrefslogtreecommitdiff
path: root/tests/freealut/src/alutInputStream.c
diff options
context:
space:
mode:
authorEhsan Akhgari <ehsan.akhgari@gmail.com>2013-04-06 12:36:08 -0700
committerEhsan Akhgari <ehsan.akhgari@gmail.com>2013-04-06 12:36:08 -0700
commit350a2b08b6b19e57abc57e6ae607edae97a66fa8 (patch)
tree5de65f8e9c83101a2444449d755a71785bb76436 /tests/freealut/src/alutInputStream.c
parent75c7e03bc5e282ee3969924c225a0e4545d5258b (diff)
parent6512c70b5487a9328e19a64f8118529eb4f77b55 (diff)
Merge pull request #1010 from azmeuk/openal
Minor OpenAL improvements.
Diffstat (limited to 'tests/freealut/src/alutInputStream.c')
-rw-r--r--tests/freealut/src/alutInputStream.c236
1 files changed, 236 insertions, 0 deletions
diff --git a/tests/freealut/src/alutInputStream.c b/tests/freealut/src/alutInputStream.c
new file mode 100644
index 00000000..9ddcb059
--- /dev/null
+++ b/tests/freealut/src/alutInputStream.c
@@ -0,0 +1,236 @@
+#include "alutInternal.h"
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#if HAVE_STAT
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#define structStat struct stat
+#elif HAVE__STAT
+#define stat(p,b) _stat((p),(b))
+#define structStat struct _stat
+#else
+#error No stat-like function on this platform
+#endif
+
+struct InputStream_struct
+{
+ ALboolean isFileStream;
+ char *fileName;
+ size_t remainingLength;
+ union
+ {
+ FILE *fileDescriptor; /* for file streams */
+ const ALvoid *data; /* for memory streams */
+ } u;
+};
+
+/****************************************************************************
+ * The functions below know the internal InputStream representation.
+ ****************************************************************************/
+
+InputStream *_alutInputStreamConstructFromFile(const char *fileName)
+{
+ InputStream *stream;
+ structStat statBuf;
+ FILE *fileDescriptor;
+ char *fileNameBuffer;
+
+ stream = (InputStream *) _alutMalloc(sizeof(InputStream));
+ if (stream == NULL)
+ {
+ return NULL;
+ }
+
+ if (stat(fileName, &statBuf))
+ {
+ _alutSetError(ALUT_ERROR_IO_ERROR);
+ free(stream);
+ return NULL;
+ }
+
+ fileDescriptor = fopen(fileName, "rb");
+ if (fileDescriptor == NULL)
+ {
+ _alutSetError(ALUT_ERROR_IO_ERROR);
+ free(stream);
+ return NULL;
+ }
+
+ fileNameBuffer = (char *)_alutMalloc(strlen(fileName) + 1);
+ if (fileNameBuffer == NULL)
+ {
+ free(stream);
+ return NULL;
+ }
+
+ stream->isFileStream = AL_TRUE;
+ stream->fileName = strcpy(fileNameBuffer, fileName);
+ stream->remainingLength = statBuf.st_size;
+ stream->u.fileDescriptor = fileDescriptor;
+ return stream;
+}
+
+InputStream *_alutInputStreamConstructFromMemory(const ALvoid * data, size_t length)
+{
+ InputStream *stream = (InputStream *) _alutMalloc(sizeof(InputStream));
+
+ if (stream == NULL)
+ {
+ return NULL;
+ }
+
+ stream->isFileStream = AL_FALSE;
+ stream->fileName = NULL;
+ stream->remainingLength = length;
+ stream->u.data = data;
+ return stream;
+}
+
+ALboolean _alutInputStreamDestroy(InputStream * stream)
+{
+ ALboolean status = (stream->isFileStream && fclose(stream->u.fileDescriptor)) ? AL_FALSE : AL_TRUE;
+
+ if (stream->fileName)
+ {
+ free(stream->fileName);
+ }
+ free(stream);
+ return status;
+}
+
+const char *_alutInputStreamGetFileName(const InputStream * stream)
+{
+ return stream->fileName;
+}
+
+size_t _alutInputStreamGetRemainingLength(const InputStream * stream)
+{
+ return stream->remainingLength;
+}
+
+ALboolean _alutInputStreamEOF(InputStream * stream)
+{
+ if (stream->isFileStream)
+ {
+ int c = fgetc(stream->u.fileDescriptor);
+
+ if (c != EOF)
+ {
+ ungetc(c, stream->u.fileDescriptor);
+ }
+ return (c == EOF) ? AL_TRUE : AL_FALSE;
+ }
+ else
+ {
+ return (stream->remainingLength == 0) ? AL_TRUE : AL_FALSE;
+ }
+}
+
+static ALboolean streamRead(InputStream * stream, void *ptr, size_t numBytesToRead)
+{
+ if (stream->isFileStream)
+ {
+ size_t numBytesRead = fread(ptr, 1, numBytesToRead, stream->u.fileDescriptor);
+
+ if (numBytesToRead != numBytesRead)
+ {
+ _alutSetError(ferror(stream->u.fileDescriptor) ? ALUT_ERROR_IO_ERROR : ALUT_ERROR_CORRUPT_OR_TRUNCATED_DATA);
+ return AL_FALSE;
+ }
+ return AL_TRUE;
+ }
+ else
+ {
+ if (stream->remainingLength < numBytesToRead)
+ {
+ _alutSetError(ALUT_ERROR_CORRUPT_OR_TRUNCATED_DATA);
+ return AL_FALSE;
+ }
+ memcpy(ptr, stream->u.data, numBytesToRead);
+ stream->u.data = ((const char *)(stream->u.data) + numBytesToRead);
+ return AL_TRUE;
+ }
+}
+
+/****************************************************************************
+ * The utility functions below do not know the internal InputStream
+ * representation.
+ ****************************************************************************/
+
+ALvoid *_alutInputStreamRead(InputStream * stream, size_t length)
+{
+ ALvoid *data = _alutMalloc(length);
+
+ if (data == NULL)
+ {
+ return NULL;
+ }
+
+ if (!streamRead(stream, data, length))
+ {
+ free(data);
+ return NULL;
+ }
+
+ return data;
+}
+
+ALboolean _alutInputStreamSkip(InputStream * stream, size_t numBytesToSkip)
+{
+ ALboolean status;
+ char *buf;
+
+ if (numBytesToSkip == 0)
+ {
+ return AL_TRUE;
+ }
+ buf = (char *)_alutMalloc(numBytesToSkip);
+ if (buf == NULL)
+ {
+ return AL_FALSE;
+ }
+ status = streamRead(stream, buf, numBytesToSkip);
+ free(buf);
+ return status;
+}
+
+ALboolean _alutInputStreamReadUInt16LE(InputStream * stream, UInt16LittleEndian * value)
+{
+ unsigned char buf[2];
+
+ if (!streamRead(stream, buf, sizeof(buf)))
+ {
+ return AL_FALSE;
+ }
+ *value = ((UInt16LittleEndian) buf[1] << 8) | ((UInt16LittleEndian) buf[0]);
+ return AL_TRUE;
+}
+
+ALboolean _alutInputStreamReadInt32BE(InputStream * stream, Int32BigEndian * value)
+{
+ unsigned char buf[4];
+
+ if (!streamRead(stream, buf, sizeof(buf)))
+ {
+ return AL_FALSE;
+ }
+ *value = ((Int32BigEndian) buf[0] << 24) | ((Int32BigEndian) buf[1] << 16) | ((Int32BigEndian) buf[2] << 8) | ((Int32BigEndian) buf[3]);
+ return AL_TRUE;
+}
+
+ALboolean _alutInputStreamReadUInt32LE(InputStream * stream, UInt32LittleEndian * value)
+{
+ unsigned char buf[4];
+
+ if (!streamRead(stream, buf, sizeof(buf)))
+ {
+ return AL_FALSE;
+ }
+ *value =
+ ((UInt32LittleEndian) buf[3] << 24) | ((UInt32LittleEndian) buf[2] << 16) | ((UInt32LittleEndian) buf[1] << 8) | ((UInt32LittleEndian) buf[0]);
+ return AL_TRUE;
+}