
Examples
========

Creation
--------

There are lots of ways of creating new bitstrings. The most flexible is via the ``auto`` parameter, which is used in this example. ::

    # Multiple parts can be joined with a single expression...
    s = BitArray('0x000001b3, uint:12=352, uint:12=288, 0x1, 0x3') 
 
    # and extended just as easily
    s += 'uint:18=48000, 0b1, uint:10=4000, 0b100'
 
    # To covert to an ordinary string use the bytes property
    open('video.m2v', 'wb').write(s.bytes)
 
    # The information can be read back with a similar syntax
    start_code, width, height = s.readlist('hex:32, uint:12, uint:12')
    aspect_ratio, frame_rate = s.readlist('2*bin:4')

Manipulation
------------

::

    s = BitArray('0x0123456789abcdef')
 
    del s[4:8]                      # deletes the '1'
    s.insert('0xcc', 12)            # inserts 'cc' between the '3' and '4'
    s.overwrite('0b01', 30)         # changes the '6' to a '5'
 
    # This replaces every '1' bit with a 5 byte Ascii string!
    s.replace('0b1', BitArray(bytes='hello'))
 
    del s[-1001:]                   # deletes final 1001 bits
    s.reverse()                     # reverses whole BitString
    s.prepend('uint:12=44')         # prepend a 12 bit integer

Parsing
-------

This example creates a class that parses a structure that is part of the H.264 video standard. ::

 class seq_parameter_set_data(object):
     def __init__(self, s):
         """Interpret next bits in BitString s as an SPS."""
         # Read and interpret bits in a single expression:
         self.profile_idc = s.read('uint:8')
         # Multiple reads in one go returns a list:
         self.constraint_flags = s.readlist('4*uint:1')
         self.reserved_zero_4bits = s.read('bin:4')
         self.level_idc = s.read('uint:8')
         self.seq_parameter_set_id = s.read('ue')
         if self.profile_idc in [100, 110, 122, 244, 44, 83, 86]:
             self.chroma_format_idc = s.read('ue')
             if self.chroma_format_idc == 3:
                 self.separate_colour_plane_flag = s.read('uint:1')
             self.bit_depth_luma_minus8 = s.read('ue')
             self.bit_depth_chroma_minus8 = s.read('ue')
             # etc.

::
 
    >>> s = BitStream('0x6410281bc0')
    >>> sps = seq_parameter_set_data(s)
    >>> print(sps.profile_idc)
    100
    >>> print(sps.level_idc)
    40
    >>> print(sps.reserved_zero_4bits)
    0b0000
    >>> print(sps.constraint_flags)
    [0, 0, 0, 1]
 
Sieve of Eratosthenes
---------------------

This classic (though inefficient) method of calculating prime numbers uses a bitstring to store whether each bit position represents a prime number. This takes much less memory than an ordinary array. ::

 
    def prime_sieve(top=1000000):
        b = BitArray(top) # bitstring of '0' bits
        for i in xrange(2, top):
            if not b[i]:
                yield i
                # i is prime, so set all its multiples to '1'.
                b.set(True, xrange(i*i, top, i))
                 




