nzbToMedia/libs/jaraco/structures/binary.py
Labrys 6bb4ae56bd Update jaraco.windows to v3.6:
Dependencies:
* backports.functools-lru-cache	1.2.1
* jaraco.classes	1.3
* jaraco.collections	1.3.2
* jaraco.functools	1.11
* jaraco.structures	1.0
* jaraco.text	1.7
* jaraco.ui	1.4
* jaraco.windows	3.6
* more-itertools	2.2
* path.py	8.2.1
* six	1.10.0
2016-06-06 13:02:07 -04:00

130 lines
2.8 KiB
Python

from __future__ import absolute_import, unicode_literals
from functools import reduce
def get_bit_values(number, size=32):
"""
Get bit values as a list for a given number
>>> get_bit_values(1) == [0]*31 + [1]
True
>>> get_bit_values(0xDEADBEEF)
[1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1]
You may override the default word size of 32-bits to match your actual
application.
>>> get_bit_values(0x3, 2)
[1, 1]
>>> get_bit_values(0x3, 4)
[0, 0, 1, 1]
"""
number += 2**size
return list(map(int, bin(number)[-size:]))
def gen_bit_values(number):
"""
Return a zero or one for each bit of a numeric value up to the most
significant 1 bit, beginning with the least significant bit.
>>> list(gen_bit_values(16))
[0, 0, 0, 0, 1]
"""
digits = bin(number)[2:]
return map(int, reversed(digits))
def coalesce(bits):
"""
Take a sequence of bits, most significant first, and
coalesce them into a number.
>>> coalesce([1,0,1])
5
"""
operation = lambda a, b: (a << 1 | b)
return reduce(operation, bits)
class Flags(object):
"""
Subclasses should define _names, a list of flag names beginning
with the least-significant bit.
>>> class MyFlags(Flags):
... _names = 'a', 'b', 'c'
>>> mf = MyFlags.from_number(5)
>>> mf['a']
1
>>> mf['b']
0
>>> mf['c'] == mf[2]
True
>>> mf['b'] = 1
>>> mf['a'] = 0
>>> mf.number
6
"""
def __init__(self, values):
self._values = list(values)
if hasattr(self, '_names'):
n_missing_bits = len(self._names) - len(self._values)
self._values.extend([0] * n_missing_bits)
@classmethod
def from_number(cls, number):
return cls(gen_bit_values(number))
@property
def number(self):
return coalesce(reversed(self._values))
def __setitem__(self, key, value):
# first try by index, then by name
try:
self._values[key] = value
except TypeError:
index = self._names.index(key)
self._values[index] = value
def __getitem__(self, key):
# first try by index, then by name
try:
return self._values[key]
except TypeError:
index = self._names.index(key)
return self._values[index]
class BitMask(type):
"""
A metaclass to create a bitmask with attributes. Subclass an int and
set this as the metaclass to use.
Here's how to create such a class on Python 3:
class MyBits(int, metaclass=BitMask):
a = 0x1
b = 0x4
c = 0x3
For testing purposes, construct explicitly to support Python 2
>>> ns = dict(a=0x1, b=0x4, c=0x3)
>>> MyBits = BitMask(str('MyBits'), (int,), ns)
>>> b1 = MyBits(3)
>>> b1.a, b1.b, b1.c
(True, False, True)
>>> b2 = MyBits(8)
>>> any([b2.a, b2.b, b2.c])
False
"""
def __new__(cls, name, bases, attrs):
newattrs = dict(
(attr, property(lambda self, value=value: bool(self & value)))
for attr, value in attrs.items()
if not attr.startswith('_')
)
return type.__new__(cls, name, bases, newattrs)