#include <stdio.h>
#include <string.h>
#pragma hdrstop

#include "objstrm.h"
#include "cryosim.h"


//  ipstream methods

ipstream::ipstream(const char *filename) {
  stream = fopen(filename,"rb");
}

ipstream::~ipstream() {
  close();
}

void ipstream::close() {
  if (stream) fclose(stream);
  stream=0;
}

uint16 ipstream::readWord16() {
  uint16 result;
  fread(&result, 2, 1, stream);
  return result;
}

uint32 ipstream::readWord32() {
  uint32 result;
  fread(&result, 4, 1, stream);
  return result;
}

float ipstream::readSingle() {
  float result;
  fread(&result, 4, 1, stream);
  return result;
}

double ipstream::readDouble() {
  double result;
  fread(&result, 8, 1, stream);
  return result;
}

char* ipstream::readString() {
  int i=0;
  fread(&i, 1, 1, stream);
  if (!i) return 0;
  char *result = new char[i+1];
  result[i]=0;
  fread(result, i, 1, stream);
  return result;
}

char* ipstream::readString(char* buf, unsigned maxLen) {
  int i=0;
  fread(&i, 1, 1, stream);
  if ((!i)||(i>=maxLen)) {	// read nothing
    if (i) 
      fseek(stream, i, SEEK_CUR); 
    return buf;
  }
  
  fread(buf, i, 1, stream);
  buf[i]=0;
  
  return buf;
}

TStreamableBase* ipstream::readObject() {
  int i=0;
  fread(&i, 1, 1, stream);
  if (i!='[') 
    return 0;
  
  char *name = readString();
  TStreamableBase *object;

  if (strcmp(name, "Solute")==0)
    object = new Solute();
  else if (strcmp(name, "SoluteProperties")==0)
    object = new SoluteProperties();
  else if (strcmp(name, "SoluteAmount")==0)
    object = new SoluteAmount();
  else if (strcmp(name, "Solution")==0)
    object = new Solution();
  else if (strcmp(name, "Compartment")==0)
    object = new Compartment();
  else if (strcmp(name, "JWCompartment")==0)
    object = new JWCompartment();
  else if (strcmp(name, "DCompartment")==0)
    object = new DCompartment();
  else if (strcmp(name, "DSubInterval")==0)
    object = new DSubInterval();
  else return 0;	// unknown object
  delete name;
  
  object->read(*this);
  return object;
}

TStreamableBase* ipstream::readObject(TStreamableBase &object) {
  int i=0;
  fread(&i, 1, 1, stream);
  if (i!='[') return 0;
  char *name = readString();
  if (strcmp(name, object.streamableName())!=0)
    return 0;
  
  object.read(*this);
  return &object;
}


//  opstream methods

opstream::opstream(const char *filename) {
  stream = fopen(filename,"wb");
}

opstream::~opstream() {
  close();
}

void opstream::close() {
  if (stream) 
    fclose(stream);
  stream=0;
}

void opstream::writeString(const char* string) {
  int i = (string ? strlen(string) : 0);
  if (i>0xFF) i=0xFF;
  fwrite(&i, 1, 1, stream);
  
  if (i)
    fwrite(string, i, 1, stream);
}

void opstream::writeObject(const TStreamableBase *t, int) {
  int c=(t ? '[' : 0);
  fwrite(&c, 1, 1, stream);
  if (!t) return;
  
  writeString(t->streamableName());
  t->write(*this);
}


