/*****
* castop.h
* Tom Prince 2005/3/18
*
* Defines some runtime functions used by the stack machine.
*
*****/
#ifndef CASTOP_H
#define CASTOP_H
#include <cfloat>
#include "common.h"
#include "stack.h"
#include "fileio.h"
#include "lexical.h"
#include "mathop.h"
#include "array.h"
namespace run {
using vm::read;
using vm::pop;
template<class T, class S>
void cast(vm::stack *s)
{
s->push((S) pop<T>(s));
}
void castDoubleInt(vm::stack *s)
{
double x=pop<double>(s);
s->push(Intcast(x));
}
template<class T>
void stringCast(vm::stack *s)
{
ostringstream buf;
buf.precision(DBL_DIG);
buf << pop<T>(s);
s->push(buf.str());
}
template<class T>
void castString(vm::stack *s)
{
string *S=pop<string*>(s);
try {
s->push(lexical::cast<T>(*S));
} catch (lexical::bad_cast&) {
s->push(vm::Default);
}
}
void initialized(vm::stack *s)
{
s->push(!vm::isdefault(pop(s)));
}
template<class T, class S>
void arrayToArray(vm::stack *s)
{
vm::array *a=pop<vm::array*>(s);
size_t size=checkArray(a);
vm::array *c=new vm::array(size);
for(size_t i=0; i < size; i++)
(*c)[i]=(S) read<T>(a,i);
s->push(c);
}
template<class T, class S>
void array2ToArray2(vm::stack *s)
{
vm::array *a=pop<vm::array*>(s);
size_t size=checkArray(a);
vm::array *c=new vm::array(size);
for(size_t i=0; i < size; ++i) {
vm::array *ai=vm::read<vm::array*>(a,i);
size_t aisize=checkArray(ai);
vm::array *ci=new vm::array(aisize);
(*c)[i]=ci;
for(size_t j=0; j < aisize; ++j)
(*ci)[j]=(S) read<T>(ai,j);
}
s->push(c);
}
template<class T>
void read(vm::stack *s)
{
camp::file *f = pop<camp::file*>(s);
T val=T();
if(f->isOpen()) {
f->read(val);
if(f->LineMode()) f->nexteol();
if(interact::interactive) f->purgeStandard(val);
}
s->push(val);
}
inline Int Limit(Int nx) {return nx == 0 ? Int_MAX : nx;}
inline void reportEof(camp::file *f, Int count)
{
if(count > 0) {
ostringstream buf;
buf << "EOF after reading " << count
<< " values from file '" << f->filename() << "'.";
vm::error(buf);
}
}
template<class T>
void readArray(vm::stack *s, Int nx=-1, Int ny=-1, Int nz=-1)
{
camp::file *f = pop<camp::file*>(s);
vm::array *c=new vm::array(0);
if(f->isOpen()) {
if(nx != -1 && f->Nx() != -1) nx=f->Nx();
if(nx == -2) {f->read(nx); f->Nx(-1); if(nx == 0) {s->push(c); return;}}
if(ny != -1 && f->Ny() != -1) ny=f->Ny();
if(ny == -2) {f->read(ny); f->Ny(-1); if(ny == 0) {s->push(c); return;}}
if(nz != -1 && f->Nz() != -1) nz=f->Nz();
if(nz == -2) {f->read(nz); f->Nz(-1); if(nz == 0) {s->push(c); return;}}
T v;
if(nx >= 0) {
for(Int i=0; i < Limit(nx); i++) {
if(ny >= 0) {
vm::array *ci=new vm::array(0);
for(Int j=0; j < Limit(ny); j++) {
if(nz >= 0) {
vm::array *cij=new vm::array(0);
bool break2=false;
for(Int k=0; k < Limit(nz); k++) {
f->read(v);
if(f->error()) {
if(nx && ny && nz) reportEof(f,(i*ny+j)*nz+k);
s->push(c);
return;
}
if(k == 0) {
if(j == 0) c->push(ci);
ci->push(cij);
}
cij->push(v);
if(f->LineMode() && f->nexteol()) {
if(f->nexteol() && !f->CSVMode()) break2=true;
break;
}
}
if(break2) break;
} else {
f->read(v);
if(f->error()) {
if(nx && ny) reportEof(f,i*ny+j);
s->push(c);
return;
}
if(j == 0) c->push(ci);
ci->push(v);
if(f->LineMode() && f->nexteol()) break;
}
}
} else {
f->read(v);
if(f->error()) {
if(nx) reportEof(f,i);
s->push(c);
return;
}
c->push(v);
if(f->LineMode() && f->nexteol()) break;
}
}
} else {
for(;;) {
f->read(v);
if(f->error()) break;
c->push(v);
if(f->LineMode() && f->nexteol()) break;
}
}
if(interact::interactive) f->purgeStandard(v);
}
s->push(c);
}
template<class T>
void readArray1(vm::stack *s)
{
readArray<T>(s,0);
}
template<class T>
void readArray2(vm::stack *s)
{
readArray<T>(s,0,0);
}
template<class T>
void readArray3(vm::stack *s)
{
readArray<T>(s,0,0,0);
}
} // namespace run
#endif // CASTOP_H