/*****
 * runfile.in
 *
 * Runtime functions for file operations.
 *
 *****/

file*    => primFile()

#include "fileio.h"
#include "callable.h"
#include "triple.h"
#include "array.h"

using namespace camp;
using namespace settings;
using namespace vm;

string commentchar="#";

// Autogenerated routines:


bool ==(file *a, file *b)
{
  return a == b;
}

bool !=(file *a, file *b)
{
  return a != b;
}

file* :nullFile()
{
  return &camp::nullfile;
}

file* input(string name, bool check=true, string comment=commentchar)
{
  char c=comment.empty() ? (char) 0 : comment[0];
  file *f=new ifile(name,c,check);
  f->open();
  return f;
}

file* output(string name, bool update=false, string comment=commentchar)
{
  file *f;
  if(update) {
    char c=comment.empty() ? (char) 0 : comment[0];
    f=new iofile(name,c);
  } else f=new ofile(name);
  f->open();
  if(update) f->seek(0,false);
  return f;
}

file* xinput(string name, bool check=true)
{
#ifdef HAVE_RPC_RPC_H
  file *f=new ixfile(name,check);
  f->open();
  return f;
#else  
  ostringstream buf;
  buf << name << ": XDR read support not enabled";
  error(buf);
  unused(&check); // Suppress unused variable warning
#endif
}

file* xoutput(string name, bool update=false)
{
#ifdef HAVE_RPC_RPC_H
  file *f;
  if(update)
    f=new ioxfile(name);
  else f=new oxfile(name);
  f->open();
  if(update) f->seek(0,false);
  return f;
#else  
  ostringstream buf;
  buf << name << ": XDR write support not enabled";
  error(buf);
  unused(&update); // Suppress unused variable warning
#endif
}

file* binput(string name, bool check=true)
{
  file *f=new ibfile(name,check);
  f->open();
  return f;
}

file* boutput(string name, bool update=false)
{
  file *f;
  if(update) f=new iobfile(name);
  else f=new obfile(name);
  f->open();
  if(update) f->seek(0,false);
  return f;
}

bool eof(file *f)
{
  return f->eof();
}

bool eol(file *f)
{
  return f->eol();
}

bool error(file *f)
{
  return f->error();
}

void clear(file *f)
{
  f->clear();
}

void close(file *f)
{
  f->close();
}

Int precision(file *f=NULL, Int digits=0) 
{
  if(f == 0) f=&camp::Stdout;
  return f->precision(digits);
}

void flush(file *f) 
{
  f->flush();
}

string getc(file *f)
{
  char c=0;
  if(f->isOpen()) f->read(c);
  static char str[1];
  str[0]=c;
  return string(str);
}

Int tell(file *f)
{
  return f->tell();
}

void seek(file *f, Int pos)
{
  f->seek(pos,pos >= 0);
}

void seekeof(file *f)
{
  f->seek(0,false);
}

string :namePart(file f)
{
  return f.filename();
}

string :modePart(file f)
{
  return f.FileMode();
}

// Set file dimensions
file* :dimensionSetHelper(Int nx=-1, Int ny=-1, Int nz=-1, file *f)
{
  f->dimension(nx,ny,nz);
  return f;
}

callable* :dimensionSet(file *f)
{
  return new thunk(new bfunc(dimensionSetHelper),f);
}

array * :dimensionPart(file f)
{
  array *a=new array(3);
  (*a)[0]=f.Nx();
  (*a)[1]=f.Ny();
  (*a)[2]=f.Nz();
  return a;
}

// Set file f to read arrays in line-at-a-time mode
file* :lineSetHelper(bool b=true, file *f)
{
  f->LineMode(b);
  return f;
}

callable* :lineSet(file *f)
{
  return new thunk(new bfunc(lineSetHelper),f);
}

bool :linePart(file f)
{
  return f.LineMode();
}

// Set file to read comma-separated values
file* :csvSetHelper(bool b=true, file *f)
{
  f->CSVMode(b);
  return f;
}

callable* :csvSet(file *f)
{
  return new thunk(new bfunc(csvSetHelper),f);
}

bool :csvPart(file f)
{
  return f.CSVMode();
}

// Set file to read whitespace-separated values
file* :wordSetHelper(bool b=true, file *f)
{
  f->WordMode(b);
  return f;
}

callable* :wordSet(file *f)
{
  return new thunk(new bfunc(wordSetHelper),f);
}

bool :wordPart(file f)
{
  return f.WordMode();
}

// Set file to read/write single precision real XDR values.
file* :singlerealSetHelper(bool b=true, file *f)
{
  f->SingleReal(b);
  return f;
}

callable* :singlerealSet(file *f)
{
  return new thunk(new bfunc(singlerealSetHelper),f);
}

bool :singlerealPart(file f)
{
  return f.SingleReal();
}

// Set file to read/write single precision int XDR values.
file* :singleintSetHelper(bool b=true, file *f)
{
  f->SingleInt(b);
  return f;
}

callable* :singleintSet(file *f)
{
  return new thunk(new bfunc(singleintSetHelper),f);
}

bool :singleintPart(file f)
{
  return f.SingleInt();
}

// Set file to read/write signed int XDR values.
file* :signedintSetHelper(bool b=true, file *f)
{
  f->SignedInt(b);
  return f;
}

callable* :signedintSet(file *f)
{
  return new thunk(new bfunc(signedintSetHelper),f);
}

bool :signedintPart(file f)
{
  return f.SignedInt();
}

// Set file to read an arrayi (i int sizes followed by an i-dimensional array)
file* :readSetHelper(Int i, file *f)
{
  switch(i) {
    case 1:
      f->dimension(-2);
      break;
      
    case 2:
      f->dimension(-2,-2);
      break;
      
    case 3:
      f->dimension(-2,-2,-2);
      break;
      
    default:
      f->dimension();
  }
  
  return f;
}

callable* :readSet(file *f)
{
  return new thunk(new bfunc(readSetHelper),f);
}

// Delete file named s.
Int delete(string *s) 
{
  checkLocal(*s);
  Int rc=unlink(s->c_str());
  if(rc == 0 && verbose > 0) 
    cout << "Deleted " << *s << endl;
  return rc;
}

// Rename file "from" to file "to".
Int rename(string *from, string *to) 
{
  checkLocal(*from);
  checkLocal(*to);
  Int rc=rename(from->c_str(),to->c_str());
  if(rc == 0 && verbose > 0) 
    cout << "Renamed " << *from << " to " << *to << endl;
  return rc;
}