import _hydra
import mmap
import struct
from os.path import exists
from os import unlink

def ReadingBloomFilter(filename):
    """
    Create a read-only bloom filter with an upperbound of
    (num_elements, max_fp_prob) as a specification and using filename
    as the backing datastore.
    """
    descriptor = open('%s.desc' % filename, 'r')
    num_elements = int(descriptor.readline())
    max_fp_prob = float(descriptor.readline())
    ignore_case = int(descriptor.readline())

    return _hydra.BloomFilter.getFilter(num_elements, max_fp_prob,
            filename=filename, ignore_case=ignore_case,
            read_only=True)

def UpdatingBloomFilter(filename):
    """
    Load an existing bloom filter in read-write mode using filename
    as the backing datastore.
    """
    descriptor = open('%s.desc' % filename, 'r')
    num_elements = int(descriptor.readline())
    max_fp_prob = float(descriptor.readline())
    ignore_case = int(descriptor.readline())

    return _hydra.BloomFilter.getFilter(num_elements, max_fp_prob,
            filename=filename, ignore_case=ignore_case,
            read_only=False)

def WritingBloomFilter(num_elements, max_fp_prob, filename=None, ignore_case=False):
    """
    Create a read/write bloom filter with an upperbound of
    (num_elements, max_fp_prob) as a specification and using filename
    as the backing datastore.
    """
    descriptor = open('%s.desc' % filename, 'w')
    descriptor.write("%d\n" % num_elements)
    descriptor.write("%0.8f\n" % max_fp_prob)
    descriptor.write("%s\n" % int(ignore_case))
    return _hydra.BloomFilter.getFilter(num_elements, max_fp_prob,
            filename=filename, ignore_case=ignore_case,
            read_only=False)

# Expose the murmur hash
murmur_hash=_hydra.hash

class Bitmap(object):
    """
    This was a pure python mmap-io class that was being used to
    persist data before the whole thing was moved into Cython.  Here
    for mainly historical reasons.
    """
    def __init__(self, filename, bitsize, start_fresh=True):
        self._filename = filename
        if start_fresh:
            if exists(filename):
                unlink(filename)
        self._file = file(filename, 'wb+')

        self._bitsize = bitsize

        # Pad out the last couple bits to a full byte
        self._size = self._bitsize / 8 + 1
        self._file.seek(self._size)
        self._file.write(struct.pack('B', 0))
        self._file.seek(0)
        self._mfile = mmap.mmap(self._file.fileno(), self._size)

    def __len__(self):
        return self._bitsize

    def __setitem__(self, k, v):
        if k >= self._bitsize:
            raise RuntimeError, "OutOfBounds! Max bit is : %d, requested: %d" % (self._bitsize, k)
        byte_offset = k / 8
        old_bitmask = struct.unpack('B', self._mfile[byte_offset])[0]
        if v:
            new_bitmask = old_bitmask | 2**(k % 8)
        else:
            new_bitmask = old_bitmask ^ 2**(k % 8)
        self._mfile[byte_offset] = struct.pack('B', new_bitmask)

    def __getitem__(self, k):
        byte_offset = k / 8
        old_bitmask = struct.unpack('B', self._mfile[byte_offset])[0]
        return bool(old_bitmask & 2**(k % 8))


@@ -1373,32 +1373,53 @@
 astore.%0A    %22%22%22%0A
+    if filename:%0A    
     descriptor =
@@ -1451,16 +1451,20 @@
 e, 'w')%0A
+    
     desc
@@ -1499,16 +1499,20 @@
 ements)%0A
+    
     desc
@@ -1549,16 +1549,20 @@
 p_prob)%0A
+    
     desc

Don't write None.desc file if filename is None