3 * Iter Vehemens ad Necem (IVAN)
4 * Copyright (C) Timo Kiviluoto
5 * Released under the GNU General
8 * See LICENSING which should be included
9 * along with this file for more details
18 #include <sys/types.h>
31 # define Xungc gzungetc
34 # define Xclre gzclearerr
41 # define Xclre clearerr
45 // ////////////////////////////////////////////////////////////////////////// //
46 outputfile::outputfile (cfestring
&FileName
, truth maxcomp
, truth AbortOnErr
) :
48 Buffer(gzopen(FileName
.CStr(), (maxcomp
?"wb9":"wb1"))),
50 Buffer(fopen(FileName
.CStr(), "wb")),
54 if (AbortOnErr
&& !IsOpen()) ABORT("Can't open %s for output!", FileName
.CStr());
58 outputfile::~outputfile () {
63 void outputfile::Close () {
75 void outputfile::Flush () {
77 gzflush(Buffer
, Z_FINISH
);
84 void outputfile::Put (char What
) {
93 void outputfile::Write (cchar
*Offset
, sLong Size
) {
95 gzwrite(Buffer
, Offset
, Size
);
97 fwrite(Offset
, 1, Size
, Buffer
);
102 sLong
outputfile::TellPos () {
103 return Xtell(Buffer
);
107 // ////////////////////////////////////////////////////////////////////////// //
108 truth
inputfile::fileExists (const festring
&fname
) {
110 if (stat(fname
.CStr(), &st
)) return false;
111 if (!S_ISREG(st
.st_mode
)) return false;
112 return access(fname
.CStr(), R_OK
) == 0;
116 festring
inputfile::GetMyDir () {
118 return IVAN_DATA_DIR
;
122 pid_t mypid
= getpid();
123 memset(myDir
, 0, sizeof(myDir
));
124 sprintf(buf
, "/proc/%u/exe", (unsigned int)mypid
);
125 if (readlink(buf
, myDir
, sizeof(myDir
)-1) < 0) {
128 char *p
= (char *)strrchr(myDir
, '/');
129 if (!p
) strcpy(myDir
, "."); else *p
= '\0';
131 if (myDir
[strlen(myDir
)-1] == '/') myDir
[strlen(myDir
)-1] = '\0';
137 festring
inputfile::buildIncludeName (cfestring
&basename
, cfestring incname
) {
138 festring xname
= incname
;
139 while (xname
.GetSize() > 0 && xname
[0] == '/') xname
.Erase(0, 1);
140 if (xname
.GetSize() == 0) ABORT("Cannot include file with empty name");
141 festring res
= basename
;
143 while (res
.GetSize() && res
[res
.GetSize()-1] != '/') res
.Erase(res
.GetSize()-1, 1);
145 //fprintf(stderr, "buildIncludeName(\"%s\", \"%s\") -> \"%s\"\n", basename.CStr(), incname.CStr(), res.CStr());
150 ////////////////////////////////////////////////////////////////////////////////
151 inputfile::inputfile () :
161 inputfile::inputfile (cfestring
&aFileName
, truth AbortOnErr
) :
163 Buffer(gzopen(aFileName
.CStr(), "rb")),
165 Buffer(fopen(aFileName
.CStr(), "rb")),
172 if (AbortOnErr
&& !IsOpen()) ABORT("File %s not found!", FileName
.CStr());
176 inputfile::~inputfile () {
181 bool inputfile::Open (cfestring
&aFileName
, truth AbortOnErr
) {
185 Buffer
= gzopen(aFileName
.CStr(), "rb");
187 Buffer
= fopen(aFileName
.CStr(), "rb");
189 FileName
= aFileName
;
190 mRetFName
= aFileName
;
191 auto mydir
= GetMyDir();
192 if (mydir
.GetSize() > 0 && mRetFName
.startsWith(mydir
)) {
193 mRetFName
.Erase(0, mydir
.GetSize()+(mydir
[mydir
.GetSize()-1] != '/' ? 1 : 0));
195 if (AbortOnErr
&& !IsOpen()) ABORT("File %s not found!", aFileName
.CStr());
200 void inputfile::Close () {
212 int inputfile::Get () {
214 int ch
= Xgetc(Buffer
);
215 return (ch
< 0 ? EOF
: ch
);
222 truth
inputfile::Eof () {
223 return (Buffer
? Xfeof(Buffer
) : true);
227 void inputfile::Read (char *Offset
, sLong Size
) {
228 if (!Buffer
) ABORT("Trying to read from unopened file '%s'!", FileName
.CStr());
230 if (gzread(Buffer
, Offset
, Size
) != Size
) ABORT("File '%s' read error!", FileName
.CStr());
232 if (fread(Offset
, Size
, 1, Buffer
) != 1) ABORT("File '%s' read error!", FileName
.CStr());
237 void inputfile::SeekPosBegin (sLong Offset
) {
238 if (Xseek(Buffer
, Offset
, SEEK_SET
) < 0) ABORT("File '%s': seek error!", FileName
.CStr());
242 void inputfile::SeekPosCurrent (sLong Offset
) {
243 if (Xseek(Buffer
, Offset
, SEEK_CUR
) < 0) ABORT("File '%s': seek error!", FileName
.CStr());
248 void inputfile::SeekPosEnd (sLong Offset
) {
249 //HACKHACK: emulate this
251 //SLOOOW, but we have to do that
253 char *buffer
, buf
[512];
255 for (bufsize
= 256*1024; bufsize
> (int)sizeof(buf
); bufsize
/= 2) {
256 if ((buffer
= (char *)malloc(bufsize
)) != NULL
) break;
258 if (buffer
== NULL
) { buffer
= buf
; bufsize
= sizeof(buf
); }
259 //fprintf(stderr, "determining file size...\n");
260 mFileSize
= opos
= gztell(Buffer
);
262 int len
= gzread(Buffer
, buffer
, bufsize
);
263 if (len
< 0) { mFileSize
= -1; break; } // error
265 if (len
< bufsize
) break; // eof reached
267 if (buffer
!= buf
) free(buffer
);
268 //fprintf(stderr, "file size: %d\n", ctx->filesize);
270 if (mFileSize
< 0) ABORT("File '%s': seek error!", FileName
.CStr());
271 if (gzseek(Buffer
, mFileSize
+Offset
, SEEK_SET
) < 0) ABORT("File '%s': seek error!", FileName
.CStr());
276 void inputfile::SeekPosEnd (sLong Offset
) {
277 if (fseek(Buffer
, Offset
, SEEK_END
) < 0) ABORT("File '%s': seek error!", FileName
.CStr());
282 sLong
inputfile::TellPos () {
283 return Xtell(Buffer
);
287 void inputfile::ClearFlags () {
292 // ////////////////////////////////////////////////////////////////////////// //
293 outputfile
&operator << (outputfile
&SaveFile
, cfestring
&String
) {
294 uShort Length
= String
.GetSize();
296 if (Length
) SaveFile
.Write(String
.CStr(), Length
);
301 inputfile
&operator >> (inputfile
&SaveFile
, festring
&String
) {
302 char *RealBuffer
, StackBuffer
[1024];
305 RealBuffer
= (Length
< 1024 ? StackBuffer
: new char[Length
+1]);
308 SaveFile
.Read(RealBuffer
, Length
);
309 RealBuffer
[Length
] = 0;
310 String
<< RealBuffer
;
312 if (RealBuffer
!= StackBuffer
) delete [] RealBuffer
;
317 outputfile
&operator << (outputfile
&SaveFile
, cchar
*String
) {
318 uShort Length
= (String
? strlen(String
) : 0);
320 if (Length
) SaveFile
.Write(String
, Length
);
325 inputfile
&operator >> (inputfile
&SaveFile
, char *&String
) {
329 String
= new char[Length
+1];
330 SaveFile
.Read(String
, Length
);