add level component saving functions which use PhysicsFS (didn't commit properly...
[btb/d2x.git] / include / physfsx.h
1 /* $Id: physfsx.h,v 1.11 2005-06-13 11:22:02 chris Exp $ */
2
3 /*
4  *
5  * Some simple physfs extensions
6  *
7  */
8
9 #ifndef PHYSFSX_H
10 #define PHYSFSX_H
11
12 #if !defined(macintosh) && !defined(_MSC_VER)
13 #include <sys/param.h>
14 #endif
15 #if defined(__linux__)
16 #include <sys/vfs.h>
17 #elif defined(__MACH__) && defined(__APPLE__)
18 #include <sys/mount.h>
19 #endif
20 #include <string.h>
21 #include <stdarg.h>
22
23 #include <physfs.h>
24
25 #include "pstypes.h"
26 #include "error.h"
27 #include "vecmat.h"
28
29 static inline int PHYSFSX_readString(PHYSFS_file *file, char *s)
30 {
31         char *ptr = s;
32
33         if (PHYSFS_eof(file))
34                 *ptr = 0;
35         else
36                 do
37                         PHYSFS_read(file, ptr, 1, 1);
38                 while (!PHYSFS_eof(file) && *ptr++ != 0);
39
40         return strlen(s);
41 }
42
43 static inline int PHYSFSX_gets(PHYSFS_file *file, char *s)
44 {
45         char *ptr = s;
46
47         if (PHYSFS_eof(file))
48                 *ptr = 0;
49         else
50                 do
51                         PHYSFS_read(file, ptr, 1, 1);
52                 while (!PHYSFS_eof(file) && *ptr++ != '\n');
53
54         return strlen(s);
55 }
56
57 static inline int PHYSFSX_writeU8(PHYSFS_file *file, PHYSFS_uint8 val)
58 {
59         return PHYSFS_write(file, &val, 1, 1);
60 }
61
62 static inline int PHYSFSX_writeString(PHYSFS_file *file, char *s)
63 {
64         return PHYSFS_write(file, s, 1, strlen(s) + 1);
65 }
66
67 static inline int PHYSFSX_puts(PHYSFS_file *file, char *s)
68 {
69         return PHYSFS_write(file, s, 1, strlen(s));
70 }
71
72 static inline int PHYSFSX_putc(PHYSFS_file *file, int c)
73 {
74         unsigned char ch = (unsigned char)c;
75
76         if (PHYSFS_write(file, &ch, 1, 1) < 1)
77                 return -1;
78         else
79                 return (int)c;
80 }
81
82 static inline int PHYSFSX_printf(PHYSFS_file *file, char *format, ...)
83 {
84         char buffer[1024];
85         va_list args;
86
87         va_start(args, format);
88         vsprintf(buffer, format, args);
89
90         return PHYSFSX_puts(file, buffer);
91 }
92
93 #define PHYSFSX_writeFix        PHYSFS_writeSLE32
94 #define PHYSFSX_writeFixAng     PHYSFS_writeSLE16
95
96 static inline int PHYSFSX_writeVector(PHYSFS_file *file, vms_vector *v)
97 {
98         if (PHYSFSX_writeFix(file, v->x) < 1 ||
99          PHYSFSX_writeFix(file, v->y) < 1 ||
100          PHYSFSX_writeFix(file, v->z) < 1)
101                 return 0;
102
103         return 1;
104 }
105
106 static inline int PHYSFSX_writeAngleVec(PHYSFS_file *file, vms_angvec *v)
107 {
108         if (PHYSFSX_writeFixAng(file, v->p) < 1 ||
109          PHYSFSX_writeFixAng(file, v->b) < 1 ||
110          PHYSFSX_writeFixAng(file, v->h) < 1)
111                 return 0;
112
113         return 1;
114 }
115
116 static inline int PHYSFSX_writeMatrix(PHYSFS_file *file, vms_matrix *m)
117 {
118         if (PHYSFSX_writeVector(file, &m->rvec) < 1 ||
119          PHYSFSX_writeVector(file, &m->uvec) < 1 ||
120          PHYSFSX_writeVector(file, &m->fvec) < 1)
121                 return 0;
122
123         return 1;
124 }
125
126 static inline int PHYSFSX_getRealPath(const char *stdPath, char *realPath)
127 {
128         const char *realDir = PHYSFS_getRealDir(stdPath);
129         const char *sep = PHYSFS_getDirSeparator();
130         char *p;
131
132         if (!realDir)
133         {
134                 realDir = PHYSFS_getWriteDir();
135                 if (!realDir)
136                         return 0;
137         }
138
139         strncpy(realPath, realDir, PATH_MAX - 1);
140         if (strlen(realPath) >= strlen(sep))
141         {
142                 p = realPath + strlen(realPath) - strlen(sep);
143                 if (strcmp(p, sep)) // no sep at end of realPath
144                         strncat(realPath, sep, PATH_MAX - 1 - strlen(realPath));
145         }
146
147         if (strlen(stdPath) >= 1)
148                 if (*stdPath == '/')
149                         stdPath++;
150
151         while (*stdPath)
152         {
153                 if (*stdPath == '/')
154                         strncat(realPath, sep, PATH_MAX - 1 - strlen(realPath));
155                 else
156                 {
157                         if (strlen(realPath) < PATH_MAX - 2)
158                         {
159                                 p = realPath + strlen(realPath);
160                                 p[0] = *stdPath;
161                                 p[1] = '\0';
162                         }
163                 }
164                 stdPath++;
165         }
166
167         return 1;
168 }
169
170 static inline int PHYSFSX_rename(char *oldpath, char *newpath)
171 {
172         char old[PATH_MAX], new[PATH_MAX];
173
174         PHYSFSX_getRealPath(oldpath, old);
175         PHYSFSX_getRealPath(newpath, new);
176         return (rename(old, new) == 0);
177 }
178
179
180 // returns -1 if error
181 // Gets bytes free in current write dir
182 static inline PHYSFS_sint64 PHYSFSX_getFreeDiskSpace()
183 {
184 #if defined(__linux__) || (defined(__MACH__) && defined(__APPLE__))
185         struct statfs sfs;
186
187         if (!statfs(PHYSFS_getWriteDir(), &sfs))
188                 return (PHYSFS_sint64)(sfs.f_bavail * sfs.f_bsize);
189
190         return -1;
191 #else
192         return 0x7FFFFFFF;
193 #endif
194 }
195
196 //Open a file for reading, set up a buffer
197 static inline PHYSFS_file *PHYSFSX_openReadBuffered(char *filename)
198 {
199         PHYSFS_file *fp;
200         PHYSFS_uint64 bufSize;
201
202         if (filename[0] == '\x01')
203         {
204                 //FIXME: don't look in dir, only in hogfile
205                 filename++;
206         }
207
208         fp = PHYSFS_openRead(filename);
209         if (!fp)
210                 return NULL;
211
212         bufSize = PHYSFS_fileLength(fp);
213         while (!PHYSFS_setBuffer(fp, bufSize) && bufSize)
214                 bufSize /= 2;   // even if the error isn't memory full, for a 20MB file it'll only do this 8 times
215
216         return fp;
217 }
218
219 //Open a file for writing, set up a buffer
220 static inline PHYSFS_file *PHYSFSX_openWriteBuffered(char *filename)
221 {
222         PHYSFS_file *fp;
223         PHYSFS_uint64 bufSize = 1024*1024;      // hmm, seems like an OK size.
224
225         fp = PHYSFS_openWrite(filename);
226         if (!fp)
227                 return NULL;
228
229         while (!PHYSFS_setBuffer(fp, bufSize) && bufSize)
230                 bufSize /= 2;
231
232         return fp;
233 }
234
235 #endif /* PHYSFSX_H */