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 // ////////////////////////////////////////////////////////////////////////// //
103 truth
inputfile::fileExists (const festring
&fname
) {
105 if (stat(fname
.CStr(), &st
)) return false;
106 if (!S_ISREG(st
.st_mode
)) return false;
107 return access(fname
.CStr(), R_OK
) == 0;
111 festring
inputfile::GetMyDir () {
113 return IVAN_DATA_DIR
;
117 pid_t mypid
= getpid();
118 memset(myDir
, 0, sizeof(myDir
));
119 sprintf(buf
, "/proc/%u/exe", (unsigned int)mypid
);
120 if (readlink(buf
, myDir
, sizeof(myDir
)-1) < 0) {
123 char *p
= (char *)strrchr(myDir
, '/');
124 if (!p
) strcpy(myDir
, "."); else *p
= '\0';
126 if (myDir
[strlen(myDir
)-1] == '/') myDir
[strlen(myDir
)-1] = '\0';
132 ////////////////////////////////////////////////////////////////////////////////
133 inputfile::inputfile () :
143 inputfile::inputfile (cfestring
&aFileName
, truth AbortOnErr
) :
145 Buffer(gzopen(aFileName
.CStr(), "rb")),
147 Buffer(fopen(aFileName
.CStr(), "rb")),
154 if (AbortOnErr
&& !IsOpen()) ABORT("File %s not found!", FileName
.CStr());
158 inputfile::~inputfile () {
163 bool inputfile::Open (cfestring
&aFileName
, truth AbortOnErr
) {
167 Buffer
= gzopen(aFileName
.CStr(), "rb");
169 Buffer
= fopen(aFileName
.CStr(), "rb");
171 FileName
= aFileName
;
172 mRetFName
= aFileName
;
173 auto mydir
= GetMyDir();
174 if (mydir
.GetSize() > 0 && mRetFName
.startsWith(mydir
)) {
175 mRetFName
.Erase(0, mydir
.GetSize()+(mydir
[mydir
.GetSize()-1] != '/' ? 1 : 0));
177 if (AbortOnErr
&& !IsOpen()) ABORT("File %s not found!", aFileName
.CStr());
182 void inputfile::Close () {
194 int inputfile::Get () {
196 int ch
= Xgetc(Buffer
);
197 return (ch
< 0 ? EOF
: ch
);
204 truth
inputfile::Eof () {
205 return (Buffer
? Xfeof(Buffer
) : true);
209 void inputfile::Read (char *Offset
, sLong Size
) {
210 if (!Buffer
) ABORT("Trying to read from unopened file '%s'!", FileName
.CStr());
212 if (gzread(Buffer
, Offset
, Size
) != Size
) ABORT("File '%s' read error!", FileName
.CStr());
214 if (fread(Offset
, Size
, 1, Buffer
) != 1) ABORT("File '%s' read error!", FileName
.CStr());
219 void inputfile::SeekPosBegin (sLong Offset
) {
220 if (Xseek(Buffer
, Offset
, SEEK_SET
) < 0) ABORT("File '%s': seek error!", FileName
.CStr());
224 void inputfile::SeekPosCurrent (sLong Offset
) {
225 if (Xseek(Buffer
, Offset
, SEEK_CUR
) < 0) ABORT("File '%s': seek error!", FileName
.CStr());
230 void inputfile::SeekPosEnd (sLong Offset
) {
231 //HACKHACK: emulate this
233 //SLOOOW, but we have to do that
235 char *buffer
, buf
[512];
237 for (bufsize
= 256*1024; bufsize
> (int)sizeof(buf
); bufsize
/= 2) {
238 if ((buffer
= (char *)malloc(bufsize
)) != NULL
) break;
240 if (buffer
== NULL
) { buffer
= buf
; bufsize
= sizeof(buf
); }
241 //fprintf(stderr, "determining file size...\n");
242 mFileSize
= opos
= gztell(Buffer
);
244 int len
= gzread(Buffer
, buffer
, bufsize
);
245 if (len
< 0) { mFileSize
= -1; break; } // error
247 if (len
< bufsize
) break; // eof reached
249 if (buffer
!= buf
) free(buffer
);
250 //fprintf(stderr, "file size: %d\n", ctx->filesize);
252 if (mFileSize
< 0) ABORT("File '%s': seek error!", FileName
.CStr());
253 if (gzseek(Buffer
, mFileSize
+Offset
, SEEK_SET
) < 0) ABORT("File '%s': seek error!", FileName
.CStr());
258 void inputfile::SeekPosEnd (sLong Offset
) {
259 if (fseek(Buffer
, Offset
, SEEK_END
) < 0) ABORT("File '%s': seek error!", FileName
.CStr());
264 sLong
inputfile::TellPos () {
265 return Xtell(Buffer
);
269 void inputfile::ClearFlags () {
274 // ////////////////////////////////////////////////////////////////////////// //
275 outputfile
&operator << (outputfile
&SaveFile
, cfestring
&String
) {
276 uShort Length
= String
.GetSize();
278 if (Length
) SaveFile
.Write(String
.CStr(), Length
);
283 inputfile
&operator >> (inputfile
&SaveFile
, festring
&String
) {
284 char *RealBuffer
, StackBuffer
[1024];
287 RealBuffer
= (Length
< 1024 ? StackBuffer
: new char[Length
+1]);
290 SaveFile
.Read(RealBuffer
, Length
);
291 RealBuffer
[Length
] = 0;
292 String
<< RealBuffer
;
294 if (RealBuffer
!= StackBuffer
) delete [] RealBuffer
;
299 outputfile
&operator << (outputfile
&SaveFile
, cchar
*String
) {
300 uShort Length
= (String
? strlen(String
) : 0);
302 if (Length
) SaveFile
.Write(String
, Length
);
307 inputfile
&operator >> (inputfile
&SaveFile
, char *&String
) {
311 String
= new char[Length
+1];
312 SaveFile
.Read(String
, Length
);