"""File Input/Output

   fio.py (c) 1999 Arne Mueller
   
   NAME   : fio.py
   TYPE   : module 
   PYTHON : 1.5.2b2
   VERSION: 1.1
   AUTHOR : Arne Mueller
   DATE   : 22.04.99

   DESCRIPTION:
   This module provides one class 'FIO', a buffered file
   object. The class does not yet implement the common
   file object operations (like read, readline, ...). The
   concept is to read lines into a list (buffer). This allows
   an 'ungeline' function.

   EXAMPLE:
   f = IO('myfile', 'r', 1024) # 1024 bytes buffered file object
   print f.getLine()

   NOTE:
   It's planed to implement full support of regular text file
   based objects (read, readline, ftell etc ...).

   Actually there's no advanced error catching or handleing, meaning
   trying to write to a read only object raises a standard exeption
   of file objects.

   TODO:
   o lots!
   o The concept of an 'unread' / 'ungetline' could be realized
     using ftell() and seek() functions of common file objects
     (this seems to be more flexible for normal files but probably
     does not work for pipes!).

   CHANGES:
   
   DATE 18/11/99
   o FIO doesn't read n lines anymore, instead it reads at most n
     bytes regardless how many lines that is (it's always at least
     1). That makes reading a bit faster since the FIO object uses
     one 'readlines' instead of 'readline' in a loop

   VERSION 1.1
   -----------
   DATE 17/02/2000
   o FIO get either a filename or a file handle as argument. That
     means FIO can read from pipe etc ...

   DATE 14/04/2000
   o Added method 'test()' that returns 0 if the file is at EOF
     otherwise 1
"""
import sys
from types import *

class FIO:

    """Input/Output

       TYPE       : class
       CONSTRUCTOR: 1. filename (default is sys.stdin)
                    2. opening modus (default 'r')
                    3. input buffer size in bytes (default 8000)
       DESCRIPTION: 
       An IO object is a normal fileobject for text files.
       Rreading operations provided by this class are buffered
       with 'self.n' lines.

       ONLY the following methods are provided at the moment:
       getLine(), get next line of buffer
       ungetLine(str), put string str back to buffer

       EXAMPLE:
       f = FIO('filename', 'r')

       See function docstrings for details.
    """
    def __init__(self, file=sys.stdin, mode='r', n=8000 ):
        self.buffer = []
        self.n = n
        if type(file) is StringType:
            self.name = file
            self.f = self.open(file, mode)
        elif type(file) is FileType:
            self.name = file.name
            self.f = file
        else:
            raise "unknown input %s" % file;
    
    def open(self, name='stdin',mode='r'):
        "Used in __init__, don't use it explicitly!"
        self.f = open(name,mode)
        return self.f

    def close(self):
        "Closes the open file object." 
        self.f.close()

    def ioErr(self, msg=''):
        "Prints it's argument 'msg' and exits the program."
        sys.stderr.write('IO Error in file %s %s\n' % (self.name, msg))
        sys.exit(1)

    def readline(self):
        return self.f.readline()

    def getLine(self):
        "Returns the next line from the object's file object."
        l = None
        if not self.buffer:
            self.buffer = self.f.readlines(self.n)
            self.buffer.reverse()
        if self.buffer:
            end = len(self.buffer) - 1
            l = self.buffer[end]
            del self.buffer[end]
        return l

    def test(self):
        "returns 1 if fio is not on EOF otherwise 0"
        l = self.getLine()
        if l != None:
            self.ungetLine(l)
            return 1
        else:
            return 0

    def ungetLine(self, line):
        "Puts back it's argument into the object's file stream."
        if line: self.buffer.append(line)
        
    def listBuffer(self):
        "Prints the objects current input buffer (for debuging)."
        for i in self.buffer:
            print 'BUFFER: ', i,

#################################################################################
