Mana
Loading...
Searching...
No Matches
physfsrwops.c
Go to the documentation of this file.
1/*
2 * This code provides a glue layer between PhysicsFS and Simple Directmedia
3 * Layer's (SDL) RWops i/o abstraction.
4 *
5 * License: this code is public domain. I make no warranty that it is useful,
6 * correct, harmless, or environmentally safe.
7 *
8 * This particular file may be used however you like, including copying it
9 * verbatim into a closed-source project, exploiting it commercially, and
10 * removing any trace of my name from the source (although I hope you won't
11 * do that). I welcome enhancements and corrections to this file, but I do
12 * not require you to send me patches if you make changes. This code has
13 * NO WARRANTY.
14 *
15 * Unless otherwise stated, the rest of PhysicsFS falls under the zlib license.
16 * Please see LICENSE.txt in the root of the source tree.
17 *
18 * SDL 1.2 falls under the LGPL license. SDL 1.3+ is zlib, like PhysicsFS.
19 * You can get SDL at https://www.libsdl.org/
20 *
21 * This file was written by Ryan C. Gordon. (icculus@icculus.org).
22 */
23
24#include <stdio.h> /* used for SEEK_SET, SEEK_CUR, SEEK_END ... */
25#include "physfsrwops.h"
26
27/* SDL's RWOPS interface changed a little in SDL 2.0... */
28#if defined(SDL_VERSION_ATLEAST)
29#if SDL_VERSION_ATLEAST(2, 0, 0)
30#define TARGET_SDL2 1
31#endif
32#endif
33
34#if !TARGET_SDL2
35#ifndef RW_SEEK_SET
36#define RW_SEEK_SET SEEK_SET
37#endif
38#ifndef RW_SEEK_CUR
39#define RW_SEEK_CUR SEEK_CUR
40#endif
41#ifndef RW_SEEK_END
42#define RW_SEEK_END SEEK_END
43#endif
44#endif
45
46#if TARGET_SDL2
47static Sint64 SDLCALL physfsrwops_size(struct SDL_RWops *rw)
48{
49 PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
50 return (Sint64) PHYSFS_fileLength(handle);
51} /* physfsrwops_size */
52#endif
53
54
55#if TARGET_SDL2
56static Sint64 SDLCALL physfsrwops_seek(struct SDL_RWops *rw, Sint64 offset, int whence)
57#else
58static int physfsrwops_seek(SDL_RWops *rw, int offset, int whence)
59#endif
60{
61 PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
62 PHYSFS_sint64 pos = 0;
63
64 if (whence == RW_SEEK_SET)
65 pos = (PHYSFS_sint64) offset;
66
67 else if (whence == RW_SEEK_CUR)
68 {
69 const PHYSFS_sint64 current = PHYSFS_tell(handle);
70 if (current == -1)
71 {
72 SDL_SetError("Can't find position in file: %s",
73 PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
74 return -1;
75 } /* if */
76
77 if (offset == 0) /* this is a "tell" call. We're done. */
78 {
79 #if TARGET_SDL2
80 return (Sint64) current;
81 #else
82 return (int) current;
83 #endif
84 } /* if */
85
86 pos = current + ((PHYSFS_sint64) offset);
87 } /* else if */
88
89 else if (whence == RW_SEEK_END)
90 {
91 const PHYSFS_sint64 len = PHYSFS_fileLength(handle);
92 if (len == -1)
93 {
94 SDL_SetError("Can't find end of file: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
95 return -1;
96 } /* if */
97
98 pos = len + ((PHYSFS_sint64) offset);
99 } /* else if */
100
101 else
102 {
103 SDL_SetError("Invalid 'whence' parameter.");
104 return -1;
105 } /* else */
106
107 if ( pos < 0 )
108 {
109 SDL_SetError("Attempt to seek past start of file.");
110 return -1;
111 } /* if */
112
113 if (!PHYSFS_seek(handle, (PHYSFS_uint64) pos))
114 {
115 SDL_SetError("PhysicsFS error: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
116 return -1;
117 } /* if */
118
119 #if TARGET_SDL2
120 return (Sint64) pos;
121 #else
122 return (int) pos;
123 #endif
124} /* physfsrwops_seek */
125
126
127#if TARGET_SDL2
128static size_t SDLCALL physfsrwops_read(struct SDL_RWops *rw, void *ptr,
129 size_t size, size_t maxnum)
130#else
131static int physfsrwops_read(SDL_RWops *rw, void *ptr, int size, int maxnum)
132#endif
133{
134 PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
135 const PHYSFS_uint64 readlen = (PHYSFS_uint64) (maxnum * size);
136 const PHYSFS_sint64 rc = PHYSFS_readBytes(handle, ptr, readlen);
137 if (rc != ((PHYSFS_sint64) readlen))
138 {
139 if (!PHYSFS_eof(handle)) /* not EOF? Must be an error. */
140 {
141 SDL_SetError("PhysicsFS error: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
142
143 #if TARGET_SDL2
144 return 0;
145 #else
146 return -1;
147 #endif
148 } /* if */
149 } /* if */
150
151 #if TARGET_SDL2
152 return (size_t) rc / size;
153 #else
154 return (int) rc / size;
155 #endif
156} /* physfsrwops_read */
157
158
159#if TARGET_SDL2
160static size_t SDLCALL physfsrwops_write(struct SDL_RWops *rw, const void *ptr,
161 size_t size, size_t num)
162#else
163static int physfsrwops_write(SDL_RWops *rw, const void *ptr, int size, int num)
164#endif
165{
166 PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
167 const PHYSFS_uint64 writelen = (PHYSFS_uint64) (num * size);
168 const PHYSFS_sint64 rc = PHYSFS_writeBytes(handle, ptr, writelen);
169 if (rc != ((PHYSFS_sint64) writelen))
170 SDL_SetError("PhysicsFS error: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
171
172 #if TARGET_SDL2
173 return (size_t) rc;
174 #else
175 return (int) rc;
176 #endif
177} /* physfsrwops_write */
178
179
180static int physfsrwops_close(SDL_RWops *rw)
181{
182 PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
183 if (!PHYSFS_close(handle))
184 {
185 SDL_SetError("PhysicsFS error: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
186 return -1;
187 } /* if */
188
189 SDL_FreeRW(rw);
190 return 0;
191} /* physfsrwops_close */
192
193
194static SDL_RWops *create_rwops(PHYSFS_File *handle)
195{
196 SDL_RWops *retval = NULL;
197
198 if (handle == NULL)
199 SDL_SetError("PhysicsFS error: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
200 else
201 {
202 retval = SDL_AllocRW();
203 if (retval != NULL)
204 {
205 #if TARGET_SDL2
206 retval->size = physfsrwops_size;
207 #endif
208 retval->seek = physfsrwops_seek;
209 retval->read = physfsrwops_read;
210 retval->write = physfsrwops_write;
211 retval->close = physfsrwops_close;
212 retval->hidden.unknown.data1 = handle;
213 } /* if */
214 } /* else */
215
216 return retval;
217} /* create_rwops */
218
219
220SDL_RWops *PHYSFSRWOPS_makeRWops(PHYSFS_File *handle)
221{
222 SDL_RWops *retval = NULL;
223 if (handle == NULL)
224 SDL_SetError("NULL pointer passed to PHYSFSRWOPS_makeRWops().");
225 else
226 retval = create_rwops(handle);
227
228 return retval;
229} /* PHYSFSRWOPS_makeRWops */
230
231
232SDL_RWops *PHYSFSRWOPS_openRead(const char *fname)
233{
234 return create_rwops(PHYSFS_openRead(fname));
235} /* PHYSFSRWOPS_openRead */
236
237
238SDL_RWops *PHYSFSRWOPS_openWrite(const char *fname)
239{
240 return create_rwops(PHYSFS_openWrite(fname));
241} /* PHYSFSRWOPS_openWrite */
242
243
244SDL_RWops *PHYSFSRWOPS_openAppend(const char *fname)
245{
246 return create_rwops(PHYSFS_openAppend(fname));
247} /* PHYSFSRWOPS_openAppend */
248
249
250/* end of physfsrwops.c ... */
SDL_RWops * PHYSFSRWOPS_openRead(const char *fname)
Open a platform-independent filename for reading, and make it accessible via an SDL_RWops structure.
SDL_RWops * PHYSFSRWOPS_openWrite(const char *fname)
Open a platform-independent filename for writing, and make it accessible via an SDL_RWops structure.
#define RW_SEEK_END
Definition physfsrwops.c:42
SDL_RWops * PHYSFSRWOPS_openAppend(const char *fname)
Open a platform-independent filename for appending, and make it accessible via an SDL_RWops structure...
#define RW_SEEK_CUR
Definition physfsrwops.c:39
#define RW_SEEK_SET
Definition physfsrwops.c:36
SDL_RWops * PHYSFSRWOPS_makeRWops(PHYSFS_File *handle)
Make a SDL_RWops from an existing PhysicsFS file handle.