// file  : testfileio.tks
// author: Bastian Spiegel <flink@tkscript.de>
// date  : 21Nov02, 01Jul03
// rem   : test program for the File, Stream and Buffer classes

//use tksdl;

Integer hexio;

class CTest {
   tag int myint;
   int myint_notserialized;
   tag float myfloat;
   float myfloat_notserialized;
   //tag Vector myvector;
   //Vector myvector_notserialized;
   tag String mystring;
   String mystring_notserialized;

   init() {
      myint=42;
      myfloat=PI;
      //myvector.init(1,2,3);
      mystring="hello, world.";

      myint_notserialized=64;
      myfloat_notserialized=2PI;
      //myvector_notserialized.init(11,22,33);
      mystring_notserialized="hello, unserialized world.";
   }
}

class CDTest : CTest {
   tag int myint2;
   int myint2_notserialized;
   tag float myfloat2;
   float myfloat2_notserialized;
   //tag Vector myvector2;
   //Vector myvector2_notserialized;
   tag String mystring2;
   String mystring2_notserialized;

   init() {
      CTest::init();
      myint2=32;
      myfloat2=E;
      //myvector2.init(16,32,64);
      mystring2="this is yet another string.";
   }
}

class CDDTest : CDTest {
   int myint3;
   float myfloat3;
   //Vector myvector3;
   String mystring3;
}

// ---- store some formatted data into the stream ----
function serialize(Pointer _stream) {
   Stream ofs;
   ofs<=_stream; // (internal) table lookup checks whether Stream is a baseclass of _stream.
   String s;
   Buffer b;
   int i;
   int l;
   float f;
   //IVector iv;
   //Vector v;
   //Vector4 v4;
   Integer io;
   Float fo;
   //Matrix m;

   ofs.writeString("test",0,0);
   trace("ofs.offset="+ofs.offset);

   // ---- store 8 bit ----
   ofs.i8=255;

   // ---- store 16 bit ----
   ofs.i16=0x7fff;

   // ---- store 32bit ----
   ofs.i32=(-0xffffffff /** 1 **/);

   // ---- store 32 bit float ----
   ofs.f32=PI;

   // ---- serialize Integer object (and store 32 bit int) ----
   io.value=42;
   ofs << io;

   // ---- serialize Float object (and store 32 bit float) ----
   fo.value=19.23;
   ofs << fo;

   // store Object representation of float value 2PI, create and serialize raw Float Object data (only 32bit float)
   // without type information
   ofs.object=tcobject(2PI); // store the (32 bit) float value into the file stream

   //// ---- serialize Vector Object ----
   //v.init(1,2,3); ofs << v;

   //// ---- serialize IVector Object ----
   //iv.init(9, 23); ofs << iv;

   //// ---- serialize Vector4 Object ----
   //v4.init(1.1, 2.2, 3.3, 4.4); ofs << v4;

   //// ---- serialize Matrix Object ----
   //m.loadIdentity();
   //m.scale(16.0);
   //ofs << m;
    
   // append "pascal" style String to file stream. store size and then chars.
   s="a <256 char test string";
   ofs.i8=s.length-1;
   ofs.writeString(s,0,s.length-1); // no ASCII zero is written

   // ---- serialize String to File stream ----
   ofs << "12345678";

   // ---- write some "raw" data taken from a string ----
   s="*DATA";
   l=s.length-1;
   for(i=0; i<16; i++)
	{
      ofs.writeString(s,0,l);
	}

   // ---- serialize a HashTable ----
   HashTable ht;
   ht.alloc(256);
   ht["myint"]=42;
   ht["myfloat"]=PI;
   ht["mystring"]="hello, hashtable.";
   //v<=new Vector;
   //v.init(32.0, 64.0, 128.0);
   //ht["vector"]=deref v;
   HashTable hti<=new HashTable;
   hti["myinnerint"]=23;
   hti["myinnerfloat"]=2PI;
   hti["myinnerstring"]="hello, inner hashtable.";
   ht["myhashtable"]=deref hti;
   trace "io.offset="+ofs.offset;
   ofs << ht;
   trace "+io.offset="+ofs.offset;

   // ---- serialize a Time ----
   //Time t;
   //t.now();
   //trace("serialize t.monthday="+t.monthday);
   //trace("serialize t.month="+t.month);
   //trace("serialize t.year="+t.year);
   //ofs << t;


   // ---- serialize a PointerArray ----
   PointerArray pa=["a1","b2","c3"];
   ofs << pa;

   // ---- serialize a Color ----
   //Color clr;
   //clr.colori=#DEADBEEF;
   //ofs << clr;

   // ---- serialize a VectorArray ----
   //Vector cva,va[3];
   //cva<=va.nextFree; cva.init(1,2,3);
   //cva<=va.nextFree; cva.init(4,5,6);
   //cva<=va.nextFree; cva.init(7,8,9);
   //trace("serialize va[0]="+va[0].string);
   //trace("serialize va[1]="+va[1].string);
   //trace("serialize va[2]="+va[2].string);
   //ofs << va;

   // ---- serialize Pool ----
   Pool pool;
   int id;
   Integer tio;
   pool.template=Integer;
   pool.alloc(8);
   //i=1;
   loop(8)
      {
         id=pool.qAlloc();
         tio<=pool[id];
         tio.value=0x80+id;
         //v<=pool[id]
         //init(i, i*i, i*i*i);
         //i++;
      }
   ofs << pool;

   // ---- serialize Class -----
   CTest ctest;
   ctest.init();
   ofs << ctest;

   // ---- serialize derived Class ----
   CDDTest cdtest;
   cdtest.init();
   ofs << cdtest;

   // ---- serialize ClassArray ----
   CDDTest cdda[4];
   for(i=0; i<4; i++)
      _=cdda[i].init();
   cdda.numElements=4;
   ofs << cdda;

   // ---- serialize a ForcePoint ----
   //ForcePoint fp;
   //fp.position.init(1,2,3);
   //fp.speed.init(4,5,6);
   //fp.acceleration.init(7,8,9);
   //fp.damping.init(10,11,12);
   //ofs << fp;

   // ---- serialize some other values to validate stream position while deserializing ----
   ofs.i32=42;
   ofs << "hello, world.";

   trace("serialized "+ofs.offset+" bytes.");
}

