Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1 | pmbaty | 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 |
||
47 | static 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 |
||
56 | static Sint64 SDLCALL physfsrwops_seek(struct SDL_RWops *rw, Sint64 offset, int whence) |
||
57 | #else |
||
58 | static 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 |
||
128 | static size_t SDLCALL physfsrwops_read(struct SDL_RWops *rw, void *ptr, |
||
129 | size_t size, size_t maxnum) |
||
130 | #else |
||
131 | static 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 |
||
160 | static size_t SDLCALL physfsrwops_write(struct SDL_RWops *rw, const void *ptr, |
||
161 | size_t size, size_t num) |
||
162 | #else |
||
163 | static 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 | |||
180 | static 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 | |||
194 | static 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 | |||
220 | SDL_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 | |||
232 | SDL_RWops *PHYSFSRWOPS_openRead(const char *fname) |
||
233 | { |
||
234 | return create_rwops(PHYSFS_openRead(fname)); |
||
235 | } /* PHYSFSRWOPS_openRead */ |
||
236 | |||
237 | |||
238 | SDL_RWops *PHYSFSRWOPS_openWrite(const char *fname) |
||
239 | { |
||
240 | return create_rwops(PHYSFS_openWrite(fname)); |
||
241 | } /* PHYSFSRWOPS_openWrite */ |
||
242 | |||
243 | |||
244 | SDL_RWops *PHYSFSRWOPS_openAppend(const char *fname) |
||
245 | { |
||
246 | return create_rwops(PHYSFS_openAppend(fname)); |
||
247 | } /* PHYSFSRWOPS_openAppend */ |
||
248 | |||
249 | |||
250 | /* end of physfsrwops.c ... */ |
||
251 |