/****************************************************************************/
/* Copyright (c) 2000 MBARI                                                 */
/* MBARI Proprietary Information. All rights reserved.                      */
/****************************************************************************/
/* Summary  :                                                               */
/* Filename : BinaryFile.cc                                                 */
/* Author   :                                                               */
/* Project  :                                                               */
/* Version  : 1.0                                                           */
/* Created  : 02/07/2000                                                    */
/* Modified :                                                               */
/* Archived :                                                               */
/****************************************************************************/
/* Modification History:                                                    */
/****************************************************************************/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "BinaryFile.h"
#include "Exception.h"
#include "ourTypes.h"
#include "Syslog.h"
#include "CharData.h"
#include "ShortData.h"
#include "IntegerData.h"
#include "FloatData.h"
#include "DoubleData.h"
#include "StringData.h"
#include "Syslog.h"

BinaryFile::BinaryFile(FILE *file)
  : FileData(file)
{
}


BinaryFile::~BinaryFile()
{
}


void BinaryFile::set(CharData *charData)
{
  char errorBuf[250];

  char value = charData->value();

  if (fwrite((void *)&value, sizeof(char), 1, _file) < 1) {
    sprintf(errorBuf, "BinaryFile::set(CharData) - %s", strerror(errno));
    throw Exception(errorBuf);
  }
}


void BinaryFile::set(ShortData *shortData)
{
  char errorBuf[250];

  short value = shortData->value();

  if (fwrite((void *)&value, sizeof(short), 1, _file) < 1) {
    sprintf(errorBuf, "BinaryFile::set(ShortData) - %s", strerror(errno));
    throw Exception(errorBuf);
  }
}


void BinaryFile::set(IntegerData *integerData)
{
  char errorBuf[250];

  int value = integerData->value();

  if (fwrite((void *)&value, sizeof(int), 1, _file) < 1) {
    sprintf(errorBuf, "BinaryFile::set(IntegerData) - %s", strerror(errno));
    throw Exception(errorBuf);
  }
}


void BinaryFile::set(FloatData *floatData)
{
  char errorBuf[250];

  float value = floatData->value();

  if (fwrite((void *)&value, sizeof(float), 1, _file) < 1) {
    sprintf(errorBuf, "BinaryFile::set(FloatData) - %s", strerror(errno));
    throw Exception(errorBuf);
  }
}


void BinaryFile::set(DoubleData *doubleData)
{
  char errorBuf[250];

  double value = doubleData->value();

  if (fwrite((void *)&value, sizeof(double), 1, _file) < 1) {
    sprintf(errorBuf, "BinaryFile::set(DoubleData) - %s", strerror(errno));
    throw Exception(errorBuf);
  }
}


void BinaryFile::set(StringData *stringData)
{
  char errorBuf[250];

  char *value = stringData->value();
  char nullChar = '\0';

  // Write string characaters and terminating null
  if (fwrite((void *)value, strlen(value), 1, _file) < 1 ||
      fwrite((void *)&nullChar, sizeof(nullChar), 1, _file) < 1) {
    sprintf(errorBuf, "BinaryFile::set(StringData) - %s", strerror(errno));
    throw Exception(errorBuf);
  }
}


void BinaryFile::get(CharData *charData)
{
  char errorBuf[250];
  char value;

  if (fread((void *)&value, sizeof(char), 1, _file) < 1) {
    if (feof(_file)) {
      throw Exception("eof");
    }
    else {
      sprintf(errorBuf, "BinaryFile::get(CharData) - %s", strerror(errno));
      throw Exception(errorBuf);
    }
  }
  else 
    charData->setValue(value);
}



void BinaryFile::get(ShortData *shortData)
{
  char errorBuf[250];
  short value;

  if (fread((void *)&value, sizeof(short), 1, _file) < 1) {
    if (feof(_file)) {
      throw Exception("eof");
    }
    else {
      sprintf(errorBuf, "BinaryFile::get(ShortData) - %s", strerror(errno));
      throw Exception(errorBuf);
    }
  }
  else 
    shortData->setValue(value);
}


void BinaryFile::get(IntegerData *integerData)
{
  char errorBuf[250];
  int value;

  if (fread((void *)&value, sizeof(int), 1, _file) < 1) {
    if (feof(_file)) {
      throw Exception("eof");
    }
    else {
      sprintf(errorBuf, "BinaryFile::get(IntegerData) - %s", strerror(errno));
      throw Exception(errorBuf);
    }
  }
  else 
    integerData->setValue(value);
}


void BinaryFile::get(FloatData *floatData)
{
  char errorBuf[250];
  float value;

  if (fread((void *)&value, sizeof(float), 1, _file) < 1) {
    if (feof(_file)) {
      throw Exception("eof");
    }
    else {
      sprintf(errorBuf, "BinaryFile::get(FloatData) - %s", strerror(errno));
      throw Exception(errorBuf);
    }
  }
  else
    floatData->setValue(value);
}



void BinaryFile::get(DoubleData *doubleData)
{
  char errorBuf[250];
  double value;

  if (fread((void *)&value, sizeof(double), 1, _file) < 1) {
    if (feof(_file)) {
      throw Exception("eof");
    }
    else {
      sprintf(errorBuf, "BinaryFile::get(DoubleData) - %s", strerror(errno));
      throw Exception(errorBuf);
    }
  }
  else
    doubleData->setValue(value);
}


void BinaryFile::get(StringData *stringData)
{
  char errorBuf[250];

  // Right now we have a hard-wired upper bound to the length of 
  // the string!!!
  char string[100];
  int nCopiedBytes = 0;
  Boolean stringFinished = False;

  while (nCopiedBytes < sizeof(string) - 1) {

    int c;
    if ((c = getc(_file)) == -1) {
      // File ended before string retrieved
      sprintf(errorBuf, "BinaryFile::get(StringData) - EOF");
      throw Exception(errorBuf);
    }

    string[nCopiedBytes++] = c;

    if (c == '\0') {
      stringFinished = True;
      break;
    }
  }

  if (!stringFinished) {
    // File data too big to fit in string
    sprintf(errorBuf, "BinaryFile::get(StringData) - too many bytes");
    throw Exception(errorBuf);
  }

  stringData->setValue(string);
}


void BinaryFile::endRecord()
{
  // Does nothing
  return;
}