// ---- read previously stored data and print it to the console ----
function deserialize(Pointer _stream) {
   Stream ifs;
   ifs<=_stream; // table lookup checks whether _stream was derived of Stream.
   String s;
   Buffer b;
   int i;
   int l;
   float f;
   //IVector iv;
   //Vector v;
   //Vector4 v4;
   Integer io;
   Float fo;
   //Matrix m;
   HashTable ht;
   HashTable hti;

   ifs.readString(s, 255);
   trace("s=\""+s+"\"");
   trace("ifs.offset="+ifs.offset);

   // ---- read 8 bit ----
   trace("i8="+ifs.i8);

   // ---- read 16 bit ----
   trace("i16="+ifs.i16);

   // ---- read 32bit ----
   trace("i32="+ifs.i32);

   // ---- read 32bit float ----
   trace("f32="+ifs.f32);

   // ---- deserialize Integer object ----
   io << ifs;
   trace("io.value="+io.value);

   // ---- deserialize Float Object ----
   fo << ifs;
   trace("fo.value="+fo.value);

   // ---- deserialize raw Float object ----
   ifs.getObject(fo);
   trace("fo.value="+fo.value);

   //// ---- deserialize Vector object ----
   //v << ifs;
   //trace("v="+v.string);

   //// ---- deserialize IVector object ----
   //iv << ifs;
   //trace("iv="+iv.string);

   //// ---- deserialize Vector4 object ----
   //v4 << ifs;
   //trace("v4="+v4.string);

   //// ---- deserialize Matrix object ----
   ////m << ifs;
   //ifs.deserialize(m, 1);
   //trace("m="+m.string);

   // ---- read "pascal" style string ----
   ifs.readString(s, ifs.i8);
   trace("pascal string=\""+s+"\"");

   // ---- read String Object ----
   s << ifs;
   //ifs.deserialize(s, 1);
   trace("\"1234567\"=\""+s+"\"");

   // ---- read some data "*DATA*DATA*DATA*DATA" ----
   int rlen=ifs.readString(s, 80);
   trace(rlen+" bytes read");
   trace("data=\""+s+"\"");

   // ---- deserialize HashTable ----
   ht << ifs;
   trace("ht.maxElements="+ht.maxElements);
   trace("ht.numElements="+ht.numElements);
   trace("ht[\"myint\"]="+ht["myint"]);
   trace("ht[\"myfloat\"]="+ht["myfloat"]);
   trace("ht[\"mystring\"]=\""+ht["mystring"]+"\"");

//      //v<=ht["vector"];
//      //trace "testptr v="+v;
//      //trace("ht[\"vector\"]="+v.string);

   hti<=ht["myhashtable"];
   trace("hti.maxElements="+hti.maxElements);
   trace("hti.numElements="+hti.numElements);
   trace("hti[\"myinnerint\"]="+hti["myinnerint"]);
   trace("hti[\"myinnerfloat\"]="+hti["myinnerfloat"]);
   trace("hti[\"myinnerstring\"]=\""+hti["myinnerstring"]+"\"");


   // ---- deserialize Time ----
   //Time t;
   //t << ifs;
   //trace("deserialize t.monthday="+t.monthday);
   //trace("deserialize t.month="+t.month);
   //trace("deserialize t.year="+t.year);

   // ---- deserialize PointerArray ----
   PointerArray pa;
   trace "deserialize ptr";
   _Debug();
   pa << ifs;
   trace("pa[0]=\""+pa[0]+"\"");
   trace("pa[1]=\""+pa[1]+"\"");
   trace("pa[2]=\""+pa[2]+"\"");

   // ---- deserialize Color ----
   //Color clr;
   //clr << ifs;
   //hexio.value=clr.colori;
   //trace("clr.rgbapi=#"+hexio.printf("%08x"));

   // ---- deserialize VectorArray ----
   //Vector va[];
   //va << ifs;
   //trace("deserialize va[0]="+va[0].string);
   //trace("deserialize va[1]="+va[1].string);
   //trace("deserialize va[2]="+va[2].string);

   // ---- deserialize Pool ----
   trace "io.offset="+ifs.offset;
   Pool pool;
   pool << ifs;
   int id;
   Integer tio;
   foreach id in pool
      {
         tio<=pool[id];
         //v<=pool[id];
         //trace("pool["+id+"]="+v.string);
         trace("pool["+id+"]="+tio.value);
      }
   trace "io.offset="+ifs.offset;

   // ---- deserialize Class ----
   CTest ctest;
   trace "ctest="+ctest;
   ctest << ifs;
   trace("ctest.myint="+ctest.myint);
   trace("ctest.myfloat="+ctest.myfloat);
   trace("ctest.mystring="+ctest.mystring);
   //trace("ctest.myvector="+ctest.myvector.string);

   // ---- deserialize derived Class ----
   CDDTest cdtest;
   cdtest << ifs;
   trace("cdtest.myint="+cdtest.myint);
   trace("cdtest.myfloat="+cdtest.myfloat);
   trace("cdtest.mystring="+cdtest.mystring);
   //trace("cdtest.myvector="+cdtest.myvector.string);
   trace("cdtest.myint2="+cdtest.myint2);
   trace("cdtest.myfloat2="+cdtest.myfloat2);
   trace("cdtest.mystring2="+cdtest.mystring2);
   //trace("cdtest.myvector2="+cdtest.myvector2.string);


   // ---- serialize ClassArray ----
   CDDTest cdda[];
   cdda << ifs;
   trace("cdda.numElements="+cdda.numElements);
   for(i=0; i<4; i++)
	{
      trace("cdda["+i+"].myint="+cdda[i].myint);
      //trace("cdda["+i+"].myvector2="+cdda[i].myvector.string);
	}

   // ---- deserialize ForcePoint ----
   //ForcePoint fp;
   //fp << ifs;
   //trace fp.position.string;
   //trace("fp.position="+ fp.position.string );
   //trace("fp.speed="+fp.speed.string);
   //trace("fp.acceleration="+fp.acceleration.string);
   //trace("fp.damping="+fp.damping.string);

   // ---- deserialize rest to see if stream position is OK ----
   trace("42="+ifs.i32);
   ifs.deserialize(s, 1);
   trace("\"hello, world.\"=\""+s+"\"");

   trace("deserialized "+ifs.offset+" bytes.");
}

