File: buffer.rst

package info (click to toggle)
python-bitarray 3.6.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,288 kB
  • sloc: python: 11,456; ansic: 7,657; makefile: 73; sh: 6
file content (131 lines) | stat: -rw-r--r-- 3,798 bytes parent folder | download | duplicates (3)
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
Buffer protocol
===============

Bitarray objects support the buffer protocol.  They can both export their
own buffer, as well as import another object's buffer.


Exporting buffers
-----------------

Here is an example where the bitarray's buffer is exported:

.. code-block:: python

    >>> from bitarray import bitarray
    >>> a = bitarray('01000001 01000010 01000011', endian='big')
    >>> v = memoryview(a)
    >>> v.tobytes()
    b'ABC'
    >>> v[1] = 255
    >>> a
    bitarray('010000011111111101000011')

Note that it is possible to change the shared buffer from both ``a`` and ``v``:

.. code-block:: python

    >>> a[6] = 1
    >>> v.tobytes()
    b'C\xffC'

However, as ``a``'s buffer is shared, it is not possible to resize it:

.. code-block:: python

    >>> a.append(0)
    Traceback (most recent call last):
        ...
    BufferError: cannot resize bitarray that is exporting buffers

When exporting the buffer of a ``frozenbitarray``, it is not possible to
change its ``memoryview`` either:

.. code-block:: python

    >>> from bitarray import frozenbitarray
    >>> a = frozenbitarray('01000001 01000010')
    >>> v = memoryview(a)
    >>> v.readonly
    True
    >>> v[0] = 15
    Traceback (most recent call last):
        ...
    TypeError: cannot modify read-only memory


Importing buffers
-----------------

As of bitarray version 2.3, it is also possible to import the buffer
from an object which exposes its buffer.  Here the bytearray:

.. code-block:: python

    >>> c = bytearray([0x41, 0xff, 0x01])
    >>> a = bitarray(buffer=c, endian='big')
    >>> a
    bitarray('010000011111111100000001')
    >>> a <<= 3  # shift all bits by 3 to the left
    >>> c
    bytearray(b'\x0f\xf8\x08')
    >>> a[20:] = 1
    >>> a
    bitarray('000011111111100000001111')

Again, the shared buffer can be represented and modify by either object ``a``
and ``c``.  When importing a buffer into a bitarray, the length of the
bitarray will always be multiple of 8 bits, as buffers are bases on bytes.
Also, we may specify the endianness of the bitarray:

.. code-block:: python

   >>> b = bitarray(buffer=c, endian='little')
   >>> b
   bitarray('111100000001111111110000')

The bytearray ``c`` is now exporting its buffer twice:
to big-endian bitarray ``a``, and a little-endian bitarray ``b``.
At this point all three object ``a``, ``b`` and ``c`` share the same buffer.
Using the ``.buffer_info()`` method, we can actually verify that the
bitarrays ``a`` and ``b`` point to the same buffer address:

.. code-block:: python

    >>> assert a.buffer_info()[0] == b.buffer_info()[0]

As bitarray's expose their buffer, we can also directly create a bitarray
which imports the buffer from another bitarray:

.. code-block:: python

    >>> a = bitarray(32)
    >>> b = bitarray(buffer=a)
    >>> # the buffer address is the same
    >>> assert a.buffer_info()[0] == b.buffer_info()[0]
    >>> a.setall(0)
    >>> assert a == b
    >>> b[::7] = 1
    >>> assert a == b
    >>> a
    bitarray('10000001000000100000010000001000')

We can also create bitarrays which share part of the buffer.  Let's create
a large bitarray ``a``, and then have ``b`` and ``c`` share different portions
of ``a``'s buffer:

.. code-block:: python

    >>> a = bitarray(1 << 23)
    >>> a.setall(0)
    >>> b = bitarray(buffer=memoryview(a)[0x10000:0x30000])
    >>> assert a.buffer_info()[0] + 0x10000 == b.buffer_info()[0]
    >>> c = bitarray(buffer=memoryview(a)[0x20000:0x50000])
    >>> assert a.buffer_info()[0] + 0x20000 == c.buffer_info()[0]
    >>> c[0] = 1
    >>> assert b[8 * 0x10000] == 1
    >>> assert a[8 * 0x20000] == 1

Finally, importing buffers allows creating bitarrays that are memory mapped
to a file.  Please see the `mmapped-file.py <../examples/mmapped-file.py>`__
example.