Skip to content

Commit

Permalink
New format specifier t for text (utf-8).
Browse files Browse the repository at this point in the history
  • Loading branch information
eerimoq committed Aug 28, 2016
1 parent 87e2609 commit cac34fd
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 11 deletions.
14 changes: 7 additions & 7 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,17 @@ wrapping the result in a named tuple:
3
An example of packing/unpacking a unsinged integer, a signed integer,
a float, a boolean and a byte string:
a float, a boolean, a byte string and a string:

.. code-block:: python
>>> from bitstruct import *
>>> pack('u5s5f32b1r13', 1, -1, 3.75, True, b'\xff\xff')
b'\x0f\xd0\x1c\x00\x00?\xff'
>>> unpack('u5s5f32b1r13', b'\x0f\xd0\x1c\x00\x00?\xff')
(1, -1, 3.75, True, b'\xff\xf8')
>>> calcsize('u5s5f32b1r13')
56
>>> pack('u5s5f32b1r13t40', 1, -1, 3.75, True, b'\xff\xff', u'hello')
b'\x0f\xd0\x1c\x00\x00?\xffhello'
>>> unpack('u5s5f32b1r13t40', b'\x0f\xd0\x1c\x00\x00?\xffhello')
(1, -1, 3.75, True, b'\xff\xf8', u'hello')
>>> calcsize('u5s5f32b1r13t24')
80
The same format and values as in the previous example, but using LSB
(Least Significant Bit) first instead of the default MSB (Most
Expand Down
17 changes: 15 additions & 2 deletions bitstruct.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import re
import struct

__version__ = "3.1.0"
__version__ = "3.2.0"


def _parse_format(fmt):
Expand Down Expand Up @@ -48,6 +48,10 @@ def _pack_bytearray(size, arg):
return bits[0:size]


def _pack_text(size, arg):
return _pack_bytearray(size, bytearray(arg.encode('utf-8')))


def _unpack_integer(_type, bits):
value = int(bits, 2)

Expand Down Expand Up @@ -87,6 +91,10 @@ def _unpack_bytearray(size, bits):
return value


def _unpack_text(size, bits):
return _unpack_bytearray(size, bits).decode('utf-8')


def pack(fmt, *args):
"""Return a byte string containing the values v1, v2, ... packed
according to the given format. If the total number of bits are not
Expand All @@ -105,12 +113,13 @@ def pack(fmt, *args):
bitorder is used for the current value. For example, in the format
string "u1<u2u3" u1 is MSB first and both u2 and u3 are LSB first.
There are six types; 'u', 's', 'f', 'b', 'r' and 'p'.
There are seven types; 'u', 's', 'f', 'b', 't', 'r' and 'p'.
- 'u' -- unsigned integer
- 's' -- signed integer
- 'f' -- floating point number of 32 or 64 bits
- 'b' -- boolean
- 't' -- text (ascii or utf-8)
- 'r' -- raw, bytes
- 'p' -- padding, ignore
Expand All @@ -134,6 +143,8 @@ def pack(fmt, *args):
value_bits = _pack_float(size, args[i])
elif _type == 'b':
value_bits = _pack_boolean(size, args[i])
elif _type == 't':
value_bits = _pack_text(size, args[i])
elif _type == 'r':
value_bits = _pack_bytearray(size, bytearray(args[i]))
else:
Expand Down Expand Up @@ -187,6 +198,8 @@ def unpack(fmt, data):
value = _unpack_float(size, value_bits)
elif _type == 'b':
value = _unpack_boolean(value_bits)
elif _type == 't':
value = _unpack_text(size, value_bits)
elif _type == 'r':
value = bytes(_unpack_bytearray(size, value_bits))
else:
Expand Down
14 changes: 12 additions & 2 deletions tests/test_bitstruct.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ def test_pack(self):
packed = pack('u5b2u1', -1, False, 1)
self.assertEqual(packed, b'\xf9')

packed = pack('b1t24', False, u"Hi!")
self.assertEqual(packed, b'$4\x90\x80')

packed = pack('b1t24', False, "Hi!")
self.assertEqual(packed, b'$4\x90\x80')

def test_unpack(self):
"""Unpack values.
Expand Down Expand Up @@ -80,6 +86,10 @@ def test_unpack(self):
unpacked = unpack('u5b2u1', packed)
self.assertEqual(unpacked, (0, True, 0))

packed = b'$4\x90\x80'
unpacked = unpack('b1t24', packed)
self.assertEqual(unpacked, (False, u"Hi!"))

# bad float size
try:
unpack('f33', b'\x00\x00\x00\x00\x00')
Expand Down Expand Up @@ -137,8 +147,8 @@ def test_calcsize(self):
size = calcsize('u1s6u7u9')
self.assertEqual(size, 23)

size = calcsize('b1s6u7u9')
self.assertEqual(size, 23)
size = calcsize('b1s6u7u9p1t8')
self.assertEqual(size, 32)

def test_byteswap(self):
"""Byte swap.
Expand Down

0 comments on commit cac34fd

Please sign in to comment.