// ------------------------------- //
// -------- Start of File -------- //
// ------------------------------- //
// ----------------------------------------------------------- // 
// C++ Source Code File Name: testprog.cpp 
// Compiler Used: MSVC40, DJGPP 2.7.2.1, GCC 2.7.2.1, HP CPP 10.24
// Produced By: Doug Gaer 
// File Creation Date: 02/04/1997  
// Date Last Modified: 10/15/1998
// Copyright (c) 1997 Douglas M. Gaer
// ----------------------------------------------------------- // 
// ------------- Program Description and Details ------------- // 
// ----------------------------------------------------------- // 
/*
This is a test program for the VBDFile class used to read and
write low level c strings to a file.

The VBD C++ classes are copyright (c) 1997, by Douglas M. Gaer.
All those who put this code or its derivatives in a commercial
product MUST mention this copyright in their documentation for
users of the products in which this code or its derivative
classes are used. Otherwise, you have the freedom to redistribute
verbatim copies of this source code, adapt it to your specific
needs, or improve the code and release your improvements to the
public provided that the modified files carry prominent notices
stating that you changed the files and the date of any change.

THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND.
THE ENTIRE RISK OF THE QUALITY AND PERFORMANCE OF THIS SOFTWARE
IS WITH YOU. SHOULD ANY ELEMENT OF THIS SOFTWARE PROVE DEFECTIVE,
YOU WILL ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR
CORRECTION.
*/
// ----------------------------------------------------------- // 
#include <iostream.h>
#include <iomanip.h>
#include "vbdfile.hpp"
#include "vbdstats.hpp"
#include <string.h>

void pause()
{
  cout << endl;
  cout << "Press enter to continue..." << endl;
  cin.get();
}

int main()
{
  VBDFilePtr f(new VBDFile);   // Should always create dynamically
  const char *FName = "cstrtst.vbd";

  if(!VBDFile::Exists(FName)) {
    cout << "Creating new file..." << endl;
    f->Create(FName);
  }
  else {
    cout << "Opening existing file..." << endl;
    f->Open(FName);
  }
  
  pause();
  VBDStats(f);
  pause();
  
  char *str = "The quick brown fox jumps over the lazy dog 0123456789";
  cout << "Adding string object to VBD file..." << endl;
  cout << "String length = " << strlen(str) << endl;

  // Allocate room for the string
  FAU addr = f->Alloc(strlen(str));
  if(addr)
    f->Write(str, strlen(str));
  else
    cout << "Could not allocate space for string" << endl;

  VBStats(f, addr);
  pause();
  
  cout << "Closing and re-opening file..." << endl; 
  f->Open(FName); // Open() closes first

  pause();
  VBDStats(f);
  pause();
  
  cout << "Reading back the string object from the VBD file..." << endl;
  char *buf;
  unsigned len = f->ObjectLength(addr);
  char *s = new char[len];
  
  f->Read(s, len, addr);
  s[len] = '\0';
  buf = s;
  cout << "String = " << buf << endl;

  pause();
  cout << "Deleting string object..." << endl;
  if(!f->Delete(addr)) cout << "Object was not deleted" << endl;
 
  cout << "Undeleting string object..." << endl;
  if(!f->UnDelete(addr)) cout << "Could not undelete" << endl;

  cout << "Removing the string object..." << endl;
  if(!f->Remove(addr)) cout << "Object was not deleted" << endl;

  cout << "Trying undelete after a remove..." << endl;
  if(!f->UnDelete(addr)) cout << "Could not undelete" << endl;

  pause();

  char *alp = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  char *num = "012345678901";

  cout << "Testing reclaim function after a remove..." << endl;
  cout << "Adding two new string objects to the VBD file" << endl;
  cout << "that will occupy the same space as the removed string" << endl;
  addr = f->Alloc(strlen(alp));
  f->Write(alp, strlen(alp));
  addr = f->Alloc(strlen(num));
  f->Write(num, strlen(num));

  pause();
  VBDStats(f);
  pause();
  
  cout << "Testing ReAlloc function..." << endl;
  cout << "Adding another string object to VBD file..." << endl;
  cout << "String length = " << strlen(str) << endl;

  addr = f->Alloc(strlen(str));
  f->Write(str, strlen(str));
  
  cout << "Reallocating space for string object..." << endl;
  len = strlen(str) + strlen(alp);
  char *comp = new char[len];
  comp[len] = '\0';
  strcpy(comp, str);
  strcat(comp, alp);

  cout << "String length = " << strlen(comp) << endl;
  addr = f->ReAlloc(addr, strlen(comp));
  if(addr)
    f->Write(comp, strlen(comp));
  else
    cout << "Could not reallocate space for string" << endl;

  pause();
  VBDStats(f);
  pause();
  
  cout << "Closing file and re-creating it..." << endl;
  f->Close();
  f->Create(FName);
  
  cout << "Adding 9 three byte string objects to the new VBD file..." << endl;
  
  char *aa = "DOG";
  char *bb = "CAT";
  char *cc = "COW";
  char *dd = "BAT";
  char *ee = "ANT";
  char *ff = "BUG";
  char *gg = "HOG";
  char *hh = "PIG";
  char *ii = "HEN";

  addr = f->Alloc(strlen(aa));
  f->Write(aa, strlen(aa));
  addr = f->Alloc(strlen(bb));
  f->Write(bb, strlen(bb));
  addr = f->Alloc(strlen(cc));
  f->Write(cc, strlen(cc));
  addr = f->Alloc(strlen(dd));
  f->Write(dd, strlen(dd));
  addr = f->Alloc(strlen(ee));
  f->Write(ee, strlen(ee));
  addr = f->Alloc(strlen(ff));
  f->Write(ff, strlen(ff));
  addr = f->Alloc(strlen(gg));
  f->Write(gg, strlen(gg));
  addr = f->Alloc(strlen(hh));
  f->Write(hh, strlen(hh));
  addr = f->Alloc(strlen(ii));
  f->Write(ii, strlen(ii));

  pause();
  VBDStats(f);
  pause();
  
  cout << "Testing Variable Block find functions..." << endl;

  FAU vb = f->FindFirstVB();
  FAU obj = f->FindFirstObject();
  if(vb) cout << "First VB address =       " << vb << endl;
  if(obj) cout << "First Object's address = " << obj << endl;
  VBStats(f, obj); // VBStats starts at object address

  pause();

  vb = f->FindNextVB(vb);
  obj = f->FindNextObject(vb);
  if(vb) cout << "Next VB address =        " << vb << endl;
  if(obj) cout << "Next Object's address =  " << obj << endl;
  VBStats(f, obj); // VBStats() starts at object address

  cout << endl;
  cout << "Closing file automatically using VBDFile destructor..." << endl;
  return 0; 
}
// ----------------------------------------------------------- //
// ------------------------------- //
// --------- End of File --------- //
// ------------------------------- //
