File: bitarray.rst

package info (click to toggle)
python-bitstring 4.3.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,312 kB
  • sloc: python: 11,397; makefile: 8; sh: 7
file content (300 lines) | stat: -rw-r--r-- 11,009 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
.. currentmodule:: bitstring

BitArray
========

.. class:: BitArray(auto: BitsType | int | None, /, length: int | None = None, offset: int | None = None, **kwargs)

    The :class:`Bits` class is the base class for :class:`BitArray` and so (with the exception of :meth:`~Bits.__hash__`) all of its methods are also available for :class:`BitArray` objects.
    The initialiser is the same as for :class:`Bits`.

    A :class:`BitArray` is a mutable :class:`Bits`, and so the one thing all of the methods listed here have in common is that  they can modify the contents of the bitstring.

----

Methods
-------

.. method:: BitArray.append(bs: BitsType) -> None

   Join a :class:`BitArray` to the end of the current :class:`BitArray`. ::

       >>> s = BitArray('0xbad')
       >>> s.append('0xf00d')
       >>> s
       BitArray('0xbadf00d')

.. method:: BitArray.byteswap(fmt: str | int | Iterable[int] | None = None, start: int | None = None, end: int | None = None, repeat: bool = True) -> int

   Change the endianness of the :class:`BitArray` in-place according to *fmt*. Return the number of swaps done.

   The *fmt* can be an integer, an iterable of integers or a compact format string similar to those used in :func:`pack` (described in :ref:`compact_format`). It defaults to 0, which means reverse as many bytes as possible. The *fmt* gives a pattern of byte sizes to use to swap the endianness of the :class:`BitArray`. Note that if you use a compact format string then the endianness identifier (``<``, ``>`` or ``=``) is not needed, and if present it will be ignored.

   *start* and *end* optionally give a slice to apply the transformation to (it defaults to the whole :class:`BitArray`). If *repeat* is ``True`` then the byte swapping pattern given by the *fmt* is repeated in its entirety as many times as possible.

       >>> s = BitArray('0x00112233445566')
       >>> s.byteswap(2)
       3
       >>> s
       BitArray('0x11003322554466')
       >>> s.byteswap('h')
       3
       >>> s
       BitArray('0x00112233445566')
       >>> s.byteswap([2, 5])
       1
       >>> s
       BitArray('0x11006655443322')

   It can also be used to swap the endianness of the whole :class:`BitArray`. ::

       >>> s = BitArray('uintle32=1234')
       >>> s.byteswap()
       >>> print(s.uintbe)
       1234

.. method:: BitArray.clear() -> None

    Removes all bits from the bitstring.

    ``s.clear()`` is equivalent to ``del s[:]`` and simply makes the bitstring empty.

.. method:: BitArray.insert(bs: BitsType, pos: int) -> None

    Inserts *bs* at *pos*.

    When used with the :class:`BitStream` class the *pos* is optional, and if not present the current bit position will be used. After insertion the property :attr:`~ConstBitStream.pos` will be immediately after the inserted bitstring. ::

        >>> s = BitStream('0xccee')
        >>> s.insert('0xd', 8)
        >>> s
        BitStream('0xccdee')
        >>> s.insert('0x00')
        >>> s
        BitStream('0xccd00ee')

.. method:: BitArray.invert(pos: int | Iterable[int] | None = None) -> None

    Inverts one or many bits from ``1`` to ``0`` or vice versa.

    *pos* can be either a single bit position or an iterable of bit positions. Negative numbers are treated in the same way as slice indices and it will raise :exc:`IndexError` if ``pos < -len(s)`` or ``pos > len(s)``. The default is to invert the entire :class:`BitArray`. ::

        >>> s = BitArray('0b111001')
        >>> s.invert(0)
        >>> s.bin
        '011001'
        >>> s.invert([-2, -1])
        >>> s.bin
        '011010'
        >>> s.invert()
        >>> s.bin
        '100101'

.. method:: BitArray.overwrite(bs: BitsType, pos: int) -> None

    Replaces the contents of the current :class:`BitArray` with *bs* at *pos*.

    When used with the :class:`BitStream` class the *pos* is optional, and if not present the current bit position will be used. After insertion the property :attr:`~ConstBitStream.pos` will be immediately after the overwritten bitstring. ::

        >>> s = BitArray(length=10)
        >>> s.overwrite('0b111', 3)
        >>> s
        BitArray('0b0001110000')
        >>> s.pos
        6

.. method:: BitArray.prepend(bs: BitsType) -> None

    Inserts *bs* at the beginning of the current :class:`BitArray`. ::

        >>> s = BitArray('0b0')
        >>> s.prepend('0xf')
        >>> s
        BitArray('0b11110')

.. method:: BitArray.replace(old: BitsType, new: BitsType, start: int | None = None, end: int | None = None, count: int | None = None, bytealigned: bool | None = None) -> int

    Finds occurrences of *old* and replaces them with *new*. Returns the number of replacements made.

    If *bytealigned* is ``True`` then replacements will only be made on byte boundaries. *start* and *end* give the search range and default to the start and end of the bitstring. If *count* is specified then no more than this many replacements will be made. ::

        >>> s = BitArray('0b0011001')
        >>> s.replace('0b1', '0xf')
        3
        >>> print(s.bin)
        0011111111001111
        >>> s.replace('0b1', '', count=6)
        6
        >>> print(s.bin)
        0011001111

.. method:: BitArray.reverse(start: int | None = None, end: int | None = None) -> None

    Reverses bits in the :class:`BitArray` in-place.

    *start* and *end* give the range of bits to reverse and default to the start and end of the bitstring. ::

        >>> a = BitArray('0b000001101')
        >>> a.reverse()
        >>> a.bin
        '101100000'
        >>> a.reverse(0, 4)
        >>> a.bin
        '110100000'

