Remove the DYNLOAD option. It's buggy and causes problems.
[alure.git] / src / istream.cpp
blob4400861ff97bb7549e04904c016962cbfe7e60f2
1 /*
2 * ALURE OpenAL utility library
3 * Copyright (c) 2009 by Chris Robinson.
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to
7 * deal in the Software without restriction, including without limitation the
8 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 * sell copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
24 /* Title: File I/O */
26 #include "config.h"
28 #include "main.h"
30 #include <stdio.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <fcntl.h>
34 #include <errno.h>
36 #include <iostream>
39 MemStreamBuf::int_type MemStreamBuf::underflow()
41 if(gptr() == egptr())
43 char_type *data = (char_type*)memInfo.Data;
44 setg(data, data + memInfo.Pos, data + memInfo.Length);
45 memInfo.Pos = memInfo.Length;
47 if(gptr() == egptr())
48 return traits_type::eof();
49 return (*gptr())&0xFF;
52 MemStreamBuf::pos_type MemStreamBuf::seekoff(off_type offset, std::ios_base::seekdir whence, std::ios_base::openmode mode)
54 if((mode&std::ios_base::out))
55 return traits_type::eof();
57 pos_type pos;
58 switch(whence)
60 case std::ios_base::beg:
61 pos = pos_type(offset);
62 break;
63 case std::ios_base::cur:
64 pos = pos_type(memInfo.Pos) - pos_type(egptr()-gptr());
65 pos += offset;
66 break;
67 case std::ios_base::end:
68 pos = memInfo.Length + pos_type(offset);
69 break;
70 default:
71 return traits_type::eof();
74 return seekpos(pos, mode);
77 MemStreamBuf::pos_type MemStreamBuf::seekpos(pos_type pos, std::ios_base::openmode mode)
79 if((mode&std::ios_base::out))
80 return traits_type::eof();
82 if(pos < 0 || pos > pos_type(memInfo.Length) || pos != pos_type(size_t(pos)))
83 return traits_type::eof();
84 memInfo.Pos = pos;
86 setg(0, 0, 0);
87 return pos;
91 int FileStreamBuf::underflow()
93 if(usrFile && gptr() == egptr())
95 ALsizei amt = fio.read(usrFile, reinterpret_cast<ALubyte*>(&buffer[0]), sizeof(buffer));
96 if(amt >= 0) setg(buffer, buffer, buffer+amt);
98 if(gptr() == egptr())
99 return traits_type::eof();
100 return (*gptr())&0xFF;
103 FileStreamBuf::pos_type FileStreamBuf::seekoff(off_type offset, std::ios_base::seekdir whence, std::ios_base::openmode mode)
105 if(!usrFile || (mode&std::ios_base::out))
106 return traits_type::eof();
108 pos_type pos = traits_type::eof();
109 switch(whence)
111 case std::ios_base::beg:
112 if(offset == off_type(alureInt64(offset)))
113 pos = pos_type(fio.seek(usrFile, offset, SEEK_SET));
114 break;
116 case std::ios_base::cur:
117 offset -= off_type(egptr()-gptr());
118 if(offset == off_type(alureInt64(offset)))
119 pos = pos_type(fio.seek(usrFile, offset, SEEK_CUR));
120 break;
122 case std::ios_base::end:
123 if(offset == off_type(alureInt64(offset)))
124 pos = pos_type(fio.seek(usrFile, offset, SEEK_END));
125 break;
127 default:
128 break;
130 if(pos >= 0)
131 setg(0, 0, 0);
132 return pos;
135 FileStreamBuf::pos_type FileStreamBuf::seekpos(pos_type pos, std::ios_base::openmode mode)
137 if(pos != pos_type(off_type(pos)))
138 return traits_type::eof();
139 return seekoff(off_type(pos), std::ios_base::beg, mode);
143 static void *open_wrap(const char *filename, ALuint mode)
145 if(mode != 0)
146 return NULL;
148 return fopen(filename, "rb");
151 static void close_wrap(void *user_data)
153 FILE *f = (FILE*)user_data;
154 fclose(f);
157 static ALsizei read_wrap(void *user_data, ALubyte *buf, ALuint bytes)
159 FILE *f = (FILE*)user_data;
160 return fread(buf, 1, bytes, f);
163 static ALsizei write_wrap(void *user_data, const ALubyte *buf, ALuint bytes)
165 FILE *f = (FILE*)user_data;
166 return fwrite(buf, 1, bytes, f);
169 static alureInt64 seek_wrap(void *user_data, alureInt64 offset, int whence)
171 FILE *f = (FILE*)user_data;
172 #ifdef HAVE_FSEEKO
173 if(offset != (off_t)offset || fseeko(f, offset, whence) != 0)
174 return -1;
175 return ftello(f);
176 #elif defined(HAVE__FSEEKI64)
177 if(_fseeki64(f, offset, whence) != 0)
178 return -1;
179 return _ftelli64(f);
180 #else
181 if(offset != (long)offset || fseek(f, offset, whence) != 0)
182 return -1;
183 return ftell(f);
184 #endif
187 UserFuncs Funcs = {
188 false,
189 NULL,
190 { open_wrap },
191 close_wrap,
192 read_wrap,
193 write_wrap,
194 seek_wrap
196 bool UsingSTDIO = true;
198 extern "C" {
200 /* Function: alureSetIOCallbacks
202 * Provides callbacks for alternative methods to handle file I/O. Passing NULL
203 * for all callbacks is a valid way to revert to normal I/O, otherwise they
204 * must all be specified. Changing the callbacks will not affect open files
205 * (they will continue using the callbacks that were set at the time they were
206 * opened).
208 * Parameters:
209 * open - This callback is called to open the named file. The given mode is the
210 * access rights the open file should have. Currently, this will always
211 * be 0 for read-only (applications should check this to make sure, as
212 * future versions may pass other values for other modes). Upon success,
213 * a non-NULL handle must be returned which will be used as a unique
214 * identifier for the file.
215 * close - This callback is called to close an opened file handle. The handle
216 * will no longer be used after this function.
217 * read - This callback is called when data needs to be read from the given
218 * handle. Up to the given number of bytes should be copied into 'buf'
219 * and the number of bytes actually copied should be returned. Returning
220 * 0 means the end of the file has been reached (so non-blocking I/O
221 * methods should ensure at least 1 byte gets read), and negative
222 * indicates an error.
223 * write - This callback is called when data needs to be written to the given
224 * handle. Up to the given number of bytes should be copied from 'buf'
225 * and the number of bytes actually copied should be returned. A return
226 * value of 0 means no more data can be written (so non-blocking I/O
227 * methods should ensure at least 1 byte gets written), and negative
228 * indicates an error.
229 * seek - This callback is called to reposition the offset of the file handle.
230 * The given offset is interpreted according to 'whence', which may be
231 * SEEK_SET (absolute position from the start of the file), SEEK_CUR
232 * (relative position from the current offset), or SEEK_END (absolute
233 * position from the end of the file), as defined by standard C. The new
234 * offset from the beginning of the file should be returned. If the file
235 * cannot seek, such as when using a FIFO, -1 should be returned.
237 * Returns:
238 * AL_FALSE on error.
240 * See also:
241 * <alureSetIOCallbacksUserdata>
243 * *Version Added*: 1.1
245 ALURE_API ALboolean ALURE_APIENTRY alureSetIOCallbacks(
246 void* (*open)(const char *filename, ALuint mode),
247 void (*close)(void *handle),
248 ALsizei (*read)(void *handle, ALubyte *buf, ALuint bytes),
249 ALsizei (*write)(void *handle, const ALubyte *buf, ALuint bytes),
250 alureInt64 (*seek)(void *handle, alureInt64 offset, int whence))
252 if(open && close && read && write && seek)
254 Funcs.hasUserdata = false;
255 Funcs.open = open;
256 Funcs.close = close;
257 Funcs.read = read;
258 Funcs.write = write;
259 Funcs.seek = seek;
260 UsingSTDIO = false;
261 return AL_TRUE;
264 if(!open && !close && !read && !write && !seek)
266 Funcs.hasUserdata = false;
267 Funcs.open = open_wrap;
268 Funcs.close = close_wrap;
269 Funcs.read = read_wrap;
270 Funcs.write = write_wrap;
271 Funcs.seek = seek_wrap;
272 UsingSTDIO = true;
273 return AL_TRUE;
276 SetError("Missing callback functions");
277 return AL_FALSE;
280 /* Function: alureSetIOCallbacksUserdata
282 * Provides callbacks for alternative methods to handle file I/O. Passing NULL
283 * for all callbacks is a valid way to revert to normal I/O, otherwise they
284 * must all be specified. Changing the callbacks will not affect open files
285 * (they will continue using the callbacks that were set at the time they were
286 * opened).
288 * Parameters:
289 * userdata - A handle passed through to the open-callback.
290 * open - This callback is called to open the named file. The given mode is the
291 * access rights the open file should have. Currently, this will always
292 * be 0 for read-only (applications should check this to make sure, as
293 * future versions may pass other values for other modes). Upon success,
294 * a non-NULL handle must be returned which will be used as a unique
295 * identifier for the file.
296 * close - This callback is called to close an opened file handle. The handle
297 * will no longer be used after this function.
298 * read - This callback is called when data needs to be read from the given
299 * handle. Up to the given number of bytes should be copied into 'buf'
300 * and the number of bytes actually copied should be returned. Returning
301 * 0 means the end of the file has been reached (so non-blocking I/O
302 * methods should ensure at least 1 byte gets read), and negative
303 * indicates an error.
304 * write - This callback is called when data needs to be written to the given
305 * handle. Up to the given number of bytes should be copied from 'buf'
306 * and the number of bytes actually copied should be returned. A return
307 * value of 0 means no more data can be written (so non-blocking I/O
308 * methods should ensure at least 1 byte gets written), and negative
309 * indicates an error.
310 * seek - This callback is called to reposition the offset of the file handle.
311 * The given offset is interpreted according to 'whence', which may be
312 * SEEK_SET (absolute position from the start of the file), SEEK_CUR
313 * (relative position from the current offset), or SEEK_END (absolute
314 * position from the end of the file), as defined by standard C. The new
315 * offset from the beginning of the file should be returned. If the file
316 * cannot seek, such as when using a FIFO, -1 should be returned.
318 * Returns:
319 * AL_FALSE on error.
321 * See also:
322 * <alureSetIOCallbacks>
324 * *Version Added*: 1.3
326 ALURE_API ALboolean ALURE_APIENTRY alureSetIOCallbacksUserdata(
327 void *userdata,
328 void* (*open)(void *userdata, const char *filename, ALuint mode),
329 void (*close)(void *handle),
330 ALsizei (*read)(void *handle, ALubyte *buf, ALuint bytes),
331 ALsizei (*write)(void *handle, const ALubyte *buf, ALuint bytes),
332 alureInt64 (*seek)(void *handle, alureInt64 offset, int whence))
334 if(open && close && read && write && seek)
336 Funcs.hasUserdata = true;
337 Funcs.userdata = userdata;
338 Funcs.openWithUserdata = open;
339 Funcs.close = close;
340 Funcs.read = read;
341 Funcs.write = write;
342 Funcs.seek = seek;
343 UsingSTDIO = false;
344 return AL_TRUE;
347 if(!open && !close && !read && !write && !seek)
349 Funcs.hasUserdata = false;
350 Funcs.open = open_wrap;
351 Funcs.close = close_wrap;
352 Funcs.read = read_wrap;
353 Funcs.write = write_wrap;
354 Funcs.seek = seek_wrap;
355 UsingSTDIO = true;
356 return AL_TRUE;
359 SetError("Missing callback functions");
360 return AL_FALSE;
362 } // extern "C"