function TestTemp() {
   trace "TestTemp()";
   File fw;
   String tmpName=fw.openTemp("",""); // default directory, no prefix
   trace "[...] temp file \""+tmpName+"\" opened.\n\n";
   fw<<tcobject(42);
   fw.close();
   File fr;
   Integer io;
   if(fr.open(tmpName, IOS_IN))
	{
      trace "fr.size="+fr.size;
      io<<fr;
      trace "fr.offset="+fr.offset;
      fr.close();
      trace "io='"+io.value+"'.";
      fw.removeTemp();
	}
   else
      die "failed to read tmp file \""+tmpName+"\"";
}

function main {
   File fs;
   Buffer b;
   // ---- serialize stuff to File ----
   fs.open("outfile2", IOS_OUT);
   serialize(fs);
   trace("wrote "+fs.offset+" bytes to \"outfile2\"");
   fs.close();

   // ---- deserialize stuff  from File ----
   fs.open("outfile2", IOS_IN);
   trace("read \"outfile2\" file size="+fs.size);
   deserialize(fs);
   fs.close();

//      // ---- read mixed binary file ----
//      fs.openLocal("outfile2", IOS_IN);
//      trace("read \"outfile2\" file size="+fs.size);
//      fs.readBuffer(b, 0 /**offset**/, l /**size**/, 1 /**autoresize**/);
//      deserialize(b);
//      fs.close();

   // ---- read/write temporary files ----
   TestTemp();
}