Skip to content

Commit e23fc1a

Browse files
committed
documentation
1 parent 0ad6fbc commit e23fc1a

10 files changed

Lines changed: 135 additions & 148 deletions

File tree

README.md

Lines changed: 84 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -14,29 +14,36 @@ C-style structs for Python
1414
Convert C struct/union definitions into Python classes with methods for
1515
serializing/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/)
1819
and add a C struct/union definition as a string in the `__def__` field.
1920

2021
The C struct/union definition is parsed at runtime and the struct format string
2122
is generated. The class offers the method `unpack` for deserializing
2223
an array of bytes into a Python object and the method `pack` for
2324
serializing the values into an array of bytes.
2425

25-
[Api Documentation](https://python-cstruct.readthedocs.io/en/latest/)
26-
2726
Install
2827
-------
2928

3029
```
3130
pip 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+
3441
Features
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
4249
class 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
5868
Partition = 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
8090
class 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
99109
class HtmlFont(cstruct.CEnum):
@@ -113,36 +123,17 @@ assert HtmlFont.HTMLFONT_BOLD == 1
113123
assert HtmlFont.HTMLFONT_ITALIC == 2
114124
```
115125

116-
Different supported `__def__` styles:
126+
Different enum styles are supported in struct/union definitions.
117127

118128
```c
119129
enum Type_A a; // externally defined using CEnum
120130
enum Type_B {A, B, C} b;
121131
enum {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
148139
class 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:
262258
cstruct.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
268264
cstruct.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

Comments
 (0)