explodethosebits 0.3.0__cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- etb/__init__.py +351 -0
- etb/__init__.pyi +976 -0
- etb/_etb.cpython-39-x86_64-linux-gnu.so +0 -0
- etb/_version.py +34 -0
- etb/py.typed +2 -0
- explodethosebits-0.3.0.dist-info/METADATA +405 -0
- explodethosebits-0.3.0.dist-info/RECORD +88 -0
- explodethosebits-0.3.0.dist-info/WHEEL +6 -0
- explodethosebits-0.3.0.dist-info/licenses/LICENSE +21 -0
- explodethosebits-0.3.0.dist-info/sboms/auditwheel.cdx.json +1 -0
- explodethosebits.libs/libcudart-c3a75b33.so.12.8.90 +0 -0
- include/etb/bit_coordinate.hpp +45 -0
- include/etb/bit_extraction.hpp +79 -0
- include/etb/bit_pruning.hpp +122 -0
- include/etb/config.hpp +284 -0
- include/etb/cuda/arch_optimizations.cuh +358 -0
- include/etb/cuda/blackwell_optimizations.cuh +300 -0
- include/etb/cuda/cuda_common.cuh +265 -0
- include/etb/cuda/etb_cuda.cuh +200 -0
- include/etb/cuda/gpu_memory.cuh +406 -0
- include/etb/cuda/heuristics_kernel.cuh +315 -0
- include/etb/cuda/path_generator_kernel.cuh +272 -0
- include/etb/cuda/prefix_pruner_kernel.cuh +370 -0
- include/etb/cuda/signature_kernel.cuh +328 -0
- include/etb/early_stopping.hpp +246 -0
- include/etb/etb.hpp +20 -0
- include/etb/heuristics.hpp +165 -0
- include/etb/memoization.hpp +285 -0
- include/etb/path.hpp +86 -0
- include/etb/path_count.hpp +87 -0
- include/etb/path_generator.hpp +175 -0
- include/etb/prefix_trie.hpp +339 -0
- include/etb/reporting.hpp +437 -0
- include/etb/scoring.hpp +269 -0
- include/etb/signature.hpp +190 -0
- include/gmock/gmock-actions.h +2297 -0
- include/gmock/gmock-cardinalities.h +159 -0
- include/gmock/gmock-function-mocker.h +518 -0
- include/gmock/gmock-matchers.h +5623 -0
- include/gmock/gmock-more-actions.h +658 -0
- include/gmock/gmock-more-matchers.h +120 -0
- include/gmock/gmock-nice-strict.h +277 -0
- include/gmock/gmock-spec-builders.h +2148 -0
- include/gmock/gmock.h +96 -0
- include/gmock/internal/custom/README.md +18 -0
- include/gmock/internal/custom/gmock-generated-actions.h +7 -0
- include/gmock/internal/custom/gmock-matchers.h +37 -0
- include/gmock/internal/custom/gmock-port.h +40 -0
- include/gmock/internal/gmock-internal-utils.h +487 -0
- include/gmock/internal/gmock-port.h +139 -0
- include/gmock/internal/gmock-pp.h +279 -0
- include/gtest/gtest-assertion-result.h +237 -0
- include/gtest/gtest-death-test.h +345 -0
- include/gtest/gtest-matchers.h +923 -0
- include/gtest/gtest-message.h +252 -0
- include/gtest/gtest-param-test.h +546 -0
- include/gtest/gtest-printers.h +1161 -0
- include/gtest/gtest-spi.h +250 -0
- include/gtest/gtest-test-part.h +192 -0
- include/gtest/gtest-typed-test.h +331 -0
- include/gtest/gtest.h +2321 -0
- include/gtest/gtest_pred_impl.h +279 -0
- include/gtest/gtest_prod.h +60 -0
- include/gtest/internal/custom/README.md +44 -0
- include/gtest/internal/custom/gtest-port.h +37 -0
- include/gtest/internal/custom/gtest-printers.h +42 -0
- include/gtest/internal/custom/gtest.h +37 -0
- include/gtest/internal/gtest-death-test-internal.h +307 -0
- include/gtest/internal/gtest-filepath.h +227 -0
- include/gtest/internal/gtest-internal.h +1560 -0
- include/gtest/internal/gtest-param-util.h +1026 -0
- include/gtest/internal/gtest-port-arch.h +122 -0
- include/gtest/internal/gtest-port.h +2481 -0
- include/gtest/internal/gtest-string.h +178 -0
- include/gtest/internal/gtest-type-util.h +220 -0
- lib/libetb_core.a +0 -0
- lib64/cmake/GTest/GTestConfig.cmake +33 -0
- lib64/cmake/GTest/GTestConfigVersion.cmake +43 -0
- lib64/cmake/GTest/GTestTargets-release.cmake +49 -0
- lib64/cmake/GTest/GTestTargets.cmake +139 -0
- lib64/libgmock.a +0 -0
- lib64/libgmock_main.a +0 -0
- lib64/libgtest.a +0 -0
- lib64/libgtest_main.a +0 -0
- lib64/pkgconfig/gmock.pc +10 -0
- lib64/pkgconfig/gmock_main.pc +10 -0
- lib64/pkgconfig/gtest.pc +9 -0
- lib64/pkgconfig/gtest_main.pc +10 -0
|
Binary file
|
etb/_version.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# file generated by setuptools-scm
|
|
2
|
+
# don't change, don't track in version control
|
|
3
|
+
|
|
4
|
+
__all__ = [
|
|
5
|
+
"__version__",
|
|
6
|
+
"__version_tuple__",
|
|
7
|
+
"version",
|
|
8
|
+
"version_tuple",
|
|
9
|
+
"__commit_id__",
|
|
10
|
+
"commit_id",
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
TYPE_CHECKING = False
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from typing import Tuple
|
|
16
|
+
from typing import Union
|
|
17
|
+
|
|
18
|
+
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
|
19
|
+
COMMIT_ID = Union[str, None]
|
|
20
|
+
else:
|
|
21
|
+
VERSION_TUPLE = object
|
|
22
|
+
COMMIT_ID = object
|
|
23
|
+
|
|
24
|
+
version: str
|
|
25
|
+
__version__: str
|
|
26
|
+
__version_tuple__: VERSION_TUPLE
|
|
27
|
+
version_tuple: VERSION_TUPLE
|
|
28
|
+
commit_id: COMMIT_ID
|
|
29
|
+
__commit_id__: COMMIT_ID
|
|
30
|
+
|
|
31
|
+
__version__ = version = '0.3.0'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 3, 0)
|
|
33
|
+
|
|
34
|
+
__commit_id__ = commit_id = 'gb249ff642'
|
etb/py.typed
ADDED
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: explodethosebits
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: ExplodeThoseBits - CUDA-accelerated exhaustive bit tree analysis
|
|
5
|
+
Keywords: forensics,bit-extraction,cuda,data-recovery,file-signatures,heuristics
|
|
6
|
+
Author-Email: Odin Glynn-Martin <odin@odinglynn.com>
|
|
7
|
+
License: MIT
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Intended Audience :: Science/Research
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: C++
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering
|
|
21
|
+
Classifier: Topic :: Security
|
|
22
|
+
Classifier: Topic :: System :: Recovery Tools
|
|
23
|
+
Project-URL: Homepage, https://github.com/odinglyn0/etb
|
|
24
|
+
Project-URL: Repository, https://github.com/odinglyn0/etb
|
|
25
|
+
Project-URL: Issues, https://github.com/odinglyn0/etb/issues
|
|
26
|
+
Requires-Python: >=3.8
|
|
27
|
+
Provides-Extra: test
|
|
28
|
+
Requires-Dist: pytest>=7.0.0; extra == "test"
|
|
29
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "test"
|
|
30
|
+
Requires-Dist: hypothesis>=6.0.0; extra == "test"
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
33
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
34
|
+
Requires-Dist: hypothesis>=6.0.0; extra == "dev"
|
|
35
|
+
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
36
|
+
Requires-Dist: isort>=5.0.0; extra == "dev"
|
|
37
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
38
|
+
Description-Content-Type: text/markdown
|
|
39
|
+
|
|
40
|
+
# ExplodeThoseBits! // ETB
|
|
41
|
+
|
|
42
|
+
Exhaustive bit-tree traversal library. Takes bytes, explodes them into bits, walks every forward-only path through the bit space, reconstructs candidate byte sequences, scores them against known file signatures and heuristics. CUDA-accelerated for Hopper/Blackwell GPUs.
|
|
43
|
+
|
|
44
|
+

