Tizen 2.1 base
[external/freealut.git] / src / alutInputStream.c
1 #include "alutInternal.h"
2 #include <stdio.h>
3 #include <string.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6
7 #if HAVE_STAT
8 #if HAVE_UNISTD_H
9 #include <unistd.h>
10 #endif
11 #define structStat struct stat
12 #elif HAVE__STAT
13 #define stat(p,b) _stat((p),(b))
14 #define structStat struct _stat
15 #else
16 #error No stat-like function on this platform
17 #endif
18
19 struct InputStream_struct
20 {
21   ALboolean isFileStream;
22   char *fileName;
23   size_t remainingLength;
24   union
25   {
26     FILE *fileDescriptor;       /* for file streams */
27     const ALvoid *data;         /* for memory streams */
28   } u;
29 };
30
31 /****************************************************************************
32  * The functions below know the internal InputStream representation.
33  ****************************************************************************/
34
35 InputStream *
36 _alutInputStreamConstructFromFile (const char *fileName)
37 {
38   InputStream *stream;
39   structStat statBuf;
40   FILE *fileDescriptor;
41   char *fileNameBuffer;
42
43   stream = (InputStream *) _alutMalloc (sizeof (InputStream));
44   if (stream == NULL)
45     {
46       return NULL;
47     }
48
49   if (stat (fileName, &statBuf))
50     {
51       _alutSetError (ALUT_ERROR_IO_ERROR);
52       free (stream);
53       return NULL;
54     }
55
56   fileDescriptor = fopen (fileName, "rb");
57   if (fileDescriptor == NULL)
58     {
59       _alutSetError (ALUT_ERROR_IO_ERROR);
60       free (stream);
61       return NULL;
62     }
63
64   fileNameBuffer = (char *) _alutMalloc (strlen (fileName) + 1);
65   if (fileNameBuffer == NULL)
66     {
67       free (stream);
68       return NULL;
69     }
70
71   stream->isFileStream = AL_TRUE;
72   stream->fileName = strcpy (fileNameBuffer, fileName);
73   stream->remainingLength = statBuf.st_size;
74   stream->u.fileDescriptor = fileDescriptor;
75   return stream;
76 }
77
78 InputStream *
79 _alutInputStreamConstructFromMemory (const ALvoid *data, size_t length)
80 {
81   InputStream *stream = (InputStream *) _alutMalloc (sizeof (InputStream));
82   if (stream == NULL)
83     {
84       return NULL;
85     }
86
87   stream->isFileStream = AL_FALSE;
88   stream->fileName = NULL;
89   stream->remainingLength = length;
90   stream->u.data = data;
91   return stream;
92 }
93
94 ALboolean
95 _alutInputStreamDestroy (InputStream *stream)
96 {
97   ALboolean status =
98     (stream->isFileStream && fclose (stream->u.fileDescriptor)) ?
99     AL_FALSE : AL_TRUE;
100   if (stream->fileName)
101     {
102       free (stream->fileName);
103     }
104   free (stream);
105   return status;
106 }
107
108 const char *
109 _alutInputStreamGetFileName (const InputStream *stream)
110 {
111   return stream->fileName;
112 }
113
114 size_t
115 _alutInputStreamGetRemainingLength (const InputStream *stream)
116 {
117   return stream->remainingLength;
118 }
119
120 ALboolean
121 _alutInputStreamEOF (InputStream *stream)
122 {
123   if (stream->isFileStream)
124     {
125       int c = fgetc (stream->u.fileDescriptor);
126       if (c != EOF)
127         {
128           ungetc (c, stream->u.fileDescriptor);
129         }
130       return (c == EOF) ? AL_TRUE : AL_FALSE;
131     }
132   else
133     {
134       return (stream->remainingLength == 0) ? AL_TRUE : AL_FALSE;
135     }
136 }
137
138 static ALboolean
139 streamRead (InputStream *stream, void *ptr, size_t numBytesToRead)
140 {
141   if (stream->isFileStream)
142     {
143       size_t numBytesRead =
144         fread (ptr, 1, numBytesToRead, stream->u.fileDescriptor);
145       if (numBytesToRead != numBytesRead)
146         {
147           _alutSetError (ferror (stream->u.fileDescriptor) ?
148                          ALUT_ERROR_IO_ERROR :
149                          ALUT_ERROR_CORRUPT_OR_TRUNCATED_DATA);
150           return AL_FALSE;
151         }
152       return AL_TRUE;
153     }
154   else
155     {
156       if (stream->remainingLength < numBytesToRead)
157         {
158           _alutSetError (ALUT_ERROR_CORRUPT_OR_TRUNCATED_DATA);
159           return AL_FALSE;
160         }
161       memcpy (ptr, stream->u.data, numBytesToRead);
162       stream->u.data = ((const char *) (stream->u.data) + numBytesToRead);
163       return AL_TRUE;
164     }
165 }
166
167 /****************************************************************************
168  * The utility functions below do not know the internal InputStream
169  * representation.
170  ****************************************************************************/
171
172 ALvoid *
173 _alutInputStreamRead (InputStream *stream, size_t length)
174 {
175   ALvoid *data = _alutMalloc (length);
176   if (data == NULL)
177     {
178       return NULL;
179     }
180
181   if (!streamRead (stream, data, length))
182     {
183       free (data);
184       return NULL;
185     }
186
187   return data;
188 }
189
190 ALboolean
191 _alutInputStreamSkip (InputStream *stream, size_t numBytesToSkip)
192 {
193   ALboolean status;
194   char *buf;
195   if (numBytesToSkip == 0)
196     {
197       return AL_TRUE;
198     }
199   buf = (char *) _alutMalloc (numBytesToSkip);
200   if (buf == NULL)
201     {
202       return AL_FALSE;
203     }
204   status = streamRead (stream, buf, numBytesToSkip);
205   free (buf);
206   return status;
207 }
208
209 ALboolean
210 _alutInputStreamReadUInt16LE (InputStream *stream, UInt16LittleEndian *value)
211 {
212   unsigned char buf[2];
213   if (!streamRead (stream, buf, sizeof (buf)))
214     {
215       return AL_FALSE;
216     }
217   *value = ((UInt16LittleEndian) buf[1] << 8) | ((UInt16LittleEndian) buf[0]);
218   return AL_TRUE;
219 }
220
221 ALboolean
222 _alutInputStreamReadInt32BE (InputStream *stream, Int32BigEndian *value)
223 {
224   unsigned char buf[4];
225   if (!streamRead (stream, buf, sizeof (buf)))
226     {
227       return AL_FALSE;
228     }
229   *value =
230     ((Int32BigEndian) buf[0] << 24) |
231     ((Int32BigEndian) buf[1] << 16) |
232     ((Int32BigEndian) buf[2] << 8) | ((Int32BigEndian) buf[3]);
233   return AL_TRUE;
234 }
235
236 ALboolean
237 _alutInputStreamReadUInt32LE (InputStream *stream, UInt32LittleEndian *value)
238 {
239   unsigned char buf[4];
240   if (!streamRead (stream, buf, sizeof (buf)))
241     {
242       return AL_FALSE;
243     }
244   *value =
245     ((UInt32LittleEndian) buf[3] << 24) |
246     ((UInt32LittleEndian) buf[2] << 16) |
247     ((UInt32LittleEndian) buf[1] << 8) | ((UInt32LittleEndian) buf[0]);
248   return AL_TRUE;
249 }