Skip to content

Commit 176e40c

Browse files
initial commit
0 parents  commit 176e40c

7 files changed

Lines changed: 814 additions & 0 deletions

File tree

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
2+
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
3+
4+
name: Python package
5+
6+
on:
7+
push:
8+
branches: [ "main" ]
9+
pull_request:
10+
branches: [ "main" ]
11+
12+
jobs:
13+
build:
14+
15+
runs-on: ubuntu-latest
16+
strategy:
17+
fail-fast: false
18+
matrix:
19+
python-version: ["3.11"]
20+
21+
steps:
22+
- uses: actions/checkout@v3
23+
- name: Set up Python ${{ matrix.python-version }}
24+
uses: actions/setup-python@v3
25+
with:
26+
python-version: ${{ matrix.python-version }}
27+
- name: Install dependencies
28+
run: |
29+
python -m pip install --upgrade pip
30+
python -m pip install pytest
31+
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
32+
- name: Run tests
33+
run: python test.py
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# This workflow will upload a Python Package using Twine when a release is created
2+
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries
3+
4+
# This workflow uses actions that are not certified by GitHub.
5+
# They are provided by a third-party and are governed by
6+
# separate terms of service, privacy policy, and support
7+
# documentation.
8+
9+
name: Upload Python Package
10+
11+
on:
12+
release:
13+
types: [published]
14+
15+
permissions:
16+
contents: read
17+
18+
jobs:
19+
deploy:
20+
21+
runs-on: ubuntu-latest
22+
23+
steps:
24+
- uses: actions/checkout@v3
25+
- name: Set up Python
26+
uses: actions/setup-python@v3
27+
with:
28+
python-version: '3.x'
29+
- name: Install dependencies
30+
run: |
31+
python -m pip install --upgrade pip
32+
pip install build
33+
pip install twine
34+
- name: Build package
35+
run: python -m build
36+
- name: Publish package
37+
run: python -m twine upload dist/* -u __token__ -p ${{ secrets.PYPI_API_TOKEN }}

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 lingeringwillx
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
A small Python library based on the BytesIO object from the standard library, designed to make parsing and editing binary files easier.
2+
3+
### Installation
4+
5+
Using pip:
6+
7+
```
8+
pip install structio
9+
```
10+
11+
### Example
12+
13+
Writing to a stream:
14+
15+
```python
16+
>>> from structio import *
17+
>>> stream = StructIO()
18+
>>> stream.write_int(10, 2)
19+
2
20+
>>> stream.write_float(3.14, 4)
21+
4
22+
>>> stream.write_cstr('Hello')
23+
6
24+
>>> stream.write_pstr('World!', 1)
25+
7
26+
>>> stream.seek(0)
27+
0
28+
>>> stream.read()
29+
b'\n\x00\xc3\xf5H@Hello\x00\x06World!'
30+
```
31+
32+
Reading from the same stream:
33+
34+
```python
35+
>>> stream.seek(0)
36+
0
37+
>>> stream.read_int(2)
38+
10
39+
>>> stream.read_float(4)
40+
3.140000104904175
41+
>>> stream.read_cstr()
42+
'Hello'
43+
>>> stream.read_pstr(1)
44+
'World!'
45+
```
46+
47+
### Objects
48+
49+
### StructIO
50+
51+
File-like object stored in memory. Extends *io.BytesIO* from the standard library, which means that it has all of the basic methods of file-like objects, including *read*, *write*, *seek*, *tell*, and *truncate*.
52+
53+
### Attributes
54+
55+
**buffer**: the current content of the object.
56+
57+
**endian**: the default endian that would be used by the object.
58+
59+
**encoding**: the default encoding used by string methods.
60+
61+
**errors**: the default error handling behavior when encoding or decoding strings. More information could be found in [Python's documentation](https://docs.python.org/3/library/codecs.html#error-handlers).
62+
63+
### Methods
64+
65+
**StructIO(b=b'', endian='little', encoding='utf-8', errors='ignore')**
66+
67+
Take bytes object *b* and returns a *StructIO* instance containing *b* with the provided arguments used as defaults.
68+
69+
**\_\_len\_\_()**
70+
71+
Returns the size/length of the file.
72+
73+
**\_\_eq\_\_(other)**
74+
75+
Checks if the content of the buffer is equal to the content of another StructIO or BytesIO object.
76+
77+
**copy()**
78+
79+
Creates a copy of the object and returns it.
80+
81+
**clear()**
82+
83+
Clear the internal buffer of the object.
84+
85+
**find(b)**
86+
87+
Searches the buffer for *b*. Returns the location in which *b* can be found, returns -1 if it's not found. Starts searching from the current position in the buffer.
88+
89+
**index(b)**
90+
91+
Same as *find* but raises a *ValueError* if it fails to find *b*.
92+
93+
**read_bool()**
94+
95+
Read one byte from the buffer and converts it into a boolean.
96+
97+
**write_bool(boolean)**
98+
99+
Writes *boolean* to the buffer.
100+
101+
**read_bits()**
102+
103+
Reads one byte from the buffer and converts it into a list of integers representing the individual bits in the byte. The first element in the list is LSB in the byte.
104+
105+
**write_bits(bits)**
106+
107+
Converts list of integers *bits* into a byte and writes it to the buffer.
108+
109+
**read_int(size, endian=None, signed=False)**
110+
111+
Reads *size* bytes from the buffer and converts it into an integer. The endian can be specified with the *endian* argument. The *signed* argument is used to specify whether the integer is signed or not.
112+
113+
**write_int(number, size, endian=None, signed=False)**
114+
115+
Converts *number* into a bytes buffer with length *size* and endian *endian*, then writes it into the buffer. The *signed* argument is used to specify whether the integer is signed or not.
116+
117+
**read_ints(size, n endian=None, signed=False)**
118+
119+
Reads *n* integers of *size* bytes from the buffer. Can be faster than *read_int* when multiple reads are required but limited to sizes 1, 2, 4, and 8.
120+
121+
**write_ints(numbers, size, endian=None, signed=False)**
122+
123+
Converts a list of integers *numbers* into a bytes buffer with length *size* and endian *endian*, then writes it into the buffer. Can be faster than *write_int* when multiple writes are required but limited to sizes 1, 2, 4, and 8.
124+
125+
**read_float(size, endian=None)**
126+
127+
Reads *size* bytes from the buffer and converts them into a float. *size* can be 2 for half precision, 4 for single precision, or 8 for double precision. The endian can be specified with the *endian* argument.
128+
129+
**write_float(number, size, endian=None)**
130+
131+
Converts *number* into a bytes buffer then writes it into the buffer. *size* can be 2 for half precision, 4 for single precision, or 8 for double precision. The endian can be specified with the *endian* argument.
132+
133+
**read_floats(size, n, endian=None)**
134+
135+
Reads *n* floats of *size* bytes from the buffer. Can be faster than *read_float* when multiple reads are required.
136+
137+
**write_floats(numbers size, endian=None)**
138+
139+
Converts a list of floats *numbers* into a bytes buffer then writes it into the buffer. Can be faster than *write_float* when multiple writes are required.
140+
141+
**read_str(length)**
142+
143+
Reads a string with length *length* from the buffer.
144+
145+
**write_str(string)**
146+
147+
Writes *string* into the buffer.
148+
149+
**read_cstr()**
150+
151+
Reads a string from the buffer up to the null termination. Raises a *ValueError* if it fails to find a null termination.
152+
153+
**write_cstr(string)**
154+
155+
Writes *string* into the buffer.
156+
157+
**skip_cstr()**
158+
159+
Skips the null-terminated string at the current position.
160+
161+
**read_pstr(size, endian=None)**
162+
163+
Reads a Pascal string from the buffer and returns it. *size* is used to specify how many bytes are used for the string's length in the buffer. The endian of the length of the string can be specified with the *endian* argument.
164+
165+
**write_pstr(string, size, endian=None)**
166+
167+
Writes *string* to the buffer as a Pascal string.
168+
169+
**skip_pstr(size, endian=None)**
170+
171+
Skips the Pascal string at the current position.
172+
173+
**read_7bint()**
174+
175+
Reads the bytes representing a 7 bit integer from the buffer at the current position and converts them into an integer.
176+
177+
**write_7bint(number)**
178+
179+
Converts *number* into a 7 bit integer and writes it to the buffer.
180+
181+
**skip_7bint()**
182+
183+
Skips the 7 bit integer at the current position.

pyproject.toml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[build-system]
2+
requires = ["setuptools>=61.0"]
3+
build-backend = "setuptools.build_meta"
4+
5+
[project]
6+
name = "structio"
7+
version = "1.4.2"
8+
description = "A Library for unparsing, parsing, and editing binary files"
9+
readme = "README.md"
10+
requires-python = ">=3.8"
11+
12+
[project.urls]
13+
"Homepage" = "https://github.com/lingeringwillx/StructIO"

0 commit comments

Comments
 (0)