| # | 
| # The Python Imaging Library. | 
| # $Id$ | 
| # | 
| # a class to read from a container file | 
| # | 
| # History: | 
| # 1995-06-18 fl     Created | 
| # 1995-09-07 fl     Added readline(), readlines() | 
| # | 
| # Copyright (c) 1997-2001 by Secret Labs AB | 
| # Copyright (c) 1995 by Fredrik Lundh | 
| # | 
| # See the README file for information on usage and redistribution. | 
| # | 
|   | 
| ## | 
| # A file object that provides read access to a part of an existing | 
| # file (for example a TAR file). | 
|   | 
| class ContainerIO: | 
|   | 
|     ## | 
|     # Create file object. | 
|     # | 
|     # @param file Existing file. | 
|     # @param offset Start of region, in bytes. | 
|     # @param length Size of region, in bytes. | 
|   | 
|     def __init__(self, file, offset, length): | 
|         self.fh = file | 
|         self.pos = 0 | 
|         self.offset = offset | 
|         self.length = length | 
|         self.fh.seek(offset) | 
|   | 
|     ## | 
|     # Always false. | 
|   | 
|     def isatty(self): | 
|         return 0 | 
|   | 
|     ## | 
|     # Move file pointer. | 
|     # | 
|     # @param offset Offset in bytes. | 
|     # @param mode Starting position. Use 0 for beginning of region, 1 | 
|     #    for current offset, and 2 for end of region.  You cannot move | 
|     #    the pointer outside the defined region. | 
|   | 
|     def seek(self, offset, mode = 0): | 
|         if mode == 1: | 
|             self.pos = self.pos + offset | 
|         elif mode == 2: | 
|             self.pos = self.length + offset | 
|         else: | 
|             self.pos = offset | 
|         # clamp | 
|         self.pos = max(0, min(self.pos, self.length)) | 
|         self.fh.seek(self.offset + self.pos) | 
|   | 
|     ## | 
|     # Get current file pointer. | 
|     # | 
|     # @return Offset from start of region, in bytes. | 
|   | 
|     def tell(self): | 
|         return self.pos | 
|   | 
|     ## | 
|     # Read data. | 
|     # | 
|     # @def read(bytes=0) | 
|     # @param bytes Number of bytes to read.  If omitted or zero, | 
|     #     read until end of region. | 
|     # @return An 8-bit string. | 
|   | 
|     def read(self, n = 0): | 
|         if n: | 
|             n = min(n, self.length - self.pos) | 
|         else: | 
|             n = self.length - self.pos | 
|         if not n: # EOF | 
|             return "" | 
|         self.pos = self.pos + n | 
|         return self.fh.read(n) | 
|   | 
|     ## | 
|     # Read a line of text. | 
|     # | 
|     # @return An 8-bit string. | 
|   | 
|     def readline(self): | 
|         s = "" | 
|         while 1: | 
|             c = self.read(1) | 
|             if not c: | 
|                 break | 
|             s = s + c | 
|             if c == "\n": | 
|                 break | 
|         return s | 
|   | 
|     ## | 
|     # Read multiple lines of text. | 
|     # | 
|     # @return A list of 8-bit strings. | 
|   | 
|     def readlines(self): | 
|         l = [] | 
|         while 1: | 
|             s = self.readline() | 
|             if not s: | 
|                 break | 
|             l.append(s) | 
|         return l |