|
|
45
|
+
|
|
46
|
+
## What it does
|
|
47
|
+
|
|
48
|
+
Given n input bytes, there are 9^n - 1 possible forward-only paths through the bit coordinate space (each byte has 8 bit positions, plus the choice to skip). The library systematically generates these paths, extracts bits along each path, packs them back into bytes, and evaluates whether the result looks like valid data.
|
|
49
|
+
|
|
50
|
+
The search space is obviously intractable for any reasonable input size. A 16-byte input has ~1.8 × 10^15 paths. So the library implements multi-level early stopping that prunes branches at 4, 8, and 16 bytes based on:
|
|
51
|
+
|
|
52
|
+
- Signature prefix matching (does it start like a PNG, JPEG, PDF, etc.)
|
|
53
|
+
- Shannon entropy bounds (too low = repeated garbage, too high = random/encrypted)
|
|
54
|
+
- Printable ASCII ratio
|
|
55
|
+
- UTF-8 validity
|
|
56
|
+
- Control character density
|
|
57
|
+
- Null byte run length
|
|
58
|
+
|
|
59
|
+
This reduces effective complexity from O(8^n) to O(k^d) where k is the effective branching factor after pruning and d is the depth at which most paths get killed.
|
|
60
|
+
|
|
61
|
+
## Installation
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
pip install explodethosebits
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Or build from source:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
git clone https://github.com/odinglyn0/etb
|
|
71
|
+
cd etb
|
|
72
|
+
pip install .
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Requires CUDA 12.x for GPU acceleration. Falls back to CPU if unavailable.
|
|
76
|
+
|
|
77
|
+
## Usage
|
|
78
|
+
|
|
79
|
+
### Basic extraction
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
import etb
|
|
83
|
+
|
|
84
|
+
# Extract from bytes
|
|
85
|
+
data = open("suspicious.bin", "rb").read()
|
|
86
|
+
candidates = etb.extract(data)
|
|
87
|
+
|
|
88
|
+
for c in candidates:
|
|
89
|
+
print(f"{c.format_name}: {c.confidence:.2%}")
|
|
90
|
+
print(f" Entropy: {c.heuristics.entropy:.2f}")
|
|
91
|
+
print(f" Path length: {c.path.length()}")
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Extract from file
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
candidates = etb.extract_from_file("suspicious.bin")
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### With metrics
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
result = etb.extract_with_metrics(data)
|
|
104
|
+
|
|
105
|
+
print(f"Evaluated {result.metrics.paths_evaluated} paths")
|
|
106
|
+
print(f"Prune rate: {result.metrics.prune_rate:.1%}")
|
|
107
|
+
print(f"Effective branching factor: {result.metrics.effective_branching_factor:.2f}")
|
|
108
|
+
print(f"Time: {result.metrics.wall_clock_seconds:.2f}s")
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Custom configuration
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
config = etb.EtbConfig()
|
|
115
|
+
|
|
116
|
+
# Adjust early stopping thresholds
|
|
117
|
+
config.early_stopping.level1_threshold = 0.3 # More aggressive pruning
|
|
118
|
+
config.early_stopping.level2_threshold = 0.4
|
|
119
|
+
config.early_stopping.adaptive_thresholds = True
|
|
120
|
+
|
|
121
|
+
# Entropy bounds
|
|
122
|
+
config.entropy_min = 0.1 # Below this = repeated pattern
|
|
123
|
+
config.entropy_max = 7.9 # Above this = random/encrypted
|
|
124
|
+
|
|
125
|
+
# Bit pruning mode
|
|
126
|
+
config.bit_pruning = etb.BitPruningConfig(etb.BitPruningMode.MSB_ONLY) # O(4^d) instead of O(8^d)
|
|
127
|
+
|
|
128
|
+
# Output options
|
|
129
|
+
config.output.top_n_results = 20
|
|
130
|
+
config.output.include_paths = True
|
|
131
|
+
|
|
132
|
+
candidates = etb.extract(data, config)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Load config from file
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
etb.load_config("config.yaml")
|
|
139
|
+
config = etb.ConfigManager.instance().get_config()
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Low-level API
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
# Bit coordinates
|
|
146
|
+
coord = etb.BitCoordinate(byte_index=0, bit_position=3)
|
|
147
|
+
|
|
148
|
+
# Paths (forward-only constraint enforced)
|
|
149
|
+
path = etb.Path()
|
|
150
|
+
path.add(etb.BitCoordinate(0, 3))
|
|
151
|
+
path.add(etb.BitCoordinate(1, 5))
|
|
152
|
+
path.add(etb.BitCoordinate(2, 1))
|
|
153
|
+
assert path.is_valid() # byte indices must be strictly increasing
|
|
154
|
+
|
|
155
|
+
# Extract bits along a path
|
|
156
|
+
bits = etb.extract_bits_from_path(data, path)
|
|
157
|
+
|
|
158
|
+
# Pack bits back to bytes
|
|
159
|
+
reconstructed = etb.bits_to_bytes(bits)
|
|
160
|
+
|
|
161
|
+
# Or do both at once
|
|
162
|
+
reconstructed = etb.path_to_bytes(data, path)
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Path generation
|
|
166
|
+
|
|
167
|
+
```python
|
|
168
|
+
# Generate all paths for small inputs (careful with this)
|
|
169
|
+
gen = etb.PathGenerator(input_length=4)
|
|
170
|
+
for path in gen:
|
|
171
|
+
# 9^4 - 1 = 6560 paths
|
|
172
|
+
pass
|
|
173
|
+
|
|
174
|
+
# With bit pruning
|
|
175
|
+
config = etb.PathGeneratorConfig(input_length=4)
|
|
176
|
+
config.bit_mask = 0xF0 # Only MSB positions
|
|
177
|
+
gen = etb.PathGenerator(config)
|
|
178
|
+
# Now 5^4 - 1 = 624 paths
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### Signature matching
|
|
182
|
+
|
|
183
|
+
```python
|
|
184
|
+
# Load signature dictionary
|
|
185
|
+
sigs = etb.SignatureDictionary()
|
|
186
|
+
sigs.load_from_json("signatures.json")
|
|
187
|
+
|
|
188
|
+
# Match against data
|
|
189
|
+
matcher = etb.SignatureMatcher(sigs)
|
|
190
|
+
match = matcher.match(data)
|
|
191
|
+
|
|
192
|
+
if match.matched:
|
|
193
|
+
print(f"Detected: {match.format_name} ({match.category})")
|
|
194
|
+
print(f"Confidence: {match.confidence:.2%}")
|
|
195
|
+
print(f"Header matched: {match.header_matched}")
|
|
196
|
+
print(f"Footer matched: {match.footer_matched}")
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Heuristics analysis
|
|
200
|
+
|
|
201
|
+
```python
|
|
202
|
+
engine = etb.HeuristicsEngine()
|
|
203
|
+
result = engine.analyze(data)
|
|
204
|
+
|
|
205
|
+
print(f"Entropy: {result.entropy:.2f} bits/byte")
|
|
206
|
+
print(f"Printable ratio: {result.printable_ratio:.2%}")
|
|
207
|
+
print(f"Control char ratio: {result.control_char_ratio:.2%}")
|
|
208
|
+
print(f"Max null run: {result.max_null_run}")
|
|
209
|
+
print(f"UTF-8 validity: {result.utf8_validity:.2%}")
|
|
210
|
+
print(f"Composite score: {result.composite_score:.2f}")
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Early stopping
|
|
214
|
+
|
|
215
|
+
```python
|
|
216
|
+
controller = etb.EarlyStoppingController()
|
|
217
|
+
|
|
218
|
+
# Check if a partial reconstruction should be abandoned
|
|
219
|
+
decision = controller.should_stop(partial_data)
|
|
220
|
+
if decision.should_stop:
|
|
221
|
+
print(f"Stopped at level {decision.level}: {decision.reason}")
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Prefix trie (for deduplication)
|
|
225
|
+
|
|
226
|
+
```python
|
|
227
|
+
trie = etb.PrefixTrie()
|
|
228
|
+
|
|
229
|
+
# Insert evaluated prefixes
|
|
230
|
+
trie.insert(prefix_bytes, etb.PrefixStatus.VALID, score=0.8)
|
|
231
|
+
trie.insert(bad_prefix, etb.PrefixStatus.PRUNED, score=0.1)
|
|
232
|
+
|
|
233
|
+
# Check before evaluating
|
|
234
|
+
if trie.is_pruned(candidate_prefix):
|
|
235
|
+
# Skip - ancestor was already pruned
|
|
236
|
+
pass
|
|
237
|
+
|
|
238
|
+
# Stats
|
|
239
|
+
print(f"Effective branching factor: {trie.get_effective_branching_factor():.2f}")
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Memoization cache
|
|
243
|
+
|
|
244
|
+
```python
|
|
245
|
+
cache = etb.PrefixCache()
|
|
246
|
+
|
|
247
|
+
# Check cache before expensive evaluation
|
|
248
|
+
entry = cache.lookup(prefix)
|
|
249
|
+
if entry is not None:
|
|
250
|
+
score = entry.score
|
|
251
|
+
should_prune = entry.should_prune
|
|
252
|
+
else:
|
|
253
|
+
# Evaluate and cache
|
|
254
|
+
result = engine.analyze(prefix)
|
|
255
|
+
cache.insert(prefix, result, score, should_prune)
|
|
256
|
+
|
|
257
|
+
print(f"Cache hit rate: {cache.hit_rate():.1%}")
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
## How the exhaustive search works
|
|
261
|
+
|
|
262
|
+
### Bit coordinate system
|
|
263
|
+
|
|
264
|
+
Each bit in the input is addressed by (byte_index, bit_position) where bit_position ∈ [0,7] and 0 is LSB.
|
|
265
|
+
|
|
266
|
+
### Forward-only paths
|
|
267
|
+
|
|
268
|
+
A path is a sequence of bit coordinates where each coordinate's byte_index is strictly greater than the previous. This constraint:
|
|
269
|
+
|
|
270
|
+
1. Ensures paths are acyclic
|
|
271
|
+
2. Limits path length to at most n (input length)
|
|
272
|
+
3. Makes the search space finite (though still exponential)
|
|
273
|
+
|
|
274
|
+
### Path enumeration
|
|
275
|
+
|
|
276
|
+
For n bytes with 8 bits each, the number of paths is:
|
|
277
|
+
|
|
278
|
+
```
|
|
279
|
+
Σ(k=1 to n) C(n,k) × 8^k = 9^n - 1
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
The library generates paths lazily using depth-first traversal with backtracking.
|
|
283
|
+
|
|
284
|
+
### Multi-level early stopping
|
|
285
|
+
|
|
286
|
+
The key to tractability. At each checkpoint depth:
|
|
287
|
+
|
|
288
|
+
**Level 1 (4 bytes):**
|
|
289
|
+
- Check signature prefix (first 4 bytes of PNG, JPEG, etc.)
|
|
290
|
+
- Basic entropy check
|
|
291
|
+
- Reject repeated byte patterns
|
|
292
|
+
- Threshold: 0.2 composite score
|
|
293
|
+
|
|
294
|
+
**Level 2 (8 bytes):**
|
|
295
|
+
- Full entropy bounds check
|
|
296
|
+
- Printable ratio for text detection
|
|
297
|
+
- Control character density
|
|
298
|
+
- Threshold: 0.3 composite score
|
|
299
|
+
|
|
300
|
+
**Level 3 (16 bytes):**
|
|
301
|
+
- Structural coherence
|
|
302
|
+
- UTF-8 validity
|
|
303
|
+
- Null run length
|
|
304
|
+
- Threshold: 0.4 composite score
|
|
305
|
+
|
|
306
|
+
Paths failing any level are pruned along with all descendants.
|
|
307
|
+
|
|
308
|
+
### Adaptive thresholds
|
|
309
|
+
|
|
310
|
+
When a high-scoring candidate is found (>0.8), thresholds tighten to 0.6. When the best score is low (<0.3), thresholds relax to 0.2. This focuses search on promising regions.
|
|
311
|
+
|
|
312
|
+
### Bit pruning modes
|
|
313
|
+
|
|
314
|
+
Reduce branching factor by limiting which bit positions are explored:
|
|
315
|
+
|
|
316
|
+
- **EXHAUSTIVE**: All 8 positions. O(8^d). Most thorough.
|
|
317
|
+
- **MSB_ONLY**: Positions 4-7 only. O(4^d). Good for most formats.
|
|
318
|
+
- **SINGLE_BIT**: 2 positions. O(2^d). Fastest.
|
|
319
|
+
- **CUSTOM**: Arbitrary bitmask.
|
|
320
|
+
|
|
321
|
+
### Scoring
|
|
322
|
+
|
|
323
|
+
Candidates are scored by weighted combination:
|
|
324
|
+
|
|
325
|
+
- Signature match: 40%
|
|
326
|
+
- Heuristic score: 30%
|
|
327
|
+
- Length score: 15%
|
|
328
|
+
- Structural validity: 15%
|
|
329
|
+
|
|
330
|
+
Top-k candidates are maintained in a min-heap for efficient tracking.
|
|
331
|
+
|
|
332
|
+
## CUDA acceleration
|
|
333
|
+
|
|
334
|
+
GPU kernels for:
|
|
335
|
+
|
|
336
|
+
- **Path generation**: Work-stealing across thread blocks, warp-level cooperative exploration
|
|
337
|
+
- **Heuristics**: Shared memory histograms for entropy calculation
|
|
338
|
+
- **Signature matching**: Constant memory broadcast for signature data
|
|
339
|
+
- **Prefix pruning**: Atomic trie updates
|
|
340
|
+
|
|
341
|
+
Optimized for SM 90 (Hopper) and SM 100 (Blackwell) with architecture-specific tuning.
|
|
342
|
+
|
|
343
|
+
## Configuration reference
|
|
344
|
+
|
|
345
|
+
See `data/config.yaml` for all options with documentation.
|
|
346
|
+
|
|
347
|
+
Key parameters:
|
|
348
|
+
|
|
349
|
+
| Parameter | Default | Description |
|
|
350
|
+
|-----------|---------|-------------|
|
|
351
|
+
| `early_stopping.level1_threshold` | 0.2 | Min score to continue at 4 bytes |
|
|
352
|
+
| `early_stopping.level2_threshold` | 0.3 | Min score to continue at 8 bytes |
|
|
353
|
+
| `early_stopping.level3_threshold` | 0.4 | Min score to continue at 16 bytes |
|
|
354
|
+
| `entropy_min` | 0.1 | Below = repeated pattern |
|
|
355
|
+
| `entropy_max` | 7.9 | Above = random/encrypted |
|
|
356
|
+
| `bit_pruning.mode` | exhaustive | Bit position selection |
|
|
357
|
+
| `memoization.max_cache_size_mb` | 1024 | LRU cache size |
|
|
358
|
+
| `output.top_n_results` | 10 | Candidates to return |
|
|
359
|
+
| `performance.batch_size` | 65536 | Paths per kernel launch |
|
|
360
|
+
|
|
361
|
+
## Supported formats
|
|
362
|
+
|
|
363
|
+
Signature detection for:
|
|
364
|
+
|
|
365
|
+
- Images: PNG, JPEG, GIF, BMP
|
|
366
|
+
- Documents: PDF
|
|
367
|
+
- Archives: ZIP, RAR, 7Z
|
|
368
|
+
- Executables: ELF, PE
|
|
369
|
+
- Audio: MP3
|
|
370
|
+
- Video: MP4
|
|
371
|
+
|
|
372
|
+
Add custom signatures via JSON:
|
|
373
|
+
|
|
374
|
+
```json
|
|
375
|
+
{
|
|
376
|
+
"format": "CUSTOM",
|
|
377
|
+
"category": "custom",
|
|
378
|
+
"signatures": [
|
|
379
|
+
{"magic": "DEADBEEF", "offset": 0, "confidence": 0.9}
|
|
380
|
+
],
|
|
381
|
+
"footer": {
|
|
382
|
+
"magic": "CAFEBABE",
|
|
383
|
+
"required": false
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
## Building from source
|
|
389
|
+
|
|
390
|
+
```bash
|
|
391
|
+
mkdir build && cd build
|
|
392
|
+
cmake ..
|
|
393
|
+
cmake --build .
|
|
394
|
+
ctest --output-on-failure
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
Requirements:
|
|
398
|
+
- CMake 3.24+
|
|
399
|
+
- CUDA Toolkit 12.x
|
|
400
|
+
- C++17 compiler
|
|
401
|
+
- Python 3.8+ (for bindings)
|
|
402
|
+
|
|
403
|
+
## License
|
|
404
|
+
|
|
405
|
+
MIT // See: LICENSE
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
etb/__init__.py,sha256=4vFFWXh9NpeuYmzGzG_s2LE3sc7dSqb578uxXMsd1Po,10139
|
|
2
|
+
etb/__init__.pyi,sha256=T0Y68PIb4WRzGbSXUvr4PdcIxK0T3K_BeArqTT-Rshw,29394
|
|
3
|
+
etb/_etb.cpython-39-x86_64-linux-gnu.so,sha256=zEscXU1ns6xlyzm7mnja475I4nkL2joZjRBSv4Jhrbo,1246513
|
|
4
|
+
etb/_version.py,sha256=3Eub_Rq48jo03WM1mzU8MyJiD0AEkE0IGyVDV4Nn9Mc,712
|
|
5
|
+
etb/py.typed,sha256=5cTSkPrzGked13zt9qANmllnHiCaAZ0n-74cQOoB6ME,89
|
|
6
|
+
explodethosebits.libs/libcudart-c3a75b33.so.12.8.90,sha256=1_Id0fBsTR_W1HjnYGHt9fScp-2_WhPZlsXu9T5r1T8,745465
|
|
7
|
+
include/etb/bit_coordinate.hpp,sha256=FPoI28-eQoMR3Q7tyEW1nhNd6MU_QiPoAL7-0-Cf4dY,1330
|
|
8
|
+
include/etb/bit_extraction.hpp,sha256=7g3xyJNGEPIm0S5g0-kFzqBrxp7wsT-Azm3mszkmqmg,2751
|
|
9
|
+
include/etb/bit_pruning.hpp,sha256=4_TV6gwW2gt55RuThwBwDVCPKv1sqCnnM8lrzRAk_zc,3576
|
|
10
|
+
include/etb/config.hpp,sha256=Ot8_ZKAniNWtdTexKwD3FBaTPyDwP7gXEyZo1Aec-2s,8123
|
|
11
|
+
include/etb/early_stopping.hpp,sha256=theUhuENFZfADyA9Qe48TSs44VZ28XVFAJwpl0C3gCw,7852
|
|
12
|
+
include/etb/etb.hpp,sha256=HXxVVRldOu3nX6kvRwfzFK96jEQ6fTOiZ116P9Xul-Q,472
|
|
13
|
+
include/etb/heuristics.hpp,sha256=5v69P2j9nO5DLE3vmF0nn5U_7wNvmLB3k3d-yyDph0I,5197
|
|
14
|
+
include/etb/memoization.hpp,sha256=NCWcLhBiu2AbNHQIRczXh4KzINdW3ONVTk37E3VuvtE,8330
|
|
15
|
+
include/etb/path.hpp,sha256=NA7dpiqtKjwNjuXj-PWmSI1Pn2RUnUu-l9Rx1OkWbjU,2227
|
|
16
|
+
include/etb/path_count.hpp,sha256=CemlhLn1qS5Q9iNCwdBsx0THvz4j-E6CCwyFQ4rJKj8,2849
|
|
17
|
+
include/etb/path_generator.hpp,sha256=rATLtVmQyCqi6g4g7RLhslzWdRbEvkjvQFCYHiEO0qY,4906
|
|
18
|
+
include/etb/prefix_trie.hpp,sha256=cyQaQPMZqmIT0YyJtFG98oYFdkvPyxb7wblQQERRTqs,11025
|
|
19
|
+
include/etb/reporting.hpp,sha256=1xokWdSeMPi_Ypknhsv4v2RHJ7GYxYG32wqImNGOwGo,13655
|
|
20
|
+
include/etb/scoring.hpp,sha256=XCNdwpQaeyYPrJokW0pJ3vO5y5gRDjnvTBUdCaQeHR0,8153
|
|
21
|
+
include/etb/signature.hpp,sha256=hjASYZc3eG6siF2IRqtTkOEz51iUe3JfyaCgD4yFUJA,6190
|
|
22
|
+
include/etb/cuda/arch_optimizations.cuh,sha256=kOj8RDQjzTvMyYJXxdEJLXXsCX3mK7ekeKZewvMKal0,10299
|
|
23
|
+
include/etb/cuda/blackwell_optimizations.cuh,sha256=gNDYFIibANlcM6dW_4lYFplfMANSE0-PSYAFe7kARhg,8842
|
|
24
|
+
include/etb/cuda/cuda_common.cuh,sha256=wXAcSxJ1n9IJCII0Y-l3tr9i4mthiSd0y3Q8vC3smkw,7701
|
|
25
|
+
include/etb/cuda/etb_cuda.cuh,sha256=rgPImi11MIF1NQcoxRQrVtjkcwBVFoZBEn_ua0Uczqc,5454
|
|
26
|
+
include/etb/cuda/gpu_memory.cuh,sha256=3i8iVf2vR5l3qc4zhPmODiXDEeYYoCLRQHfNyLE8p30,11633
|
|
27
|
+
include/etb/cuda/heuristics_kernel.cuh,sha256=QKd2QSByZ96Cch1NeeTyDUvHArQPB6yCPrvxn0BUxw4,9681
|
|
28
|
+
include/etb/cuda/path_generator_kernel.cuh,sha256=yYtkHfQe-BKkmC6GLxQ6w9P4glWotYaKKKJXlLq1YrM,7865
|
|
29
|
+
include/etb/cuda/prefix_pruner_kernel.cuh,sha256=D4Jmo5MCCUUpe07qlwbYXmwMaMXueKQRnSSG-wng5FY,11642
|
|
30
|
+
include/etb/cuda/signature_kernel.cuh,sha256=VKLLygzl8YPcJs9t24_AOVsZfNoxWBluRmL5TZ5t_ac,9785
|
|
31
|
+
include/gmock/gmock-actions.h,sha256=umcVDeXRNfFSN4ffXEO1aILIUF2ABY2OHtl12-OAMXs,87946
|
|
32
|
+
include/gmock/gmock-cardinalities.h,sha256=pWV4fz4V-B4Yc9H_nZeIirHjdGYWUljP_9bUuvwIYhQ,6118
|
|
33
|
+
include/gmock/gmock-function-mocker.h,sha256=hKFLJRqSV_JFU-FQB1IyZot_-bUgdr2jl-i0A1_OMDY,25756
|
|
34
|
+
include/gmock/gmock-matchers.h,sha256=JdFlhCQ5sRps3uvBhCeWT__el8aScHCPM-tMF3SzxOQ,210247
|
|
35
|
+
include/gmock/gmock-more-actions.h,sha256=OM5d19cj8Ii9B-CP5kyyUdaaE0fXYnv5ZQ7KxBr_GWk,38344
|
|
36
|
+
include/gmock/gmock-more-matchers.h,sha256=td-mAvTwWpIAD__gYjbLutsgvajhpOVbHN3ye6WGIy8,4499
|
|
37
|
+
include/gmock/gmock-nice-strict.h,sha256=dTJNL3ltp9YR-10dphDJBfU-dCR7Apgspj9dy5H0wzw,10858
|
|
38
|
+
include/gmock/gmock-spec-builders.h,sha256=RD3FxdshhINRSrzb22HG1AzsgWRdPYQv4joefW7rjY0,82067
|
|
39
|
+
include/gmock/gmock.h,sha256=pMzoMOhc6Ij0GwmOGzL9p0SyGtyX96ux7qLgcqJh-98,3723
|
|
40
|
+
include/gmock/internal/gmock-internal-utils.h,sha256=Af8yApQyClDoNCaK6u4WHBXWqakqAUMDPjzNSUIJdl4,19372
|
|
41
|
+
include/gmock/internal/gmock-port.h,sha256=NsmGCLIQGcPvmVpr4F1iDH-OfuWTNH8SOhZqoKN16c8,6070
|
|
42
|
+
include/gmock/internal/gmock-pp.h,sha256=X82tFwexcvgADZ9Bn0HUQxhVhgCwCRZ4VRbq5JhDu08,13491
|
|
43
|
+
include/gmock/internal/custom/README.md,sha256=Hs3AwbmmtM56lBHftQw7is7SqgPULmfuA3enogHV_2Q,510
|
|
44
|
+
include/gmock/internal/custom/gmock-generated-actions.h,sha256=jv0WBks-GdmHJqFfi8QNqlk1duShkLLouVpv7nJCw28,314
|
|
45
|
+
include/gmock/internal/custom/gmock-matchers.h,sha256=ttJF6V8GSahap-KUV_Q32kwvH7rbBALPxA9oAVneUQ8,1918
|
|
46
|
+
include/gmock/internal/custom/gmock-port.h,sha256=7izIcgLnV1nP2YpdZXxp7oZOSSosY1hFhpONqBq4SZU,1953
|
|
47
|
+
include/gtest/gtest-assertion-result.h,sha256=1lYuIsMW6DG_vCzeOxWPBjgKIufhxsHhgGiavuXFuXI,8503
|
|
48
|
+
include/gtest/gtest-death-test.h,sha256=jey7huu_oUL9eKg8--tMXnPpgXkFjOcPzCeZNcSXQpo,14910
|
|
49
|
+
include/gtest/gtest-matchers.h,sha256=1jfdGIlEQzxi2WoGL5sa2rhRV0xTfXAhJwx6UqJ1mpA,33067
|
|
50
|
+
include/gtest/gtest-message.h,sha256=8ce9TgwCJA6ITe7SWi4L_QTl4MP9d4o7Emy7ZFMfZac,9203
|
|
51
|
+
include/gtest/gtest-param-test.h,sha256=GttG4X5H_C9A3FuOms7E8B76OJoZu-ol0yrqKLlOMuY,24008
|
|
52
|
+
include/gtest/gtest-printers.h,sha256=8zlupV1XfuBPFaKxSxS3btuKhNOFyDHe_YjP-FNbwnM,40511
|
|
53
|
+
include/gtest/gtest-spi.h,sha256=_Au-uushG4Gi7D3ziOXl8lp8IukBhoOYVNLlsmziJuY,12843
|
|
54
|
+
include/gtest/gtest-test-part.h,sha256=Inm5v9CK_3wPdkonFr3g06YdwSVzaHos_5ElaxdoG_A,7164
|
|
55
|
+
include/gtest/gtest-typed-test.h,sha256=1WMTgwvzDWJx18H4ylfcUtlaELl-Ss5u-g8IWuUZMDo,15889
|
|
56
|
+
include/gtest/gtest.h,sha256=k9oD3fbVub30CuTe2ZOQZ8ntC23pP3h_fo0Ydgm2sC0,91459
|
|
57
|
+
include/gtest/gtest_pred_impl.h,sha256=hehQ5zWkLrtfmgGgGHCMHAubfYPJSxS31dKVEsALb_0,12783
|
|
58
|
+
include/gtest/gtest_prod.h,sha256=PGMB71M9uGhuR03VoN5NmKMcu2MOInP3EkctG-JaomE,2502
|
|
59
|
+
include/gtest/internal/gtest-death-test-internal.h,sha256=pw0RdO9mhjnHryF2REL45Iew_HDCN6cPkOMWGo6CYtY,13929
|
|
60
|
+
include/gtest/internal/gtest-filepath.h,sha256=VEzpXS4eS3rhfuFw9IKqoJ4X0AVpmcTOfnpgl8OnVc8,10339
|
|
61
|
+
include/gtest/internal/gtest-internal.h,sha256=ozgGyObKXrb4ObjgFb346uhIZBA1-UmYNPnUArgj1f4,63416
|
|
62
|
+
include/gtest/internal/gtest-param-util.h,sha256=7_obPmo1VKro_IL76IwcMhX3I7s-LkRL9CT2iMR2oDA,38172
|
|
63
|
+
include/gtest/internal/gtest-port-arch.h,sha256=N_bVxwMi7l9PhPr8tOji9Lvwilr8ZKZjbPap9F1EIZg,4305
|
|
64
|
+
include/gtest/internal/gtest-port.h,sha256=wi71yGDavD50Il86VMLXIkN1rS3Sr2GdP4y-fpF_x1Q,90033
|
|
65
|
+
include/gtest/internal/gtest-string.h,sha256=DMCMdGvOsrEBxh_7yQXFmOti_uPCYsRYXCGxDYo-ZQg,7323
|
|
66
|
+
include/gtest/internal/gtest-type-util.h,sha256=wc9TRjV5Alp7JUZuloCneNdL7_UtimS26D_LbdmeS7c,7349
|
|
67
|
+
include/gtest/internal/custom/README.md,sha256=YI7FrFdKbmTk_C9Lziz8f_dToE1oItb_luQ__1HGzME,1269
|
|
68
|
+
include/gtest/internal/custom/gtest-port.h,sha256=XgZ0fJ6LhunYQfq9YcLwRbK7ETNxbxJ75KljztHETgE,1873
|
|
69
|
+
include/gtest/internal/custom/gtest-printers.h,sha256=uVr9okJujE8JwR0yltUi-zNrJIwNp-B4OI20uwcsIWY,2094
|
|
70
|
+
include/gtest/internal/custom/gtest.h,sha256=IdIKHGTqOMIMSxIzfCYaGhiYnSowcQqD37XNmjuzxV4,1858
|
|
71
|
+
lib/libetb_core.a,sha256=FcEXBmw-5rIybCUM3X5gltBqpziR_qKuI_mZyaecHfE,613770
|
|
72
|
+
lib64/libgmock.a,sha256=OjOBFsYqA-uOZs6zufryp4BwA3J3FZB8CMhwbNDBocE,216152
|
|
73
|
+
lib64/libgmock_main.a,sha256=dc-xljvl9jiCr1Gt92-grIcqrzwNuKORJGPuuDOlciw,2302
|
|
74
|
+
lib64/libgtest.a,sha256=6y521XKJd1KsWpLraoHSkV9PYvMpSTH6rMMmM3cqZt0,924530
|
|
75
|
+
lib64/libgtest_main.a,sha256=0H094qb5NcuEpfxnShDkgq3nPhXBS8tVaUKHXRuFixQ,2310
|
|
76
|
+
lib64/cmake/GTest/GTestConfig.cmake,sha256=5MiTs-meYwnesdFVxLr9P6p8i-NDsIoMcGX37tDFUGw,1073
|
|
77
|
+
lib64/cmake/GTest/GTestConfigVersion.cmake,sha256=4KpyG_iigbXIsrdVrFEPNhReAGuPgZ-ztbSDepzcPm4,1862
|
|
78
|
+
lib64/cmake/GTest/GTestTargets-release.cmake,sha256=5qblhjj2_YHot0xkyD5lzsC8UWJtgAZy3g1SvzMRzR0,2276
|
|
79
|
+
lib64/cmake/GTest/GTestTargets.cmake,sha256=QII3nhQtDWavEIhikc2KiUzdZSat7zuUpiE9iZ-nun4,5418
|
|
80
|
+
lib64/pkgconfig/gmock.pc,sha256=diJMLCQN5FUXZLIyAxFtRLPEVkLAjWgVIuqT5wneQOM,322
|
|
81
|
+
lib64/pkgconfig/gmock_main.pc,sha256=rDMeLMh3n1B5dyiaDU0QMKKZ9OGx9YKrd7uFSxOsqUs,329
|
|
82
|
+
lib64/pkgconfig/gtest.pc,sha256=yOLxfIgh_apH26949y1SGz80vDDZ0-cGv1ymP3rfQmE,297
|
|
83
|
+
lib64/pkgconfig/gtest_main.pc,sha256=BDse7t3rKcuktqCq21d_91xU-XXRQThQ2U7rw1f0iLk,329
|
|
84
|
+
explodethosebits-0.3.0.dist-info/METADATA,sha256=mza30WHxCRBDGLoIKMoAQWM4yItz9cx8fxzLG772qh8,11444
|
|
85
|
+
explodethosebits-0.3.0.dist-info/WHEEL,sha256=177YrMfLRJpclnQFtuDXCuQvUj0IE4OiC0tN0TTOv_E,153
|
|
86
|
+
explodethosebits-0.3.0.dist-info/RECORD,,
|
|
87
|
+
explodethosebits-0.3.0.dist-info/licenses/LICENSE,sha256=9vYYUwkzSB_caEDeiotaG1xPudQwqs4j2NxEvKXQVw4,1063
|
|
88
|
+
explodethosebits-0.3.0.dist-info/sboms/auditwheel.cdx.json,sha256=lYP8BPF_X5hRPYYC66xbZTwlVNQTA95wVOEV1q2Rw7o,1496
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Odin G.
|
|
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.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"bomFormat": "CycloneDX", "specVersion": "1.4", "version": 1, "metadata": {"component": {"type": "library", "bom-ref": "pkg:pypi/explodethosebits@0.3.0?file_name=explodethosebits-0.3.0-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", "name": "explodethosebits", "version": "0.3.0", "purl": "pkg:pypi/explodethosebits@0.3.0?file_name=explodethosebits-0.3.0-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl"}, "tools": [{"name": "auditwheel", "version": "6.6.0"}]}, "components": [{"type": "library", "bom-ref": "pkg:pypi/explodethosebits@0.3.0?file_name=explodethosebits-0.3.0-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", "name": "explodethosebits", "version": "0.3.0", "purl": "pkg:pypi/explodethosebits@0.3.0?file_name=explodethosebits-0.3.0-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl"}, {"type": "library", "bom-ref": "pkg:rpm/almalinux/cuda-cudart-12-8@12.8.90-1#08ffa5b368f3fe6bbbd64a1e92f39f76564e25c38342c0a2e3b36431d519f50c", "name": "cuda-cudart-12-8", "version": "12.8.90-1", "purl": "pkg:rpm/almalinux/cuda-cudart-12-8@12.8.90-1"}], "dependencies": [{"ref": "pkg:pypi/explodethosebits@0.3.0?file_name=explodethosebits-0.3.0-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", "dependsOn": ["pkg:rpm/almalinux/cuda-cudart-12-8@12.8.90-1#08ffa5b368f3fe6bbbd64a1e92f39f76564e25c38342c0a2e3b36431d519f50c"]}, {"ref": "pkg:rpm/almalinux/cuda-cudart-12-8@12.8.90-1#08ffa5b368f3fe6bbbd64a1e92f39f76564e25c38342c0a2e3b36431d519f50c"}]}
|
|
Binary file
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#ifndef ETB_BIT_COORDINATE_HPP
|
|
2
|
+
#define ETB_BIT_COORDINATE_HPP
|
|
3
|
+
|
|
4
|
+
#include <cstdint>
|
|
5
|
+
|
|
6
|
+
namespace etb {
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Represents a coordinate in the bit extraction system.
|
|
10
|
+
* Maps each bit to (byte_index, bit_position) where bit_position is in range [0,7].
|
|
11
|
+
*/
|
|
12
|
+
struct BitCoordinate {
|
|
13
|
+
uint32_t byte_index; // Index into input byte array
|
|
14
|
+
uint8_t bit_position; // Position within byte [0-7], 0 = LSB
|
|
15
|
+
|
|
16
|
+
BitCoordinate() : byte_index(0), bit_position(0) {}
|
|
17
|
+
BitCoordinate(uint32_t byte_idx, uint8_t bit_pos)
|
|
18
|
+
: byte_index(byte_idx), bit_position(bit_pos) {}
|
|
19
|
+
|
|
20
|
+
// Comparison operators for ordering
|
|
21
|
+
bool operator<(const BitCoordinate& other) const {
|
|
22
|
+
return byte_index < other.byte_index;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
bool operator==(const BitCoordinate& other) const {
|
|
26
|
+
return byte_index == other.byte_index && bit_position == other.bit_position;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
bool operator!=(const BitCoordinate& other) const {
|
|
30
|
+
return !(*this == other);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Check if this coordinate is valid for a given input length.
|
|
35
|
+
* @param input_length Length of the input byte array
|
|
36
|
+
* @return true if coordinate is within bounds
|
|
37
|
+
*/
|
|
38
|
+
bool is_valid(uint32_t input_length) const {
|
|
39
|
+
return byte_index < input_length && bit_position <= 7;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
} // namespace etb
|
|
44
|
+
|
|
45
|
+
#endif // ETB_BIT_COORDINATE_HPP
|