uproot-custom 2.0.0.dev0__tar.gz → 2.1.1__tar.gz
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.
- {uproot_custom-2.0.0.dev0 → uproot_custom-2.1.1}/.github/workflows/build-wheels.yml +4 -4
- {uproot_custom-2.0.0.dev0 → uproot_custom-2.1.1}/.github/workflows/deploy-docs.yml +5 -5
- uproot_custom-2.1.1/.github/workflows/semantic-pr-titles.yml +19 -0
- uproot_custom-2.1.1/.github/workflows/test-package.yml +57 -0
- uproot_custom-2.1.1/.github/workflows/weekly-build.yml +10 -0
- {uproot_custom-2.0.0.dev0 → uproot_custom-2.1.1}/PKG-INFO +28 -24
- {uproot_custom-2.0.0.dev0 → uproot_custom-2.1.1}/README.md +25 -2
- {uproot_custom-2.0.0.dev0 → uproot_custom-2.1.1}/cpp/include/uproot-custom/uproot-custom.hh +220 -13
- {uproot_custom-2.0.0.dev0 → uproot_custom-2.1.1}/cpp/src/uproot-custom.cc +496 -62
- uproot_custom-2.1.1/docs/Doxyfile +2618 -0
- uproot_custom-2.1.1/docs/conf.py +151 -0
- {uproot_custom-2.0.0.dev0/docs/examples → uproot_custom-2.1.1/docs/example}/override-streamer.md +3 -3
- {uproot_custom-2.0.0.dev0/docs/examples → uproot_custom-2.1.1/docs/example}/read-tobjarray.md +4 -4
- {uproot_custom-2.0.0.dev0 → uproot_custom-2.1.1}/docs/index.md +34 -20
- uproot_custom-2.1.1/docs/reference/api/cpp-api.md +8 -0
- uproot_custom-2.1.1/docs/reference/api/cpp-module.md +6 -0
- uproot_custom-2.1.1/docs/reference/api/uproot-custom-ref.md +12 -0
- uproot_custom-2.1.1/docs/reference/api/uproot_custom.rst +37 -0
- uproot_custom-2.1.1/docs/reference/api.md +10 -0
- uproot_custom-2.1.1/docs/reference/version-requirements.md +23 -0
- {uproot_custom-2.0.0.dev0/docs/architecture → uproot_custom-2.1.1/docs/tutorial/customize-factory-reader}/binary-data.md +7 -6
- {uproot_custom-2.0.0.dev0/docs/architecture → uproot_custom-2.1.1/docs/tutorial/customize-factory-reader}/bootstrap.md +7 -7
- {uproot_custom-2.0.0.dev0/docs/architecture → uproot_custom-2.1.1/docs/tutorial/customize-factory-reader}/reader-and-factory.md +10 -10
- uproot_custom-2.1.1/docs/tutorial/customize-factory-reader/template-python-project.md +51 -0
- uproot_custom-2.1.1/docs/tutorial/customize-factory-reader.md +26 -0
- uproot_custom-2.0.0.dev0/docs/get-started.md → uproot_custom-2.1.1/docs/tutorial/use-built-in.md +4 -12
- {uproot_custom-2.0.0.dev0 → uproot_custom-2.1.1}/pyproject.toml +24 -24
- {uproot_custom-2.0.0.dev0/example/gen-demo-data → uproot_custom-2.1.1/tests/gen-test-data}/CMakeLists.txt +4 -7
- uproot_custom-2.1.1/tests/gen-test-data/README.md +24 -0
- {uproot_custom-2.0.0.dev0/example/gen-demo-data → uproot_custom-2.1.1/tests/gen-test-data}/include/LinkDef.h +0 -2
- {uproot_custom-2.0.0.dev0/example/gen-demo-data → uproot_custom-2.1.1/tests/gen-test-data}/include/TComplicatedSTL.hh +0 -1
- {uproot_custom-2.0.0.dev0/example/gen-demo-data → uproot_custom-2.1.1/tests/gen-test-data}/src/main.cc +2 -13
- uproot_custom-2.1.1/tests/test-data.root +0 -0
- {uproot_custom-2.0.0.dev0 → uproot_custom-2.1.1}/tests/test_AsCustom.py +29 -13
- {uproot_custom-2.0.0.dev0 → uproot_custom-2.1.1}/uproot_custom/AsCustom.py +26 -2
- uproot_custom-2.1.1/uproot_custom/__init__.py +27 -0
- {uproot_custom-2.0.0.dev0 → uproot_custom-2.1.1}/uproot_custom/_version.py +3 -3
- {uproot_custom-2.0.0.dev0 → uproot_custom-2.1.1}/uproot_custom/cpp.pyi +38 -36
- {uproot_custom-2.0.0.dev0 → uproot_custom-2.1.1}/uproot_custom/factories.py +17 -9
- {uproot_custom-2.0.0.dev0 → uproot_custom-2.1.1}/uproot_custom/utils.py +1 -1
- uproot_custom-2.1.1/uv.lock +1853 -0
- uproot_custom-2.0.0.dev0/.github/workflows/run-pytest.yml +0 -37
- uproot_custom-2.0.0.dev0/docs/conf.py +0 -65
- uproot_custom-2.0.0.dev0/example/README.md +0 -83
- uproot_custom-2.0.0.dev0/example/cpp/CMakeLists.txt +0 -31
- uproot_custom-2.0.0.dev0/example/cpp/my_reader.cc +0 -80
- uproot_custom-2.0.0.dev0/example/gen-demo-data/include/TObjInObjArray.hh +0 -114
- uproot_custom-2.0.0.dev0/example/gen-demo-data/include/TOverrideStreamer.hh +0 -16
- uproot_custom-2.0.0.dev0/example/gen-demo-data/src/TOverrideStreamer.cc +0 -34
- uproot_custom-2.0.0.dev0/example/my_reader/OverrideStreamerFactory.py +0 -46
- uproot_custom-2.0.0.dev0/example/my_reader/TObjArrayFactory.py +0 -76
- uproot_custom-2.0.0.dev0/example/my_reader/__init__.py +0 -12
- uproot_custom-2.0.0.dev0/example/my_reader/my_reader_cpp.pyi +0 -11
- uproot_custom-2.0.0.dev0/example/pyproject.toml +0 -21
- uproot_custom-2.0.0.dev0/example/read-dask.py +0 -19
- uproot_custom-2.0.0.dev0/example/read-data.py +0 -26
- uproot_custom-2.0.0.dev0/tests/test-data.root +0 -0
- uproot_custom-2.0.0.dev0/tests/test_AsGroupedMap.py +0 -35
- uproot_custom-2.0.0.dev0/tests/test_docs.py +0 -15
- uproot_custom-2.0.0.dev0/tests/test_downstream_build.py +0 -38
- uproot_custom-2.0.0.dev0/tests/test_downstream_build_pyproject.toml +0 -20
- uproot_custom-2.0.0.dev0/uproot_custom/AsBinary.py +0 -94
- uproot_custom-2.0.0.dev0/uproot_custom/AsGroupedMap.py +0 -44
- uproot_custom-2.0.0.dev0/uproot_custom/__init__.py +0 -58
- {uproot_custom-2.0.0.dev0 → uproot_custom-2.1.1}/.clang-format +0 -0
- {uproot_custom-2.0.0.dev0 → uproot_custom-2.1.1}/.github/workflows/python-publish.yml +0 -0
- {uproot_custom-2.0.0.dev0 → uproot_custom-2.1.1}/.gitignore +0 -0
- {uproot_custom-2.0.0.dev0 → uproot_custom-2.1.1}/CHANGELOG.md +0 -0
- {uproot_custom-2.0.0.dev0 → uproot_custom-2.1.1}/LICENSE +0 -0
- {uproot_custom-2.0.0.dev0 → uproot_custom-2.1.1}/cpp/CMakeLists.txt +0 -0
- {uproot_custom-2.0.0.dev0 → uproot_custom-2.1.1}/cpp/share/cmake/uproot-customConfig.cmake +0 -0
- {uproot_custom-2.0.0.dev0/docs → uproot_custom-2.1.1/docs/reference}/binary-format.md +0 -0
- {uproot_custom-2.0.0.dev0/docs/architecture → uproot_custom-2.1.1/docs/tutorial/customize-factory-reader}/streamer-info.md +0 -0
- {uproot_custom-2.0.0.dev0 → uproot_custom-2.1.1}/tests/conftest.py +0 -0
- {uproot_custom-2.0.0.dev0/example/gen-demo-data → uproot_custom-2.1.1/tests/gen-test-data}/include/TBasicTypes.hh +0 -0
- {uproot_custom-2.0.0.dev0/example/gen-demo-data → uproot_custom-2.1.1/tests/gen-test-data}/include/TCStyleArray.hh +0 -0
- {uproot_custom-2.0.0.dev0/example/gen-demo-data → uproot_custom-2.1.1/tests/gen-test-data}/include/TNestedSTL.hh +0 -0
- {uproot_custom-2.0.0.dev0/example/gen-demo-data → uproot_custom-2.1.1/tests/gen-test-data}/include/TRootObjects.hh +0 -0
- {uproot_custom-2.0.0.dev0/example/gen-demo-data → uproot_custom-2.1.1/tests/gen-test-data}/include/TSTLArray.hh +0 -0
- {uproot_custom-2.0.0.dev0/example/gen-demo-data → uproot_custom-2.1.1/tests/gen-test-data}/include/TSTLMap.hh +0 -0
- {uproot_custom-2.0.0.dev0/example/gen-demo-data → uproot_custom-2.1.1/tests/gen-test-data}/include/TSTLMapWithObj.hh +0 -0
- {uproot_custom-2.0.0.dev0/example/gen-demo-data → uproot_custom-2.1.1/tests/gen-test-data}/include/TSTLSeqWithObj.hh +0 -0
- {uproot_custom-2.0.0.dev0/example/gen-demo-data → uproot_custom-2.1.1/tests/gen-test-data}/include/TSTLSequence.hh +0 -0
- {uproot_custom-2.0.0.dev0/example/gen-demo-data → uproot_custom-2.1.1/tests/gen-test-data}/include/TSTLString.hh +0 -0
- {uproot_custom-2.0.0.dev0/example/gen-demo-data → uproot_custom-2.1.1/tests/gen-test-data}/include/TSimpleObject.hh +0 -0
- {uproot_custom-2.0.0.dev0 → uproot_custom-2.1.1}/uproot_custom/share/cmake/__init__.py +0 -0
|
@@ -5,11 +5,11 @@ on:
|
|
|
5
5
|
workflow_call:
|
|
6
6
|
|
|
7
7
|
jobs:
|
|
8
|
-
|
|
9
|
-
uses: ./.github/workflows/
|
|
8
|
+
test-package:
|
|
9
|
+
uses: ./.github/workflows/test-package.yml
|
|
10
10
|
|
|
11
11
|
build-wheels:
|
|
12
|
-
needs:
|
|
12
|
+
needs: test-package
|
|
13
13
|
runs-on: ${{ matrix.os }}
|
|
14
14
|
name: Build wheels on ${{ matrix.os }}
|
|
15
15
|
strategy:
|
|
@@ -29,7 +29,7 @@ jobs:
|
|
|
29
29
|
path: ./wheelhouse/*.whl
|
|
30
30
|
|
|
31
31
|
build-sdist:
|
|
32
|
-
needs:
|
|
32
|
+
needs: test-package
|
|
33
33
|
name: Build source distribution
|
|
34
34
|
runs-on: ubuntu-latest
|
|
35
35
|
steps:
|
|
@@ -13,15 +13,15 @@ jobs:
|
|
|
13
13
|
steps:
|
|
14
14
|
- uses: actions/checkout@v4
|
|
15
15
|
|
|
16
|
-
-
|
|
17
|
-
uses: actions/setup-python@v4
|
|
16
|
+
- uses: astral-sh/setup-uv@v5
|
|
18
17
|
with:
|
|
19
|
-
python-version:
|
|
18
|
+
python-version: "3.13"
|
|
20
19
|
|
|
21
20
|
- name: Install dependencies
|
|
22
21
|
run: |
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
sudo apt-get update
|
|
23
|
+
sudo apt-get install -y doxygen
|
|
24
|
+
uv sync --group=docs
|
|
25
25
|
|
|
26
26
|
- name: Build docs
|
|
27
27
|
run: |
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
name: 'Lint PR'
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request_target:
|
|
5
|
+
types:
|
|
6
|
+
- opened
|
|
7
|
+
- edited
|
|
8
|
+
- reopened
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
main:
|
|
12
|
+
name: Validate PR title
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
permissions:
|
|
15
|
+
pull-requests: read
|
|
16
|
+
steps:
|
|
17
|
+
- uses: amannn/action-semantic-pull-request@v6
|
|
18
|
+
env:
|
|
19
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
name: Test package
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
workflow_call:
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
test-package:
|
|
16
|
+
runs-on: ${{ matrix.os }}
|
|
17
|
+
strategy:
|
|
18
|
+
matrix:
|
|
19
|
+
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
|
|
20
|
+
os: ["ubuntu-latest", "macos-latest", "windows-latest"]
|
|
21
|
+
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@v4
|
|
24
|
+
|
|
25
|
+
- uses: astral-sh/setup-uv@v5
|
|
26
|
+
with:
|
|
27
|
+
python-version: ${{ matrix.python-version }}
|
|
28
|
+
|
|
29
|
+
- name: Install dependencies
|
|
30
|
+
run: |
|
|
31
|
+
uv lock --upgrade
|
|
32
|
+
uv sync --all-extras
|
|
33
|
+
|
|
34
|
+
- name: Run pytest
|
|
35
|
+
run: |
|
|
36
|
+
pytest --version
|
|
37
|
+
pytest -v tests/
|
|
38
|
+
|
|
39
|
+
test-build-docs:
|
|
40
|
+
runs-on: ubuntu-latest
|
|
41
|
+
steps:
|
|
42
|
+
- uses: actions/checkout@v4
|
|
43
|
+
|
|
44
|
+
- uses: astral-sh/setup-uv@v5
|
|
45
|
+
with:
|
|
46
|
+
python-version: "3.13"
|
|
47
|
+
|
|
48
|
+
- name: Install dependencies
|
|
49
|
+
run: |
|
|
50
|
+
sudo apt-get update
|
|
51
|
+
sudo apt-get install -y doxygen
|
|
52
|
+
uv lock --upgrade
|
|
53
|
+
uv sync --all-extras
|
|
54
|
+
|
|
55
|
+
- name: Build docs
|
|
56
|
+
run: |
|
|
57
|
+
sphinx-build -b html docs/ build/html
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: uproot-custom
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.1.1
|
|
4
4
|
Summary: uproot extension for reading custom classes
|
|
5
5
|
Author-Email: Mingrun Li <mrli@ihep.ac.cn>
|
|
6
6
|
Classifier: Development Status :: 3 - Alpha
|
|
@@ -27,28 +27,9 @@ Classifier: Topic :: Software Development
|
|
|
27
27
|
Classifier: Topic :: Utilities
|
|
28
28
|
Project-URL: Homepage, https://github.com/mrzimu/uproot-custom
|
|
29
29
|
Requires-Python: <3.14,>=3.9
|
|
30
|
-
Requires-Dist: uproot>=5.
|
|
30
|
+
Requires-Dist: uproot>=5.6.7
|
|
31
31
|
Requires-Dist: numpy
|
|
32
|
-
Requires-Dist: awkward
|
|
33
|
-
Provides-Extra: dev
|
|
34
|
-
Requires-Dist: pytest; extra == "dev"
|
|
35
|
-
Requires-Dist: pytest-xdist; extra == "dev"
|
|
36
|
-
Requires-Dist: dask[complete]; extra == "dev"
|
|
37
|
-
Requires-Dist: dask-awkward; extra == "dev"
|
|
38
|
-
Requires-Dist: build; extra == "dev"
|
|
39
|
-
Provides-Extra: docs
|
|
40
|
-
Requires-Dist: sphinx>=8.2; extra == "docs"
|
|
41
|
-
Requires-Dist: sphinx-book-theme; extra == "docs"
|
|
42
|
-
Requires-Dist: myst_parser; extra == "docs"
|
|
43
|
-
Requires-Dist: sphinx-design; extra == "docs"
|
|
44
|
-
Requires-Dist: sphinx-copybutton; extra == "docs"
|
|
45
|
-
Requires-Dist: sphinxext-rediraffe; extra == "docs"
|
|
46
|
-
Requires-Dist: sphinxext-opengraph; extra == "docs"
|
|
47
|
-
Requires-Dist: sphinx-tippy; extra == "docs"
|
|
48
|
-
Requires-Dist: sphinx-togglebutton; extra == "docs"
|
|
49
|
-
Requires-Dist: sphinxcontrib-mermaid; extra == "docs"
|
|
50
|
-
Requires-Dist: sphinx-autobuild; extra == "docs"
|
|
51
|
-
Requires-Dist: sphinx-intl; extra == "docs"
|
|
32
|
+
Requires-Dist: awkward>=2.8.0
|
|
52
33
|
Description-Content-Type: text/markdown
|
|
53
34
|
|
|
54
35
|
# Introduction
|
|
@@ -63,13 +44,36 @@ Description-Content-Type: text/markdown
|
|
|
63
44
|
|
|
64
45
|
`uproot-custom` uses a `reader`/`factory` mechanism to read classes:
|
|
65
46
|
|
|
47
|
+
```mermaid
|
|
48
|
+
flowchart TD
|
|
49
|
+
subgraph py["Python field"]
|
|
50
|
+
direction TB
|
|
51
|
+
AsCustom --> fac["Factory (Primitive, STLVector, TString, ...)"]
|
|
52
|
+
fac["Factory (Primitive, STLVector, TString, ...)"] -- Optional --> form(["construct awkward forms"])
|
|
53
|
+
fac --> build_reader(["build corresponding C++ reader"])
|
|
54
|
+
fac --> build_ak(["construct awkward arrays"])
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
user_fac["User's Factory"] -. Register .-> fac
|
|
58
|
+
|
|
59
|
+
subgraph cpp["C++ field"]
|
|
60
|
+
direction TB
|
|
61
|
+
build_reader --> reader["C++ Reader"]
|
|
62
|
+
reader --> read_bin(["read binary data"])
|
|
63
|
+
read_bin --> ret_data(["return data"])
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
ret_data --> raw_data[("tuple, list, numpy arrays, ...")]
|
|
67
|
+
raw_data --> build_ak
|
|
68
|
+
```
|
|
69
|
+
|
|
66
70
|
- `reader` is a C++ class that implements the logic to read data from binary buffers.
|
|
67
71
|
- `factory` is a Python class that creates, combines `reader`s, and post-processes the data read by `reader`s.
|
|
68
72
|
|
|
69
|
-
This machanism is implemented
|
|
73
|
+
This machanism is implemented basing on `uproot_custom.AsCustom` interpretation. This makes `uproot-custom` well compatible with `uproot`.
|
|
70
74
|
|
|
71
75
|
> [!TIP]
|
|
72
|
-
> Users can implement their own `factory` and `reader`, register them to `uproot-custom`. An example of implementing a custom `factory`/`reader` can be found in [the repository](https://github.com/mrzimu/uproot-custom
|
|
76
|
+
> Users can implement their own `factory` and `reader`, register them to `uproot-custom`. An example of implementing a custom `factory`/`reader` can be found in [the example repository](https://github.com/mrzimu/uproot-custom-example).
|
|
73
77
|
|
|
74
78
|
> [!NOTE]
|
|
75
79
|
> `uproot-custom` does not provide a full reimplementation of `ROOT`'s I/O system. Users are expected to implement their own `factory`/`reader` for their custom classes that built-in factories cannot handle.
|
|
@@ -10,13 +10,36 @@
|
|
|
10
10
|
|
|
11
11
|
`uproot-custom` uses a `reader`/`factory` mechanism to read classes:
|
|
12
12
|
|
|
13
|
+
```mermaid
|
|
14
|
+
flowchart TD
|
|
15
|
+
subgraph py["Python field"]
|
|
16
|
+
direction TB
|
|
17
|
+
AsCustom --> fac["Factory (Primitive, STLVector, TString, ...)"]
|
|
18
|
+
fac["Factory (Primitive, STLVector, TString, ...)"] -- Optional --> form(["construct awkward forms"])
|
|
19
|
+
fac --> build_reader(["build corresponding C++ reader"])
|
|
20
|
+
fac --> build_ak(["construct awkward arrays"])
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
user_fac["User's Factory"] -. Register .-> fac
|
|
24
|
+
|
|
25
|
+
subgraph cpp["C++ field"]
|
|
26
|
+
direction TB
|
|
27
|
+
build_reader --> reader["C++ Reader"]
|
|
28
|
+
reader --> read_bin(["read binary data"])
|
|
29
|
+
read_bin --> ret_data(["return data"])
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
ret_data --> raw_data[("tuple, list, numpy arrays, ...")]
|
|
33
|
+
raw_data --> build_ak
|
|
34
|
+
```
|
|
35
|
+
|
|
13
36
|
- `reader` is a C++ class that implements the logic to read data from binary buffers.
|
|
14
37
|
- `factory` is a Python class that creates, combines `reader`s, and post-processes the data read by `reader`s.
|
|
15
38
|
|
|
16
|
-
This machanism is implemented
|
|
39
|
+
This machanism is implemented basing on `uproot_custom.AsCustom` interpretation. This makes `uproot-custom` well compatible with `uproot`.
|
|
17
40
|
|
|
18
41
|
> [!TIP]
|
|
19
|
-
> Users can implement their own `factory` and `reader`, register them to `uproot-custom`. An example of implementing a custom `factory`/`reader` can be found in [the repository](https://github.com/mrzimu/uproot-custom
|
|
42
|
+
> Users can implement their own `factory` and `reader`, register them to `uproot-custom`. An example of implementing a custom `factory`/`reader` can be found in [the example repository](https://github.com/mrzimu/uproot-custom-example).
|
|
20
43
|
|
|
21
44
|
> [!NOTE]
|
|
22
45
|
> `uproot-custom` does not provide a full reimplementation of `ROOT`'s I/O system. Users are expected to implement their own `factory`/`reader` for their custom classes that built-in factories cannot handle.
|
|
@@ -26,6 +26,10 @@
|
|
|
26
26
|
# error "Unsupported compiler!"
|
|
27
27
|
#endif
|
|
28
28
|
|
|
29
|
+
/**
|
|
30
|
+
* @brief Macro to import the uproot_custom.cpp module.
|
|
31
|
+
* @note This macro should be used in the `PYBIND11_MODULE` definition of your module.
|
|
32
|
+
*/
|
|
29
33
|
#define IMPORT_UPROOT_CUSTOM_CPP pybind11::module_::import( "uproot_custom.cpp" );
|
|
30
34
|
|
|
31
35
|
namespace uproot {
|
|
@@ -59,12 +63,23 @@ namespace uproot {
|
|
|
59
63
|
<< 13 ///< if object ctor succeeded but object should not be used
|
|
60
64
|
};
|
|
61
65
|
|
|
66
|
+
/**
|
|
67
|
+
* @brief Construct a BinaryBuffer from numpy arrays.
|
|
68
|
+
* @param data A numpy array of uint8_t containing the raw data.
|
|
69
|
+
* @param offsets A numpy array of uint32_t containing the offsets for each entry.
|
|
70
|
+
*/
|
|
62
71
|
BinaryBuffer( py::array_t<uint8_t> data, py::array_t<uint32_t> offsets )
|
|
63
72
|
: m_data( static_cast<uint8_t*>( data.request().ptr ) )
|
|
64
73
|
, m_offsets( static_cast<uint32_t*>( offsets.request().ptr ) )
|
|
65
74
|
, m_entries( offsets.request().size - 1 )
|
|
66
75
|
, m_cursor( static_cast<uint8_t*>( data.request().ptr ) ) {}
|
|
67
76
|
|
|
77
|
+
/**
|
|
78
|
+
* @brief Read a value of type T from the buffer, handling endianness.
|
|
79
|
+
*
|
|
80
|
+
* @tparam T The type to read.
|
|
81
|
+
* @return The value read from the buffer.
|
|
82
|
+
*/
|
|
68
83
|
template <typename T>
|
|
69
84
|
const T read() {
|
|
70
85
|
constexpr auto size = sizeof( T );
|
|
@@ -107,8 +122,19 @@ namespace uproot {
|
|
|
107
122
|
}
|
|
108
123
|
}
|
|
109
124
|
|
|
125
|
+
/**
|
|
126
|
+
* @brief Read the fVersion field from the buffer
|
|
127
|
+
*
|
|
128
|
+
* @return The fVersion value
|
|
129
|
+
*/
|
|
110
130
|
const int16_t read_fVersion() { return read<int16_t>(); }
|
|
111
131
|
|
|
132
|
+
/**
|
|
133
|
+
* @brief Read the fNBytes field from the buffer, checking the byte count mask.
|
|
134
|
+
*
|
|
135
|
+
* @return The fNBytes value without the mask.
|
|
136
|
+
* @exception std::runtime_error if the byte count mask is not set.
|
|
137
|
+
*/
|
|
112
138
|
const uint32_t read_fNBytes() {
|
|
113
139
|
auto byte_count = read<uint32_t>();
|
|
114
140
|
if ( !( byte_count & kByteCountMask ) )
|
|
@@ -116,6 +142,11 @@ namespace uproot {
|
|
|
116
142
|
return byte_count & ~kByteCountMask;
|
|
117
143
|
}
|
|
118
144
|
|
|
145
|
+
/**
|
|
146
|
+
* @brief Read a null-terminated (`\0`) string from the buffer.
|
|
147
|
+
*
|
|
148
|
+
* @return The string read from the buffer.
|
|
149
|
+
*/
|
|
119
150
|
const std::string read_null_terminated_string() {
|
|
120
151
|
auto start = m_cursor;
|
|
121
152
|
while ( *m_cursor != 0 ) { m_cursor++; }
|
|
@@ -123,6 +154,14 @@ namespace uproot {
|
|
|
123
154
|
return std::string( start, m_cursor );
|
|
124
155
|
}
|
|
125
156
|
|
|
157
|
+
/**
|
|
158
|
+
* @brief Read an object header from the buffer. The object header has `fNBytes`,
|
|
159
|
+
* `fVersion`, `fTag`. If `fTag == kNewClassTag`, then a null-terminated class name
|
|
160
|
+
* follows.
|
|
161
|
+
*
|
|
162
|
+
* @return The class name if the object is a new class, empty string
|
|
163
|
+
* otherwise.
|
|
164
|
+
*/
|
|
126
165
|
const std::string read_obj_header() {
|
|
127
166
|
read_fNBytes();
|
|
128
167
|
auto fTag = read<uint32_t>();
|
|
@@ -130,6 +169,13 @@ namespace uproot {
|
|
|
130
169
|
else return std::string();
|
|
131
170
|
}
|
|
132
171
|
|
|
172
|
+
/**
|
|
173
|
+
* @brief Read a TString from the buffer. A TString has `length` (uint8_t). If `length
|
|
174
|
+
* == 255`, then the `length` is a following uint32_t. Then following `length` bytes of
|
|
175
|
+
* string data.
|
|
176
|
+
*
|
|
177
|
+
* @return The TString data read from the buffer, as a std::string.
|
|
178
|
+
*/
|
|
133
179
|
const std::string read_TString() {
|
|
134
180
|
uint32_t length = read<uint8_t>();
|
|
135
181
|
if ( length == 255 ) length = read<uint32_t>();
|
|
@@ -138,21 +184,48 @@ namespace uproot {
|
|
|
138
184
|
return std::string( start, m_cursor );
|
|
139
185
|
}
|
|
140
186
|
|
|
187
|
+
/**
|
|
188
|
+
* @brief Skip `n` bytes in the buffer.
|
|
189
|
+
*
|
|
190
|
+
* @param n Number of bytes to skip.
|
|
191
|
+
*/
|
|
141
192
|
void skip( const size_t n ) { m_cursor += n; }
|
|
142
193
|
|
|
143
|
-
|
|
194
|
+
/**
|
|
195
|
+
* @brief Skip the fNBytes field. Equivalent to read_fNBytes() but does not return the
|
|
196
|
+
* value, since the mask need to be checked.
|
|
197
|
+
*/
|
|
198
|
+
void skip_fNBytes() { read_fNBytes(); }
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* @brief Skip the fVersion field.
|
|
202
|
+
*/
|
|
144
203
|
void skip_fVersion() { skip( 2 ); }
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* @brief Skip a null-terminated (`\0`) string in the buffer.
|
|
207
|
+
*/
|
|
145
208
|
void skip_null_terminated_string() {
|
|
146
209
|
while ( *m_cursor != 0 ) { m_cursor++; }
|
|
147
210
|
m_cursor++;
|
|
148
211
|
}
|
|
149
212
|
|
|
213
|
+
/**
|
|
214
|
+
* @brief Skip an object header in the buffer. The object header has `fNBytes`,
|
|
215
|
+
* `fVersion`, `fTag`. If `fTag == kNewClassTag`, then a null-terminated class name
|
|
216
|
+
* follows.
|
|
217
|
+
*/
|
|
150
218
|
void skip_obj_header() {
|
|
151
219
|
skip_fNBytes();
|
|
152
220
|
auto fTag = read<uint32_t>();
|
|
153
221
|
if ( fTag == kNewClassTag ) skip_null_terminated_string();
|
|
154
222
|
}
|
|
155
223
|
|
|
224
|
+
/**
|
|
225
|
+
* @brief Skip a TObject in the buffer. A TObject has `fVersion` (2 bytes), `fUniqueID`
|
|
226
|
+
* (4 bytes), `fBits` (4 bytes). If `fBits & kIsReferenced`, then a `pidf` (2 bytes)
|
|
227
|
+
* follows.
|
|
228
|
+
*/
|
|
156
229
|
void skip_TObject() {
|
|
157
230
|
// TODO: CanIgnoreTObjectStreamer() ?
|
|
158
231
|
skip_fVersion();
|
|
@@ -161,21 +234,41 @@ namespace uproot {
|
|
|
161
234
|
if ( fBits & ( kIsReferenced ) ) skip( 2 ); // pidf
|
|
162
235
|
}
|
|
163
236
|
|
|
237
|
+
/**
|
|
238
|
+
* @brief Get the raw data pointer.
|
|
239
|
+
*/
|
|
164
240
|
const uint8_t* get_data() const { return m_data; }
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* @brief Get the current cursor pointer.
|
|
244
|
+
*/
|
|
165
245
|
const uint8_t* get_cursor() const { return m_cursor; }
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* @brief Get the entry offsets array pointer.
|
|
249
|
+
*/
|
|
166
250
|
const uint32_t* get_offsets() const { return m_offsets; }
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* @brief Get the number of entries.
|
|
254
|
+
*/
|
|
167
255
|
const uint64_t entries() const { return m_entries; }
|
|
168
256
|
|
|
257
|
+
/**
|
|
258
|
+
* @brief Debug print the next `n` bytes from the current cursor.
|
|
259
|
+
*
|
|
260
|
+
* @param n Number of bytes to print.
|
|
261
|
+
*/
|
|
169
262
|
void debug_print( const size_t n = 100 ) const {
|
|
170
263
|
for ( size_t i = 0; i < n; i++ ) { std::cout << (int)*( m_cursor + i ) << " "; }
|
|
171
264
|
std::cout << std::endl;
|
|
172
265
|
}
|
|
173
266
|
|
|
174
267
|
private:
|
|
175
|
-
uint8_t* m_cursor;
|
|
176
|
-
const uint64_t m_entries;
|
|
177
|
-
const uint8_t* m_data;
|
|
178
|
-
const uint32_t* m_offsets;
|
|
268
|
+
uint8_t* m_cursor; ///< current cursor position
|
|
269
|
+
const uint64_t m_entries; ///< number of entries
|
|
270
|
+
const uint8_t* m_data; ///< raw data pointer
|
|
271
|
+
const uint32_t* m_offsets; ///< entry offsets pointer
|
|
179
272
|
};
|
|
180
273
|
|
|
181
274
|
/*
|
|
@@ -184,24 +277,74 @@ namespace uproot {
|
|
|
184
277
|
-----------------------------------------------------------------------------
|
|
185
278
|
*/
|
|
186
279
|
|
|
187
|
-
|
|
280
|
+
/**
|
|
281
|
+
* @brief Interface for element readers. All element readers must inherit from this class.
|
|
282
|
+
*/
|
|
283
|
+
class IReader {
|
|
188
284
|
protected:
|
|
189
|
-
const std::string m_name;
|
|
285
|
+
const std::string m_name; ///< name of the reader
|
|
190
286
|
|
|
191
287
|
public:
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
288
|
+
/**
|
|
289
|
+
* @brief Construct a new IReader object.
|
|
290
|
+
*
|
|
291
|
+
* @param name Name of the reader.
|
|
292
|
+
*/
|
|
293
|
+
IReader( std::string name ) : m_name( name ) {}
|
|
294
|
+
|
|
295
|
+
virtual ~IReader() = default;
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* @brief Get the name of the reader.
|
|
299
|
+
*
|
|
300
|
+
* @return Name of the reader.
|
|
301
|
+
*/
|
|
195
302
|
virtual const std::string name() const { return m_name; }
|
|
196
303
|
|
|
304
|
+
/**
|
|
305
|
+
* @brief Read an element from the buffer.
|
|
306
|
+
*
|
|
307
|
+
* @param buffer The binary buffer to read from.
|
|
308
|
+
*/
|
|
197
309
|
virtual void read( BinaryBuffer& buffer ) = 0;
|
|
198
|
-
virtual py::object data() const = 0;
|
|
199
310
|
|
|
311
|
+
/**
|
|
312
|
+
* @brief Get the data read by the reader. This should be called after the whole
|
|
313
|
+
* reading process.
|
|
314
|
+
*
|
|
315
|
+
* @return The data read by the reader.
|
|
316
|
+
*/
|
|
317
|
+
virtual py::object data() const = 0;
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* @brief Read multiple elements from the buffer in one go. Repeatedly calls @ref
|
|
321
|
+
* read() by default.
|
|
322
|
+
*
|
|
323
|
+
* @note When multiple elements are stored together, some classes may have "one common
|
|
324
|
+
* header + multiple data objects" format. This method can be overridden to handle such
|
|
325
|
+
* cases more efficiently.
|
|
326
|
+
*
|
|
327
|
+
* @param buffer The binary buffer to read from.
|
|
328
|
+
* @param count Number of elements to read.
|
|
329
|
+
* @return Number of elements read.
|
|
330
|
+
*/
|
|
200
331
|
virtual uint32_t read_many( BinaryBuffer& buffer, const int64_t count ) {
|
|
201
332
|
for ( int32_t i = 0; i < count; i++ ) { read( buffer ); }
|
|
202
333
|
return count;
|
|
203
334
|
}
|
|
204
335
|
|
|
336
|
+
/**
|
|
337
|
+
* @brief Read elements from the buffer until reaching the end position. Repeatedly
|
|
338
|
+
* calls @ref read() method by default.
|
|
339
|
+
*
|
|
340
|
+
* @note When multiple elements are stored together, some classes may have "one common
|
|
341
|
+
* header + multiple data objects" format. This method can be overridden to handle such
|
|
342
|
+
* cases more efficiently.
|
|
343
|
+
*
|
|
344
|
+
* @param buffer The binary buffer to read from.
|
|
345
|
+
* @param end_pos The end position pointer.
|
|
346
|
+
* @return Number of elements read.
|
|
347
|
+
*/
|
|
205
348
|
virtual uint32_t read_until( BinaryBuffer& buffer, const uint8_t* end_pos ) {
|
|
206
349
|
uint32_t cur_count = 0;
|
|
207
350
|
while ( buffer.get_cursor() < end_pos )
|
|
@@ -212,6 +355,15 @@ namespace uproot {
|
|
|
212
355
|
return cur_count;
|
|
213
356
|
}
|
|
214
357
|
|
|
358
|
+
/**
|
|
359
|
+
* @brief Read multiple elements from the buffer in member-wise fashion. This method
|
|
360
|
+
* checks for negative count and calls @ref read_many() by default. It can be
|
|
361
|
+
* overridden to handle member-wise reading more efficiently.
|
|
362
|
+
*
|
|
363
|
+
* @param buffer The binary buffer to read from.
|
|
364
|
+
* @param count Number of elements to read.
|
|
365
|
+
* @return Number of elements read.
|
|
366
|
+
*/
|
|
215
367
|
virtual uint32_t read_many_memberwise( BinaryBuffer& buffer, const int64_t count ) {
|
|
216
368
|
if ( count < 0 )
|
|
217
369
|
{
|
|
@@ -223,7 +375,19 @@ namespace uproot {
|
|
|
223
375
|
}
|
|
224
376
|
};
|
|
225
377
|
|
|
226
|
-
|
|
378
|
+
/**
|
|
379
|
+
* @brief Deprecated alias for IReader.
|
|
380
|
+
* @deprecated Use IReader instead.
|
|
381
|
+
*/
|
|
382
|
+
using IElementReader
|
|
383
|
+
[[deprecated( "IElementReader is deprecated. Use IReader instead." )]] = IReader;
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* @brief Shortcut for shared pointer to IReader.
|
|
387
|
+
* @note When a reader requires another reader as a member, it must use
|
|
388
|
+
* `std::shared_ptr<IReader>` to properly handle lifetime management.
|
|
389
|
+
*/
|
|
390
|
+
using SharedReader = shared_ptr<IReader>;
|
|
227
391
|
|
|
228
392
|
/*
|
|
229
393
|
-----------------------------------------------------------------------------
|
|
@@ -231,14 +395,33 @@ namespace uproot {
|
|
|
231
395
|
-----------------------------------------------------------------------------
|
|
232
396
|
*/
|
|
233
397
|
|
|
398
|
+
/**
|
|
399
|
+
* @brief Helper function to create a shared pointer to a reader. Pybind11 requires
|
|
400
|
+
* shared_ptr to handle object lifetime correctly.
|
|
401
|
+
*
|
|
402
|
+
* @tparam ReaderType The type of the reader.
|
|
403
|
+
* @tparam Args The argument types for the reader constructor.
|
|
404
|
+
* @param args The arguments for the reader constructor.
|
|
405
|
+
* @return The shared pointer to the created reader.
|
|
406
|
+
*/
|
|
234
407
|
template <typename ReaderType, typename... Args>
|
|
235
408
|
shared_ptr<ReaderType> CreateReader( Args... args ) {
|
|
236
409
|
return std::make_shared<ReaderType>( std::forward<Args>( args )... );
|
|
237
410
|
}
|
|
238
411
|
|
|
412
|
+
/**
|
|
413
|
+
* @brief Helper function to declare a reader class in a pybind11 module. Automatically
|
|
414
|
+
* wraps the class' constructor to return a shared_ptr. User should always use this
|
|
415
|
+
* function to declare reader classes.
|
|
416
|
+
*
|
|
417
|
+
* @tparam ReaderType The type of the reader.
|
|
418
|
+
* @tparam Args The argument types for the reader constructor.
|
|
419
|
+
* @param m The declaring pybind11 module.
|
|
420
|
+
* @param name The name of the reader class in Python.
|
|
421
|
+
*/
|
|
239
422
|
template <typename ReaderType, typename... Args>
|
|
240
423
|
void declare_reader( py::module& m, const char* name ) {
|
|
241
|
-
py::class_<ReaderType, shared_ptr<ReaderType>,
|
|
424
|
+
py::class_<ReaderType, shared_ptr<ReaderType>, IReader>( m, name ).def(
|
|
242
425
|
py::init( &CreateReader<ReaderType, Args...> ) );
|
|
243
426
|
}
|
|
244
427
|
|
|
@@ -248,6 +431,14 @@ namespace uproot {
|
|
|
248
431
|
-----------------------------------------------------------------------------
|
|
249
432
|
*/
|
|
250
433
|
|
|
434
|
+
/**
|
|
435
|
+
* @brief Convert a shared pointer to a std::vector<T> to a numpy array without copying.
|
|
436
|
+
* User can use this function to return numpy arrays from reader's data() method.
|
|
437
|
+
*
|
|
438
|
+
* @tparam T The element type of the vector.
|
|
439
|
+
* @param seq The shared pointer to the std::vector<T>.
|
|
440
|
+
* @return The numpy array wrapping the vector data.
|
|
441
|
+
*/
|
|
251
442
|
template <typename T>
|
|
252
443
|
inline py::array_t<T> make_array( shared_ptr<std::vector<T>> seq ) {
|
|
253
444
|
auto size = seq->size();
|
|
@@ -266,6 +457,14 @@ namespace uproot {
|
|
|
266
457
|
-----------------------------------------------------------------------------
|
|
267
458
|
*/
|
|
268
459
|
|
|
460
|
+
/**
|
|
461
|
+
* @brief Debug print function. Prints only when macro or environment varialbe with name
|
|
462
|
+
* `UPROOT_DEBUG` is defined. Use this function like `printf()`.
|
|
463
|
+
*
|
|
464
|
+
* @tparam Args Argument types. No need to specify explicitly.
|
|
465
|
+
* @param msg The format string.
|
|
466
|
+
* @param args Arguments to format.
|
|
467
|
+
*/
|
|
269
468
|
template <typename... Args>
|
|
270
469
|
inline void debug_printf( const char* msg, Args... args ) {
|
|
271
470
|
bool do_print = getenv( "UPROOT_DEBUG" );
|
|
@@ -276,6 +475,14 @@ namespace uproot {
|
|
|
276
475
|
printf( msg, std::forward<Args>( args )... );
|
|
277
476
|
}
|
|
278
477
|
|
|
478
|
+
/**
|
|
479
|
+
* @brief Debug print function for BinaryBuffer. Prints only when macro or environment
|
|
480
|
+
* varialbe with name `UPROOT_DEBUG` is defined. Call @ref BinaryBuffer::debug_print()
|
|
481
|
+
* internally.
|
|
482
|
+
*
|
|
483
|
+
* @param buffer The BinaryBuffer to print.
|
|
484
|
+
* @param n Number of bytes to print.
|
|
485
|
+
*/
|
|
279
486
|
inline void debug_printf( uproot::BinaryBuffer& buffer, const size_t n = 100 ) {
|
|
280
487
|
bool do_print = getenv( "UPROOT_DEBUG" );
|
|
281
488
|
#ifdef UPROOT_DEBUG
|