@@ -14,29 +14,36 @@ C-style structs for Python
1414Convert C struct/union definitions into Python classes with methods for
1515serializing/deserializing.
1616
17- The usage is very simple: create a class subclassing cstruct.MemCStruct
17+ The usage is very simple: create a class subclassing
18+ [ ` cstruct.MemCStruct ` ] ( https://python-cstruct.readthedocs.io/en/latest/api/mem_cstruct/ )
1819and add a C struct/union definition as a string in the ` __def__ ` field.
1920
2021The C struct/union definition is parsed at runtime and the struct format string
2122is generated. The class offers the method ` unpack ` for deserializing
2223an array of bytes into a Python object and the method ` pack ` for
2324serializing the values into an array of bytes.
2425
25- [ Api Documentation] ( https://python-cstruct.readthedocs.io/en/latest/ )
26-
2726Install
2827-------
2928
3029```
3130pip install cstruct
3231```
3332
33+ Examples
34+ --------
35+
36+ * [ Read the DOS-type (MBR) partition table] ( https://python-cstruct.readthedocs.io/en/latest/examples/fdisk/ )
37+ * [ Print information about logged uses] ( https://python-cstruct.readthedocs.io/en/latest/examples/who/ )
38+ * [ Flexible Array Member (FAM)] ( https://python-cstruct.readthedocs.io/en/latest/examples/flexible_array/ )
39+
40+
3441Features
3542--------
3643
3744### Structs
3845
39- Struct definition subclassing ` cstruct.MemCStruct `
46+ Struct definition subclassing ` cstruct.MemCStruct ` . Methods can access stuct values as instance variables.
4047
4148``` python
4249class Position (cstruct .MemCStruct ):
@@ -47,18 +54,21 @@ class Position(cstruct.MemCStruct):
4754 unsigned char cyl;
4855 }
4956 """
57+ @ property
58+ def lba (self ):
59+ return (self .cyl * 16 + self .head) * 63 + (self .sector - 1 )
5060
51- pos = Position(head = 10 , sector = 20 , cyl = 30 )
52- print (f " head: { pos.head} sector: { pos.sector} cyl: { pos.cyl} " )
61+ pos = Position(cyl = 15 , head = 15 , sector = 63 )
62+ print (f " head: { pos.head} sector: { pos.sector} cyl: { pos.cyl} lba: { pos.lba } " )
5363```
5464
55- Struct definition using ` cstruct.parse `
65+ Struct definition using ` cstruct.parse ` .
5666
5767``` python
5868Partition = cstruct.parse("""
59- struct {
60- #define ACTIVE_FLAG 0x80
69+ #define ACTIVE_FLAG 0x80
6170
71+ struct Partition {
6272 unsigned char status; /* 0x80 - active */
6373 struct Position start;
6474 unsigned char partition_type;
@@ -74,7 +84,7 @@ part.status = cstruct.getdef('ACTIVE_FLAG')
7484
7585### Unions
7686
77- Union definition subclassing ` cstruct.MemCStruct `
87+ Union definition subclassing ` cstruct.MemCStruct ` .
7888
7989``` python
8090class Data (cstruct .MemCStruct ):
@@ -93,7 +103,7 @@ assert data.integer != 2
93103
94104### Enums
95105
96- Enum definition subclassing ` cstruct.CEnum `
106+ Enum definition subclassing ` cstruct.CEnum ` .
97107
98108``` python
99109class HtmlFont (cstruct .CEnum ):
@@ -113,36 +123,17 @@ assert HtmlFont.HTMLFONT_BOLD == 1
113123assert HtmlFont.HTMLFONT_ITALIC == 2
114124```
115125
116- Different supported ` __def__ ` styles:
126+ Different enum styles are supported in struct/union definitions.
117127
118128``` c
119129enum Type_A a; // externally defined using CEnum
120130enum Type_B {A, B, C} b;
121131enum {A, B, C} c;
122132```
123133
124- ```python
125- class Type_A(cstruct.CEnum):
126- __size__ = 2
127- __enum__ = """
128- #define SOME_DEFINE 7
129-
130- A,
131- B,
132- C = 5,
133- D,
134- E = 7 + SOME_DEFINE
135- """
136-
137- # this is a nice gimmick that works, but wasn't really planned to be supported
138- class Type_C(cstruct.CEnum):
139- A = 0,
140- B = 1,
141- C = 2,
142- D = 3
143- ```
134+ ### Nested structs/unions
144135
145- ### Nested structures ( named/ anonymous)
136+ Nested stucts and unions are supported, both named and anonymous.
146137
147138```python
148139class Packet(cstruct.MemCStruct):
@@ -204,28 +195,33 @@ pkg.data = [10, 20, 30, 40]
204195
205196### Pack and Unpack
206197
198+ A code example illustrating how to use
199+ [ ` pack ` ] ( https://python-cstruct.readthedocs.io/en/latest/api/abstract/#cstruct.abstract.AbstractCStruct.pack ) to pack a structure into binary form.
200+
207201``` python
208- class StructWithEnum (cstruct .MemCStruct ):
202+ class Position (cstruct .MemCStruct ):
209203 __byte_order__ = cstruct.LITTLE_ENDIAN
210204 __def__ = """
211- struct StructWithEnum {
212- enum HtmlFont font;
213- unsigned int font_size;
205+ struct {
206+ unsigned char head;
207+ unsigned char sector;
208+ unsigned char cyl;
214209 }
215210 """
216211
217- # Pack
218- s.font = HtmlFont.HTMLFONT_NONE
219- s.font_size = 20
220- assert s.font == HtmlFont.HTMLFONT_NONE
221- assert s.font_size == 20
222- packed = s.pack()
223-
224- # Unpack
225- s1 = StructWithEnum()
226- s1.unpack(packed)
227- assert s1.font == HtmlFont.HTMLFONT_NONE
228- assert s1.font_size == 20
212+ pos = Position(head = 10 , sector = 20 , cyl = 3 )
213+ packed = pos.pack()
214+ ```
215+
216+ Binary representation can be converted into structure using
217+ [ ` unpack ` ] ( https://python-cstruct.readthedocs.io/en/latest/api/abstract/#cstruct.abstract.AbstractCStruct.unpack ) .
218+
219+ ```
220+ pos1 = Position()
221+ pos1.unpack(packed)
222+ assert pos1.head == 10
223+ assert pos1.sector == 20
224+ assert pos1.cyl == 3
229225```
230226
231227### Define, Sizeof, and Eval
@@ -262,7 +258,7 @@ Get structure size:
262258cstruct.sizeof(Partition)
263259```
264260
265- Evaluate C expression:
261+ Evaluate C expression using [ ` c_eval ` ] ( https://python-cstruct.readthedocs.io/en/latest/api/c_expr/ ) :
266262
267263``` python
268264cstruct.c_eval(" A1 / 10" )
@@ -294,90 +290,47 @@ class MBR(cstruct.MemCStruct):
294290 """
295291```
296292
297- Example
298- -------
293+ ### Ispect memory
299294
300- The following program reads the DOS partition information from a disk .
295+ The [ ` inspect ` ] ( https://python-cstruct.readthedocs.io/en/latest/api/abstract/#cstruct.abstract.AbstractCStruct.inspect ) methods displays memory contents in hexadecimal .
301296
302297``` python
303- # !/usr/bin/env python
304- import cstruct
305-
306- class Position (cstruct .MemCStruct ):
307- __byte_order__ = cstruct.LITTLE_ENDIAN
308- __def__ = """
309- struct {
310- unsigned char head;
311- unsigned char sector;
312- unsigned char cyl;
313- }
314- """
315-
316-
317- class Partition (cstruct .MemCStruct ):
318- __byte_order__ = cstruct.LITTLE_ENDIAN
319- __def__ = """
320- #define ACTIVE_FLAG 0x80
321-
322- typedef struct Position Position;
323-
324- struct {
325- unsigned char status; /* 0x80 - active */
326- Position start;
327- unsigned char partition_type;
328- Position end;
329- unsigned int start_sect; /* starting sector counting from 0 */
330- unsigned int sectors; /* nr of sectors in partition */
331- }
332- """
333-
334- def print_info (self ):
335- print (f " bootable: { ' Y' if self .status & cstruct.getdef(' ACTIVE_FLAG' ) else ' N' } " )
336- print (f " partition_type: { self .partition_type:02X } " )
337- print (f " start: head: { self .start.head:X } sectory: { self .start.sector:X } cyl: { self .start.cyl:X } " )
338- print (f " end: head: { self .end.head:X } sectory: { self .end.sector:X } cyl: { self .end.cyl:X } " )
339- print (f " starting sector: { self .start_sect:08x } " )
340- print (f " size MB: { self .sectors / 2 / 1024 } " )
341-
342-
343- class MBR (cstruct .MemCStruct ):
344- __byte_order__ = cstruct.LITTLE_ENDIAN
345- __def__ = """
346- #define MBR_SIZE 512
347- #define MBR_DISK_SIGNATURE_SIZE 4
348- #define MBR_USUALY_NULLS_SIZE 2
349- #define MBR_SIGNATURE_SIZE 2
350- #define MBR_BOOT_SIGNATURE 0xaa55
351- #define MBR_PARTITIONS_NUM 4
352- #define MBR_PARTITIONS_SIZE (sizeof(Partition) * MBR_PARTITIONS_NUM)
353- #define MBR_UNUSED_SIZE (MBR_SIZE - MBR_DISK_SIGNATURE_SIZE - MBR_USUALY_NULLS_SIZE - MBR_PARTITIONS_SIZE - MBR_SIGNATURE_SIZE)
354-
355- typedef struct Partition Partition;
356-
357- struct {
358- char unused[MBR_UNUSED_SIZE];
359- unsigned char disk_signature[MBR_DISK_SIGNATURE_SIZE];
360- unsigned char usualy_nulls[MBR_USUALY_NULLS_SIZE];
361- Partition partitions[MBR_PARTITIONS_NUM];
362- uint16 signature;
363- }
364- """
298+ print (mbr.inspect())
299+ ```
365300
366- @ property
367- def disk_signature_str (self ):
368- return " " .join(reversed ([f " { x:02x } " for x in self .disk_signature]))
369-
370- def print_info (self ):
371- print (f " disk signature: { self .disk_signature_str} " )
372- for i, partition in enumerate (self .partitions):
373- print (" " )
374- print (f " partition: { i} " )
375- partition.print_info()
376-
377- disk = " mbr"
378- with open (disk, " rb" ) as f:
379- mbr = MBR()
380- mbr.unpack(f)
381- mbr.print_info()
301+ Output example:
302+ ```
303+ 00000000 eb 48 90 00 00 00 00 00 00 00 00 00 00 00 00 00 |.H..............|
304+ 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
305+ 00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
306+ 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 02 |................|
307+ 00000040 ff 00 00 80 61 cb 04 00 00 08 fa 80 ca 80 ea 53 |....a..........S|
308+ 00000050 7c 00 00 31 c0 8e d8 8e d0 bc 00 20 fb a0 40 7c ||..1....... ..@||
309+ 00000060 3c ff 74 02 88 c2 52 be 79 7d e8 34 01 f6 c2 80 |<.t...R.y}.4....|
310+ 00000070 74 54 b4 41 bb aa 55 cd 13 5a 52 72 49 81 fb 55 |tT.A..U..ZRrI..U|
311+ 00000080 aa 75 43 a0 41 7c 84 c0 75 05 83 e1 01 74 37 66 |.uC.A|..u....t7f|
312+ 00000090 8b 4c 10 be 05 7c c6 44 ff 01 66 8b 1e 44 7c c7 |.L...|.D..f..D|.|
313+ 000000a0 04 10 00 c7 44 02 01 00 66 89 5c 08 c7 44 06 00 |....D...f.\..D..|
314+ 000000b0 70 66 31 c0 89 44 04 66 89 44 0c b4 42 cd 13 72 |pf1..D.f.D..B..r|
315+ 000000c0 05 bb 00 70 eb 7d b4 08 cd 13 73 0a f6 c2 80 0f |...p.}....s.....|
316+ 000000d0 84 f0 00 e9 8d 00 be 05 7c c6 44 ff 00 66 31 c0 |........|.D..f1.|
317+ 000000e0 88 f0 40 66 89 44 04 31 d2 88 ca c1 e2 02 88 e8 |..@f.D.1........|
318+ 000000f0 88 f4 40 89 44 08 31 c0 88 d0 c0 e8 02 66 89 04 |..@.D.1......f..|
319+ 00000100 66 a1 44 7c 66 31 d2 66 f7 34 88 54 0a 66 31 d2 |f.D|f1.f.4.T.f1.|
320+ 00000110 66 f7 74 04 88 54 0b 89 44 0c 3b 44 08 7d 3c 8a |f.t..T..D.;D.}<.|
321+ 00000120 54 0d c0 e2 06 8a 4c 0a fe c1 08 d1 8a 6c 0c 5a |T.....L......l.Z|
322+ 00000130 8a 74 0b bb 00 70 8e c3 31 db b8 01 02 cd 13 72 |.t...p..1......r|
323+ 00000140 2a 8c c3 8e 06 48 7c 60 1e b9 00 01 8e db 31 f6 |*....H|`......1.|
324+ 00000150 31 ff fc f3 a5 1f 61 ff 26 42 7c be 7f 7d e8 40 |1.....a.&B|..}.@|
325+ 00000160 00 eb 0e be 84 7d e8 38 00 eb 06 be 8e 7d e8 30 |.....}.8.....}.0|
326+ 00000170 00 be 93 7d e8 2a 00 eb fe 47 52 55 42 20 00 47 |...}.*...GRUB .G|
327+ 00000180 65 6f 6d 00 48 61 72 64 20 44 69 73 6b 00 52 65 |eom.Hard Disk.Re|
328+ 00000190 61 64 00 20 45 72 72 6f 72 00 bb 01 00 b4 0e cd |ad. Error.......|
329+ 000001a0 10 ac 3c 00 75 f4 c3 00 00 00 00 00 00 00 00 00 |..<.u...........|
330+ 000001b0 00 00 00 00 00 00 00 00 40 e2 01 00 00 00 80 00 |........@.......|
331+ 000001c0 02 00 83 fe 3f 86 01 00 00 00 c6 17 21 00 00 00 |....?.......!...|
332+ 000001d0 01 87 8e fe ff ff c7 17 21 00 4d d3 de 00 00 00 |........!.M.....|
333+ 000001e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
334+ 000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
382335```
383336
0 commit comments