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