moved almost all hardcoded constants to "define.dat"
[k8-i-v-a-n.git] / src / felib / fesave.cpp
blobe7099090615e812be3f7988a9fbf61c593d0b91d
1 /*
3 * Iter Vehemens ad Necem (IVAN)
4 * Copyright (C) Timo Kiviluoto
5 * Released under the GNU General
6 * Public License
8 * See LICENSING which should be included
9 * along with this file for more details
12 #ifndef _GNU_SOURCE
13 # define _GNU_SOURCE
14 #endif
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <unistd.h>
22 #include <cctype>
24 #include "fesave.h"
25 #include "femath.h"
28 #ifdef USE_ZLIB
29 # define Xgetc gzgetc
30 # define Xfeof gzeof
31 # define Xungc gzungetc
32 # define Xseek gzseek
33 # define Xtell gztell
34 # define Xclre gzclearerr
35 #else
36 # define Xgetc fgetc
37 # define Xfeof feof
38 # define Xungc ungetc
39 # define Xseek fseek
40 # define Xtell ftell
41 # define Xclre clearerr
42 #endif
45 // ////////////////////////////////////////////////////////////////////////// //
46 outputfile::outputfile (cfestring &FileName, truth maxcomp, truth AbortOnErr) :
47 #ifdef USE_ZLIB
48 Buffer(gzopen(FileName.CStr(), (maxcomp?"wb9":"wb1"))),
49 #else
50 Buffer(fopen(FileName.CStr(), "wb")),
51 #endif
52 FileName(FileName)
54 if (AbortOnErr && !IsOpen()) ABORT("Can't open %s for output!", FileName.CStr());
58 outputfile::~outputfile () {
59 Close();
63 void outputfile::Close () {
64 if (Buffer) {
65 #ifdef USE_ZLIB
66 gzclose(Buffer);
67 #else
68 fclose(Buffer);
69 #endif
70 Buffer = 0;
75 void outputfile::Flush () {
76 #ifdef USE_ZLIB
77 gzflush(Buffer, Z_FINISH);
78 #else
79 fflush(Buffer);
80 #endif
84 void outputfile::Put (char What) {
85 #ifdef USE_ZLIB
86 gzputc(Buffer, What);
87 #else
88 fputc(What, Buffer);
89 #endif
93 void outputfile::Write (cchar *Offset, sLong Size) {
94 #ifdef USE_ZLIB
95 gzwrite(Buffer, Offset, Size);
96 #else
97 fwrite(Offset, 1, Size, Buffer);
98 #endif
102 // ////////////////////////////////////////////////////////////////////////// //
103 truth inputfile::fileExists (const festring &fname) {
104 struct stat st;
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 () {
112 #ifdef IVAN_DATA_DIR
113 return IVAN_DATA_DIR;
114 #else
115 char myDir[8192];
116 char buf[128];
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) {
121 strcpy(myDir, ".");
122 } else {
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';
127 return myDir;
128 #endif
132 ////////////////////////////////////////////////////////////////////////////////
133 inputfile::inputfile () :
134 Buffer(0),
135 FileName("")
136 #ifdef USE_ZLIB
137 , mFileSize(-1)
138 #endif
143 inputfile::inputfile (cfestring &aFileName, truth AbortOnErr) :
144 #ifdef USE_ZLIB
145 Buffer(gzopen(aFileName.CStr(), "rb")),
146 #else
147 Buffer(fopen(aFileName.CStr(), "rb")),
148 #endif
149 FileName(aFileName)
150 #ifdef USE_ZLIB
151 , mFileSize(-1)
152 #endif
154 if (AbortOnErr && !IsOpen()) ABORT("File %s not found!", FileName.CStr());
158 inputfile::~inputfile () {
159 Close();
163 bool inputfile::Open (cfestring &aFileName, truth AbortOnErr) {
164 Close();
165 #ifdef USE_ZLIB
166 mFileSize = -1;
167 Buffer = gzopen(aFileName.CStr(), "rb");
168 #else
169 Buffer = fopen(aFileName.CStr(), "rb");
170 #endif
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());
178 return IsOpen();
182 void inputfile::Close () {
183 if (Buffer) {
184 #ifdef USE_ZLIB
185 gzclose(Buffer);
186 #else
187 fclose(Buffer);
188 #endif
189 Buffer = 0;
194 int inputfile::Get () {
195 if (Buffer) {
196 int ch = Xgetc(Buffer);
197 return (ch < 0 ? EOF : ch);
198 } else {
199 return EOF;
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());
211 #ifdef USE_ZLIB
212 if (gzread(Buffer, Offset, Size) != Size) ABORT("File '%s' read error!", FileName.CStr());
213 #else
214 if (fread(Offset, Size, 1, Buffer) != 1) ABORT("File '%s' read error!", FileName.CStr());
215 #endif
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());
229 #ifdef USE_ZLIB
230 void inputfile::SeekPosEnd (sLong Offset) {
231 //HACKHACK: emulate this
232 if (mFileSize < 0) {
233 //SLOOOW, but we have to do that
234 int opos;
235 char *buffer, buf[512];
236 int bufsize;
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);
243 for (;;) {
244 int len = gzread(Buffer, buffer, bufsize);
245 if (len < 0) { mFileSize = -1; break; } // error
246 mFileSize += len;
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());
256 #else
258 void inputfile::SeekPosEnd (sLong Offset) {
259 if (fseek(Buffer, Offset, SEEK_END) < 0) ABORT("File '%s': seek error!", FileName.CStr());
261 #endif
264 sLong inputfile::TellPos () {
265 return Xtell(Buffer);
269 void inputfile::ClearFlags () {
270 Xclre(Buffer);
274 // ////////////////////////////////////////////////////////////////////////// //
275 outputfile &operator << (outputfile &SaveFile, cfestring &String) {
276 uShort Length = String.GetSize();
277 SaveFile << Length;
278 if (Length) SaveFile.Write(String.CStr(), Length);
279 return SaveFile;
283 inputfile &operator >> (inputfile &SaveFile, festring &String) {
284 char *RealBuffer, StackBuffer[1024];
285 uShort Length;
286 SaveFile >> Length;
287 RealBuffer = (Length < 1024 ? StackBuffer : new char[Length+1]);
288 String.Empty();
289 if (Length) {
290 SaveFile.Read(RealBuffer, Length);
291 RealBuffer[Length] = 0;
292 String << RealBuffer;
294 if (RealBuffer != StackBuffer) delete [] RealBuffer;
295 return SaveFile;
299 outputfile &operator << (outputfile &SaveFile, cchar *String) {
300 uShort Length = (String ? strlen(String) : 0);
301 SaveFile << Length;
302 if (Length) SaveFile.Write(String, Length);
303 return SaveFile;
307 inputfile &operator >> (inputfile &SaveFile, char *&String) {
308 uShort Length;
309 SaveFile >> Length;
310 if (Length) {
311 String = new char[Length+1];
312 SaveFile.Read(String, Length);
313 String[Length] = 0;
314 } else {
315 String = 0;
317 return SaveFile;