// File: io7.C
//
// reusing our GetLine function

#include <iostream.h>
#include <fstream.h>    // for ifstream, ofstream, etc
#include <iomanip.h>    // for endl, setw(), etc
#include <limits.h>     // for INT_MAX constant, etc
#include <stdlib.h>     // for NULL, EOF, etc

// Function Prototype

char *GetLine(istream&) ;


char *GetLine(istream& istrm) {

   char *str, *newstr ;
   const int INITLEN=5 ;
   int ch, i=0, j, len, newlen ;


   // First check for EOF
   //

   ch = istrm.get() ;  // peek ahead to trigger EOF settings
   if (istrm.eof()) {
      return NULL ; 
   }
   istrm.putback(ch) ; // continue as if we didn't peek


   // initialize str to default length
   len = INITLEN ;
   str = new char[len] ;
   if (str == NULL) {
      cerr << "Out of Memory Error in GetLine: 0" << endl ;
      exit(1) ;
   }

   // keep reading until done
   // loop invariants:
   //    i = index of new char.
   //    always have room for one more character.

   while(true) {
      ch = istrm.get() ;
      if (ch == EOF || ch == '\n') break ;

      if (i > len - 2) {  // get more space?

         // double the length of new space.
         //
         newlen = 2 * len ;
         newstr = new char[newlen] ;

         if (newstr == NULL) {
            cerr << "Out of Memory Error in GetLine: 1" << endl ;
            exit(1) ;
         }

         // copy old data to new location
         //
         for (j = 0 ; j < i ; j++) {
            newstr[j] = str[j] ;
         }

         delete [] str ;
         str = newstr ;
         len = newlen ;
      }

      str[i] = ch ;
      i++ ;
   }

   str[i] = '\0' ;

   // Don't worry about exact fit for short strings or
   // strings that are almost full
   //
   if (len == INITLEN || i >= 0.75 * len) {
       return str ;
   }

   // Get block of memory that is an exact fit.
   //
   newlen = i+1 ;
   newstr = new char[newlen] ;
   if (newstr == NULL) {
      cerr << "Out of Memory Error in GetLine: 2" << endl ;
      exit(1) ;
   }

   // Copy data to new location
   //
   for (j = 0 ; j < newlen ; j++) {
      newstr[j] = str[j] ;
   }
   delete [] str ;

   return newstr ;
}


main() {
   ifstream ifile ;
   char *fname ;
   char *p ;

   cout << "Enter a filename: " ;
   fname = GetLine(cin) ;

   ifile.open(fname) ;
   if (ifile == NULL) {
      cerr << "Could not open file: " << fname << endl ;
      exit(1) ;
   }

   // Print out contents of the file
   //
   while (p = GetLine(ifile)) {  // ends with p == NULL
      cout << p << endl ; 
      delete [] p ;
   }

   ifile.close() ;
}
