// ----------------------------------------------------------------------------
//
// Copyright (C) Columbia University, 1994. All Rights Reserved.
// Sameer A. Nene, Shree K. Nayar, Hiroshi Murase
//
// See file LICENSE for details of software license agreement.
//
// ----------------------------------------------------------------------------
//
// ioutil.C
//
// Author:               Sameer Nene
// Date:                 05/24/94
// Version:              1.0
// Modification History:
//   08/15/94: Fixed bug in IOUtil::get(Persistent*) & get(Handle*) which
//             incorrectly returned file-format errors file short files.
//
// Bugs:
//
// Classes:
//   IOUtil
//
// Notes:
//   This module contains implementation of classes declared in ioutil.h
//   
// ----------------------------------------------------------------------------

#include <string.h>
#include <stdio.h>
#include "errorscope.h"
#include "registry.h"
#include "persistent.h"
#include "handle.h"
#include "ioutil.h"

ErrorScope::Error IOUtil::get(Persistent *p, const char *fileName)
{
  char *buf = new char[strlen(p -> name()) + 2];
  Error error;
  
  FILE *file = fopen(fileName, "r");
  if(file == 0)
    return FILE_OPEN_ERROR;

  // +2 instead of +1 to take care of terminal '\0'
  if(fgets(buf, strlen(p -> name()) + 2, file) == 0) {
    fclose(file);
    delete[] buf;
    return INCORRECT_FORMAT;
  }
  
  if(strcmp(buf, p -> name()) != 0) {
    fclose(file);
    delete[] buf;
    return INCORRECT_FORMAT;
  }
  
  if((error = p -> get(file)) != OK) {
    fclose(file);
    delete[] buf;
    return error;
  }

  fclose(file);
  delete[] buf;
  return OK;
}

ErrorScope::Error IOUtil::get(Handle *h, const char *fileName)
{
  int i = 0, c;
  char *buf;
  Entry *e;
  Error error;
  
  FILE *file = fopen(fileName, "r");
  if(file == 0)
    return FILE_OPEN_ERROR;

  do
    if((c = fgetc(file)) == EOF) {
      fclose(file);
      return FILE_READ_ERROR;
    }
    else
      ++i;
  while(c != '\0');

  rewind(file);

  // +2 instead of +1 to take care of terminal '\0'
  buf = new char[i + 2];
  if(fgets(buf, i + 1, file) == 0) {
    fclose(file);
    delete[] buf;
    return FILE_READ_ERROR;
  }

  if((e = Registry::lookup(buf)) == 0) {
    fclose(file);
    delete[] buf;
    return INCORRECT_FORMAT;
  }

  h -> set((e -> createFunc())());
  if((error = (*h)() -> get(file)) != OK) {
    fclose(file);
    delete[] buf;
    return error;
  }

  fclose(file);
  delete[] buf;
  return OK;
}

ErrorScope::Error IOUtil::put(const Persistent &p, const char *fileName)
{
  Error error;
  
  FILE *file = fopen(fileName, "w");
  if(file == 0)
    return FILE_OPEN_ERROR;
  
  if(fputs(p.name(), file) == EOF) {
    fclose(file);
    return FILE_WRITE_ERROR;
  }

  if(fputc(0, file) == EOF) {
    fclose(file);
    return FILE_WRITE_ERROR;
  }

  if((error = p.put(file)) != OK) {
    fclose(file);
    return error;
  }

  return fclose(file) ? FILE_CLOSE_ERROR : OK;
}
