class blockwriter_base:
    """
    Base class for other blockwriters. Each blockwriter should
    have a constructor with at least the same parameters as this
    one.
    
    Every subclass should define a _putblock(blocknumber,data) method,
    which should store data to the file or write it to the stream
    with appropriate buffering (that is, in the correct order).
    Calling programs will use the putblock method, which will make
    various checks, and call _putblock eventually.
    Requesting an invalid blocknumber (negative, or too large)
    will throw an IndexError ; trying to store a block of the wrong
    size will throw a ValueError.

    The rationale for using block numbers instead of byte offsets is
    that we can thus bypass the 4 Gb limit due to 32 bits offsets.
    """
    def __init__(self,filename,blocksize,wholeblocks,lastblocksize):
        self.filename      = filename
        self.blocksize     = blocksize     # size of all blocks, but last one
        self.wholeblocks   = wholeblocks   # number of blocks of this size
        self.lastblocksize = lastblocksize # size of last block (0 means same)
        self.blockcount    = wholeblocks   # total number of blocks
        if lastblock: self.blockcount += 1
    def checkblock(self,blocknumber,data):
        if blocknumber<0 or blocknumber>=self.blockcount:
            raise IndexError("block %d not in 0..%d"%\
                             (blocknumber,self.blockcount))
        if blocknumber<self.wholeblocks-1 and len(data)!=self.blocksize:
            raise ValueError("block %d has wrong size (%d instead of %d)"%\
                             (blocknumber,len(data),self.blocksize))
        if blocknumber==self.wholeblocks and len(data)!=self.lastblocksize:
            raise ValueError("block %d has wrong size (%d instead of %d)"%\
                             (blocknumber,len(data),self.lastblocksize))
    def putblock(self,blocknumber,data):
        self.checkblock(blocknumber,data)
        self._putblock(blocknumber,data)
    def _putblock(self,blocknumber,data): pass
        
