1 // implementation of generic tools
6 ///////////////////////// file system ///////////////////////
11 #include <sys/types.h>
16 vector
<char *> packagedirs
;
20 for(char *t
= s
; (t
= strpbrk(t
, "/\\")); *t
++ = PATHDIV
);
21 for(char *prevdir
= NULL
, *curdir
= s
;;)
23 prevdir
= curdir
[0]==PATHDIV
? curdir
+1 : curdir
;
24 curdir
= strchr(prevdir
, PATHDIV
);
26 if(prevdir
+1==curdir
&& prevdir
[0]=='.')
28 memmove(prevdir
, curdir
+1, strlen(curdir
+1)+1);
31 else if(curdir
[1]=='.' && curdir
[2]=='.' && curdir
[3]==PATHDIV
)
33 if(prevdir
+2==curdir
&& prevdir
[0]=='.' && prevdir
[1]=='.') continue;
34 memmove(prevdir
, curdir
+4, strlen(curdir
+4)+1);
41 char *path(const char *s
, bool copy
)
49 const char *parentdir(const char *directory
)
51 const char *p
= strrchr(directory
, '/');
52 if(!p
) p
= strrchr(directory
, '\\');
55 size_t len
= p
-directory
+1;
56 s_strncpy(parent
, directory
, len
);
60 bool fileexists(const char *path
, const char *mode
)
63 if(mode
[0]=='w' || mode
[0]=='a') path
= parentdir(path
);
65 if(GetFileAttributes(path
) == INVALID_FILE_ATTRIBUTES
) exists
= false;
67 if(access(path
, R_OK
| (mode
[0]=='w' || mode
[0]=='a' ? W_OK
: 0)) == -1) exists
= false;
72 bool createdir(const char *path
)
74 size_t len
= strlen(path
);
75 if(path
[len
-1]==PATHDIV
)
78 path
= s_strncpy(strip
, path
, len
);
81 return CreateDirectory(path
, NULL
)!=0;
83 return mkdir(path
, 0777)==0;
87 static void fixdir(char *dir
)
90 size_t len
= strlen(dir
);
91 if(dir
[len
-1]!=PATHDIV
)
98 void sethomedir(const char *dir
)
100 fixdir(s_strcpy(homedir
, dir
));
103 void addpackagedir(const char *dir
)
105 fixdir(packagedirs
.add(newstringbuf(dir
)));
108 const char *findfile(const char *filename
, const char *mode
)
113 s_sprintf(s
)("%s%s", homedir
, filename
);
114 if(fileexists(s
, mode
)) return s
;
115 if(mode
[0]=='w' || mode
[0]=='a')
119 char *dir
= strchr(dirs
[0]==PATHDIV
? dirs
+1 : dirs
, PATHDIV
);
123 if(!fileexists(dirs
, "r") && !createdir(dirs
)) return s
;
125 dir
= strchr(dir
+1, PATHDIV
);
130 if(mode
[0]=='w' || mode
[0]=='a') return filename
;
133 s_sprintf(s
)("%s%s", packagedirs
[i
], filename
);
134 if(fileexists(s
, mode
)) return s
;
139 FILE *openfile(const char *filename
, const char *mode
)
141 const char *found
= findfile(filename
, mode
);
142 if(!found
) return NULL
;
143 return fopen(found
, mode
);
146 gzFile
opengzfile(const char *filename
, const char *mode
)
148 const char *found
= findfile(filename
, mode
);
149 if(!found
) return NULL
;
150 return gzopen(found
, mode
);
153 char *loadfile(const char *fn
, int *size
)
155 FILE *f
= openfile(fn
, "rb");
157 fseek(f
, 0, SEEK_END
);
159 if(len
<=0) { fclose(f
); return NULL
; }
160 fseek(f
, 0, SEEK_SET
);
161 char *buf
= new char[len
+1];
162 if(!buf
) { fclose(f
); return NULL
; }
164 size_t rlen
= fread(buf
, 1, len
, f
);
166 if(size_t(len
)!=rlen
)
171 if(size
!=NULL
) *size
= len
;
175 bool listdir(const char *dir
, const char *ext
, vector
<char *> &files
)
177 int extsize
= ext
? (int)strlen(ext
)+1 : 0;
179 s_sprintfd(pathname
)("%s\\*.%s", dir
, ext
? ext
: "*");
180 WIN32_FIND_DATA FindFileData
;
181 HANDLE Find
= FindFirstFile(path(pathname
), &FindFileData
);
182 if(Find
!= INVALID_HANDLE_VALUE
)
185 files
.add(newstring(FindFileData
.cFileName
, (int)strlen(FindFileData
.cFileName
) - extsize
));
186 } while(FindNextFile(Find
, &FindFileData
));
191 s_strcpy(pathname
, dir
);
192 DIR *d
= opendir(path(pathname
));
196 while((de
= readdir(d
)) != NULL
)
198 if(!ext
) files
.add(newstring(de
->d_name
));
201 int namelength
= (int)strlen(de
->d_name
) - extsize
;
202 if(namelength
> 0 && de
->d_name
[namelength
] == '.' && strncmp(de
->d_name
+namelength
+1, ext
, extsize
-1)==0)
203 files
.add(newstring(de
->d_name
, namelength
));
213 int listfiles(const char *dir
, const char *ext
, vector
<char *> &files
)
216 if(listdir(dir
, ext
, files
)) dirs
++;
220 s_sprintf(s
)("%s%s", homedir
, dir
);
221 if(listdir(s
, ext
, files
)) dirs
++;
225 s_sprintf(s
)("%s%s", packagedirs
[i
], dir
);
226 if(listdir(s
, ext
, files
)) dirs
++;
231 ///////////////////////// misc tools ///////////////////////
233 void endianswap(void *memory
, int stride
, int length
) // little endian as storage format
235 static const int littleendian
= 1;
236 if(!*(const char *)&littleendian
) loop(w
, length
) loop(i
, stride
/2)
238 uchar
*p
= (uchar
*)memory
+w
*stride
;
240 p
[i
] = p
[stride
-i
-1];
246 ////////////////////////// rnd numbers ////////////////////////////////////////
250 #define K (0x9908B0DFU)
251 #define hiBit(u) ((u) & 0x80000000U)
252 #define loBit(u) ((u) & 0x00000001U)
253 #define loBits(u) ((u) & 0x7FFFFFFFU)
254 #define mixBits(u, v) (hiBit(u)|loBits(v))
256 static uint state
[N
+1];
258 static int left
= -1;
260 void seedMT(uint seed
)
262 register uint x
= (seed
| 1U) & 0xFFFFFFFFU
, *s
= state
;
264 for(left
=0, *s
++=x
, j
=N
; --j
; *s
++ = (x
*=69069U) & 0xFFFFFFFFU
);
269 register uint
*p0
=state
, *p2
=state
+2, *pM
=state
+M
, s0
, s1
;
271 if(left
< -1) seedMT(time(NULL
));
272 left
=N
-1, next
=state
+1;
273 for(s0
=state
[0], s1
=state
[1], j
=N
-M
+1; --j
; s0
=s1
, s1
=*p2
++) *p0
++ = *pM
++ ^ (mixBits(s0
, s1
) >> 1) ^ (loBit(s1
) ? K
: 0U);
274 for(pM
=state
, j
=M
; --j
; s0
=s1
, s1
=*p2
++) *p0
++ = *pM
++ ^ (mixBits(s0
, s1
) >> 1) ^ (loBit(s1
) ? K
: 0U);
275 s1
=state
[0], *p0
= *pM
^ (mixBits(s0
, s1
) >> 1) ^ (loBit(s1
) ? K
: 0U);
277 s1
^= (s1
<< 7) & 0x9D2C5680U
;
278 s1
^= (s1
<< 15) & 0xEFC60000U
;
279 return(s1
^ (s1
>> 18));
285 if(--left
< 0) return(reloadMT());
288 y
^= (y
<< 7) & 0x9D2C5680U
;
289 y
^= (y
<< 15) & 0xEFC60000U
;
290 return(y
^ (y
>> 18));