1 /******
2  * fileio.h
3  * Tom Prince and John Bowman 2004/05/10
4  *
5  * Handle input/output
6  ******/
7 
8 #ifndef FILEIO_H
9 #define FILEIO_H
10 
11 #include <fstream>
12 #include <iostream>
13 #include <sstream>
14 
15 #include "common.h"
16 
17 #ifdef HAVE_RPC_RPC_H
18 #include "xstream.h"
19 #endif
20 
21 #include "pair.h"
22 #include "triple.h"
23 #include "guide.h"
24 #include "pen.h"
25 
26 #include "camperror.h"
27 #include "interact.h"
28 #include "errormsg.h"
29 #include "util.h"
30 #include "process.h"
31 #include "locate.h"
32 #include "parser.h"
33 
34 namespace vm {
35 extern bool indebugger;
36 }
37 
38 namespace camp {
39 
40 extern string tab;
41 extern string newline;
42 
43 enum Mode {NOMODE,INPUT,OUTPUT,UPDATE,BINPUT,BOUTPUT,BUPDATE,XINPUT,XOUTPUT,
44            XUPDATE,OPIPE};
45 
46 static const string FileModes[]=
47 {"none","input","output","output(update)",
48  "input(binary)","output(binary)","output(binary,update)",
49  "input(xdr)","output(xdr)","output(xdr,update)","output(pipe)"};
50 
51 extern FILE *pipeout;
52 
openpipeout()53 inline void openpipeout()
54 {
55   int fd=intcast(settings::getSetting<Int>("outpipe"));
56   if(!pipeout && fd >= 0) pipeout=fdopen(fd,"w");
57   if(!pipeout) {
58     ostringstream buf;
59     buf << "Cannot open outpipe " << fd;
60     reportError(buf);
61   }
62 }
63 
locatefile(string name)64 inline string locatefile(string name) {
65   string s=settings::locateFile(name);
66   return s.empty() ? name : s;
67 }
68 
69 class file : public gc {
70 protected:
71   string name;
72   bool check;      // Check whether input file exists.
73   Mode type;
74 
75   Int nx,ny,nz;    // Array dimensions
76   bool linemode;   // Array reads will stop at eol instead of eof.
77   bool csvmode;    // Read comma-separated values.
78   bool wordmode;   // Delimit strings by white space instead of eol.
79   bool singlereal; // Read/write single-precision XDR/binary reals.
80   bool singleint;  // Read/write single-precision XDR/binary ints.
81   bool signedint;  // Read/write signed XDR/binary ints.
82 
83   bool closed;     // File has been closed.
84   bool standard;   // Standard input/output
85   bool binary;     // Read in binary mode.
86 
87   bool nullfield;  // Used to detect a final null field in csv+line mode.
88   string whitespace;
89   size_t index;    // Terminator index.
90 
91 public:
92 
Standard()93   bool Standard() {return standard;}
94 
standardEOF()95   void standardEOF() {
96 #if defined(HAVE_LIBREADLINE) && defined(HAVE_LIBCURSES)
97     cout << endl;
98 #endif
99   }
100 
101   template<class T>
purgeStandard(T &)102   void purgeStandard(T&) {
103     if(standard) {
104       int c;
105       if(cin.eof())
106         standardEOF();
107       else {
108         cin.clear();
109         while((c=cin.peek()) != EOF) {
110           cin.ignore();
111           if(c == '\n') break;
112         }
113       }
114     }
115   }
116 
purgeStandard(string &)117   void purgeStandard(string&) {
118     if(cin.eof())
119       standardEOF();
120   }
121 
122   void dimension(Int Nx=-1, Int Ny=-1, Int Nz=-1) {
123     if(Nx < -2 || Ny < -2 || Nz < -2) {
124       ostringstream buf;
125       buf << "Invalid array dimensions: " << Nx << ", " << Ny << ", " << Nz;
126       reportError(buf);
127     }
128 
129     nx=Nx; ny=Ny; nz=Nz;
130   }
131 
132   file(const string& name, bool check=true, Mode type=NOMODE,
133        bool binary=false, bool closed=false) :
name(name)134     name(name), check(check), type(type), linemode(false), csvmode(false),
135     wordmode(false), singlereal(false), singleint(true), signedint(true),
136     closed(closed), standard(name.empty()), binary(binary), nullfield(false),
137     whitespace("") {dimension();}
138 
open()139   virtual void open() {}
140 
Check()141   void Check() {
142     if(error()) {
143       ostringstream buf;
144       buf << "Cannot open file \"" << name << "\"";
145       reportError(buf);
146     }
147   }
148 
~file()149   virtual ~file() {}
150 
isOpen()151   bool isOpen() {
152     if(closed) {
153       ostringstream buf;
154       buf << "I/O operation attempted on ";
155       if(name != "") buf << "closed file \'" << name << "\'";
156       else buf << "null file";
157       reportError(buf);
158     }
159     return true;
160   }
161 
filename()162   string filename() {return name;}
eol()163   virtual bool eol() {return false;}
nexteol()164   virtual bool nexteol() {return false;}
text()165   virtual bool text() {return false;}
eof()166   virtual bool eof() {return true;}
error()167   virtual bool error() {return true;}
close()168   virtual void close() {}
clear()169   virtual void clear() {}
precision(Int)170   virtual Int precision(Int) {return 0;}
flush()171   virtual void flush() {}
tell()172   virtual size_t tell() {return 0;}
173   virtual void seek(Int, bool=true) {}
174 
FileMode()175   string FileMode() {return FileModes[type];}
176 
unsupported(const char * rw,const char * type)177   void unsupported(const char *rw, const char *type) {
178     ostringstream buf;
179     buf << rw << " of type " << type << " not supported in " << FileMode()
180         << " mode";
181     reportError(buf);
182   }
183 
noread(const char * type)184   void noread(const char *type) {unsupported("Read",type);}
nowrite(const char * type)185   void nowrite(const char *type) {unsupported("Write",type);}
186 
Read(bool &)187   virtual void Read(bool&) {noread("bool");}
Read(Int &)188   virtual void Read(Int&) {noread("int");}
Read(double &)189   virtual void Read(double&) {noread("real");}
Read(float &)190   virtual void Read(float&) {noread("real");}
Read(pair &)191   virtual void Read(pair&) {noread("pair");}
Read(triple &)192   virtual void Read(triple&) {noread("triple");}
Read(char &)193   virtual void Read(char&) {noread("char");}
Read(string &)194   virtual void Read(string&) {noread("string");}
readwhite(string &)195   virtual void readwhite(string&) {noread("string");}
196 
write(bool)197   virtual void write(bool) {nowrite("bool");}
write(Int)198   virtual void write(Int) {nowrite("int");}
write(double)199   virtual void write(double) {nowrite("real");}
write(const pair &)200   virtual void write(const pair&) {nowrite("pair");}
write(const triple &)201   virtual void write(const triple&) {nowrite("triple");}
write(const string &)202   virtual void write(const string&) {nowrite("string");}
write(const pen &)203   virtual void write(const pen&) {nowrite("pen");}
write(guide *)204   virtual void write(guide *) {nowrite("guide");}
write(const transform &)205   virtual void write(const transform&) {nowrite("transform");}
writeline()206   virtual void writeline() {nowrite("string");}
207 
ignoreComment()208   virtual void ignoreComment() {};
csv()209   virtual void csv() {};
210 
211   template<class T>
ignoreComment(T &)212   void ignoreComment(T&) {
213     ignoreComment();
214   }
215 
ignoreComment(string &)216   void ignoreComment(string&) {}
ignoreComment(char &)217   void ignoreComment(char&) {}
218 
219   template<class T>
read(T & val)220   void read(T& val) {
221     if(binary) Read(val);
222     else {
223       if(standard) clear();
224       if(errorstream::interrupt) throw interrupted();
225       else {
226         ignoreComment(val);
227         val=T();
228         if(!nullfield)
229           Read(val);
230         csv();
231         whitespace="";
232       }
233     }
234   }
235 
Nx()236   Int Nx() {return nx;}
Ny()237   Int Ny() {return ny;}
Nz()238   Int Nz() {return nz;}
239 
Nx(Int n)240   void Nx(Int n) {nx=n;}
Ny(Int n)241   void Ny(Int n) {ny=n;}
Nz(Int n)242   void Nz(Int n) {nz=n;}
243 
LineMode(bool b)244   void LineMode(bool b) {linemode=b;}
LineMode()245   bool LineMode() {return linemode;}
246 
CSVMode(bool b)247   void CSVMode(bool b) {csvmode=b; if(b) wordmode=false;}
CSVMode()248   bool CSVMode() {return csvmode;}
249 
WordMode(bool b)250   void WordMode(bool b) {wordmode=b; if(b) csvmode=false;}
WordMode()251   bool WordMode() {return wordmode;}
252 
SingleReal(bool b)253   void SingleReal(bool b) {singlereal=b;}
SingleReal()254   bool SingleReal() {return singlereal;}
255 
SingleInt(bool b)256   void SingleInt(bool b) {singleint=b;}
SingleInt()257   bool SingleInt() {return singleint;}
258 
SignedInt(bool b)259   void SignedInt(bool b) {signedint=b;}
SignedInt()260   bool SignedInt() {return signedint;}
261 };
262 
263 class opipe : public file {
264 public:
opipe(const string & name)265   opipe(const string& name) : file(name,false,OPIPE) {standard=false;}
266 
open()267   void open() {
268     openpipeout();
269   }
270 
text()271   bool text() {return true;}
eof()272   bool eof() {return pipeout ? feof(pipeout) : true;}
error()273   bool error() {return pipeout ? ferror(pipeout) : true;}
clear()274   void clear() {if(pipeout) clearerr(pipeout);}
flush()275   void flush() {if(pipeout) fflush(pipeout);}
276 
277   void seek(Int pos, bool begin=true) {
278     if(!standard && pipeout) {
279       clear();
280       fseek(pipeout,pos,begin ? SEEK_SET : SEEK_END);
281     }
282   }
283 
tell()284   size_t tell() {
285     return pipeout ? ftell(pipeout) : 0;
286   }
287 
write(const string & val)288   void write(const string& val) {
289     fprintf(pipeout,"%s",val.c_str());
290   }
291 
write(bool val)292   void write(bool val) {
293     ostringstream s;
294     s << val;
295     write(s.str());
296   }
297 
write(Int val)298   void write(Int val) {
299     ostringstream s;
300     s << val;
301     write(s.str());
302   }
write(double val)303   void write(double val) {
304     ostringstream s;
305     s << val;
306     write(s.str());
307   }
write(const pair & val)308   void write(const pair& val) {
309     ostringstream s;
310     s << val;
311     write(s.str());
312   }
write(const triple & val)313   void write(const triple& val) {
314     ostringstream s;
315     s << val;
316     write(s.str());
317   }
318 
write(const pen & val)319   void write(const pen &val) {
320     ostringstream s;
321     s << val;
322     write(s.str());
323   }
324 
write(guide * val)325   void write(guide *val) {
326     ostringstream s;
327     s << *val;
328     write(s.str());
329   }
330 
write(const transform & val)331   void write(const transform& val) {
332     ostringstream s;
333     s << val;
334     write(s.str());
335   }
336 
writeline()337   void writeline() {
338     fprintf(pipeout,"\n");
339     if(errorstream::interrupt) throw interrupted();
340   }
341 };
342 
343 class ifile : public file {
344 protected:
345   istream *stream;
346   std::fstream *fstream;
347   stringstream buf;
348   char comment;
349   std::ios::openmode mode;
350   bool comma;
351 
352 public:
353   ifile(const string& name, char comment, bool check=true, Mode type=INPUT,
354         std::ios::openmode mode=std::ios::in) :
file(name,check,type)355     file(name,check,type), stream(&cin), fstream(NULL),
356     comment(comment), mode(mode), comma(false) {}
357 
358   // Binary file
359   ifile(const string& name, bool check=true, Mode type=BINPUT,
360         std::ios::openmode mode=std::ios::in) :
file(name,check,type,true)361     file(name,check,type,true), mode(mode) {}
362 
~ifile()363   ~ifile() {close();}
364 
365   void open();
366   bool eol();
367   bool nexteol();
368 
text()369   bool text() {return true;}
eof()370   bool eof() {return stream->eof();}
error()371   bool error() {return stream->fail();}
372 
close()373   void close() {
374     if(!standard && fstream) {
375       fstream->close();
376       closed=true;
377       delete fstream;
378       fstream=NULL;
379       processData().ifile.remove(index);
380     }
381   }
382 
clear()383   void clear() {stream->clear();}
384 
385   void seek(Int pos, bool begin=true) {
386     if(!standard && fstream) {
387       clear();
388       fstream->seekg(pos,begin ? std::ios::beg : std::ios::end);
389     }
390   }
391 
tell()392   size_t tell() {
393     if(fstream)
394       return fstream->tellg();
395     else
396       return 0;
397   }
398 
399   void csv();
400 
401   virtual void ignoreComment();
402 
403   // Skip over white space
readwhite(string & val)404   void readwhite(string& val) {val=string(); *stream >> val;}
405 
Read(bool & val)406   void Read(bool &val) {string t; readwhite(t); val=(t == "true");}
Read(Int & val)407   void Read(Int& val) {*stream >> val;}
Read(double & val)408   void Read(double& val) {*stream >> val;}
Read(pair & val)409   void Read(pair& val) {*stream >> val;}
Read(triple & val)410   void Read(triple& val) {*stream >> val;}
Read(char & val)411   void Read(char& val) {stream->get(val);}
412   void Read(string& val);
413 };
414 
415 class iofile : public ifile {
416 public:
417   iofile(const string& name, char comment=0) :
418     ifile(name,comment,true,UPDATE,std::ios::in | std::ios::out) {}
419 
precision(Int p)420   Int precision(Int p) {
421     return p == 0 ? stream->precision(settings::getSetting<Int>("digits")) :
422       stream->precision(p);
423   }
flush()424   void flush() {if(fstream) fstream->flush();}
425 
write(bool val)426   void write(bool val) {*fstream << (val ? "true " : "false ");}
write(Int val)427   void write(Int val) {*fstream << val;}
write(double val)428   void write(double val) {*fstream << val;}
write(const pair & val)429   void write(const pair& val) {*fstream << val;}
write(const triple & val)430   void write(const triple& val) {*fstream << val;}
write(const string & val)431   void write(const string& val) {*fstream << val;}
write(const pen & val)432   void write(const pen& val) {*fstream << val;}
write(guide * val)433   void write(guide *val) {*fstream << *val;}
write(const transform & val)434   void write(const transform& val) {*fstream << val;}
435 
writeline()436   void writeline() {
437     *fstream << newline;
438     if(errorstream::interrupt) throw interrupted();
439   }
440 };
441 
442 class ofile : public file {
443 protected:
444   ostream *stream;
445   std::ofstream *fstream;
446   std::ios::openmode mode;
447 public:
448   ofile(const string& name, Mode type=OUTPUT,
449         std::ios::openmode mode=std::ios::trunc) :
file(name,true,type)450     file(name,true,type), stream(&cout), fstream(NULL), mode(mode) {}
451 
~ofile()452   ~ofile() {close();}
453 
open()454   void open() {
455     if(standard) {
456       if(mode & std::ios::binary)
457         reportError("Cannot open standard output in binary mode");
458       stream=&cout;
459     } else {
460       name=outpath(name);
461       stream=fstream=new std::ofstream(name.c_str(),mode | std::ios::trunc);
462       stream->precision(settings::getSetting<Int>("digits"));
463       index=processData().ofile.add(fstream);
464       Check();
465     }
466   }
467 
text()468   bool text() {return true;}
eof()469   bool eof() {return stream->eof();}
error()470   bool error() {return stream->fail();}
471 
close()472   void close() {
473     if(!standard && fstream) {
474       fstream->close();
475       closed=true;
476       delete fstream;
477       fstream=NULL;
478       processData().ofile.remove(index);
479     }
480   }
clear()481   void clear() {stream->clear();}
precision(Int p)482   Int precision(Int p) {
483     return p == 0 ? stream->precision(settings::getSetting<Int>("digits")) :
484       stream->precision(p);
485   }
flush()486   void flush() {stream->flush();}
487 
488   void seek(Int pos, bool begin=true) {
489     if(!standard && fstream) {
490       clear();
491       fstream->seekp(pos,begin ? std::ios::beg : std::ios::end);
492     }
493   }
494 
tell()495   size_t tell() {
496     if(fstream)
497       return fstream->tellp();
498     else
499       return 0;
500   }
501 
enabled()502   bool enabled() {return !standard || settings::verbose > 1 ||
503       interact::interactive || !settings::getSetting<bool>("quiet");}
504 
write(bool val)505   void write(bool val) {*stream << (val ? "true " : "false ");}
write(Int val)506   void write(Int val) {*stream << val;}
write(double val)507   void write(double val) {*stream << val;}
write(const pair & val)508   void write(const pair& val) {*stream << val;}
write(const triple & val)509   void write(const triple& val) {*stream << val;}
write(const string & val)510   void write(const string& val) {*stream << val;}
write(const pen & val)511   void write(const pen& val) {*stream << val;}
write(guide * val)512   void write(guide *val) {*stream << *val;}
write(const transform & val)513   void write(const transform& val) {*stream << val;}
514 
515   void writeline();
516 };
517 
518 class ibfile : public ifile {
519 public:
520   ibfile(const string& name, bool check=true, Mode type=BINPUT,
521          std::ios::openmode mode=std::ios::in) :
522     ifile(name,check,type,mode | std::ios::binary) {}
523   template<class T>
iread(T & val)524   void iread(T& val) {
525     val=T();
526     if(fstream) fstream->read((char *) &val,sizeof(T));
527   }
528 
Read(bool & val)529   void Read(bool& val) {iread(val);}
Read(Int & val)530   void Read(Int& val) {
531     if(signedint) {
532       if(singleint) {int ival; iread(ival); val=ival;}
533       else iread(val);
534     } else {
535       if(singleint) {unsigned ival; iread(ival); val=Intcast(ival);}
536       else {unsignedInt ival; iread(ival); val=Intcast(ival);}
537     }
538   }
Read(char & val)539   void Read(char& val) {iread(val);}
Read(string & val)540   void Read(string& val) {char c; iread(c); val=c;}
541 
Read(double & val)542   void Read(double& val) {
543     if(singlereal) {float fval; iread(fval); val=fval;}
544     else iread(val);
545   }
546 };
547 
548 class iobfile : public ibfile {
549 public:
iobfile(const string & name)550   iobfile(const string& name) :
551     ibfile(name,true,BUPDATE,std::ios::in | std::ios::out) {}
552 
flush()553   void flush() {if(fstream) fstream->flush();}
554 
555   template<class T>
iwrite(T val)556   void iwrite(T val) {
557     if(fstream) fstream->write((char *) &val,sizeof(T));
558   }
559 
write(bool val)560   void write(bool val) {iwrite(val);}
write(Int val)561   void write(Int val) {
562     if(signedint) {
563       if(singleint) iwrite(intcast(val));
564       else iwrite(val);
565     } else {
566       if(singleint) iwrite(unsignedcast(val));
567       else iwrite(unsignedIntcast(val));
568     }
569   }
write(const string & val)570   void write(const string& val) {iwrite(val);}
write(const pen & val)571   void write(const pen& val) {iwrite(val);}
write(guide * val)572   void write(guide *val) {iwrite(val);}
write(const transform & val)573   void write(const transform& val) {iwrite(val);}
write(double val)574   void write(double val) {
575     if(singlereal) iwrite((float) val);
576     else iwrite(val);
577   }
write(const pair & val)578   void write(const pair& val) {
579     write(val.getx());
580     write(val.gety());
581   }
write(const triple & val)582   void write(const triple& val) {
583     write(val.getx());
584     write(val.gety());
585     write(val.getz());
586   }
writeline()587   void writeline() {}
588 };
589 
590 class obfile : public ofile {
591 public:
obfile(const string & name)592   obfile(const string& name) : ofile(name,BOUTPUT,std::ios::binary) {}
593 
594   template<class T>
iwrite(T val)595   void iwrite(T val) {
596     if(fstream) fstream->write((char *) &val,sizeof(T));
597   }
598 
write(bool val)599   void write(bool val) {iwrite(val);}
write(Int val)600   void write(Int val) {
601     if(signedint) {
602       if(singleint) iwrite(intcast(val));
603       else iwrite(val);
604     } else {
605       if(singleint) iwrite(unsignedcast(val));
606       else iwrite(unsignedIntcast(val));
607     }
608   }
write(const string & val)609   void write(const string& val) {iwrite(val);}
write(const pen & val)610   void write(const pen& val) {iwrite(val);}
write(guide * val)611   void write(guide *val) {iwrite(val);}
write(const transform & val)612   void write(const transform& val) {iwrite(val);}
write(double val)613   void write(double val) {
614     if(singlereal) iwrite((float) val);
615     else iwrite(val);
616   }
write(const pair & val)617   void write(const pair& val) {
618     write(val.getx());
619     write(val.gety());
620   }
write(const triple & val)621   void write(const triple& val) {
622     write(val.getx());
623     write(val.gety());
624     write(val.getz());
625   }
626 
writeline()627   void writeline() {}
628 };
629 
630 #ifdef HAVE_RPC_RPC_H
631 
632 class ixfile : public file {
633 protected:
634   xdr::ioxstream *fstream;
635   xdr::xios::open_mode mode;
636 public:
637   ixfile(const string& name, bool check=true, Mode type=XINPUT,
638          xdr::xios::open_mode mode=xdr::xios::in) :
file(name,check,type,true)639     file(name,check,type,true), fstream(NULL), mode(mode) {}
640 
open()641   void open() {
642     name=locatefile(inpath(name));
643     fstream=new xdr::ioxstream(name.c_str(),mode);
644     index=processData().ixfile.add(fstream);
645     if(check) Check();
646   }
647 
close()648   void close() {
649     if(fstream) {
650       fstream->close();
651       closed=true;
652       delete fstream;
653       fstream=NULL;
654       processData().ixfile.remove(index);
655     }
656   }
657 
~ixfile()658   ~ixfile() {close();}
659 
eof()660   bool eof() {return fstream ? fstream->eof() : true;}
error()661   bool error() {return fstream ? fstream->fail() : true;}
662 
clear()663   void clear() {if(fstream) fstream->clear();}
664 
665   void seek(Int pos, bool begin=true) {
666     if(!standard && fstream) {
667       clear();
668       fstream->seek(pos,begin ? xdr::xios::beg : xdr::xios::end);
669     }
670   }
671 
tell()672   size_t tell() {
673     if(fstream)
674       return fstream->tell();
675     else
676       return 0;
677   }
678 
Read(Int & val)679   void Read(Int& val) {
680     if(signedint) {
681       if(singleint) {int ival=0; *fstream >> ival; val=ival;}
682       else {val=0; *fstream >> val;}
683     } else {
684       if(singleint) {unsigned ival=0; *fstream >> ival; val=Intcast(ival);}
685       else {unsignedInt ival=0; *fstream >> ival; val=Intcast(ival);}
686     }
687   }
Read(double & val)688   void Read(double& val) {
689     if(singlereal) {float fval=0.0; *fstream >> fval; val=fval;}
690     else {
691       val=0.0;
692       *fstream >> val;
693     }
694   }
Read(pair & val)695   void Read(pair& val) {
696     double x,y;
697     Read(x);
698     Read(y);
699     val=pair(x,y);
700   }
Read(triple & val)701   void Read(triple& val) {
702     double x,y,z;
703     Read(x);
704     Read(y);
705     Read(z);
706     val=triple(x,y,z);
707   }
708 };
709 
710 class ioxfile : public ixfile {
711 public:
ioxfile(const string & name)712   ioxfile(const string& name) : ixfile(outpath(name),true,XUPDATE,
713                                        xdr::xios::out) {}
714 
flush()715   void flush() {if(fstream) fstream->flush();}
716 
write(Int val)717   void write(Int val) {
718     if(signedint) {
719       if(singleint) *fstream << intcast(val);
720       else *fstream << val;
721     } else {
722       if(singleint) *fstream << unsignedcast(val);
723       else *fstream << unsignedIntcast(val);
724     }
725   }
write(double val)726   void write(double val) {
727     if(singlereal) *fstream << (float) val;
728     else *fstream << val;
729   }
write(const pair & val)730   void write(const pair& val) {
731     write(val.getx());
732     write(val.gety());
733   }
write(const triple & val)734   void write(const triple& val) {
735     write(val.getx());
736     write(val.gety());
737     write(val.getz());
738   }
739 };
740 
741 class oxfile : public file {
742   xdr::oxstream *fstream;
743 public:
oxfile(const string & name)744   oxfile(const string& name) : file(name,true,XOUTPUT), fstream(NULL) {}
745 
open()746   void open() {
747     fstream=new xdr::oxstream(outpath(name).c_str(),xdr::xios::trunc);
748     index=processData().oxfile.add(fstream);
749     Check();
750   }
751 
close()752   void close() {
753     if(fstream) {
754       fstream->close();
755       closed=true;
756       delete fstream;
757       fstream=NULL;
758       processData().oxfile.remove(index);
759     }
760   }
761 
~oxfile()762   ~oxfile() {close();}
763 
eof()764   bool eof() {return fstream ? fstream->eof() : true;}
error()765   bool error() {return fstream ? fstream->fail() : true;}
clear()766   void clear() {if(fstream) fstream->clear();}
flush()767   void flush() {if(fstream) fstream->flush();}
768 
769   void seek(Int pos, bool begin=true) {
770     if(!standard && fstream) {
771       clear();
772       fstream->seek(pos,begin ? xdr::xios::beg : xdr::xios::end);
773     }
774   }
775 
tell()776   size_t tell() {
777     if(fstream)
778       return fstream->tell();
779     else
780       return 0;
781   }
782 
write(Int val)783   void write(Int val) {
784     if(signedint) {
785       if(singleint) *fstream << intcast(val);
786       else *fstream << val;
787     } else {
788       if(singleint) *fstream << unsignedcast(val);
789       else *fstream << unsignedIntcast(val);
790     }
791   }
write(double val)792   void write(double val) {
793     if(singlereal) *fstream << (float) val;
794     else *fstream << val;
795   }
write(const pair & val)796   void write(const pair& val) {
797     write(val.getx());
798     write(val.gety());
799   }
write(const triple & val)800   void write(const triple& val) {
801     write(val.getx());
802     write(val.gety());
803     write(val.getz());
804   }
805 };
806 
807 #endif
808 
809 extern ofile Stdout;
810 extern file nullfile;
811 
812 } // namespace camp
813 
814 #endif // FILEIO_H
815