"""Convert module does file I/O with binary files.

author:  jonathan lung
"""

import array
import os
import stat

BYTE_SIZE_IN_BITS = 8		# Assume 8 bits in a byte.

def write_string_as_binary(stringIn, fileOutName):
    """Writes a string of "0"s and "1"s as a binary file.
    Assumes input string is a multiple of BYTE_SIZE_IN_BITS characters.
    """
    arrayOut = array.array('B')	# Create an array of uint bytes
    fileOut = open(fileOutName, "wb")
    strLength = len(stringIn) / BYTE_SIZE_IN_BITS  # Cache string length
    
    for byteNumber in xrange(0, strLength):
        byteData = stringIn[byteNumber * BYTE_SIZE_IN_BITS:
                            (byteNumber + 1) * BYTE_SIZE_IN_BITS]
        byteVal = 0     # The current byte's value
        
        # Convert block of chars to an int
        for byte in byteData:
            byteVal = (byteVal << 1) + (byte == "1")
        
        # Append the byte to the array
        arrayOut.append(byteVal)
    
    arrayOut.tofile(fileOut)
    fileOut.close()

def read_binary_file(fileInName):
    """Returns a Python string of "0"s and "1"s from a file."""
    
    arrayIn = array.array('B')	# Create an array of uint bytes
    
    fileIn = open(fileInName, "rb")
    fileInLength = os.stat(fileInName)[stat.ST_SIZE]

    fileData = arrayIn.fromfile(fileIn, fileInLength)
    fileIn.close()
    
    strArray = []    # Cache "0"s and "1"s
    
    bitMask = 2 << (BYTE_SIZE_IN_BITS - 2)
    
    for byte in arrayIn:
        for bit in xrange(0, BYTE_SIZE_IN_BITS):
            if bitMask & byte:
                strArray.append("1")
            else:
                strArray.append("0")
            byte <<= 1
    return "".join(strArray)