.. method:: BitArray.rol(bits: int, start: int | None = None, end: int | None = None) -> None

    Rotates the contents of the :class:`BitArray` in-place by *bits* bits to the left.

    *start* and *end* define the slice to use and default to the start and end of the bitstring.

    Raises :exc:`ValueError` if ``bits < 0``. ::

        >>> s = BitArray('0b01000001')
        >>> s.rol(2)
        >>> s.bin
        '00000101'

.. method:: BitArray.ror(bits: int, start: int | None = None, end: int | None = None) -> None

    Rotates the contents of the :class:`BitArray` in-place by *bits* bits to the right.

    *start* and *end* define the slice to use and default to the start and end of the bitstring.

    Raises :exc:`ValueError` if ``bits < 0``.

.. method:: BitArray.set(value: bool, pos: int | Iterable[int] | None = None) -> None

    Sets one or many bits to either ``1`` (if *value* is ``True``) or ``0`` (if *value* isn't ``True``). *pos* can be either a single bit position or an iterable of bit positions. Negative numbers are treated in the same way as slice indices and it will raise :exc:`IndexError` if ``pos < -len(s)`` or ``pos > len(s)``. The default is to set every bit in the :class:`BitArray`.

    Using ``s.set(True, x)`` can be more efficient than other equivalent methods such as ``s[x] = 1``, ``s[x] = "0b1"`` or ``s.overwrite('0b1', x)``, especially if many bits are being set. In particular using a ``range`` object as an iterable is treated as a special case and is done efficiently. ::

        >>> s = BitArray('0x0000')
        >>> s.set(True, -1)
        >>> print(s)
        0x0001
        >>> s.set(1, (0, 4, 5, 7, 9))
        >>> s.bin
        '1000110101000001'
        >>> s.set(0)
        >>> s.bin
        '0000000000000000'
        >>> s.set(1, range(0, len(s), 2))
        >>> s.bin
        '1010101010101010'

----

Properties
----------

Note that the ``bin``, ``oct``, ``hex``, ``int``, ``uint`` and ``float`` properties can all be shortened to their initial letter.
Properties can also have a length in bits appended to them to make properties such as ``u8`` or ``floatle64`` (with the exception of the ``bytes`` property which uses a unit of bytes instead of bits, so ``bytes4`` is 32 bits long). These properties with lengths can be used to quickly create a new bitstring. ::

    >>> a = BitArray()
    >>> a.f32 = 17.6
    >>> a.h
    '418ccccd'
    >>> a.i7 = -1
    >>> a.b
    '1111111'


The binary interpretation properties of the :class:`Bits` class all become writable in the :class:`BitArray` class.

For integer types, the properties can have a bit length appended to it such as ``u32`` or ``int5`` to specify the new length of the bitstring.
Using a length too small to contain the value given will raise a :exc:`CreationError`.

When used  as a setter without a new length the value must fit into the current length of the :class:`BitArray`, else a :exc:`ValueError` will be raised. ::

    >>> s = BitArray('0xf3')
    >>> s.int
    -13
    >>> s.int = 1232
    ValueError: int 1232 is too large for a BitArray of length 8.


Other types also have restrictions on their lengths, and using an invalid length will raise a :exc:`CreationError`.
For example trying to create a 20 bit floating point number or a two bit bool will raise this exception.

----

Special Methods
---------------

.. method:: BitArray.__delitem__(key)

    ``del s[start:end:step]``

    Deletes the slice specified.

.. method:: BitArray.__iadd__(bs)

    ``s1 += s2``

    Appends *bs* to the current bitstring.

    Note that for :class:`BitArray` objects this will be an in-place change, whereas for :class:`Bits` objects using ``+=`` will not call this method - instead a new object will be created (it is equivalent to a copy and an :meth:`~Bits.__add__`). ::

        >>> s = BitArray(ue=423)
        >>> s += BitArray(ue=12)
        >>> s.read('ue')
        423
        >>> s.read('ue')
        12

.. method:: BitArray.__iand__(bs)

    ``s &= bs``

    In-place bit-wise AND between two bitstrings. If the two bitstrings are not the same length then a :exc:`ValueError` is raised.

.. method:: BitArray.__ilshift__(n)

    ``s <<= n``

    Shifts the bits in-place *n* bits to the left. The *n* right-most bits will become zeros and bits shifted off the left will be lost.

.. method:: BitArray.__imul__(n)

    ``s *= n``

    In-place concatenation of *n* copies of the current bitstring.

        >>> s = BitArray('0xbad')
        >>> s *= 3
        >>> s.hex
        'badbadbad'

.. method:: BitArray.__ior__(bs)

    ``s |= bs``

    In-place bit-wise OR between two bitstrings. If the two bitstrings are not the same length then a :exc:`ValueError` is raised.

.. method:: BitArray.__irshift__(n)

    ``s >>= n``

    Shifts the bits in-place *n* bits to the right. The *n* left-most bits will become zeros and bits shifted off the right will be lost.

.. method:: BitArray.__ixor__(bs)

    ``s ^= bs``

    In-place bit-wise XOR between two bitstrings. If the two bitstrings are not the same length then a :exc:`ValueError` is raised.

.. method:: BitArray.__setitem__(key, value)

    ``s1[start:end:step] = s2``

    Replaces the slice specified with a new value. ::

        >>> s = BitArray('0x00000000')
        >>> s[::8] = '0xf'
        >>> print(s)
        0x80808080
        >>> s[-12:] = '0xf'
        >>> print(s)
        0x80808f