Tryag File Manager
Home
-
Turbo Force
Current Path :
/
usr
/
lib
/
python2.4
/
site-packages
/
rhsm
/
Upload File :
New :
File
Dir
//usr/lib/python2.4/site-packages/rhsm/bitstream.py
# Copyright (c) 2012 Red Hat, Inc. # # This software is licensed to you under the GNU General Public License, # version 2 (GPLv2). There is NO WARRANTY for this software, express or # implied, including the implied warranties of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 # along with this software; if not, see # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. # # Red Hat trademarks are not licensed under GPLv2. No permission is # granted to use or replicate Red Hat trademarks that are incorporated # in this software or its documentation. from collections import deque class GhettoBitStream(object): """ Accepts binary data and makes it available as a stream of bits or one byte at a time. Python does not provide a built-in way to read a stream of bits, or a way to represent a single bit. Thus, this class uses character '0' or '1' to represent the status of each bit. Data is converted into the '0' and '1' characters one byte at a time, since that operation multiplies the size of the data by a factor of 8, and it may not be desirable to inflate all of the data at once. """ def __init__(self, data): """ :param data: binary data in a string :type data: str """ self.bytes = deque(ord(x) for x in data) self._bit_buffer = deque() def __iter__(self): return self def next(self): """ converts one byte at a time into a bit representation, waiting until those bits have been consumed before converting another byte :return: next bit in the stream, either '0' or '1' :rtype: string """ if not self._bit_buffer: try: byte = self.pop_byte() except IndexError: raise StopIteration bits = self._byte_to_bits(byte) self._bit_buffer.extend(bits) return self._bit_buffer.popleft() def pop_byte(self): """ :return: next entire byte in the stream, as an int :rtype: int """ return self.bytes.popleft() @classmethod def _byte_to_bits(cls, byte): """ Produces a string representation of a byte as a base-2 number. Python versions < 2.6 lack the "bin()" builtin as well as the below "format()" method of strings, so this method falls back to using a home-brew implementation. :param byte: positive int < 256 :type byte: int :return: binary representation of byte as 8-char string :rtype: str """ try: return '{0:08b}'.format(byte) except AttributeError: # python < 2.6, so we must do this ourselves return cls._bin_backport(byte) @staticmethod def _bin_backport(x): """ In python versions < 2.6, there is no built-in way to produce a string representation of base-2 data. Thus, we have to do it manually. :param byte: positive int < 256 :type byte: int :return: binary representation of byte as 8-char string :rtype: str """ chars = [] for n in range(7, -1, -1): y = x - 2 ** n if y >= 0: chars.append('1') x = y else: chars.append('0') return ''.join(chars) @staticmethod def combine_bytes(data): """ combine unsigned ints read from a bit stream into one unsigned number, reading data as big-endian :param data: iterable of positive ints, each representing a byte of uint binary data that should be combined such that the right-most byte stays as-is, and then each byte to the left gets left-shifted by 8 * n bits. For example, [1, 2] would give you 258 ((1 << 8) + 2) :type data: iterable of positive ints :return: positive int, composed from input bytes combined as one int :rtype: int """ copy = data[:] copy.reverse() return sum(x << n * 8 for n, x in enumerate(copy))