From e6b2906b7befb8aa5b1d8f559099d5b36630718a Mon Sep 17 00:00:00 2001 From: Jim Pivarski Date: Fri, 13 Dec 2019 13:59:33 -0600 Subject: [PATCH] Replace DressedType with parameters on all the Types. (#32) * duplicate test_PR019 to create pull request in github * correct PR number, update test a bit * oops, forgot the files * [WIP] Replace DressedType with parameters on all the Types. * unhappy with booleans * Attach Parameters to all Types. * Added parameters to all Type constructors except UnionType and RecordType: need to change their signatures to accomodate. * All Type constructors can accept 'parameters'. * Updated Pickle getstate/setstate to pass on 'parameters'. * Parameters are persistent properties of all non-dressed types. * Type::equal can check parameters as part of equality, but Content::accepts still works. * Remove Type::shallow_equal, which was only ever used in Content::accepts. * Type parameters pass through Numba. * Switched RecordType field name quoting to double quotes. * Dress types using a user-controllable namespace, without DressedType. * Implemented the '__class__' and '__str__' parameters. * Replace all raw pointers 'Fillable*' with smart 'std::shared_ptr'. * Removed the old DressedType completely (commented out). * Removed the old DressedType completely (deleted). * [skip ci] Fillable::beginrecord with name; Numba doesn't work yet. * [skip ci] FillableArray.beginrecord works in Numba. * Record names declared in FillableArray are now attached as a Type parameter. * Various clean-ups: parameters_FIXME and Fillable Type::none() FIXMEs. * [skip ci] FillableArray::type doesn't require a snapshot, but baretype does. (Get rid of FillableArray::type? It's redundant because you can always take a snapshot.) * [skip ci] Working on adding Fillable*::string, but it doesn't compile yet. * Fillable*::string compiles and works in Python. * Fix Python-side bugs. * Strings can be written out with 'tojson'. * Fix Python 2.7. * Fix Python 2.7 some more. * Tested fromiter and fromjson for strings. Everything works. Done with this PR. * Updating README. * Updating README. * Updating README. * Updating README. * Updating README. * Updating README. * Updating README. * Updating README. * Updating README. * Updating README. * Updating README. * Updating README. * Updating README. * Updating README. * Updating README. * Updating README. * Updating README. * Updating README. * Updating README. * Updating README. * Updating README. --- CMakeLists.txt | 1 + QUICKSTART.md | 26 + README.md | 140 +- VERSION_INFO | 2 +- awkward1/__init__.py | 3 + awkward1/_numba/fillable.py | 6 +- awkward1/_numba/libawkward.py | 18 +- awkward1/_numba/types.py | 199 ++- awkward1/_numba/util.py | 9 +- awkward1/_util.py | 7 +- awkward1/behavior/string.py | 32 +- awkward1/highlevel.py | 151 +- awkward1/operations/convert.py | 12 +- docs/img/awkward-0-popularity.pdf | Bin 0 -> 52113 bytes docs/img/awkward-0-popularity.png | Bin 0 -> 146109 bytes docs/img/awkward-0-popularity.svg | 1373 +++++++++++++++++++ docs/img/awkward-1-0-layers.pdf | Bin 14227 -> 14222 bytes docs/img/awkward-1-0-layers.png | Bin 103741 -> 109520 bytes docs/img/awkward-1-0-layers.svg | 578 ++++---- docs/img/logo-300px.png | Bin 0 -> 13084 bytes docs/img/logo-600px.png | Bin 0 -> 26635 bytes docs/img/logo.svg | 152 ++ include/awkward/array/NumpyArray.h | 1 + include/awkward/array/RawArray.h | 44 +- include/awkward/fillable/BoolFillable.h | 31 +- include/awkward/fillable/Fillable.h | 35 +- include/awkward/fillable/FillableArray.h | 36 +- include/awkward/fillable/Float64Fillable.h | 43 +- include/awkward/fillable/Int64Fillable.h | 31 +- include/awkward/fillable/ListFillable.h | 37 +- include/awkward/fillable/OptionFillable.h | 42 +- include/awkward/fillable/RecordFillable.h | 48 +- include/awkward/fillable/StringFillable.h | 49 + include/awkward/fillable/TupleFillable.h | 33 +- include/awkward/fillable/UnionFillable.h | 34 +- include/awkward/fillable/UnknownFillable.h | 31 +- include/awkward/io/json.h | 42 +- include/awkward/type/ArrayType.h | 8 +- include/awkward/type/DressedType.h | 115 -- include/awkward/type/ListType.h | 7 +- include/awkward/type/OptionType.h | 7 +- include/awkward/type/PrimitiveType.h | 7 +- include/awkward/type/RecordType.h | 13 +- include/awkward/type/RegularType.h | 8 +- include/awkward/type/Type.h | 39 +- include/awkward/type/UnionType.h | 5 +- include/awkward/type/UnknownType.h | 5 +- src/libawkward/Content.cpp | 6 +- src/libawkward/array/EmptyArray.cpp | 7 +- src/libawkward/array/ListArray.cpp | 9 +- src/libawkward/array/ListOffsetArray.cpp | 9 +- src/libawkward/array/NumpyArray.cpp | 160 ++- src/libawkward/array/Record.cpp | 6 +- src/libawkward/array/RecordArray.cpp | 10 +- src/libawkward/array/RegularArray.cpp | 16 +- src/libawkward/fillable/BoolFillable.cpp | 113 +- src/libawkward/fillable/FillableArray.cpp | 115 +- src/libawkward/fillable/Float64Fillable.cpp | 114 +- src/libawkward/fillable/Int64Fillable.cpp | 115 +- src/libawkward/fillable/ListFillable.cpp | 156 +-- src/libawkward/fillable/OptionFillable.cpp | 100 +- src/libawkward/fillable/RecordFillable.cpp | 231 ++-- src/libawkward/fillable/StringFillable.cpp | 154 +++ src/libawkward/fillable/TupleFillable.cpp | 177 +-- src/libawkward/fillable/UnionFillable.cpp | 189 +-- src/libawkward/fillable/UnknownFillable.cpp | 111 +- src/libawkward/io/json.cpp | 9 +- src/libawkward/io/root.cpp | 4 +- src/libawkward/type/ArrayType.cpp | 18 +- src/libawkward/type/ListType.cpp | 28 +- src/libawkward/type/OptionType.cpp | 34 +- src/libawkward/type/PrimitiveType.cpp | 26 +- src/libawkward/type/RecordType.cpp | 103 +- src/libawkward/type/RegularType.cpp | 31 +- src/libawkward/type/Type.cpp | 55 + src/libawkward/type/UnionType.cpp | 32 +- src/libawkward/type/UnknownType.cpp | 26 +- src/pyawkward.cpp | 362 +++-- tests/test_PR018_fromiter_fillable.py | 2 +- tests/test_PR025_record_array.py | 32 +- tests/test_PR028_add_dressed_types.py | 47 +- tests/test_PR030_recordarray_in_numba.cpp | 48 + tests/test_PR031_types_in_numba.py | 26 +- tests/test_PR032_replace_dressedtype.py | 231 ++++ 84 files changed, 4287 insertions(+), 2085 deletions(-) create mode 100644 QUICKSTART.md create mode 100644 docs/img/awkward-0-popularity.pdf create mode 100644 docs/img/awkward-0-popularity.png create mode 100644 docs/img/awkward-0-popularity.svg create mode 100644 docs/img/logo-300px.png create mode 100644 docs/img/logo-600px.png create mode 100644 docs/img/logo.svg create mode 100644 include/awkward/fillable/StringFillable.h delete mode 100644 include/awkward/type/DressedType.h create mode 100644 src/libawkward/fillable/StringFillable.cpp create mode 100644 tests/test_PR030_recordarray_in_numba.cpp create mode 100644 tests/test_PR032_replace_dressedtype.py diff --git a/CMakeLists.txt b/CMakeLists.txt index 851f460fe9..35b3f8b46b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,6 +55,7 @@ set_target_properties(awkward-static PROPERTIES CXX_VISIBILITY_PRESET hidden) set_target_properties(awkward PROPERTIES CXX_VISIBILITY_PRESET hidden) addtest(PR016 tests/test_PR016_finish_getitem_for_rawarray.cpp) addtest(PR019 tests/test_PR019_use_json_library.cpp) +addtest(PR030 tests/test_PR030_recordarray_in_numba.cpp) pybind11_add_module(layout src/pyawkward.cpp) set_target_properties(layout PROPERTIES CXX_VISIBILITY_PRESET hidden) diff --git a/QUICKSTART.md b/QUICKSTART.md new file mode 100644 index 0000000000..15982b57b0 --- /dev/null +++ b/QUICKSTART.md @@ -0,0 +1,26 @@ +# Awkward 1.0 + +### Dependencies +- cmake +- gcc +- g++ +- pytest + + +### Setup +- Clone the repo: + `git clone --recursive https://github.com/scikit-hep/awkward-1.0.git` + +- Build awkward: + `python setup.py build` + +- Test build: + `pytest -vv tests` + + +### Contribution +- Branch off, create a pull request - PR# used to name new tests +- Clean build dir with: + - rm -rf **/*~ **/__pycache__ build dist *.egg-info awkward1/*.so **/*.pyc + - Do this whenever: + - CMakeLists.txt changes (cpp tests must be manually included, follow existing format) diff --git a/README.md b/README.md index bc4ccb0237..b13d31ff84 100644 --- a/README.md +++ b/README.md @@ -1,54 +1,128 @@ + + # awkward-1.0 -Development of awkward 1.0, to replace [scikit-hep/awkward-array](https://github.com/scikit-hep/awkward-array) in 2020. +Development of Awkward 1.0, to replace [scikit-hep/awkward-array](https://github.com/scikit-hep/awkward-array#readme) in 2020. + + * The [original motivations document](https://docs.google.com/document/d/1lj8ARTKV1_hqGTh0W_f01S6SsmpzZAXz9qqqWnEB3j4/edit?usp=sharing) from July 2019, now a little out-of-date. + * My [PyHEP talk](https://indico.cern.ch/event/833895/contributions/3577882) on October 17, 2019. + * My [CHEP talk](https://indico.cern.ch/event/773049/contributions/3473258) on November 7, 2019. + +## Motivation for a new Awkward Array - * [Motivation and requirements](https://docs.google.com/document/d/1lj8ARTKV1_hqGTh0W_f01S6SsmpzZAXz9qqqWnEB3j4/edit?usp=sharing) as a Google Doc (for comments). +Awkward Array has proven to be a useful way to analyze variable-length and tree-like data in Python, by extending Numpy's idioms from rectilinear arrays to arrays of complex data structures. For over a year, physicists have been using Awkward Array both in and out of [uproot](https://github.com/scikit-hep/uproot#readme); it is already one of the most popular Python packages in particle physics. -## Short summary +

-Awkward-array has proven to be a useful way to analyze variable-length and tree-like data in Python, by extending Numpy's idioms from flat arrays to arrays of data structures. Unlike previous iterations of this idea ([Femtocode](https://github.com/diana-hep/femtocode), [OAMap](https://github.com/diana-hep/oamap)), awkward-array is used in data analysis, with feedback from users. +However, its pure-NumPy implementation is hard to extend (finding for-loop-free implementations of operations on nested data is _hard_) and maintain (most bugs are NumPy corner cases). Also, the feedback users have given me through [GitHub](https://github.com/scikit-hep/awkward-array/issues), [StackOverflow](https://stackoverflow.com/questions/tagged/awkward-array), and [in-person tutorials](https://github.com/jpivarski/2019-07-29-dpf-python#readme) have pointed out some design mistakes. A backward-incompatible release will allow us to fix design mistakes while providing freedom to make deep changes in the implementation. -The original awkward-array is written in pure Python + Numpy, and it incorporates some clever tricks to do nested structure manipulations with only Numpy calls (e.g. Jaydeep Nandi's [cross-join](https://gitlab.com/Jayd_1234/GSoC_vectorized_proof_of_concepts/blob/master/argproduct.md) and [self-join without replacement](https://gitlab.com/Jayd_1234/GSoC_vectorized_proof_of_concepts/blob/master/argpairs.md), Nick Smith's [N choose k for k < 5](https://github.com/scikit-hep/awkward-array/pull/102), Jonas Rembser's [JaggedArray concatenation for axis=1](https://github.com/scikit-hep/awkward-array/pull/117), and my [deep JaggedArray get-item](https://github.com/scikit-hep/awkward-array/blob/423ca484e17fb0d0b3938e2ec0a0dcd8ef26c735/awkward/array/jagged.py#L597-L775)). However, cleverness is hard to scale: JaggedArray get-item raises `NotImplementedError` for some triply nested or deeper cases. Also, most bugs reported by users have been related to Numpy special cases, such as Numpy's raising an error for the min or max of an empty array. And finally, these implementations make multiple passes over the data, whereas a straightforward implementation (where we're allowed to use for loops, because it's compiled code) would be single-pass and therefore more cache-friendly. +The Awkward 1.0 project is a major investment, a six-month sprint from late August 2019 to late February 2020. The time spent on a clean, robust Awkward Array is justified by the widespread adoption of Awkward 0.x: its usefulness to the community has been demonstrated. -Awkward-array 1.0 will be rewritten in C++ using simple, single-pass algorithms, and exposed to Python through pybind11 and Numba. It will consist of four layers: +## Main goals of Awkward 1.0 - 1. A single `Array` class in Python that can be lowered in Numba, representing a sequence of abstract objects according to a high-level [datashape](https://datashape.readthedocs.io/en/latest/). - 2. Its columnar implementation in terms of nested `ListArray`, `RecordArray`, `MaskedArray`, etc., exposed to Python through pybind11. The modularity of this "layout" is very useful for engineering, but it has some features that have tripped up users, such as different physical arrays representing the same logical objects. - 3. Memory management of this layout in C++ classes, and again as [Numba extensions](https://numba.pydata.org/numba-doc/dev/extending/index.html). As a side-effect, `libawkward.so` would be a library for creating and manipulating awkward-arrays purely in C++, with no pybind11 dependencies. - 4. Implementations of the actual algorithms for (a) CPUs and (b) GPUs. This layer performs no memory management (arrays must be allocated and owned by the caller), but they perform all loops over data, reading old arrays, filling new arrays. + * Full access to create and manipulate Awkward Arrays in C++ with no Python dependencies. This is so that C++ libraries can produce and share data with Python front-ends. + * Easy installation with `pip install` and `conda install` for most users (Mac, Windows, and [most Linux](https://github.com/pypa/manylinux)). + * Imperative (for-loop-style) access to Awkward Arrays in [Numba](https://numba.pydata.org/), a just-in-time compiler for Python. This is so that physicists can write critical loops in straightforward Python without a performance penalty. + * A single `awkward.Array` class that hides the details of how columnar data is built, with a suite of operations that apply to all internal types. + * Conformance to NumPy, where Awkward and NumPy overlap. + * Better control over "behavioral mix-ins," such as `LorentzVector` (i.e. adding methods like `pt()` to arrays of records with `px` and `py` fields). In Awkward 0.x, this was achieved with multiple inheritance, but that was brittle. + * Support for set operations and database-style joins, which can be put to use in a [declarative analysis language](https://github.com/jpivarski/PartiQL#readme), but requires database-style accounting of an index (like a Pandas index). + * Better interoperability with Pandas, NumExpr, and Dask, while maintaining support for ROOT, Arrow, and Parquet. + * Ability to add GPU implementations of array operations in the future. + * Better error messages and extensive documentation. -Below is a diagram of how each component uses those at a lower level of abstraction: +## Architecture of Awkward 1.0 + +To achieve these goals, Awkward 1.0 is separated into four layers: + + 1. The user-facing Python layer with a single `awkward.Array` class, whose data is described by a [datashape](https://datashape.readthedocs.io/en/latest/) type. + 2. The columnar representation (i.e. nested `ListArray`, `RecordArray`, etc.) is accessible but hidden, and these are all C++ classes presented to Python through [pybind11](https://pybind11.readthedocs.io/en/stable/). + 3. Two object models for the columnar representation, one in C++11 (with only header-only dependencies) and the other as [Numba extensions](https://numba.pydata.org/numba-doc/dev/extending/index.html). This is the only layer in which array-allocation occurs. + 4. A suite of operations on arrays, computing new values but not allocating memory. The first implementation of this suite is in C++ with a pure-C interface; the second may be CUDA (or other GPU language). With one exception (`FillableArray`), iterations over arrays only occur at this level, so performance optimizations can focus on this layer.

-Layer 4 is a dynamically linked library named `{lib,}awkward-cpu-kernels.{so,dylib,dll}` with an unmangled C FFI interface. The layer 3 C++ library is `{lib,}awkward.{so,dylib,dll}` and layer 3 Numba extensions are in the `numbaext` submodule of the `awkward1` Python library. Layer 2 is the `layout` submodule, linked via pybind11, and layer 1 is the Python code in `awkward1`. +## The Awkward transition + +Since Awkward 1.0 is not backward-compatible, existing users of Awkward 0.x will need to update their scripts or only use the new version on new scripts. Awkward 1.0 is already available to early adopters as [awkward1 in pip](https://pypi.org/project/awkward1/) (`pip install awkward1` and `import awkward1` in Python). When [uproot](https://github.com/scikit-hep/uproot#readme) is ready to use the new Awkward Array, + + * it will be released as **uproot 4.0**, + * **awkward1** will be renamed **awkward**, and + * the old Awkward 0.x will be renamed **awkward0**. + +The original Awkward 0.x will be available in perpetuity as **awkward0**, but only minor bugs will be fixed, and that only for the duration of 2020. This repository will replace [scikit-hep/awkward-array](https://github.com/scikit-hep/awkward-array#readme) on GitHub. + +## Compiling from source + +Awkward 1.0 is available to early adopters as [awkward1 in pip](https://pypi.org/project/awkward1/) (`pip install awkward1` and `import awkward1` in Python), but developers will need to compile from source. For that, you will need + + * [CMake/CTest](https://cmake.org/), + * a C++11-compliant compiler, -The original `awkward` library will continue to be maintained while `awkward1` is in development, and the two will be swapped, becoming `awkward0` and `awkward`, respectively, in a gradual deprecation process in 2020. [Uproot 3.x](https://github.com/scikit-hep/uproot) will continue to depend on `awkward0`, but uproot 4.x will make the new `awkward` an optional but highly recommended dependency. Many users are only directly aware of uproot, so a major change in version from 3 to 4 will alert them to changes in interface. +and optionally -## What will not change + * Python 2.7, 3.5, 3.6, 3.7, or 3.8 (CPython, not an alternative like PyPy), + * NumPy 1.13.1 or later, + * pytest 3.9 or later (to run tests), + * Numba 0.46 or later (to run all the tests). -The following features of awkward 0.x will be features of awkward 1.x. +To get the code from GitHub, be sure to use `--recursive` to get Awkward's git-module dependencies (pybind11 and RapidJSON): - * The efficient, columnar data representation built out of "layout" classes, such as `ListArray` (`JaggedArray`), `RecordArray` (`Table`), and `MaskedArray` (same name). This was the key idea in the transition from OAMap to awkward-array, and it has paid off. If anything, we will be increasing the composability, with a larger number of classes that take on smaller roles (e.g. separate `ListArray` from `ListOffsetArray` for the starts/stops vs offsets cases). - * Numpy-like interface: awkward 1.x will be more consistent with Numpy's API, not less. - * Interoperability with ROOT, Arrow, Parquet and Pandas, as well as planned interoperability with Numba and Dask. - * The goals of zero-copy and shallow manipulations, such as slicing an array of objects without necessarily loading all of their attributes. - * The ability to attach domain-specific methods to arrays, such as Lorentz transformations for arrays of Lorentz vectors. - * `VirtualArrays`, and therefore lazy-loading, will be supported. +```bash +git clone --recursive https://github.com/scikit-hep/awkward-1.0.git +``` -## What will change +To compile _without Python_ (unusual case): - * Awkward 0.x's single specification, many implementations model: awkward 1.x will have at most two implementations of each algorithm, one for CPUs and one for GPUs. All the goals of precompiled kernels, Numba interface, Pandas interoperability, etc. will be accomplished through the four-layer system described above instead of completely separate implementations. Each of the four layers will be fully specified by documentation, though. - * Native access to the layout in C++ and the ability to develop an implementation in any language that supports C FFI (i.e. all of them). - * Data analysts will see a single `Array` class that hides details about the layout. This is an API-breaking change for data analysis scripts, but one that would help new users. - * All manipulations of this `Array` class will be through functions in the `awkward` namespace, such as `awkward.cross(a, b)` instead of `a.cross(b)` to mean a cross-join of `a` and `b` per element. The namespace on the arrays is therefore free for data fields like `a.x`, `a.y`, `a.z` and domain-specific methods like `a.cross(b)` meaning 3-D cross product. This is an API-breaking change for data analysis scripts, but one that would help new users. - * Arrays will pass through optional Pandas-style indexes for high-level operations [like these](https://github.com/jpivarski/PartiQL#readme). +```bash +mkdir build +cd build +cmake .. +make all +make CTEST_OUTPUT_ON_FAILURE=1 test # optional: run C++ tests +cd .. +``` + +To compile _with Python_ (the usual case): + +```bash +python setup.py build +pytest -vv tests # optional: run Python tests +``` + +In lieu of "make clean" for Python builds, I use the following to remove compiled code from the source tree: + +```bash +rm -rf **/*~ **/__pycache__ build dist *.egg-info awkward1/*.so **/*.pyc +``` + +
+

See Azure Pipelines buildtest-awkward (CI) and deploy-awkward (CD).

+
## Roadmap -The rough estimate for development time to a minimally usable library for physics was six months, starting in late August (i.e. finishing in late February). **Progress is currently on track.** +**The six-month sprint:** + + * [X] **September 2019:** Set up CI/CD; define jagged array types in C++; pervasive infrastructure like database-style indexing. + * [X] **October 2019:** NumPy-compliant slicing; the Numba implementation. Feature parity will be maintained in Numba continuously. + * [X] **November 2019:** Fillable arrays to create columnar data; high-level type objects; all list and record types. + * [ ] **December 2019:** The `awkward.Array` user interface; behavioral mix-ins, including the string type; [NEP 13](https://www.numpy.org/neps/nep-0013-ufunc-overrides.html) and [NEP 18](https://www.numpy.org/neps/nep-0018-array-function-protocol.html). + * [ ] **January 2020:** The rest of the array nodes: option and union types, indirection, chunking, and laziness. + * [ ] **February 2020:** The array operations: flattening, padding, concatenating, combinatorics, etc. + +**Updating dependent libraries:** + + * [ ] **March 2020:** Update [vector](https://github.com/scikit-hep/vector) (from [hepvector](https://github.com/henryiii/hepvector#readme) and [uproot-methods](https://github.com/scikit-hep/uproot-methods#readme)). This work will be done with [Henry Schreiner](https://github.com/henryiii). + * [ ] **April 2020:** Update [uproot](https://github.com/scikit-hep/uproot#readme) to 4.0 using Awkward 1.0. + +Most users will see Awkward 1.0 for the first time when uproot 4.0 is released. + +
+

Progress is currently on track.

+
-### Approximate order of implementation +### Checklist of features for the six-month sprint Completed items are ☑check-marked. See [closed PRs](https://github.com/scikit-hep/awkward-1.0/pulls?q=is%3Apr+is%3Aclosed) for more details. @@ -75,9 +149,9 @@ Completed items are ☑check-marked. See [closed PRs](https://github.com/scikit- * [X] `RegularArray`: for building rectilinear, N-dimensional arrays of arbitrary contents, e.g. putting jagged dimensions inside fixed dimensions. * [X] `RecordArray`: the new `Table` _without_ lazy-slicing. * [X] Implement it in Numba as well. - * [ ] `MaskedArray`, `BitMaskedArray`, `IndexedMaskedArray`: same as the old versions. + * [ ] `OptionArray`: for nullable data, covering both bit and byte granularity (old `MaskedArray` and `BitMaskedArray`). * [ ] `UnionArray`: same as the old version; `SparseUnionArray`: the additional case found in Apache Arrow. - * [ ] `IndexedArray`: same as the old version. + * [ ] `IndexedArray`: same as the old version, but allowing negative values to be `None`; hence, it has option type and fills the role of `IndexedMaskedArray`. * [ ] `RedirectArray`: an explicit weak-reference to another part of the structure (no hard-linked cycles). Often used with an `IndexedArray`. * [ ] `SlicedArray`: lazy-slicing (from old `Table`) that can be applied to any type. * [ ] `SparseArray`: same as the old version. @@ -118,7 +192,7 @@ Completed items are ☑check-marked. See [closed PRs](https://github.com/scikit- * [ ] `awkward.join`: performs an inner join of multiple arrays; requires `Identity`. Because the `Identity` is a surrogate index, this is effectively a per-event intersection, zipping all fields. * [ ] `awkward.union`: performs an outer join of multiple arrays; requires `Identity`. Because the `Identity` is a surrogate index, this is effectively a per-event union, zipping fields where possible. -### Soon after (possibly within) the six-month timeframe +### Soon after the six-month sprint * [ ] Update [hepvector](https://github.com/henryiii/hepvector#readme) to be Derived classes, replacing the `TLorentzVectorArray` in uproot-methods. * [ ] Update uproot (on a branch) to use Awkward 1.0. @@ -128,7 +202,7 @@ Completed items are ☑check-marked. See [closed PRs](https://github.com/scikit- * [ ] Universal `array.get[...]` as a softer form of `array[...]` that inserts `None` for non-existent indexes, rather than raising errors. * [ ] Explicit interface with [NumExpr](https://numexpr.readthedocs.io/en/latest/index.html). -### At some point in the future +### Thereafter * [ ] Demonstrate Awkward 1.0 as a C++ wrapping library with [FastJet](http://fastjet.fr/). * [ ] GPU implementations of the cpu-kernels in Layer 4, with the Layer 3 C++ passing a "device" variable at every level of the layout to indicate whether the data pointers refer to main memory or a particular GPU. diff --git a/VERSION_INFO b/VERSION_INFO index db7a480479..28d0075395 100644 --- a/VERSION_INFO +++ b/VERSION_INFO @@ -1 +1 @@ -0.1.31 +0.1.32 diff --git a/awkward1/__init__.py b/awkward1/__init__.py index 6e14fe6de5..225c666f78 100644 --- a/awkward1/__init__.py +++ b/awkward1/__init__.py @@ -1,10 +1,13 @@ # BSD 3-Clause License; see https://github.com/jpivarski/awkward-1.0/blob/master/LICENSE +namespace = {} + import awkward1.layout import awkward1._numba import awkward1.highlevel from awkward1.highlevel import Array from awkward1.highlevel import Record +from awkward1.highlevel import FillableArray from awkward1.operations.convert import * from awkward1.operations.describe import * diff --git a/awkward1/_numba/fillable.py b/awkward1/_numba/fillable.py index 2760692b2a..75b473c208 100644 --- a/awkward1/_numba/fillable.py +++ b/awkward1/_numba/fillable.py @@ -258,7 +258,7 @@ def lower_beginrecord(context, builder, sig, args): tpe, = sig.args val, = args proxyin = numba.cgutils.create_struct_proxy(tpe)(context, builder, value=val) - call(context, builder, libawkward.FillableArray_beginrecord, (proxyin.rawptr, context.get_constant(numba.int64, 0))) + call(context, builder, libawkward.FillableArray_beginrecord, (proxyin.rawptr,)) return context.get_dummy_value() @numba.extending.lower_builtin("beginrecord", FillableArrayType, numba.types.StringLiteral) @@ -266,8 +266,8 @@ def lower_beginrecord(context, builder, sig, args): tpe, nametpe = sig.args val, nameval = args proxyin = numba.cgutils.create_struct_proxy(tpe)(context, builder, value=val) - name = util.globalstring(context, builder, nametpe.literal_value, inttype=numba.int64) - call(context, builder, libawkward.FillableArray_beginrecord, (proxyin.rawptr, name)) + name = util.globalstring(context, builder, nametpe.literal_value) + call(context, builder, libawkward.FillableArray_beginrecord_fast, (proxyin.rawptr, name)) return context.get_dummy_value() @numba.extending.lower_builtin("field", FillableArrayType, numba.types.StringLiteral) diff --git a/awkward1/_numba/libawkward.py b/awkward1/_numba/libawkward.py index 73b4bb0b5c..1aae40a1fd 100644 --- a/awkward1/_numba/libawkward.py +++ b/awkward1/_numba/libawkward.py @@ -95,13 +95,27 @@ FillableArray_endtuple.restype = ctypes.c_uint8 FillableArray_endtuple.numbatpe = numba.typing.ctypes_utils.make_function_type(FillableArray_endtuple) -# uint8_t awkward_FillableArray_beginrecord(void* fillablearray, int64_t disambiguator); +# uint8_t awkward_FillableArray_beginrecord(void* fillablearray); FillableArray_beginrecord = lib.awkward_FillableArray_beginrecord FillableArray_beginrecord.name = "FillableArray.beginrecord" -FillableArray_beginrecord.argtypes = [ctypes.c_voidp, ctypes.c_int64] +FillableArray_beginrecord.argtypes = [ctypes.c_voidp] FillableArray_beginrecord.restype = ctypes.c_uint8 FillableArray_beginrecord.numbatpe = numba.typing.ctypes_utils.make_function_type(FillableArray_beginrecord) +# uint8_t awkward_FillableArray_beginrecord_fast(void* fillablearray, const char* name); +FillableArray_beginrecord_fast = lib.awkward_FillableArray_beginrecord_fast +FillableArray_beginrecord_fast.name = "FillableArray.beginrecord_fast" +FillableArray_beginrecord_fast.argtypes = [ctypes.c_voidp, ctypes.c_voidp] +FillableArray_beginrecord_fast.restype = ctypes.c_uint8 +FillableArray_beginrecord_fast.numbatpe = numba.typing.ctypes_utils.make_function_type(FillableArray_beginrecord_fast) + +# uint8_t awkward_FillableArray_beginrecord_check(void* fillablearray, const char* name); +FillableArray_beginrecord_check = lib.awkward_FillableArray_beginrecord_check +FillableArray_beginrecord_check.name = "FillableArray.beginrecord_check" +FillableArray_beginrecord_check.argtypes = [ctypes.c_voidp, ctypes.c_voidp] +FillableArray_beginrecord_check.restype = ctypes.c_uint8 +FillableArray_beginrecord_check.numbatpe = numba.typing.ctypes_utils.make_function_type(FillableArray_beginrecord_check) + # uint8_t awkward_FillableArray_field_fast(void* fillablearray, const char* key); FillableArray_field_fast = lib.awkward_FillableArray_field_fast FillableArray_field_fast.name = "FillableArray.field_fast" diff --git a/awkward1/_numba/types.py b/awkward1/_numba/types.py index 7082046aaf..f51d504abe 100644 --- a/awkward1/_numba/types.py +++ b/awkward1/_numba/types.py @@ -1,5 +1,7 @@ # BSD 3-Clause License; see https://github.com/jpivarski/awkward-1.0/blob/master/LICENSE +import json + import numba import awkward1.layout @@ -36,80 +38,76 @@ def typeof_ArrayType(val, c): @numba.extending.typeof_impl.register(awkward1.layout.UnknownType) def typeof_UnknownType(val, c): - return UnknownTypeType() + return UnknownTypeType(val.parameters) @numba.extending.typeof_impl.register(awkward1.layout.PrimitiveType) def typeof_PrimitiveType(val, c): - return PrimitiveTypeType(val.dtype) + return PrimitiveTypeType(val.dtype, val.parameters) @numba.extending.typeof_impl.register(awkward1.layout.RegularType) def typeof_RegularType(val, c): - return RegularTypeType(numba.typeof(val.type)) + return RegularTypeType(numba.typeof(val.type), val.parameters) @numba.extending.typeof_impl.register(awkward1.layout.ListType) def typeof_ListType(val, c): - return ListTypeType(numba.typeof(val.type)) + return ListTypeType(numba.typeof(val.type), val.parameters) @numba.extending.typeof_impl.register(awkward1.layout.OptionType) def typeof_OptionType(val, c): - return OptionTypeType(numba.typeof(val.type)) + return OptionTypeType(numba.typeof(val.type), val.parameters) @numba.extending.typeof_impl.register(awkward1.layout.UnionType) def typeof_UnionType(val, c): - return UnionTypeType([numba.typeof(x) for x in val.types]) + return UnionTypeType([numba.typeof(x) for x in val.types], val.parameters) @numba.extending.typeof_impl.register(awkward1.layout.RecordType) def typeof_RecordType(val, c): - return RecordTypeType([numba.typeof(x) for x in val.types], val.lookup, val.reverselookup) - -@numba.extending.typeof_impl.register(awkward1.layout.DressedType) -def typeof_DressedType(val, c): - return DressedTypeType(numba.typeof(val.type), val.dress, val.parameters) + return RecordTypeType([numba.typeof(x) for x in val.types], val.lookup, val.reverselookup, val.parameters) class TypeType(numba.types.Type): pass class UnknownTypeType(TypeType): - def __init__(self): - super(UnknownTypeType, self).__init__(name="ak::UnknownTypeType()") + def __init__(self, parameters): + super(UnknownTypeType, self).__init__(name="ak::UnknownTypeType(parameters={0})".format(json.dumps(parameters))) + self.parameters = parameters class PrimitiveTypeType(TypeType): - def __init__(self, dtype): - super(PrimitiveTypeType, self).__init__(name="ak::PrimitiveTypeType({0})".format(dtype)) + def __init__(self, dtype, parameters): + super(PrimitiveTypeType, self).__init__(name="ak::PrimitiveTypeType({0}, parameters={1})".format(dtype, json.dumps(parameters))) self.dtype = dtype + self.parameters = parameters class RegularTypeType(TypeType): - def __init__(self, typetpe): - super(RegularTypeType, self).__init__(name="ak::RegularTypeType({0})".format(typetpe.name)) + def __init__(self, typetpe, parameters): + super(RegularTypeType, self).__init__(name="ak::RegularTypeType({0}, parameters={1})".format(typetpe.name, json.dumps(parameters))) self.typetpe = typetpe + self.parameters = parameters class ListTypeType(TypeType): - def __init__(self, typetpe): - super(ListTypeType, self).__init__(name="ak::ListTypeType({0})".format(typetpe.name)) + def __init__(self, typetpe, parameters): + super(ListTypeType, self).__init__(name="ak::ListTypeType({0}, parameters={1})".format(typetpe.name, json.dumps(parameters))) self.typetpe = typetpe + self.parameters = parameters class OptionTypeType(TypeType): - def __init__(self, typetpe): - super(OptionTypeType, self).__init__(name="ak::OptionTypeType({0})".format(typetpe.name)) + def __init__(self, typetpe, parameters): + super(OptionTypeType, self).__init__(name="ak::OptionTypeType({0}, parameters={1})".format(typetpe.name, json.dumps(parameters))) self.typetpe = typetpe + self.parameters = parameters class UnionTypeType(TypeType): - def __init__(self, typetpes): - super(UnionTypeType, self).__init__(name="ak::UnionTypeType([{0}])".format(", ".join(x.name for x in typetpes))) + def __init__(self, typetpes, parameters): + super(UnionTypeType, self).__init__(name="ak::UnionTypeType([{0}], parameters={1})".format(", ".join(x.name for x in typetpes), json.dumps(parameters))) self.typetpes = typetpes + self.parameters = parameters class RecordTypeType(TypeType): - def __init__(self, typetpes, lookup, reverselookup): - super(RecordTypeType, self).__init__(name="ak::RecordTypeType([{0}], {1}, {2})".format(", ".join(x.name for x in typetpes), repr(lookup), repr(reverselookup))) + def __init__(self, typetpes, lookup, reverselookup, parameters): + super(RecordTypeType, self).__init__(name="ak::RecordTypeType([{0}], {1}, {2}, parameters={3})".format(", ".join(x.name for x in typetpes), repr(lookup), repr(reverselookup), json.dumps(parameters))) self.typetpes = typetpes self.lookup = lookup self.reverselookup = reverselookup - -class DressedTypeType(TypeType): - def __init__(self, typetpe, dress, parameters): - super(DressedTypeType, self).__init__(name="ak::DressedTypeType({0}, {1}, {2})".format(typetpe.name, repr(dress), repr(parameters))) - self.typetpe = typetpe - self.dress = dress self.parameters = parameters @numba.extending.register_model(UnknownTypeType) @@ -129,18 +127,24 @@ def __init__(self, dmm, fe_type): ("size", numba.int64)] super(RegularTypeModel, self).__init__(dmm, fe_type, members) +numba.extending.make_attribute_wrapper(RegularTypeType, "type", "type") + @numba.extending.register_model(ListTypeType) class ListTypeModel(numba.datamodel.models.StructModel): def __init__(self, dmm, fe_type): members = [("type", fe_type.typetpe)] super(ListTypeModel, self).__init__(dmm, fe_type, members) +numba.extending.make_attribute_wrapper(ListTypeType, "type", "type") + @numba.extending.register_model(OptionTypeType) class OptionTypeModel(numba.datamodel.models.StructModel): def __init__(self, dmm, fe_type): members = [("type", fe_type.typetpe)] super(OptionTypeModel, self).__init__(dmm, fe_type, members) +numba.extending.make_attribute_wrapper(OptionTypeType, "type", "type") + def field(i): return "f" + str(i) @@ -160,12 +164,6 @@ def __init__(self, dmm, fe_type): members.append((field(i), tpe)) super(RecordTypeModel, self).__init__(dmm, fe_type, members) -@numba.extending.register_model(DressedTypeType) -class DressedTypeModel(numba.datamodel.models.StructModel): - def __init__(self, dmm, fe_type): - members = [("type", fe_type.typetpe)] - super(DressedTypeModel, self).__init__(dmm, fe_type, members) - @numba.extending.unbox(UnknownTypeType) def unbox_UnknownType(tpe, obj, c): proxyout = numba.cgutils.create_struct_proxy(tpe)(c.context, c.builder) @@ -236,27 +234,21 @@ def unbox_RecordType(tpe, obj, c): is_error = numba.cgutils.is_not_null(c.builder, c.pyapi.err_occurred()) return numba.extending.NativeValue(proxyout._getvalue(), is_error) -@numba.extending.unbox(DressedTypeType) -def unbox_DressedType(tpe, obj, c): - proxyout = numba.cgutils.create_struct_proxy(tpe)(c.context, c.builder) - type_obj = c.pyapi.object_getattr_string(obj, "type") - - proxyout.type = c.pyapi.to_native_value(tpe.typetpe, type_obj).value - c.pyapi.decref(type_obj) - is_error = numba.cgutils.is_not_null(c.builder, c.pyapi.err_occurred()) - return numba.extending.NativeValue(proxyout._getvalue(), is_error) - @numba.extending.box(UnknownTypeType) def box_UnknownType(tpe, val, c): - proxyin = numba.cgutils.create_struct_proxy(tpe)(c.context, c.builder, value=val) - class_obj = c.pyapi.unserialize(c.pyapi.serialize_object(awkward1.layout.UnknownType)) - out = c.pyapi.call_function_objargs(class_obj, ()) - c.pyapi.decref(class_obj) - return out + return c.pyapi.unserialize(c.pyapi.serialize_object(awkward1.layout.UnknownType(tpe.parameters))) @numba.extending.box(PrimitiveTypeType) def box_PrimitiveType(tpe, val, c): - return c.pyapi.unserialize(c.pyapi.serialize_object(awkward1.layout.PrimitiveType(tpe.dtype))) + return c.pyapi.unserialize(c.pyapi.serialize_object(awkward1.layout.PrimitiveType(tpe.dtype, tpe.parameters))) + +def box_parameters(parameters, c): + jsonloads_obj = c.pyapi.unserialize(c.pyapi.serialize_object(json.loads)) + paramstr_obj = c.pyapi.unserialize(c.pyapi.serialize_object(json.dumps(parameters))) + param_obj = c.pyapi.call_function_objargs(jsonloads_obj, (paramstr_obj,)) + c.pyapi.decref(jsonloads_obj) + c.pyapi.decref(paramstr_obj) + return param_obj @numba.extending.box(RegularTypeType) def box_RegularType(tpe, val, c): @@ -264,10 +256,12 @@ def box_RegularType(tpe, val, c): class_obj = c.pyapi.unserialize(c.pyapi.serialize_object(awkward1.layout.RegularType)) type_obj = c.pyapi.from_native_value(tpe.typetpe, proxyin.type, c.env_manager) size_obj = c.pyapi.long_from_longlong(proxyin.size) - out = c.pyapi.call_function_objargs(class_obj, (type_obj, size_obj)) + parameters_obj = box_parameters(tpe.parameters, c) + out = c.pyapi.call_function_objargs(class_obj, (type_obj, size_obj, parameters_obj)) c.pyapi.decref(class_obj) c.pyapi.decref(type_obj) c.pyapi.decref(size_obj) + c.pyapi.decref(parameters_obj) return out @numba.extending.box(ListTypeType) @@ -275,9 +269,11 @@ def box_ListType(tpe, val, c): proxyin = numba.cgutils.create_struct_proxy(tpe)(c.context, c.builder, value=val) class_obj = c.pyapi.unserialize(c.pyapi.serialize_object(awkward1.layout.ListType)) type_obj = c.pyapi.from_native_value(tpe.typetpe, proxyin.type, c.env_manager) - out = c.pyapi.call_function_objargs(class_obj, (type_obj,)) + parameters_obj = box_parameters(tpe.parameters, c) + out = c.pyapi.call_function_objargs(class_obj, (type_obj, parameters_obj)) c.pyapi.decref(class_obj) c.pyapi.decref(type_obj) + c.pyapi.decref(parameters_obj) return out @numba.extending.box(OptionTypeType) @@ -285,84 +281,67 @@ def box_OptionType(tpe, val, c): proxyin = numba.cgutils.create_struct_proxy(tpe)(c.context, c.builder, value=val) class_obj = c.pyapi.unserialize(c.pyapi.serialize_object(awkward1.layout.OptionType)) type_obj = c.pyapi.from_native_value(tpe.typetpe, proxyin.type, c.env_manager) - out = c.pyapi.call_function_objargs(class_obj, (type_obj,)) + parameters_obj = box_parameters(tpe.parameters, c) + out = c.pyapi.call_function_objargs(class_obj, (type_obj, parameters_obj)) c.pyapi.decref(class_obj) c.pyapi.decref(type_obj) + c.pyapi.decref(parameters_obj) return out @numba.extending.box(UnionTypeType) def box_UnionType(tpe, val, c): proxyin = numba.cgutils.create_struct_proxy(tpe)(c.context, c.builder, value=val) class_obj = c.pyapi.unserialize(c.pyapi.serialize_object(awkward1.layout.UnionType)) - args = c.pyapi.tuple_new(len(tpe.typetpes)) + types_obj = c.pyapi.tuple_new(len(tpe.typetpes)) for i, t in enumerate(tpe.typetpes): x_obj = c.pyapi.from_native_value(t, getattr(proxyin, field(i)), c.env_manager) - c.pyapi.tuple_setitem(args, i, x_obj) - kwargs = c.pyapi.dict_new(0) - out = c.pyapi.call(class_obj, args, kwargs) + c.pyapi.tuple_setitem(types_obj, i, x_obj) + parameters_obj = box_parameters(tpe.parameters, c) + out = c.pyapi.call_function_objargs(class_obj, (types_obj, parameters_obj)) c.pyapi.decref(class_obj) - c.pyapi.decref(args) - c.pyapi.decref(kwargs) + c.pyapi.decref(types_obj) + c.pyapi.decref(parameters_obj) return out @numba.extending.box(RecordTypeType) def box_RecordType(tpe, val, c): proxyin = numba.cgutils.create_struct_proxy(tpe)(c.context, c.builder, value=val) class_obj = c.pyapi.unserialize(c.pyapi.serialize_object(awkward1.layout.RecordType)) - from_lookup_obj = c.pyapi.object_getattr_string(class_obj, "from_lookup") types_obj = c.pyapi.tuple_new(len(tpe.typetpes)) for i, t in enumerate(tpe.typetpes): x_obj = c.pyapi.from_native_value(t, getattr(proxyin, field(i)), c.env_manager) c.pyapi.tuple_setitem(types_obj, i, x_obj) + parameters_obj = box_parameters(tpe.parameters, c) + if tpe.lookup is None: - lookup_obj = c.pyapi.make_none() - else: - lookup_obj = c.pyapi.dict_new(len(tpe.lookup)) - for key, fieldindex in tpe.lookup.items(): - key_obj = c.pyapi.unserialize(c.pyapi.serialize_object(key)) - fieldindex_obj = c.pyapi.unserialize(c.pyapi.serialize_object(fieldindex)) - c.pyapi.dict_setitem(lookup_obj, key_obj, fieldindex_obj) - c.pyapi.decref(key_obj) - c.pyapi.decref(fieldindex_obj) - if tpe.reverselookup is None: - reverselookup_obj = c.pyapi.make_none() + out = c.pyapi.call_function_objargs(class_obj, (types_obj, parameters_obj)) + else: - reverselookup_obj = c.pyapi.list_new(c.context.get_constant(numba.intp, 0)) - for key in tpe.reverselookup: - key_obj = c.pyapi.unserialize(c.pyapi.serialize_object(key)) - c.pyapi.list_append(reverselookup_obj, key_obj) - c.pyapi.decref(key_obj) - out = c.pyapi.call_function_objargs(from_lookup_obj, (types_obj, lookup_obj, reverselookup_obj)) - c.pyapi.decref(class_obj) - c.pyapi.decref(from_lookup_obj) - c.pyapi.decref(types_obj) - c.pyapi.decref(lookup_obj) - c.pyapi.decref(reverselookup_obj) - return out + from_lookup_obj = c.pyapi.object_getattr_string(class_obj, "from_lookup") + if tpe.lookup is None: + lookup_obj = c.pyapi.make_none() + else: + lookup_obj = c.pyapi.dict_new(len(tpe.lookup)) + for key, fieldindex in tpe.lookup.items(): + key_obj = c.pyapi.unserialize(c.pyapi.serialize_object(key)) + fieldindex_obj = c.pyapi.unserialize(c.pyapi.serialize_object(fieldindex)) + c.pyapi.dict_setitem(lookup_obj, key_obj, fieldindex_obj) + c.pyapi.decref(key_obj) + c.pyapi.decref(fieldindex_obj) + if tpe.reverselookup is None: + reverselookup_obj = c.pyapi.make_none() + else: + reverselookup_obj = c.pyapi.list_new(c.context.get_constant(numba.intp, 0)) + for key in tpe.reverselookup: + key_obj = c.pyapi.unserialize(c.pyapi.serialize_object(key)) + c.pyapi.list_append(reverselookup_obj, key_obj) + c.pyapi.decref(key_obj) + out = c.pyapi.call_function_objargs(from_lookup_obj, (types_obj, lookup_obj, reverselookup_obj, parameters_obj)) + c.pyapi.decref(from_lookup_obj) + c.pyapi.decref(lookup_obj) + c.pyapi.decref(reverselookup_obj) -@numba.extending.box(DressedTypeType) -def box_DressedType(tpe, val, c): - proxyin = numba.cgutils.create_struct_proxy(tpe)(c.context, c.builder, value=val) - class_obj = c.pyapi.unserialize(c.pyapi.serialize_object(awkward1.layout.DressedType)) - type_obj = c.pyapi.from_native_value(tpe.typetpe, proxyin.type, c.env_manager) - dress_obj = c.pyapi.unserialize(c.pyapi.serialize_object(tpe.dress)) - args = c.pyapi.tuple_new(2) - c.pyapi.tuple_setitem(args, 0, type_obj) - c.pyapi.tuple_setitem(args, 1, dress_obj) - kwargs = c.pyapi.dict_new(len(tpe.parameters)) - for n, x in tpe.parameters.items(): - n_obj = c.pyapi.unserialize(c.pyapi.serialize_object(n)) - x_obj = c.pyapi.unserialize(c.pyapi.serialize_object(x)) - c.pyapi.dict_setitem(kwargs, n_obj, x_obj) - c.pyapi.decref(n_obj) - c.pyapi.decref(x_obj) - out = c.pyapi.call(class_obj, args, kwargs) c.pyapi.decref(class_obj) - c.pyapi.decref(args) - c.pyapi.decref(kwargs) + c.pyapi.decref(types_obj) + c.pyapi.decref(parameters_obj) return out - -numba.extending.make_attribute_wrapper(RegularTypeType, "type", "type") -numba.extending.make_attribute_wrapper(ListTypeType, "type", "type") -numba.extending.make_attribute_wrapper(OptionTypeType, "type", "type") -numba.extending.make_attribute_wrapper(DressedTypeType, "type", "type") diff --git a/awkward1/_numba/util.py b/awkward1/_numba/util.py index 50646b1136..5dd9468ec6 100644 --- a/awkward1/_numba/util.py +++ b/awkward1/_numba/util.py @@ -20,15 +20,12 @@ def debug(context, builder, *args): """, globals()) dynamic_addrs = {} -def globalstring(context, builder, pyvalue, inttype=None): +def globalstring(context, builder, pyvalue): if pyvalue not in dynamic_addrs: buf = dynamic_addrs[pyvalue] = numpy.array(pyvalue.encode("utf-8") + b"\x00") context.add_dynamic_addr(builder, buf.ctypes.data, info="str({0})".format(repr(pyvalue))) - if inttype is None: - ptr = context.get_constant(numba.types.uintp, dynamic_addrs[pyvalue].ctypes.data) - return builder.inttoptr(ptr, llvmlite.llvmpy.core.Type.pointer(llvmlite.llvmpy.core.Type.int(8))) - else: - return context.get_constant(inttype, dynamic_addrs[pyvalue].ctypes.data) + ptr = context.get_constant(numba.types.uintp, dynamic_addrs[pyvalue].ctypes.data) + return builder.inttoptr(ptr, llvmlite.llvmpy.core.Type.pointer(llvmlite.llvmpy.core.Type.int(8))) RefType = numba.int64 diff --git a/awkward1/_util.py b/awkward1/_util.py index bbd3a1baee..7999c15251 100644 --- a/awkward1/_util.py +++ b/awkward1/_util.py @@ -5,11 +5,12 @@ import numpy -def wrap(content): +def wrap(content, namespace): import awkward1.layout if isinstance(content, (awkward1.layout.Content, awkward1.layout.Record)): - if isinstance(content.type.nolength(), awkward1.layout.DressedType): - return content.type.nolength().dress(content) + t = content.type.nolength() + if t.parameters.get("__class__") in namespace: + return namespace[t.parameters["__class__"]](content, namespace=namespace) elif isinstance(content, awkward1.layout.Record): return awkward1.Record(content) else: diff --git a/awkward1/behavior/string.py b/awkward1/behavior/string.py index 433e7c0255..f2c71dcbc0 100644 --- a/awkward1/behavior/string.py +++ b/awkward1/behavior/string.py @@ -7,16 +7,6 @@ import awkward1.highlevel class CharBehavior(awkward1.highlevel.Array): - @staticmethod - def typestr(baretype, parameters): - encoding = parameters.get("encoding") - if encoding is None: - return "char" - elif codecs.getdecoder(encoding) is codecs.getdecoder("utf-8"): - return "utf8" - else: - return "encoded[{0}]".format(repr(encoding)) - def __bytes__(self): return numpy.asarray(self.layout).tostring() @@ -38,17 +28,11 @@ def __iter__(self): for x in str(self): yield x -class StringBehavior(awkward1.highlevel.Array): - @staticmethod - def typestr(baretype, parameters): - encoding = baretype.inner().parameters.get("encoding") - if encoding is None: - return "bytes" - elif codecs.getdecoder(encoding) is codecs.getdecoder("utf-8"): - return "string" - else: - return "string[{0}]".format(repr(encoding)) +awkward1.namespace["char"] = CharBehavior +byte = awkward1.layout.PrimitiveType("uint8", {"__class__": "char", "__str__": "byte", "encoding": None}) +utf8 = awkward1.layout.PrimitiveType("uint8", {"__class__": "char", "__str__": "utf8", "encoding": "utf-8"}) +class StringBehavior(awkward1.highlevel.Array): def __iter__(self): if self.type.nolength().inner().parameters.get("encoding") is None: for x in super(StringBehavior, self).__iter__(): @@ -60,8 +44,6 @@ def __iter__(self): def __eq__(self, other): raise NotImplementedError("return one boolean per string, not lists of booleans per character") -char = awkward1.layout.DressedType(awkward1.layout.PrimitiveType("uint8"), CharBehavior) -utf8 = awkward1.layout.DressedType(awkward1.layout.PrimitiveType("uint8"), CharBehavior, encoding="utf-8") - -bytestring = awkward1.layout.DressedType(awkward1.layout.ListType(char), StringBehavior) -string = awkward1.layout.DressedType(awkward1.layout.ListType(utf8), StringBehavior) +awkward1.namespace["string"] = StringBehavior +bytestring = awkward1.layout.ListType(byte, {"__class__": "string", "__str__": "bytes"}) +string = awkward1.layout.ListType(utf8, {"__class__": "string", "__str__": "string"}) diff --git a/awkward1/highlevel.py b/awkward1/highlevel.py index acefe9f036..bd6fe8ea02 100644 --- a/awkward1/highlevel.py +++ b/awkward1/highlevel.py @@ -6,7 +6,7 @@ import awkward1.operations.convert class Array(object): - def __init__(self, data, type=None, copy=False): + def __init__(self, data, type=None, namespace=None): if isinstance(data, awkward1.layout.Content): layout = data elif isinstance(data, Array): @@ -19,11 +19,14 @@ def __init__(self, data, type=None, copy=False): layout = awkward1.operations.convert.fromiter(data).layout if not isinstance(layout, awkward1.layout.Content): raise TypeError("could not convert data into an awkward1.Array") - if copy: - layout = layout.deep_copy() self.layout = layout + self.namespace = namespace if type is not None: self.type = type + else: + t = self.layout.type.nolength() + if t.parameters.get("__class__") in self._namespace: + self.__class__ = self._namespace[t.parameters["__class__"]] @property def layout(self): @@ -44,27 +47,39 @@ def type(self, type): if not isinstance(type, awkward1.layout.Type): raise TypeError("type must be a subclass of awkward1.layout.Type") t = type.nolength() - if isinstance(t, awkward1.layout.DressedType) and isinstance(t.dress, __builtins__["type"]): - self.__class__ = t.dress + if t.parameters.get("__class__") in self._namespace: + self.__class__ = self._namespace[t.parameters["__class__"]] self._layout.type = type @property def baretype(self): return self._layout.baretype + @property + def namespace(self): + return self._namespace + + @namespace.setter + def namespace(self, namespace): + if namespace is None: + self._namespace = awkward1.namespace + else: + self._namespace = namespace + def __iter__(self): for x in self.layout: - yield awkward1._util.wrap(x) + yield awkward1._util.wrap(x, self._namespace) def __str__(self, limit_value=85): if len(self) == 0: return "[]" - def forward(x, space, brackets=True): + def forward(x, space, brackets=True, wrap=True): done = False - if isinstance(x, awkward1.layout.Content): - if isinstance(x.type.nolength(), awkward1.layout.DressedType): - y = x.type.nolength().dress(x) + if wrap and isinstance(x, awkward1.layout.Content): + t = x.type.nolength() + if t.parameters.get("__class__") in self._namespace: + y = self._namespace[t.parameters["__class__"]](x, namespace=self._namespace) if "__repr__" in type(y).__dict__: yield space + repr(y) done = True @@ -94,11 +109,12 @@ def forward(x, space, brackets=True): else: yield space + repr(x) - def backward(x, space, brackets=True): + def backward(x, space, brackets=True, wrap=True): done = False - if isinstance(x, awkward1.layout.Content): - if isinstance(x.type.nolength(), awkward1.layout.DressedType): - y = x.type.nolength().dress(x) + if wrap and isinstance(x, awkward1.layout.Content): + t = x.type.nolength() + if t.parameters.get("__class__") in self._namespace: + y = self._namespace[t.parameters["__class__"]](x, namespace=self._namespace) if "__repr__" in type(y).__dict__: yield repr(y) + space done = True @@ -141,8 +157,8 @@ def forever(iterable): halfway = len(self.layout) // 2 left, right = ["["], ["]"] leftlen, rightlen = 1, 1 - leftgen = forever(forward(self.layout[:halfway], "", brackets=False)) - rightgen = forever(backward(self.layout[halfway:], "", brackets=False)) + leftgen = forever(forward(self.layout[:halfway], "", brackets=False, wrap=False)) + rightgen = forever(backward(self.layout[halfway:], "", brackets=False, wrap=False)) while True: l = next(leftgen) if l is not None: @@ -194,16 +210,14 @@ def __len__(self): return len(self.layout) def __getitem__(self, where): - return awkward1._util.wrap(self.layout[where]) + return awkward1._util.wrap(self.layout[where], self._namespace) class Record(object): - def __init__(self, data, type=None, copy=False): + def __init__(self, data, type=None): # FIXME: more checks here layout = data if not isinstance(layout, awkward1.layout.Record): raise TypeError("could not convert data into an awkward1.Record") - if copy: - layout = layout.deep_copy() self.layout = layout if type is not None: self.type = type @@ -226,10 +240,103 @@ def type(self): def type(self, type): if not isinstance(type, awkward1.layout.Type): raise TypeError("type must be a subclass of awkward1.layout.Type") - if isinstance(type, awkward1.layout.DressedType) and isinstance(type.dress, __builtins__["type"]): - self.__class__ = t.dress + t = type.nolength() + if t.parameters.get("__class__") in self._namespace: + self.__class__ = self._namespace[t.parameters["__class__"]] self._layout.type = type @property def baretype(self): return self._layout.baretype + +class FillableArray(object): + def __init__(self, namespace=None): + self._fillablearray = awkward1.layout.FillableArray() + self.namespace = namespace + + @property + def type(self): + return self._fillablearray.type + + @property + def baretype(self): + return self._fillablearray.snapshot().baretype + + @property + def namespace(self): + return self._namespace + + @namespace.setter + def namespace(self, namespace): + if namespace is None: + self._namespace = awkward1.namespace + else: + self._namespace = namespace + + def __len__(self): + return len(self._fillablearray) + + def __getitem__(self, where): + return awkward1._util.wrap(self._fillablearray[where], self._namespace) + + def __iter__(self): + for x in self._fillablearray.snapshot(): + yield awkward1._util.wrap(x, self._namespace) + + def __str__(self, limit_value=85, snapshot=None): + if snapshot is None: + snapshot = self.snapshot() + return snapshot.__str__(limit_value=limit_value) + + def __repr__(self, limit_value=40, limit_total=85): + snapshot = self.snapshot() + value = self.__str__(limit_value=limit_value, snapshot=snapshot) + + limit_type = limit_total - len(value) - len("") + type = repr(str(snapshot.type)) + if len(type) > limit_type: + type = type[:(limit_type - 4)] + "..." + type[-1] + + return "".format(value, type) + + def snapshot(self): + return awkward1._util.wrap(self._fillablearray.snapshot(), self._namespace) + + def null(self): + self._fillablearray.null() + + def boolean(self, x): + self._fillablearray.boolean(x) + + def integer(self, x): + self._fillablearray.integer(x) + + def real(self, x): + self._fillablearray.real(x) + + def bytestring(self, x): + self._fillablearray.bytestring(x) + + def string(self, x): + self._fillablearray.string(x) + + def beginlist(self): + self._fillablearray.beginlist() + + def endlist(self): + self._fillablearray.endlist() + + def begintuple(self): + self._fillablearray.begintuple() + + def endtuple(self): + self._fillablearray.endtuple() + + def beginrecord(self, name=None): + self._fillablearray.beginrecord(name) + + def field(self, key): + self._fillablearray.field(key) + + def endrecord(self): + self._fillablearray.endrecord() diff --git a/awkward1/operations/convert.py b/awkward1/operations/convert.py index f0e31adb0d..3f56a96a2c 100644 --- a/awkward1/operations/convert.py +++ b/awkward1/operations/convert.py @@ -21,16 +21,16 @@ def recurse(array): return awkward1.layout.NumpyArray(array) else: return awkward1.layout.RegularArray(recurse(array.reshape((-1,) + array.shape[2:])), array.shape[1]) - return awkward1._util.wrap(recurse(array)) + return awkward1._util.wrap(recurse(array), awkward1.namespace) def fromiter(iterable, initial=1024, resize=2.0): out = awkward1.layout.FillableArray(initial=initial, resize=resize) for x in iterable: out.fill(x) - return awkward1._util.wrap(out.snapshot()) + return awkward1._util.wrap(out.snapshot(), awkward1.namespace) def fromjson(source, initial=1024, resize=2.0, buffersize=65536): - return awkward1._util.wrap(awkward1.layout.fromjson(source, initial=initial, resize=resize, buffersize=buffersize)) + return awkward1._util.wrap(awkward1.layout.fromjson(source, initial=initial, resize=resize, buffersize=buffersize), awkward1.namespace) def tolist(array): import awkward1.highlevel @@ -41,6 +41,12 @@ def tolist(array): elif sys.version_info[0] < 3 and isinstance(array, unicode): return array + elif isinstance(array, awkward1.behavior.string.CharBehavior): + if array.type.parameters.get("encoding") is None: + return array.__bytes__() + else: + return array.__str__() + elif isinstance(array, awkward1.highlevel.Array): return [tolist(x) for x in array] diff --git a/docs/img/awkward-0-popularity.pdf b/docs/img/awkward-0-popularity.pdf new file mode 100644 index 0000000000000000000000000000000000000000..9b2721be27458f6e47819609a4ceba59843639ea GIT binary patch literal 52113 zcmce;1z23mvM&w)cbmc8CAhmg!6m_iI|O%kf@^Ts;O-8AJd(ZlIp^N9 zzrVb9-euM|t5>b=>Z)IL_f++&1-ZPaI6X518v=RVarq+x8-NL5YhZ!E%L`zXHnuT! zG6S%`kQ5OB005)7xs{W#!^_!9-^p0i*wEI<7=fQ3!O_XVSl=4KEv-y**an{qXXTK# zG5!N{_pKq%UMB>kzYxW1kC>An3?6e+tKq8j(XG?nXt63caj-T`>Xp#-yO@u}@lvL2F2t3>h^pp(=-w`9n>|EL3>Y6w(;3~D|9<$5@CqId2@%?2WYN;#2d+nZ&s$?@*&w(u zh1cnhks%msRz7U_46%FI<)W>;B4de#DzOZrFsipTJlnfsc!miK=wUotFbL_f6ib}k z524tm68$g;pTb#S40>@rK8V9jy*n_%@$iTd$2USrHai+eWHX_}4DMst&v;kB+XgZ` zV_9d(?L%n;>?HvL5UDL(lrpuBBZg{4$@6VKlGE^9L4BULWuT1<@%9$oJ~}4HE31md zt0rTVPpX}s&}^HYi@@?Ab9N9l2+63Juy_UA?cj5B9W%gsde|yzs5mK6TqVLd9{QA! z=Ik*)cOPGnXy!ySj0TQP&VFMS$b^cxNTRf))XqO0di4Qn8$|8D0=jgTC@mitlZ*+y zHvKVh1lKRhe*t824b-P#Y@;-E3Dmdva$jxPY$o4Xxi4PEbwc@%O8R%dXCEFhN*;bg#h zFWV!*`Xb?CRP3+Ty1Zqu+&%VH5L2sOFM@j~cuo^`F~@Y@8q6TsYtsox1oZtnlcXH- zbTPAbRpvbJqjftYbOtpRkP#^5&V~UOM_%+co5QL)M?ybwa;n*j79Zp#4Z%)RJtjr) zCfMWeqqFFIQ*#SzyscSM6Tw)*8AFOCSytEk));QPj`efRyKPIV-PQ1lk_)i;8PZJ% z^T4}8Sh8>g4b9>Z+Vhe|EpHu}slB-5$fBN-pW^4kF4y(Cg>%8a$4H2yfs+%w$Ql+z zDnl4%dNu?qy7@&UT8AP_(@1HPj@EI{YxNToDv&kSE(7LETj|zp2!_&Z1Z*-A9}TtT zaStKM=Ci!(b~V{I)Am%F)!&el&QsNsNcEDEZGIk=(r!|UAgLUf*?K-1CU>ZM{*02l z98C9FE8+d{=Cq<%ji|GEyVm=9d+?eiT&1@|AU96wzcH77th28Rt`PK%~&=SH@6b?Cm z-FPK_7RW`yJ2e>1sxJ#SR$KRon~d4TER_K^0lf3uCf}lFe=rI;lV1gbs6`wq>H4C(txudK3PIJ;e|_@yl7A!op5scL6P<$QU4-43QARKh0U~ zhu6irel4vkFXEP8#wh-ai&IQ;X;$#rNNn;xFJ+)Hw^L@yT^e7J-g zl_Ki-DJKQUBf)3Vv~83VB`>_LLrM9~;rd6w;uv}OUoV)*+41Tj=_=w~$jaJHHE_0Z zvSlFprOJsuj<&wGYYi<SdqD?>H`~*U2eW?u8I~*0U09 zeFim9Au=n|W9f6ND1%>{-?lP|>54|VY!RJ2T|eC?>*%fVZQM@n?BxIOc5doCCHBP> zO4qaTiN~L4SQ0p#<4wqtNQ^O6^m&*1WticH6(Pzc%Z-M0u`%d37FDgWdjQ{0O0mq z!aXE$tiVOJ5A`h88ahNdt$9YAz(JrE2^+;*A3{TEnDC`}%y=~nic*el9501{>El;p zgUDGTg0fb9YXWzEr2fqdiFcjtKG zX1iA#8Owjj>|;TX+(hbgWQva$1Jn~W1%fa9Z+( ztx|RFUN9ZD4oXEO`D&jq&RNtB3)b7o>CD&82Uo=pm z)H(^#=+RNiTx;u@YhMwtIyB%C0cT%$Ts{e`4deMX(xJ|1)I2vnUF};;u`V9?W}cz6 zAsE{j{pqi~lzw?SzucQ&=NAWug@u{*SA}1ftp9L?e!D(mZcY+PPA_f`fS30d;pLA} zpXucSz$hXFUc4!yI72Tt{`h88mou<1Hgx)3$BhHP@ym?@FuHL9IR7kh0l0pb z{;V%9cE$ikd3{r306Bp9SJjsb z2jdrB%zw3Ilrc6k*B7>R18BXFm;h`nTnz6x*g4pl0W2I$44fQXEF3HVo!@OmUZi+w z>eYNFf?`q`~qF^mrMDlp1&~rOV2;OQRaVY^>^;*FZKVB?@#!D z^~0#-Y~b`8CUIK_>)#aNe?fzl=>-PnKlT5oFwDQ8`Yp{r99-Hhnk^P(CJ14;0 znPyqhx}{lq`eu3GW5=-J0wGfO;b{JSg#8xzml`jkuyX#T+i&)NDEC{U|I-o1%mR2h zUL^hn>pvm!|R;70FA$3**($YV%}yN)e|Y?qc5q3a2vH50=pQKm|?hC_$-zVdQYOIh`Ff9 z?mXJT%opD7`DT!qgVEQz_hlDzh&YBSZ~w*+e@)33LohS_b1?ss@;^D4IRVUnEtAY# zfS2Q!RT$k^UZ(2rY5A-CvU>eq41SeaUKa1a>aYS>evi9fbT+`t@n>6h0LvfNeWAYt zyc~bhIbNp!@A7|{IKL;;e=|GFZ#n)a%+B&#`~MPM({8cILv-di!90n+3c502Fl6PE zLPUfiBV*-LVr7NFYqa4ImF312u&4-Bo?>79c#V^fXY{<^>*Lw83 z$Nzm3{&U6oJ%#=oaIF7htMw8os@{;Z}C!%`feo7NIK?xf7kzN40rcB7w)+3qs>&-wYh2NM^I&cNDs>b@h7uPt;DbQ zqK9IjgbydC%j7Huz^23So*57Er)3k7vXt*@qxISCsyP8;;nVb!0*;8&#kQaBrq@a6 z>Br=j4pmlLe0B)KM%S|*!p0##U59ar1xHyOjjd|s5vKBIo{(_v#%`5UD5t8qT`$~r zz1{?_51Ng%0x|Vg<_t%v!bXp{WTev0{AW6ReO#7nI@S(kSgI_Ob#*5KF>4RSEN&gm zL{he;V7MN4`9%{FD0sBWAy~TcE!(@B?7O-RA7m%1#LC>~FYZ6Cc9>viJDSSIb<_E5 zZS8u-dS_gY_v45NItKICai6xB4OIVxqWAT(wl;v#E($v;BGVQ*kz;WICVPIx_S?BB zpxF5O2B(gEVJaV;gA{S%fSF#PULbc6jW-LQuMNFK%^pP5gaOh-zQ+T4Uz*O+u#Ql+e$Pk#qbAAN=q_~#v zSpFdaS*A>cwv{{c6I)E8LW9hy+{a7nLnfyqBi^19YXTnJ0X1vu_1+t^D&YOqjb3zfGJ?2opzbNm|4G7O@5dhXScW_Tu?AM zE$ikhKc-5(!U;FTP$P@=#>*v-FA0mL^)f1l9cM=Xp=b9Me9-A zCyT`ZTzqrIS~VUXRRXf|=5Hr`FS5;EIfn^4i`kNm@k%)!sgM1>7A~J*>3U9DrFuZPPS(($1hR9%th5!> zdVR6unWOGX-bw@_YRaIPm{{+{`>q}y`Kl86jdJX8>UvU1fS(}W&D{e5%a&PbdL|J# zQlM>eG;bD5f09fiHYLbxk?}(wJJ&ZKa9DUK3D?c5=-iD!Z_mx?Ty;&7p)>!7S|mZJ zefV9UBnh+c-}{bN!iB}W#BC1 zk)9votnI6-jI0JaMm7K=wV8#bzhIHLLBIdHBMAiz2I{ z%@G?|o=bWeFB(Vcw{*V!J|dl?laL3no^#{`dMg6>n6uA(C`p9|e!$?WU_u}NFio-- zn3SYmD!BaJiL&$7%E6l(iq$4`%bdx64ya3VNTS4T>K+8xbqlgsj=q<#DM2X|fdBAW zcXxs<-H4XjvV<~rpjYU`iQ%=PZxALz2*c;GHVSXxdOkSPkqSG%de|)wF~$g zNUxGJ(}a=sWL$b>b`5zFS6`J7{iq~_qT|Oa#q(@%Bl<#teexx+O0GYb5imwAF6wm$ zh{P#f#dXijWJv3Rnbg`a>2oaW|CZIRLI%&L9^9o5YsBhKaQ9>bi})ZNlOKBwcL?T8 zF(OjKEp$YAvk0FTIzPr8AyOe_8n7j#R7tG0s-F%4%>HK1j~qR`3%{%`NeXg%eDWeC z(A37$6lD|O+51yMSJKQzu5V;HMK#avOG_bN@(s-GAp zr#v?oDkM#yMPI9V7o$VBd{Ox(iegtxTSeQ4%=2V%@E!CzE(Y=3J`hqPt-;C{OgEZp zlr&hE{*lq_$E^P~<{mI6q^8N0&#$kcGG~j0YvI&+1}64ViB+iiv*;l;o;x1LO!Mc( zC^f-rt<=jIV+yWrQ@53(Yy{sN-#7wjoJ00gJ_|Y2F`Vf4su9sR7tlE^e0|3z)0H_t zQ?Qk#isgo^0V0V~8^x-jN8?(fLqbYpSXWg2=F{7KF`{GGK#V5=cqD83z;bg}5`|5; zoPfw;6vYm?sKyg`QzHY^E0k=>5u~gWhLrdyhxl(0OgdC`>~ZDFS@Bu^Vh-uu+1O4e z^viF&SP4!L)pxEau)iS>t9b(y$coq&t;`;(q88+sK{?7=!0at(ntiAz>#61#MqV=8E*XW&}9yjre7;!~2B-e}i zNyfDYkV#zAZ^3zY65l9S_m2A2%QkjAA!9to+%jgN+5(r+B)Ly(^@gAAMqk12WGi6Q ziF(Mtt{Omf!nBYuG=&xI8f$-=mL6BpLI}ejhEwCg=)jEy-Gpe#Vr((W6 z6LeQdu7;MCZ>mTvN2wi}R}+H&9>u~3<~4XN>mV-RwsaWSY!rPA7HYGa8?owcW!-9> zrD6{8U>pS^8KJZ33gDfQhP>CL-nm6=8CKD9nc zRUQmWISg~XNUm_9`ggSbdxOz|xyFSHTKB?T>g!J#&=}3?(Rwrn^t7`RDl_0n#LICW zK`@YO=rP9f0!De%YUrb9%r@XHS@#X2% zG4coRAlt9b+_5W-Fv|IO1mX^|TJ4OoQq?PKJ!HNh7bD5DI14KQdB<<6GC;)ufW~VQ zG4j{A5$)UEuJ9S2-xA_QEzp3sFe-yvg0U*E@f4ly+3MPV=yXMOgoxngI8@2y1hjCb z8G8pKUL(SWUEwl3-QPLv3hUu61=k+{`pr$AuFk?&RlkY8v8yq*{!{La*-KL&_tM=j*81KdBn-$3A~ zS@O@`zg14Tf&8$?<$T9T4IGaBglO?RpWqWqVjd<8{FZO7du=bKbw9`F@4b1*D_9PL zN7;m>{qT(@OqF!5ZFl7LG+?+S{mqFbSUsWr^vZ}pnokQm$MTw^x`aYKS?r09E#)WY-Dfp0@EJ?) zDo`lh-MWcJ9Yoqn|F~nuCt}FElyfyrALaFiUbHCYh#>dAOsqzk9y~paRF^_ZmTS6) zib6qk-y4u$@C_+5MlsmPgU{xRxE3{T|5!SMm|Tpx+#)V7nKR)ale{ma-7@5aG%=V! z1}_)Uildua5k8Ipf5R3nz6hCo^seO<^@X+9)lHyGqXfWy8l?8@_H=zMb^qlD>Z*^E z&EJG;e{B!FL`keHZ2yRKe@8n1k$~-Qc7|C0pC6b1Cj+)Ww(Am2qL6PoP-LH|}mVL<4*%Ppw$L)I&IBZJ|ecxJt0z=!y^Zcv6?FEZ~He+ZZSwxw}j$8!N&x z*Tf-GGNW(D%UJ&Dy+~;KL*`Wr{1H(1?7F@ngi~Hg>EVnF7qA|Qr zpG=x8Bkj^Z8;w!0lq?C_>SLrls+fwrH+eUiC1kQd+O3ohr@?14wahN8yR1MApHng1 zqo2;o{<`cs!^nnzhRrw*)<{79W&+_|;3ly8fX*=188xU>sD$FN+_OdIRv8tma#^7^ z*(_?kpSOofKBtAq6R3gV-Ob6?^POmW%$tasWL!O^;`W>liZv}moC`jOkUd)*lm&z- zwV-Cq)v1n2q^ykSbIA3MEo~ALZ>K#$_jwf6at^dJGkh=LM6V7YC`+*ta5>q?IJAJ@ z**j@sH+RH7L_sz8#Qb>NV9KQ0X6TML4F?ZZvl8{Cire4Ln1gJPfk-CR2ad<)KHFyE zLn%5J0cIW!JP9lu1~qqUD=n|3d7;JB%B6U$v%Fd@5R*rbu*@p(eSFL((m{nuDPU-S6#m++{j@lD)?S~7OL)dDJF zDV>X&oNj7qdxFU)xmCn#N#Z^R7@{}?tC5sWdh<7Hj26OjL1WmBx7GOVfRWuoVIvZn zt!4ROQ;n;0FRTosF%Jrv7~!1D(82j8Xc0wBdEiRsHEm?u{s6w5_;3mtApxbZIP0Bh zHWbw6I3o)EE;8^+MiBj2!Mkn`a&9ED@x_b-Rc?|_OHq`|4v>jc^k|t)SEQy;V3H8E zxOImr0WAiW;6Jk+srtW`A?ds2u8qY*`dp5~~Q7ZGJ# z$rXdh5a`(`Q^&ZY)N396lY2JuQ(Au*jw>dyC0W=z$bpeWA?zg`31F6MyQooeWn3#F z$O$cGe7=ylyR03^&emb4{hTC3Kyt*Q<{gyUHS02Q7VTWQA$_kI2kj$9f#>`uKBF^PKH(y}j^{9iwKTr}rHA{*tL5|K^`@tUvf z8!w2X2aW0E_wP@AosrQJ!G=vVXda9Q-_ebVRb!~jvt^JborQ4v$KrLy+RnHiC?kf9 ztF;AMsV#A5)^LA@%y9^);Kf7HQ6cK?XUWrF+KhcyOsphh$P4xNy6dronICG1VWeAjS1v}MDBa(j*tQe3#Zs62H>Yj{m-W&zQew; z^H`%!Z-E87+-l%(7uKLX^RHTq7%07?Mm8m*D)d|NrU&CHNO4f(BUplZqvBdO8k@NA z$^n&O*7(N-ky0;l66OGrePRB?`9Wo-Cno{PX%zj{x$kN#;b^tkmbA+4?W6#=BMS)^ zeY(-Pp$NWKL?dP)PIhrh>ic6N>zyT$9SOzhEU-zi`lUNhLZu5$>oVf!YSJ#jI)l#73N}VI%eTtTkADC2;-b2rN+iy(ZSvJWj1H4 zg^|>3Ct~!erkN2BL$46n>P#B4wOp`SZ6^ zuJg?IQAhWvmhrFqZEv1~zCSc~U!Ko0E5uSKYS-9Na`AQvrO9$jXSLyWFCt|eLtvHJF?y*hFU1o%#99+KUw8PWNJUX;(8LyAg~rZ-fyHbaWW0BxGuT!& zHM#m6u<^74R+y`;Z=8H%PPd?xNqk@`5@XNoA@MH zu)aAsrUhQnzZtB69DqGo{O~#@GqH&5jwd{|Cz0?BryQ44n6j7JxruDd@*?)D{qL`Ab z3Z@M`2f9n@F;IR8r}vC-7t-}LR&f5IJc=es4OEAo7&)q3#)V;5gvoC4_IQ?%x^_Er zd7AnijYbccsrmGz;P7%7lz1Cwt{IRox3ik0r4eY_NEPE1;BcKJ>@vsiXFvp*&uEEUVYh{4qanKklXl ze43MhIQS}o8hUj5u~jgjV*B_L&yY1d@D)GVDGyI+8^Jf?Azoc9XY1=T3k_o4yQDa_ zG%q>6$7opf0^f)?{JO-j?ZIw}L7a`{&<>nwi7qF8GsKx?Q*mjghg6ff%89|@e8x;} zQ`(BHQ%`59W;TpqpGrKCeuCB1HBW`3vqX1!dX#y0OlfsHjz<bpJ0RvG->I6DHYyf+v5I@F ztiY`G(SkTp0MILMj1H#i$KBs)k{kuzOqm?C2%D*R8rz?o7UjYwAmdOU2f_ zE5CIEr;J!hZ23wo=owQqa+^ib{i_ebj;iD3$dB*$b8}-apPvx^GnpxW6aW27Y7Z+b z%e%jxbh7@HOz=mt4degM%!_|M>HPgD`j0^JAKB8Z|6`c}tpA=Fppw!Q$skn~^yCr# z6Q+59+QAJ92t@iS`gTtj9{$4zCO7X{w1ul#X4%_@nreqobFu4=jEmVBgETpJQ!TQC z-P9lF4Vh~{>b#zBP7B)4@5iS2J3J3|PscKU`ZI4|{*);mcpQ znd$lDb$mXnD)941bm@fPLyMZ%Go<30s>oJtg3*aJ#^GfYY@xmzJDyKzM;(ET&Jd{j za5~97a=>kgpLCN=4(n81hiYgxYdjw4oiyUw_ams(71b{|I}Mj-$+qHKp~r~3mQ{=y z-(WK3ASo_PE?-Q@$A_CXq8Np^qXig`J)3Ast`oSBTV`>RA7t3>~M_nWOUS~ z)ox+qQdosXc1R>l(UYond38xZQ}+6$wtUUv5d@fTmk78VrGyR1G`PdzR*rI$55<-k zqspy&d*m|Qww0vv^FwB(S!Rb41;A#cK9cV{9Cun*rze7Rj%fLlpsboXw$KuK<1`1gQH&%xla~ zG>vifTvhgX7u@^kKu<g_JZIYUbu~)U>)*%62yd~|qo;%}^3`vJ4P;KUX zCBqI7!3;Yj3%yex%U$V{eqJcWbW|`u*(|u|d}!P>?~*`ban=^S84D`AY!p;=+aRBs z5Pi2*XD^WvdSc_h;+A9B4Kq|`>&fn8(OsZD3#u-TYI;KtCon_LN*_)yo-2b~tQ9rL z<>lLofsv+uo#axBEL!dVJ}c}Z?Ze_#*3Xz3SKS(Tlq%H-i%g1Y3DarZOIGWFp+U-bm;~TrE%x903MUMU z(+rN42mbUA7{!pw$;FP8hAxwyc@1p4KaODa={!GnEc?!cWuq=G{rXMLdu^B$pS?yR zz{?{{gHcHP8$e8zzZvFO!OR8%B-NTOZR?m}tFvF(E5}Mw`(_;K?0|~VIXyUg_fde- z`WG6^)FXbe6Hy(=4NGQzRJp*JNOHD%V*HAoCT2gu890NJ<;0gf893K~tU&=`_BEn% zIYDjZI&S^-`MzZY7~p_^h#}h9=MK%Fr%%ss*<&_0US(NamK7yI>s!4AQ^;ZWgg^o| zVf-|PG4Mv495UqXm?j*e%Nz}+;aWR!laWCQE_etWwSha57l=)xA9CyT5&N@pE&`04 zko7-ELf{*VraZuA@W7S8#3onVv{C`f_g1va#_FjVs?(k{tntS69&2mPeW}+72Am6sN z$6wr~^7@ygKHr|CBu9kBL8p3tyb!Zn8Aw40;4z(=eCBm794DSgH8-e0yIgAs9;f^jD3>Nl18{Nc#`4q%|h!+DQO@!#A z;hj)`rbua{R8WDbKGq5dEA#v)m)F^7N-sbDM9-A|V8(s?Vh`c)qzq<4|wy)mh|bZwjs z#0?T{HtE?=7Y|@VOF=mgTrMsMDF~m?gtG5|iZI_W>)Eq{W5`%!AD;??wnCAn+Ot&3 zPC%n>7~t>UiYvt@wME8kQz5x@-gCQU`Ng&7HkQ8|-R{Gh+iNb%-YcEauUa@2G%)q5 z+0V}S{5r2QJKpEx;-FaqV)$(^M+hp`@}wV<9nE*Jc;sLtc8rcin`|l7HaR4&WIBZU zGCrq(q&KIXNjAL3t0kB3(os1#DLzdqxM3U_kZ2vOez8V@!LtPJ9~7+M1+Dzhtt+C^ zNfMwsqWRKA=rxy4Y($_j3mBsbJ1yefKV3NThn);mL$rrRkC3|?Yt;@h_jth_zL)u@UJ}3Tw1N$Hx z6ZABvZ=Vn53gF}cWih6kDG_aLo=IXvVHC8m4Cye`%Ug~oWQR9?Xd6T1%nr0}yurLa z`lPIb1$&K^)vz)hDWy#lzFCaj6I)xHF(XPwZmtp+)ImHp{8i*Dis2K9KVDvWnt7AA zG1RSBAd5}Lc8U)>u3uQ1d0l)Juro_AHub$JhJIYJmFEZ;cc}(eva9@CB0;8{bKyE) z={B8;e175Nl&HwJGL-8Q6ZkO6IFz!IS-8+)l-MS|y2N=Bmxc8yQA_d|vQqp7dzypK zc0Fev`Q?J#^%T()tVkL-&Y^mBa(;cuU^)f;6q$7+A_ zHOkKBnr)V9Bg!fhWNfOm!fLI37ol@~K~z?sA`XC>kjiuYq|7L}6MH?O@|spJars{8UcH!iXM11jO zR?dn)L0wm~N`B%l8sPHP+V>Y*} zhO;mCty^OAE|R$KTuL!F>*YNe>suP>l`%9lmT@dXpj2uC<>;4`UB~pI2no?d3-U+? zG!hF@g=4;ax_(|Y9g>7Vb^jqRL;9`XRJp*(OnyN>jZTRBYJ0}(geAHX!i%kL40dlw zupv_ZU|$4zx2gzA8{Ms;y`7x6k2kFRtKrg0;C4>vrv_Ws?;4nO30oHYNx78V3-Z)O zpB|_d_^B6B!vt(Y=Q{xpcjkha&c+6$-W$o}h#avq+P2uIpS#ZPjLY;`c%g4eQ=uj} zGKnvdION+^>_c)kg=^JLtpXXeC7il2Weyn@r~5k!7Dp|KXt8G$6q%CE4P(E_iy^6v zF&fr;l2vy@KMcL4q%A>VH|29)enmQ8R1y`yT$?&GJ&1w`uNBgM69aUBO&B0FkVVFc zHB`$N9x}Ww0LP|>q*VpeWE(Z{@|oOiqGvjMmYY8P{2)zDkfaQXcjhq`Ufo+{hmV7Y zM+l~zaP{rE{7yO~IUZN|W0M!gJ(V2ekNyCu|UG$Np>Op&- zFPV*qWX2O~r0M9`K`xV#F-A4E@TNE_qNQ?rN>rkkAWZF()6TQVa<^$;9FN4iWN`J| zcM3;|6wy|%QsJ5LlhQHqcfcd#QXh*vxXoQ>YUG~5CoZw(ExFqqvlcjcIO2GuOWuYopE2I!rtFy9$)tQ+ zXVurpA(m57Yt^?mJm=>>(O=al^Ai$AM56>HRx2?;?<$-}{ozD>d_~?d2~f#gKV6;c zB!ym(O&Rm8rfCCDo{fIDhzByRn%h~@`4xu5wcaqry2u7p<<2ouc-p4WmrURTS|4-w zWohY+g(fYFcl6__F0yG9oj9eKp1kfk(z~Ia-n2IDj}H4mng@B_g4C{Et6H; znR8Co`%OH>v9L)a+-v7@s&Hp8M|CN&b--Gx6 zvHWh<@^+0_H3{2_`g{c_x4dYe$B%X5e zFcewaZGV6KeB8XoBWru<+@W>Dn)1wY`*AMQ=jX%9+R2>2Pscjf_Gi!QIpXr0hq>#- z4ug@WhyIz9IbywzHYS*#PiMrwKd&u5=t+1!%`>s`MNm$epv-ML2T*kHV0zWNFh~nd)pS0}n9z$;OQ4}C~?UP)lNriTh4!LS6 z0oS?WxatRL176>(rVb>Rfii?d?oV!MY9HS%5Y@iFm}bLYv^^$qmVAxK(7|a^rV>g# zvD=d9wtDPFd}kfQ)z&j>%w?Z)IF9DhLDW-2R+Whf%Z{u%AnQWcBU>j2d9ez`SuX`= zW9{Ntp>cO`wO>jgWT)hlHy53-^T}>&`Xdlp6dEo7l0lP+vdg!>W5aM0f_G+pg2_HCeNY# zn@L%c(MWH{HLRe$9o``Fd%_`{lh?K)1Nsr4wH=Q7B%Cgi+MNheO<|cbX<(RQ=H5)y zzd>yooz5C+nwp07`K~-40FqC3483|QhB8EslpX)2py_Rl6EW$)C{|HhhG^${|3+9; zzzRnhRmP(ItmoEbR`D|+loQkXD2>}AK1&6lz6gJ%7sN}kRk92e|;zgI+h(VRUSklE{nr;U8Y^n`Z=(lwNXbHMR(q-_Y_jGDI+tDSLlQI5d57L*J-ZqtKLcPtAp%9 z9d-}oWfjF9nqP}`qgcKv#vs&`TnQtxL_J66hYs%I4kLe8yZ3e$4EzQi{{G%jn`ZEt zV2q%S6z9;P-2x5Fjb=OMZ+C!=u!Js3?fh^H4q#YIBy_rRmn=FyZjp5grOtfIFCY<9 zx>reYD6e#zHYcYi1y2A4%k^~^iEv9^Oqqt%!UDKtd;rgCmgSXW=)t$UGItAj6tcJu430O`CF4`Im=E_RSoQOZyiO`Lp}vtt;# zpv3Bp8CJHhNqUA3Pu>th1C?^B(co1fKz1l`Arn`-!1V~{Y zs73)aX3iGwjA5seBi_Vl3F+bNldi%8cIXg5m?*h|Ohs7G%FPuJ9Eax%sq;7b1p0 zQ^Hs9LY3-3iyW)-6<~ii28npVkZ|`Omm1(6drRZj=bV_GDy5spM;`1g^G_At_@IBm zNY>=DL_<-TI#~*KsoRcr1G~LOD;y&&!TB>^G_s60(o+f?gAQ ztA%{d#I%IsK(!$-U2k!2}+!}{Sa8VtlNN};Mi$W^?zJJ=}iOzO+ z*kVdeSl=Kg1g#i-OAKt$=EX*;dCcocqxQlwIOg7PrWgR;;7TmWX#eb*iq7uh9bTx1xxbe zM9nHQKto3^Ez=PS#tyYaWxFJ%BsX7A%8RI|plXfnkoW^urB4)$0%59WOa*Z?vTf>) zhX-OhipOB$W7$zRdUTj0L@C(rX{X@~>tIRCM6-8tgJx z-9;0&nL}Y%4`Q}wj~-aYDlS?2>DA@@1-~HcdI$#Bz#9=q*&hhjpU+AGjv*REzEGol z&}<-Fy@i<96NkLEeYby&G{HJ^6^FMXOVYqQkj@C$0xk(2+!;vberqAJg}dTqvi-t0 zm}AirxNH&ztS!P*G{s!v=8>D}@Oy|GeLZ-C7C1$|WsM}DjCR-QCmK#F*VfT%7D)-h zp{;(a!-67W2c?FtN*Y--@_}f&1S?FFIZXG9nZzwxUPNY=BFPA5Akmh7iref}oRUq^ zTTC#IBo*v|`UM4e4j(Ekk1(_sQ9134&O=z>)*Z5BjSKp_x8ElD=mF^1MtW;Gk-X2U zci)Bb;K=uR`&RLqX}(j6ZyT!>_U5?W*RhQ$%?i3S9mbG1Bz`I;>o|V?$v<#zUN!hg zB}=1oBK>_+sUi5tG~?vrW+f!xkofR{D6|eEb(Hj|BZXq+?FhP7d9BgKiWify0VokB zE(r|Ep=AjxXZ3nrJEbmC9ZQJ-va_G`#@Z<4^(fyit=!h{z5aGl`F$hhi><%P$vhz_ zrv&X1wEliqDVtGZ!_dsfIJgFlT+O!X<2PN}MIRZZ#uHKxnc*ikd1XgxCjux!!<@To zM~t{gmb4ie!z=e%6l#WyiU93IpAX?A{8I6R;6$l`u*w5wQpxTxx1cX-zDx<)(Bn%^ z8j^aFMgtf@1E;M(+2A4paDIg{($u?fko1?-5Tr7Mr+X)4{^+Vff6?3UdOiE8puQe^ z{uy4QJ!Pb^W^`yqoTVwr&&N9)oHjD2a3K1!PfH#5fk+}Av2tV*?6w#M`CNB*&$b2b zmyK+k#XCy)cEn~6AqbJo3qFxEGDghkZwQl5F)t~kp{^MJVL@(tGW_#aU+1T zF5%MK$Dc81xDNX;Op8tq;cQnX!+`ylxr*6Wx&E6YP#!C}#>6Or?d3^nJ?Xl_8t5uy zSBtk{Bla!!saK>0!rB<=wCqF}zi&9C%V zOkz}g)F7J!ot(dA6)Cy|AOFL`ij*5>5=&3YX0UH$!t{na{p9nU`=wqHKPZ?}Ose-rHdl}P$4 zQ&jI1X1WEQ*~B&ylc)C1>LA>ZRhDFV2tP`NkZDWjiU5+94xDldyt&_8T@RR z_s;bG$76@r^VQtd{i!ei{SyDr+xW2#{`*UTF<+m9g6Hix{-4)dSN9EL0{j}jd1J)q z9UV_kgY5r{x3`R`BMj7ai?p~)ad(%6YjJm2xVt;W9Tx6T++pGFPH}ga;ts_fZuh=9 z=k8>mfA?hnnoMRg-z48m^5vQLea2UHQpW4Knl`t`A2G$K$ggZ2;R6 zNcB>VRk;MYuuFc+CHoDpYi|^caNkIoJM8Z-n;rfYj|V2>IO9Pth+48N_5~;tu_e>R zZ`gHjn7Hc_hI|dbAp5P{7n&}+*h|E$=>bM=n2AXD`p?@^vZxW4n=*Z>+(etvyDM)6$hZBVHmpz&aQqBAI|;fkmYXBzw+ ztl-Zg@U$7l(RiZsZR8w_Vpw#GG|)O-c%C|@K*f5YxIy!8(E^-l(lv}{X7ax7k8^y2 zVn89&?BL3!ae+wya7nt+XIG4#pvi$~Yw1~!wj>1cLbev~HyBJ+<9|HPH-ochfA&`I zk};44q!6Uk_ht1Jtp8PbVDc7h+b2$LY}B%Ev%kqCE`X8>nLcaua)@)9+B5qoLm?#G zBvp$kE2Vt)v$hf*u%zex+zcor*7h-)XC04%r4W;jP(#&0QBdOx6iLK%dT#t?HEXY# z|1FY)an#=(D9DUfAsx}g8TO;+5pK!)gBGj68HDVdXyZjgmqo;@FC#QzIa%w4 zlACh1S2}~au%&uiZmS;S{jj<={{B6bci{XRUQ(3Bz%HxPzU4{h*IjtnV$Pik9MepU zz@^?9n#gkafj$W`uYUKWXd_NNjv`UbY9o!Hl$sza%hY4o0xg~rFd4WnrzvtRep>|< zWW>%(r<$Fs>FUXt_iH0d3tmE0memI92XXrn?roRH>F;NWY;-uiK;(15v$wviJ$#sh zd|wN3|C0_qo)n}`XKf`^#gerETZeWT#z?7o@y9PsGrdE0t<0y9)nS(v_Qw;Wmf}c8 z8kj2NoUkbI18V9AQHzC^_XHyvA^GRNCzgPCK^fHS7?c$mLR&8&A`*^|&|=EE@wy81 zec1*`GIR<24Rb+V@3}zj{5Ud?L%Y&~gs`%M>3YgltyYh|A#X1(KH1X0@XJY9_zV6$ z)!{$M1sp3{OnZAx@^NHa07X8t2IvK+yHE`H9ipD`_R?1m8^a`7+h?vwvrAcPk7!i7 zZte=z=itp5egt&LJf^<)t;jNT;*>v*H6z0MpkfCi2~|6LD|nDs`nWx@?XYRVykzRc z!jMaKsV&7)hY(9?m7&Nn=A25h`(z+L9Zr?*x;9CwAy_Wj@BsrFD+4 z`s$$<7@3Gms%xCb#kVjf<}qZejyp{!8{wwiB4WI)bXkVfWeS6$QSc%x<)b;L#BH7wqS3qpiZ;VB#eJI|xvSw=>-4zp z^b?A@l^2@ws4UoM%d0jPnbYtj^W!KfQT}S3LLhLgrr=sPb@hzQ;CSe*ibg&1jQq-b zb`oJ>yYW&q5GCbdR`ZFu?SrZG$O=BEz@mXZRPQ08pr2NQqSzNlxc~Sf-yBu7Y_}t5 zhiA=iSFg4g=*3KC5-KUnX+W)-xJ^Cm+X-k~39raABNVx#Tk^b_LNmkDD&AO(yVCMT zkUB`Ez<@vC^EoB7HgS_TqQCwT=ax`%<=SY@JOQDYQz!2?A{5(B{C5waIigSQc#M zEl8XAvNaby0P(J#_M|m|QW5uV&tJ>@`6BGrXt2P3`oNxt2FgK^X_QvPZrHAwS1LYN zA*rguM>_tqY7ygvKa2pQ{ui-3jQfV28*ggAnQsRo7{Zg+e9m@bv4+vpj0yE;j36h9 zX3c%e3c<4o$E=^+leE8Ki}dRLYb}#?2|U%4Xjs3OX^5sZPY=`6y*xeU5K-qS}ahEp(;M(;CwZ*JYvNq1V&iZ z&NFVm#oqGine`JlT`(a+uWZQ5*4a-7h|P@7Z#%UaBKU$-1uyJ93KR7h(k@ zE)I}&v6By3kGvWSH+m@reJhX2+7%maCx~>9_{9XH1N^EK%MTTKJ?3(1>O0t3*GV!+ zo8-(`-}-TJ#dXAZaK#KYa&mx;;>js+a-qO7cjzQ~NiC~K7>-{l>kV9uSQuj@?USrQ zJI#fa>?A{irIxHDL)|1$=>J>@dym)z4nu--n<|)7~RjZ=p3_BkLTT`Oc+K9M!^8 zuuY%F3R71;o1e4^h(Nz1|0^46cE)?V;lc1dh!ni-S8K-Q3~3hcyI2r@4r6Q3G;pC{ z6{I{WMrT`vJc(qTqTcoRji{tJGH*0 z!#P!G?D5qSC^WyF)#zB?rgbVc+SHw=uV+oOpAgtW(fo-*EyLzf|K8}oIO6`g@IigsUQ_?)m>#Dlv^DbRW-iM{Lc6^)|$%Nc;j2nGHc@zmwtGC9LHl` zQMqlwq$7Be^V+S!#NMl9k~h)L#&MHOcX-(eOm&;@MB$8FQL2{8Ok9VA!>aZEeP(GR z_A>i5FTu~4t7Ce%$b>cU+G}4Ufu+;@eRt}63V_Z=ZCO?8Hmdn-RAH5$c-3h7n^$jh zevqeq_w}@AJIV_!f9o$vAB7<0#gOY4uf2h$>56hV_6H7;TQHS{p8<=B0lQ&ev;e&< z+8gGSk4xe*V|XMUwV;@}DP7Sx2I`$-MN&bnF_gI3SN-#DUJmHT{g@>!KZVl-slM0> zxw$SfEVn+!=MBr)2kd3iM$On(x?o!ku0Y68qce|c1-v)y%(${IeMYMuyF>l8zV`~@ zd>za-NGYJ)?PAmDT;wx9o0s7>L?)BoT3-PklA_LTF1EH{sST7=)}570K3`F{{WEfE z`;w_tv#lF3)dVpm^Pun!hi9Z8r1a5_q8EB?A7O4Po|)xH`HE!c>f-T|*F9CDu9a! zv58q)a-m#`S9_LhOC7q{#<3Nt?_2=8J2eHE7JW zMzo9$60$|??G>tz0()#!ccBp&&e%Qx8N7wcup`iJZcyXqRzU{N;QEBnd44HKIf({* z+of0SL#A^L>3T-NVc5AH3wkYLS50N=hzv`2LI)2R4bMU?aWl@~MoM&e*{bsnmwM&9 z*nYxRDSf-f_^`E)$6BJVdmS*hy>rWt6L#ajsk&NrNE!aKY34bp1t2>Cb2Fu zFe~R5F>?OqJj)p7ox3k4gIR6U@^h+lI00H(k9+nU_+F`-3oy2oUf=1H$@~&XaoQZ9 z5el!DTBsI>Kq|foUjrvxm!U)x}hCitRBO;nUC z#674jma$?0Tf!W38{dxdaBVnA=^0)%o- z=gxLW{X0M{0Ut)BNrK_d(^GKk5^m@1RUk@vt|9c|d6Qx3r#v4re)@;C{ut~Gc__}D z*8vT)<{U7X{vBzt3t=(wr*vZ!ZBU_18*AfN(t-NaiS^trmj#ud%fA;mM0Y|iM~0QA zfnQ84Z#u`@>9Uo?d?c(_ov>h|XX>|sWej`_mEsCZW;VF6y#0llq?-BsrwemnhV{Q- z^I@hf%Tzeb53?c&9=sV)YmYm?Ni$C89)ztE;qy!2Rsb4!TN}9=hjKV_LHtSQz320`OaETb_dyt{amaE!zWRp;O;E5W8=-RS3 zDOp(glxed(7Icrb==`QzJLhC;ZXU@puw1FV>t~rQOLlEv8Qa1y85fz*&+n_)D4LZz zii=Kc=|2`WTv;0bT(G7Ljbx2r&0Ok$8r@nC`?aATuFdCSWum^UWNsgGc$;j&t}PUON)o&=5hjc)Y@m43s= zBxC0d>HboMUkwe??WfB=37z=GiW%i#F`t9nA%x+#fGU28L7exOcci^at@x`VM<;io^sn&rcBSVy@Y|K1 z&ejX+>G{FQ{Nz$%cMQCFQxodv!l{^FIc78@)cZFE7-4dd!gM=!se7&8^-lGGCPcea z>+E4o{@Sy@BA@)&n6P8B(g7?O$}`v5UM%iu$V?x7Kj))`57Wrd>pjxkmpRH%G5T8b zv$H_b#;egD&c^qclqCW`>=^`9XO^T!*r3~ZkaQMORacF@b`?U)?H3G2mBQjHIwc2m z$ux*{g4$$*m_=e!SuIgjO3Lv?JkucIC2bW6*FzuqBcjz!;`4TNyhu!`*%IotPd&pH z*8AZ?FfB3w1PAe>ELtZqVG>{p{VJ)7R&(ho=oSFgkUcb_2FjoPc*pU0rS&Qd2qd+r3 zuJKrle_MfMUdjWc&VjZCHqV2=Ibg8N>f_eH; zCnstG-=>Jl%VDJhCwc&ww7l2<)_DVmQm5t2j|*;jLOBF}{ET7^bFkfwXnX!t zHVXm0=!mU(V&$ddgvr)w)*?EsY8zbx=IC268%DC-GKAGZY54@AnG+){rbS2gww6Vo z)@2A?1Iv%L*|;Sv59c^W8u$edh6Uk%TL1KraSw=j>a}0 zW8v3x(;8MajqwB;p%HER2{oHminVijIX7+26suws8m{c9w0M{nIO(fJH+jz?@1#wC zl|=RmOu(W7-HpAb1=9`o+oB>JTe7hm0k%#!p&e}7h#zvq*te;;hj4-ZQw?u zc@~snypi8x`{!1E_2AupR~(&)*UeTNmiX8aVf5WO- zkcR3`EcTPS4_dv-Ek61T3A{j5Dy@BuC&CQBk~Vm zB%Vo=nEyT<9ixXT+NRB=J8SeYAf}}b=2m$`blZ9p*EO`f41r6wrj~aAE_F{-L{wso zW*^R2i3_c|pZ`{Hv7|PVAp(T|k}#o}Ablg%ASwAN8J4u)Hh-)VC0zsSjz%q_*k&UUdsuanx}s=90ZCMzh2D$%^3ghOyF zBei2kIz)W&u1av$HVle{=qE@@Z)Xyo;mlW z?DIuB_p{acT_fhg3hw^tZ+*oK!5-7#*h|Z#7xvk9dRN^Zp9M+h=D)YE`S!1LUVN$WRnz;f0^7GVvRoliO!G#0e*2fDYJwi%1sIq~nPJmOZ z0tvi2AoVeIv#C|Y@%i^n@7!P1B;jt8DL)$@7Z27HqtLa0Q!{Nci1%L=>EE3;y{M+g zIPefxa=NTv1$(F6#$4!dx36xgGSzV|z$a7VdEesC9tm^)d1hGXDP+W!5p_eN|5UZj zTV&AS3C~0#p;miNMFW?7{JRWA_=VNr3wDaNOJrm5sSchsf?hJ#bvXXmV$XJ_Yf^hBcX{@$lWLhM)@$!HzlnYN0Pu@2x}Gt5yd457!h7P5%{Fl|EY4|l zQP{aq8qWQm`h>Z#wS^fKg&W$B;0TtnKql6*Xe454@$j6BhK~c0UGUe0%O{sgn{Xf7 zcMnJ84D?3QMw%*pY^D-gSfLSOv?c|309ZnBA62c3C0(?%TDD~}9??$@a-zu+ zb6{2(q_)0ZAdq=~2^{`mBdA0QL=kjJ1yPABy%$ZtP&psiGt^sTF=OZS9d z4NocljvUr(wbNeyB1g)iX8ta|X*N%Fb-2J5((Rgz*=LdV5P&3Tb$W3-jy-;<3Mz2U z+X*(O*_|~_c3%R&&VOSA7WBcHgG5}CMZQC~52VspvdRaJP7KY;XpIabRsBKF)hXy_ zZXb9Wx_B336ZmoV7HHXVC<5{3OD`=%f)+(?WgA_n6H{5mdO86M3~R;M(TSi-;>NT< zW##1lGVUj+>bfB9s4mp0wg`q7PBYyX_UMp>kIT5{!u7NgHU9M~; zBVVjV1LrhhS-?_4-=gjbece0D*Sr9Dr9#G-D0Bb{Gk=*SG-&}@kuoBnoSqeU))6B` zo!Zsk-^^FPA7>QVuWzhb3%)v9jA|p;aj5WQzlEl0I^gNOC0bVd+}$PE)27b;ZdmY7Yl_&A~!k0xPuQEYn(Q%w0- zS|*Ktza+}FlA_Gn+g^UK-;5NwBh`?lrjlnGh^M!pdy7`l>ylJa;_2AbOCGJi{afYU z*hKIs9s-3a1($&<^$4h(H`a~bE>bTi6eZXFzYTk>RM8^uT_M?Ydhhb5Sv~riw4+e!`?VQ zB&uqf^b#i%F^xMiP)p~k=7j0v8sOI1!25KzTJ7jDko#IWKtRof zeO`jHik+uv@T~h5;6)wMF|_%JC#NYn9|dKZ>Jr9SDG{r971TsuBl*$ubdL7@l5L3} zRe|0QuZUQ}4LR~no=K;y(P8dVo{fH*sVv)jmiwuV$4m(Fw?_yT$H0M;MBw?uw$#fa zKQ#LN8}v_&W)la8{GW{ZLwXKzo?0rF3LfF1mLal9*lzv50Mrjz#Vd{$>5LockZu>q z$Lj%=WRGUd8fLS3W2OZTP=Mb8<(Vi;E9c=@Unz`kRMLJmzZ&&JNN41{R8Uv=6M2*; zKiJ*dpHfmlk!&=nv>)jYTRfsxl)l)*`E<=vQq_6o++FhL5};R<{$@bG7`8OkW4}9l z9-$R7qMd|EAjIuxQqlMc)1nMRbxZQ#S$yt@hpP!P1#E#!hAq$EhBAnNtTG3Vs3ww# z6fvGMPJ5HYb(2R-z#Qmbjf0r70hw>>MPCY1q)hq}M(=KrZu=;NjTpYn$~3BU2eVqu zcYn%%TiQ3l`SL909Uz{vI@RKa8`X0Ag+l1hqB{aZMXu!t>Q4clBFUN;JLiS7@3RR$ ziyQ|+-KQAQU4aO!E$R`9Cnsr85R;}?+31D#n1Z7x&8NaWZ0&R+V46pgfB%sjTb z9?1oshEhSZi3>=XYSqq9Wl@An{B2Z)orIu|L(^Q0S<_#eP=rc{=FdNWq^3WYGk8}J zS}iq`p=C`#2GC7RocUO!WO|awgG(2U$ms?S5SvYWL4ABD@yS8+$6B zC{XF~LzABd-Z$5+z1yC}$2jF>4=H|T{+W7@0(;f~6>>Qwb-riKoTVx6=!@1Lgm%-d zCpG|ITf$K#?}%g+*%)(F!f3oC%XXdz1AThl{LH4=lyj#7+B%jUXuZIS1~@l`QNbxJ z%9##p5j1JjWUQFb+YmvR#Wu9XoP+xn*g|q-iQzBF*7bZjSQaC$x4TI*W^8T$N<8p+ z$U79q?ZzQZLd*mcfnBH)VRG%BLR_ZlM4_o!dM^!M&94wg{eO*81pjM$<*joTQ(8OY zG@mT_BUmhBXm4=gNt%Y(sjWMR*YgrJ8rgKl=;YM`;S9^~*@y7v(&bz0zlO<2nmc`J z`)qS5sO=|)380Xr-6;sy2Id6_)cLEGEmmkE@a@E&N+B=vE2BVob2JY-P0X{%>RI#1 z#&GAid1GlAR0yTW6Ats|n$}rXHDIyFnp~P9HW_0)E5yVLhip~>$p*49AR)Yy$v1`1 z3u?PHQ-RM2Yh6>6H=+jp#tAvH`xDyw8v({kH0_-CP{ zxpJs8|81)Z+^UL3F(XrtF;b0AEGyo*l!Uw% zzX${rPH14e`_GKkOA}j#7t1PlnFNs%P4UlKV-ZDlnPAv%!2%UoiB|ZXMo_cosq3r5 z9&~%6bB;0WfJrEh$pzG2Bsz2!A-eCcuZC&=c8JdTja+v&KB-HCCtq)eNYVJ$Ju9WB1l>UopuBDcoU*nvL!0*{I1h{~bto{M0tZLIWZdi4Gw*kJcW z#TS0Kj-}}kWPpsIPICkQ4A6`--Q!hUfDNi@Q*S3Qhkg_XB@%fcxWGdHO2*)hgfv3& zUB3JH-vp-kkiQfR2X}ldESg1i6P@1>=@awpdk}$ZR)WQtk+TW9BIUW7wrmKRFLS~H zIHygrl~^Y+@+X4RCS&@fNu!UYVmHDLM-DnTYlu=#T@dFF;s;>+ERIpK93pHR8Kaai zaYQw0`Y7{&QR@*lbb8xOH(gkWax(r*$n^7%1hb9>wcWqRWfdVvcv~DZv7&RrIDM9y z{91dOG@DnpPSDAB26#D6bKfAfIz9%j`7}%Ste|($2X4?5zdOYOA!q+~DpCbf-HPV8 zM9yydsB<3J-+WO89q}@U&_jP$o_%5{!>Iml`@mL>`UE3ymv5tR1NWk4jj%ww&^o6S z3TBnyCbynyq{(H|DwsdPKxf6iFPj*m0Aicvy0Qyr#2MzU;XuWdxoBi$3uly!9dM2`E@JBB-y>MqABD2~fy@0Bvc z1-kP*s$u_8>OsN`0?^H(w;VHf>+1`nIQfpcwQQHyG7$>M-MXemMYW+|sGnXMMj-n; z9OyXPT~VIUEO*4;kuL%degM#OrVAY+vl!LvAe`yK!SrKMg+hM?&c#-Cr;6V~TXcv< zzZEce6?Q+)_eCoo1$^6?8-66*`nz{9TTgBjEK9TWG*vyH?q`!ls+|`$_J!F}SbF?7Yt z3zEW>%81Z$aS3}4z)w$UEr+B$;oatbQU89kf?a@`?=_{*U1C4^hZonoX_sVIccYc- zbakU}*iFXhQiodD>;xX6Ch5xsmKSqqr7SgFjj^ovHPDPNc{i3Y>|0mpRC1rDEGfeH zg*MscAetg~GZOXl^Am+=_A0?SYIiRVic${COr&l9a#HBJ%Vr_DRfdtO$3}0fkjGI8 z-1XZ&5&6%2(u~tc4N;m)2rG4Jx|vy$PKrgn-X9sUnnWqVT)d))tVSamQdAZMJ~PGT z1&T0=;!&0yZtSf2%i`*Z3W*vzM{x?Ny%x`baE>|3HRa zjcCWoAv}Y^Nj6-}GXnPZS=E5%+!Eb;%21$Z%2=PxrD2ZKpYhdx9l-*~>n;n$;E;Lu znsN!Q-lJOzn5g8o{bTJ2?m9zE;vDavdOYR_IQ8?|&Ia+IM`WkeeoI8j*@F^$A+fLh zRt+_0?N{F!w9MjrD0gkj74%ZeOlC1CzsqN{DLF> zG~~8`{kG*YA!hJOdRunbOWRpsN6W%o9|?4g{NlehyaoApEq#%@<#(1zoj4>b6;(c% z5mfm)psLf$#&ml|H6D8j_h~z}<~t-GoWs{8tlthJoWjaj!OH~gPP)LNVHfLhjkIk< z@>9B`!stu%LSpXxqeKgJAnc58``YsE0}bk<;|CDQ$I%4Mz;r|)rfPr@Z|YBLh+*+_ zGt7~l{WqxVu^iGaw4v40jB;&_AxjC;kQkaFJ$x!as5KUkVwD)CE~RaWhU=6TFr_R6 zRGg}Aw_ZEPeFaPkTxidAMN>E5uR19}$GO^S!d?UM#pqs5x_FUoHU2hG0oU#6Z*nx> z*jRFTkT5#r9H3r5=$TYRaB{J}HK63ts=^hg!an+dt-tO1@@FZrsfVsMm6sO?p-^do z+x1nJmk#!@xt;^SnDK<1kX#rp%8#-F?ujafV%%5mbA#=vg$5o=5>*FMtVkSGE|WD} z=xwF?Ej~T%QTD^0cuOIz5Eb<1Wani9lvtgjP@I$sr>~n$KSW4^Rme4=gtPJ|axw* zzd8SlBr2TFZQ`#_jCc0s`aK7HaT-Fr;kol}qgF%2WcunIbYo|H3ZG+5TIhp3i;-$g(Y17s+WB)V%P z>7nta@}XpMrfeDXKTUE)?gG(Hxyf(hlT?6m1{-U#tdy+|Fohi|k^nc$3U!mrc|+)D zOTfjxu-q4BHhb~j)`;?yw$3VZT-p`>ijHPojPrILayB2OB`hXSdTBq{kJJUTrkzW| z`J_q;LXZcIBYlN=zEWh7)XQ{kkFI~)2TBE~JoW#;4gVL``wwo&!}`B}zww{I?f(il z{QuM_|J!H+_#ZP`0{*+v@*g)urs#4C`H!4nz?zSc0!eSc_xiN3??H$-ER~^oq19J% z63|+Twy)uGpPnCu{5}q*cW#CJ{dZgZKCX-Yg#)i|d;Wz3 zZ>T@hIG(Sl!=`(DKg{id->*=fdV1deN&kIBVjsKZ0h3_rJD1OY;YiKI=*ftK8_GDjoWmG~|v4d=a<$yc+S)oQA zH?^{ZH3vDbNs>12$BVq@TfrQ=5?l;;m}BON(5;~GA*Rq)LJb|J{K#rs17Dlcb-RaE zK0a$+G*#!*YO()xY|BOhxR+_tju+!lg%)Exfucq1))0EwVnJ+0$cdC<$w@4BvEBYc z_fQ}TBaPvUo9U#dxg6z;*;7YFl8c^~N;f+pR%oU_V!^;kefEw&juV=ng|9>x0d`0A z2gKKDgcL?#Dc^7<`)srMdmm{2_QEgrQ8hLQ^i6TFa@+n(nwh>Q1L3>qa83XOMS!2= zfHs?a()3W^<#5YrpSbRI8Ot6T7-X_#nFYRZUJFqRlTDpySd7ia{+J2uRhsHa&BKZP!1iwl6@OMo#wKD=a>L%6LuzeQD0}CXJ~Gj zcytG~)wHe)mP>^Bmb5SgU+!48gTZ(dm=R7uYNJL)T{@m-&hf<7I?~hAkV%QmbyZ?7KKSavo9b-Md7J$muH< z_(xzc^cGd?Ls00h4i2cDy~j+1o}oK*t`DzdO{oTo=2m9A_C!Ly-$a`rAA87a#E`aZ zl|gq27h{Q1Tn}OeHFOv=XuK)rzJ2REvcWhBm7Exn3=^OS-B-s41?}Ku!%5qA;%cj- zDqy5b;(!y{seY=h7cr&DPZ1dAmB{p`y>-CW>PzvW(x{{{QTmgcGOqPXOsXQFv!n5qJf+hyn2GOu0EsY!)NZ{wCrOU*Z2Ab#} zOMl%XQ0u4Qe=YEcs=-s!(x9?dxg6NEi{8cT*5vy= z7v1-+FG*hBq>pY0;>Gj{I35o{;I;nU=gg+&K^~Mdyy-1CX9}yQb&8h$3rQ|5pL2{k zgH{jCOw(1R-SU`p9Q76}2NZTQ7^&;HA_AAJJk1=)hN0%Y5)RAj(S#>Muh&fA_V3$~ z2ayf9q?6fagv1xfZcyAx4X|5z8S!|;?$@|^R`D?rV8N#BzWTu`Mx!^Pp=`bVxVut~S=$;V`$c z+{>WS{P^mgcy+%IKJXE8PlNBFnn=|IKZ?fIU>hHjFl4w3qM|EFI*3B~PNuBrPaY;1 z3C!vSm3$Q!!`d1%Q8k$>%ks5~EM&|+-=3KXLYKLrpHjsubiEt}Q8m3MnoDZwPyJ}R zdu5GL=6!@3xIvPfmsTO{u|zoXlhHB3G~bRO!Bp_=E&`#v+t4xKkH5{$NkpbxO47@v zsWyUmEyM2@A|wthGS?+y+f7y6f00XRnDsh}h*zGa@Z!00q&7$-di8kMHwA|pmx<7e z(LdiZrygh&aa;M?u1_gj-L27yWHxXfIk1l%N{osejdfmQ$*5@@+JRG29C&StFYy^L zHv?NG%xQpv51LHzgqvkkuecQvL3&!2A<%uKB-AV*nw)jXR^Nb`?rng)#sOtPr#$t~0`g^By zzvstpsuLdwiP=tfa6=h$p4cNqB`)x1!Ftp0@qN--L>C7%j(;Q-18CW6 zT@x+|cU@=#NlijTZ1*)fOXOi2S7FCnbU$3hD%_hy4CHw|GFF59%l;XhF9AXM-VEu< zud_TpAYQsqD>~-JR!+ZlIm%T`_?Da$B~>6&-@WhTpLooiZYufhq-;Lbmy$ul1@d9p%vX~gyb8)>4gHAaPnflYDO(_;V(dD`-ZQY zg4L%bh^O=RO|5=FNg|DWg>!`X-z$1~SBtqeMje7>Pzb-N2R>|5MRC>Wc|kVbcen9Q zrvJb@6|xG;FI!&1C5?KW5mH>GC@gJ|$UNM~ESA+W$adqMqei0Fv+hu(_81(_-ozUl zYfs6;30A*7wVg}lDXYwPJ&6BSj(*+SbhY)|if!B!igR?ohKO}=2*XjVGI5JE=~~*s zQBCs^4lFtO_DawL`=Oxo88$V?TE7Fqy(Zy46#*U_nF1Y!iJiY<`kIYiS*66aR4MPf z6%sG3KW|A|h`YCRQxYnJ@9U1hcOUDK$WQfBGg>K|jOzol@x;5tE3p}BS_<;o5?j-% z?yE~q?+`TfkINM9TA~()&Bu3W?WO)B&4Mlh6bs(@9ZmQzU0x+}rwzZ~E33B(cKu$W zxgzU-HrH2W5--1#77jNQruNj%)u0}DC<2e~NHru>%|PAm)R|2O$y7b6-LBiWdw!A% zJ&OFS*QCJ?T`1g%N42zDd*!b6ieZc8fNN7wYOm54BVWkb6fNpsV%$LQd?w(~ro5@! zM~xdfI`^{OU&lT)j=HPwbDl5eRTSUtMpAIMGo=3La^WDvQrTHQ&ejocxEtKS+{N#R zRfn4)K=!5ZjC?>>odse$ohE1>A@jeS+IO0g;FQPaxo-u-B5&)*pby%=;}@;r5a6(o zf%W3#7`#gA+aTh&Oksze1TObSasI6&$-tYuFkk2ZhWb_TgO>ue^}4GzhF`5chSWV{ zmkaf)NV&I!QE&;amMfV`iJ0d+;8E4(96DOejFR}p7Mk*}47rY)y5ZduNMATz9=AMe zJ=#y}?WWvB722vAHX@wkmQOEKMOw54OaWF8DdZ#8tD+oY{;zp7%pDGk#L`punsDf- zl;<&)>E~6PY!?X);T!H(2lnbkhNU%RY1%GAk(lS_7s|B2*KFMU_csadNIpIF^yvz; z_M6DK3gx7+E?CAC_6aKXwVwSI)inG~EC(brUnG^8q23(=CW`#R`Y1q_-KwgAXe@kc zdZDN36^YlZuOtW8%5W?6JnH1}W>4lx%g`jrr>WJ3sKjQ2n?%3?%kpzY(vu=DcVX7? ziOXHQ-E6Q@TT8b{P%f`=R@fgg16T>y?W4XaM?((^`$O^=%A`M?m*DdW7A;{SvZuuw zKJ2wciz0DtPoi0R1tzDQl%cybzZC58id(ueem#zinJa2r^uBj)y_W|vbqJ9L7E2N4 zVjmF6Pe~Axv@1#=V;9+1{kx*%=T-Y38f?@8mMmnT^hTa=VFWLaD_HI3@B>(wK%G9q z7$A!#&0Oh2;pV{r?-&L4JQ0~?p5!mHcAg-`3pDeCG@cb_9q-=iECOJGTMPm*8`wgU z6&=+l9cYnWeHTgsChE;YoBE@Mp9wJuA8k$Ut4_xgsO-xT#5|w27tl=yzy?8=`kftf zGc9POFQ5d$>`@P=psXHq1*7#jJQSWpmpwqHIeRRXb^LooV&C~m!la>LjzYhMJTAWH z`9s~s|L`_|!f$L4Nc@&3ed61cQQ71zbg*BRE2+ycg=2Y|HHG*iu13SLHIRty`1)*2 z>beW{?Hp)JaALlXy}^Dh?lopWPWnNOJpYsI zT@N-}U7OSQCaE9o?W|iSS=eyJRZ~Vd8^x41raglm(akfeS-Gf^8woO~I7Ux&LH~7! zG`QIJLFydfG=&Wi>(bj5hQ@$_zlq;*oLNBbPv6TM_idy`9=*|^dAvB%Xby+%o>K1M z_SAi9cbr>ZjQ|%`ZOK7pxqW2~iO&j(#iH)XCcM^EPR}P_6A~S*Vb2g4d#?9>X5Rw7 z)cTJi%K6_hVa$C3*^WTnQ$Mu2r`k+P%(^i|B^xJF^bge38Y-vRBxN)WIl1#Ax^Jm0 zTxV0zcrxC{TAj<;W>Zjk3QW2;d|j7*hOB7JIPErZzF7|P#E=uc5&}%i&K>M6_-E$Z zR27n}z4FOWe%*4Y7j-IjX3IavYeHNO$DL(O&2s)mDZuTnI?3AOf!&wGAFDFhlw4#S zf1cveqYg${b^pCHa+vj)PMn2K{W_t@H8E_Q?{qA8u=Y2}g^8{E0H1elh-(8Vi8^3b zDy-)sAR)Jhp^m#*|3EN%yyV%wY1Sru<445CQ_@~bScqTxdsY6WZwvvGo4cH?ShIC6 zy4u||rJfwLkAT#+c5_WIyWkG>hctuEI7lb;Ho2l|jau@6&d6Cr)qB(NUOg!G$uy5= zj15Cs`;TR3xfpgNn`4mwu#jnEZE$l7srE_*t}?JsT^O2KdTW9y#6to})z^|KJ;<$n zy1qgk?-1mEfAcv5OfbwYtsHg>%RUERn$@A9+__shG098(b6+Ueney=FW4zmo^{ovO zO_^f3kft*AB`%(V4jWIM2sqT?L#I}+oJ&*kEn1e;Df^R)dg)tv@p&I~OvEj2-^`)( z>&Ty{bdNc*a%~-Rmq^w<@yDjD+a0uO=%`;SY=6xw^IKc0-p0!>1{+FuM0^y6h0*xd zNOWXmP}w{{x?;%`R+4mFRh1tHYeG~d;Y)TvW>A{1`kRv|Vh!8GS~6d0?r1#imoX%f zeLjnt$0x|WGDF}YseR75E$oZ*pxrx4GSs-ln6!vk=z0CTTs=4ir}m*ys)$3i#hQp@ z%H%hA>K>1c=BNk}e&tJKjX_7CUg-8cJUus)V@CVyn^RNW+1;_YEg_Iq<~ITk=fio% zR`)z47`vmb;v6Ao&t&>2yW@em>O+F9LWQB981-`aInr4u@3u zN#lVIF}>z$9Z_C&eo_RO&oT>Utgk=)|?P7UPB&Z}29+716io`A9FrE+oC#xhUwP`oKkBJcN`1L=}Jx^8b- zwB*+b0>0_;wQ}PHR74ny%|C}Z9028aR-LnUspYC*FO4BvD8a?t3Db=ZPxggs0vje~ zrB_dR!FRkP82pTIr^o^i3ss35KT-1IKlC?^>&i?$F<|a>*D-P#C-)Ne0^L0qvt+x@ zBgcV?SlsO5ToH5Xj`;K+QwZat-DHPS^@$!@Hbh!4&KU=)>vC9Z05$s|=2PW;f*R4r za9jH5FlDuoHwhi11+C(~&Wct7^~F48`3(Z%>qw%)QQm58+RIQ`c|27Xlg8NX$>tpJ zCli;}qDm}PuTdd%MSe}B;Q=Rye+M%EI*iM zsIc^u6nku!e6<_oJp@{W65TvQXN#+Q@!k9k{rQKXAa)#WJk{e_J?G-BR(^WH_03IU zNv+w3s!(=x$#8b{$y(0_Q?$Hz#5|;Fn4xOIWp2)QaD>P0rKu*<85+|;7Pg$-uTVt+ zZ!<|Z@p=&Hbax(;{e8WDkwPtL+#|FiW8+ zWU8k(NRuXLjz$vLJIYKi@!zybs6{=;{bEWZCH&D?~S#OYY zj8#*O4A^&+IR$Nhy0n3Wle3>a->%eO$nd8V82A!Ow#AN7*U@_3fXgVj2jWMelXBhZ2xh_e*o0~M3DbiNb3I@;J+p?|Hs_WfdB4>zQ~Xr6KFvjJnD+< zfbh8UtL#M`>78ORMMZ~&_BLeu``}VOrM#`-4U>P}OWe~_R3W*jtls3uw>$jt`aC?H z`++9-`EfNX*h74BYw`D!!2k7?I&0^)hCFQAK(HrYuh(Dbum9)Uy%c4R-PAOSRSEm> z!}I;EcwLTB>@>6R3B$FtcA0Q~R&V$U&Z;J_XiV%4&)kYKk4vwiQ*6V*IXJs227%C+ z9bj^wRmgp65%nA)As-g`X=Itjlk)FClP7y-T#{$W#}|$#g4)O>Bz0Tq=K|46WMW!l zsU*K@9|pyIb6+3+)hzaXyjoKUI$IZoD!Uc-JD~ zD=w8GJwpw9S#cWA43j0ibjUS?#sW_acyeAGnSLULz3{#XNd758d91u>eyPDmh&dVT z`R9@VwrHuM)Hjms;aodh0{Bww^}&!i!MS)FpHcoo;vuQ#Z^UIVPkpVwP&dEOJWv2O z@EvG!NM8-nJ|&jF$qEQ%-p}P&wxdBV?yfI7#X9L%A=f?Q(Em0byH64c<#dv)8W`4O zxzvB`bA)BRLSVkxzk+a+(#n422`XM~*}LRkQ@ZpaG=QGJ~HXh_LbEBk&>_)^zV03 zfxBkZ>hpskG?d4yP!WBUX~A9>jvoLM-WsNwD6|Amy}? zkoG8Mr5pkqnY2HhHpZ=()}&*49VoBPCS({H)!o7zul>{$)>G7UOx*;Zs5Sz2J#bux@Mwg$ote^kOf;816@Cb4YHq z+mkPS*46)_#BFzdPm=$t1OwRowgm|ADNY=`A?@3cR6zj0JgwWq6pR)e#TLfruh#OH z{FvVYl*vZ}oCAIw_yJKx+lF5U5Sv(-?YIXdaJ?I7Ry!#Ml#0tLpDhq9RkzK}E5qth z!uY_Cga^e*Hs6s_*tkg9sfs%vvuH2o16o?BM;io(=!mQxOj2sHs&f{Z1FF>ZL{238 z`!d3BbQ+pNZeqP;U+J8vr>;zSa1fc(y0i>}Ub3}3T)MTw@}+xvCK$q9CnE#+&= zR6l>veP@eEJl01*QR(0x3|%= z@#rf9s>yvfN*H16G-2@JLYIk-NV-4~1)Y3BEQOlXnx|DyU3$;=l)~--Rd{80gb2hf6mF%KHc&-ksz14$Ct4}JFhIiXt4>mX&&#NvGJGO1?<=@y^5Pb? zf#h(BMn)=umIWKI4^xLGLyyW7BWl~uvzku^`w1uZGbj{&S8c7q63}aa$Q4~#DO2tUwvOww6l7k9^ zQkscH*sgRRf=9!SE^L~&vF*~vkjy{u%^Gi8V=iK;kIeT_%R<%_rS9@Ol=BK_A*%Xi z6x$_l&v)$y#4r%uutvCMMa;w<2*eidv)(+YboXUDp$%R6AqoOk&<~`1*n9pZf;(zt zgh;;FX=&PoT9l{6=1#QIJ8Lrt=1W*@yx3fa@C^z6zzruEHf2D3BC+v2Gdv5S4pS|J zPC*Jan>QJiGii+|C7CEDAg}eILblwxC&TUk>Fq6`;z*meVI&YF1PK=0gEPY55ZqmZ zySuvucMYxy?(P~iXmAU`A;H}t|0Mf7`|f7dJVHi|*P z0d7+uD{gn~6%sR0tO@4c&!WL&n0!`S&{C%mP51x?LI>4aJn~1HO1Ck|FcR~xT(UDitgyhyOq0z45OJIm+eva!v?{^XP{DR{ zwfYU)<4U`Qv4+Yis7Ckl7@7Oen4a%s$ zc&sOujx|hGpC>m;_RU$pkh}q{3PrvP(C|hQlBw@Oo9Nn&hrvjK>5w&&72{TyHOg8z z-4?c6-S199!->F{df5GbLC(f=`op8<9V_pE2)MvBxPo-Lu3!#>7?Q+V8z!S#x*(i# zXowY*>=&j;edRLX5zOOf+F_)&0=Ov;t2s*KZ zE3Zm(d-daNLWMpZlmRVxcIDG{Qvcs+d>tD^58{ODfE;f6MsNA>v;rD8fR zO;(b@j_J2_vkA;?mL;SatuB#-nDxuO2<~@4Jfjh^=Dc^U zDj;}<*W2AG?T?V6cKu`u(6m$@Bj$Z_@erF=j4 zrlBxqVG5HM2#XVnV(EMLWs_l(&#Hy{X6?Mm?Ask_$_m86%_+lirj`)jFZry;i$GO< zZ4-4FE>1Y&8G{1K>obp z`CrSY`#&B14|U}KSUz3Wf9BIYNRfI@1Ht-99ch7q_~d0?BFDzQff=4)6eWvdwZIKU zn0p1Hyze|R?dVjUic=h^G`|!uT&*)uD>GF#IkE`3A&coBh zyX4ZOySqE~GKT9T!pEZ>-AbJ+C6m@p^H$#WvAelDmg(E6rIyYw?e7MXyrbG|a=5Z; z=H8X@)?T7ZO=s88$fu5{F;6ee8AVp9>~}XNryM=%hwam~BU;G4R58Q8BWTWlc#F;+ z6*XYxoAOx;HFy58&PK3x^oPhjldsp{ ztcU2C-dSonio0-U#pV7O{>L+}gYQ9EN9WIr`0~f3M%tbVX@sM?mkZ;l!|q-y&soF7V$xN2@5(eUuwR*s9sB+XRJjy<5;WUe!9G6z_cO-0AkXEI7-r1l}A zJ@@Eujwxh$g;FY9i$-Czi=|2F3zJUdWXRXf{=Sb7hCp`G6-QlU<)WMGfVK@s#|c}s zQjk&#W6; z;g~$U(9A|z?7c9TL(qD!LH%Qnf|>Nh(;C^2m%wS|eiC6Em^x9)lJDH0G{N{_(azq_ zho{P8=#ml|rdEDlts}MDR)P|nDuxsAQ8h-EcJB&LsTSD+k2gRo(q<->=jYp4AL50r zYMxo^lRDs3u<2{~`k1rlpN@pBt6LDcA?hnaNCY{?%pgT%L(Hw0p%fE86j?%DiyUf(nBn7X zU`~i&4d4aF=LN{(ql5=$ziJd}jUbn+yKLSL`Q8|a%AEWxo4gxlbO!*sRDOv}!cJSOaWTlY` zVfx8i2VFBbScBq=d@cV|3H}!KJnl)Na%`W#WL#DO`VMQZv=1Y_G{xs3M3h$?xHqwFy*_VR`FZO> z8I1u&%+=u{N1wBZ#tc?VDH5Z|g6{0Yp2XH53CDGXayB*~xhk@xd$R=w%pu0vM?OiD z(#_&wHb+L(rpoNUR8msurb#y>U*;5qh(?EkFncNsA5^BG@AG^6qus1ngr`WdCOZ5Sl^^wo>^#`r8InV@F~avvj)6xDG-Lk{KCWG#}hN% zuS@gZu9v#Ody;Wd-v~%k+o)0RRP)y(Z%ru772okvz4E8xBAl9@ z1U=+P;gsw!1w-$Q;7{CO)!jqjyA#EgK95Zc0?_>UDR;K2s2g!@OZ-`bY^a!|o)&$t zcsdKRdsMJAKi(SDJy>F+{s!g~c~fK;Y_ak9a@ndF72meciWnwJ@P ztACGw4*04Jf6yi}lSzO-=(O{src99Gb6;PtU@0@X1ph?TC&_0u^kK{cb_Uz4@PVCF zr)^(qkV+%Tr8%dB%emU$6xzGbV=N@`)ku_EEg!Du>R(7%DSni;Fnc$^Y}~?}o6cel!9b?oHK#eh>lJR2lB!P;MXAf8=XMx|+2$y%T9i;fUzf0I zLc@D`GmBFJIu&>3+^hsyinxh!T%|(z=Bsgc5zQ<G&b-V%qpK;93F=u_laB<4070djxaV76;&@z z=-asg2`|U=3Eb9Owv+j2urCVSODR$ufrS?N_RXog+e5hy9J!!xVM5$1n47{$P z+9Qx7!mO{)TZ7IoPMUz!GA}|c6C%C0`cdLT=12bB1cK|NLBOLFoy6FlfAxy%C9!-z zRbX@mm5eObH*gbSijituPTeprUF=Q`N3;lh?15}qEoOzihw^0Ejj=?}tSqcO+Ae-3 zO-n)ru18Eo#kMOI*~D=CqJ=(2`Nvmu;~#l%r;~+I?U@W>v#Q-5ZzSmqI?UBrKkb;m zuCSO;ZRxY<>R2BjA1JaR5R%*Nx{IruT$pyYa!8CfF-vBOFFGhw;GaVx+6=Hki*PjL zBrNz`ccA*hA^urs0((0G*oXG!o9xj z%f%A)NT3vXnGl!;I+ZG%9g+->jD4Vj7k;hw(r!*ODyi|&`U5;#i<0f#_WC!vl85)i z7W}nfmVUQ@uOcopbG#@u7X_Y8V$$}4?v0{nd0y&mUq6grH1j0?xF}}-7asU8SN-{v z0?Gr2u>Se*;+J3jZ#=w!{7br6$p3r#h(8j`0?B|tRyGb4X!co0CkJDFYZSMPEf04u zY?YQv&Yf~4743G{mRgs1S*}cshTcFJ*uXTTL7HG^m_B3-id8`jOaMUtB^HGlKN&4W z9X^JCcjz-3d<;kp(#SWYuWQeBl;3{Ck2_gk4cy%9n8}10%D?uq+mjUZih1#oM#gj9o;3Akwv_m3NT9re^8G5MqX!Q# zA{Ki;VHusTt;)b9r;}erTnl}4ioE5;Eu;w*NfTmA)5W80iU5rF%n%n zi#k)5%O8Oc59s4rY(Z5qEm-j_1b6i@((3Yz*6}+S@oX4(P+u*;yHa@!4>1o4JboD% zN1;HCb7DbME@@`sAWflU%bbhApKA!$R? z@4lSTZ#m=Msybzs&ekjv?&z0@QTL<{^9}BqnYYYN`@se0Sz0)0bzdyv@Wd4tqKC3X zqxbvb`$DqN$>6`iuyujSqFq%$)6bODtl3g!Oludi7VHZ?InoZLVPlmg4~RbStvki; zGrkYpRLh%8@=ltv9phqiUJOAGvs}lQvAuaqUvG6cB;(9>*_GEb;Bh{`)XZ=o10fJN z!pdf|`qJqdK|Un_)F}~7CF+&B-LtQD?%l4~uqd~N@IJXXkxjliqzx;wvf~Mlf9E`U z9NXXDZ;2)o9n6s0QcR{VAqZHjeG(@7oa154O3s&vDmwZmLCHL3y2{yZ-pNK=J9|z_ zHm;#TiMq1(YbDR!K7;7eLW|n03yv)2#k!c*Ug2k3S)C3qEJ6>aTMZoYNx(UTW#N5c zUvIxa-P|YY^-ZlI$F@x^TeOxrNvgq6Aw%UeQBMB;xaXB8k;FPLI4?WaAcxggGDVc1 zUGlDk&yOg@1RDm;1SKjULE4eNrN_4BQFE9Mz!KA_g#NRWp@hkV`>>`{d=U!8NNk2a z`=gCbWOtqYFHHmO!{X{AHS@;y!)@H3#yED2K%B9g5<}l5JTAnt!M&;u&t$|&8p{R) zRjXVzL`U-FOy!z)-qq-Ox2=8xzvy^>C~(ymYT4>?kR~^G>29>~`9{UvHM50suhjKu zMTdx`gFM(f@=dAm%_vp)^#u~=HwuAajk#U3gt;sj9XTzh!M=}&TTSs238_e8(63&sZa?@^ygA|zUik!&3 zX=fk~_4*Tk9pd=)v)EYe= z=oG23Z2Ppem*z^+;WUH4;l(@ZZ-5h?%tu(_S;cm#H10eX@v{YO@^o8)RMZpClTFxV zmOlD1keHX1y!}&R993K@sq)fyyMeSUGhI@wAsMS?xxv-kRtEs9Wj>M+AW0oJm*t?n zf|#z3eJG+B?Gs8n{IS>`k1w0A=JoN9l|s$YTrxk`rxt{Q*IS={O$UA-6zY6f4Oofx zFlT(-D#c^j7{TCsQ+nOK!|g7%?LV51o|i|kVOxqN;zS(1B7J&}1g0E9)DcS3XrkXy zWQk)8_T`G4h>L9?=$W6J+#DGl&1->7m1v%oBg{(fsh09^QY?LsZT(DSsP&4E!}}x) z);Q+0c66`zYR*Nao$xdcYg&yxQa|d6IIpP0d(I&v%1Y5s&TNI1j3+sbW4e1<#Kz`31=H;FHT>adEZFfe7Z63GiO*Ielhf7*n3NYA$~3oVXC5l+KFfJM1BAs z0U03-q2q1ddLZ;K0bTpa_(19~DKDw`_pd1Xopbs!>yoFk1Nf6O(xyI`x=bFB<9vFq zJ74Q`dFEVS55KE+$hqJVP@~3%ON7t;aGdv}ZKx(fvS5t2@wK<`-lVpO($@u-Z=t15 zDp!ZClam_HR=7etv_f0L$#^gD0hm<^&0n_5>ZdIei;ePfv%78J_abwKzL}C`P6aKP z`TFmmlLQ+IC!%gF$}~kJqFCZFEmjp)Fds#^9}yYPlwZ{{X*Lp7*f1rdT*|WCKetv6 zV=F=FvqwqIDHI;;)i5FN7U%pH_2m#rgFb%FL+vT!CmLI6!9cuttPMC0q{#h#I~^xQf4tIs=$5v97Js`f$KQ%#sG{3`)VIv#uF$qmFtsFq5KeOK$Py0W+{-e>vOQb_m( zlLyH9UVH+f8KE6E1J+4wIN)9A&V~VwjC-wy(WOG#^ZE3%uchTU$oGPdQ zkiEI_y{OwS$w0O`Pn~;-Ysq^|hbm;dN}4X=YStsoQ^P~k(YpCkdWR)c*0~^n`MXxK zvxwT6bULr|MSW8z!mySRds2osPrTm7$3g>c1hH!+CG2JSCe`eca*k;MbGwKX|40Vic$El98 zaRQ+AJco5jxOSl>ZV#{A)2(-YpK9WY_ZCKk?DgYj0lBeZejL-@+FBLqk+4>ZzYk-A zxd*E&NN+W#HhvU>i8mkA~>udyRo)I$?nTPS1<1qE;FJ zy%6L0me6&8ypV+v^`<3>Q*B=Dn`-(%9G`fB!%6sw zP;7GtK(6NJdNzIM#o^S6q{J~Dx$rrgk0>z1FrJE91t0QrKhX{gBH3I^C>2rIX#s17 zth+G26@^DlQYl035|l8EDY;FP8dV=z2#D%h2p)7_!AuK3Q?7^fRtm(TeA^I<|_!a1yeY8bZe*a8Al>y5Xc; zpIK_ix0mNB?Zw)})>mZA#Fbr|ceQm}W6`7!afVhZkSOhAGf1eoBi-MGxgZ5=TzmCy zuZ4PeU-I6kHVF{x%IC-vG`l>cZu|v zvVD+tR49-gL~MB>7pQ6?$#^F6gm*T_JaZrIcJ^j&sFatbP|Sl8smZXdm@fqHOBfC3 zGA*o)3S)ttTed*c0ETU&wqcQSGc+>do2rEB`J}S0fdbN0XlDn?6S= zMa8Q-FVX|ex}_>&2eD!T!vIVM^^yT4hBwH5kQhI8WCs)}nd$eKm1UB+=^OXQ1Yi^s zG-MOt6YduuohdB{#?LK>cKw*XKM5W~hR^3pmoNndN>hP9d7WY_P?+PzOSbaMam9bN zY@XxF!kutGmv|#kj?W!B85@;47xN}F5xz!Gc{8-uRIZM%3!VvY%}MG~7BdgwDCqu> zm~~okfq1=D+bP}ajYsA*SXL$MnJO_82Z^B;lT2#Mg8rn;O#z%zb(qqJeb8jo}EVaci1prL5fR?T_{wBJ7@7MzK0H zXTFLtFZ^U^Ghw7C%0T6sT1e3{MmK|CVSBPUVP7Jnu>2{2>t(L@_A8#|Px`$*=xSQ8 zw>}ZGrslnDKEq5dudCnl$=s`PEH!d+3$#01% zhf;Eq5)4yABgRRf(qVp)ej^#S0E99a6$sUm!FCxaQUS-Nj z^@guGq7!qqmbYctVjihBATo&BEZ&N#%1hjZbb1e0#;;HjzEt_7_X)FrH??J^+c|3- z)eYD=v{ePprTlc*$^LRYzJaF!eFIsXeObnU?gJw((q?tJQE@L)P-Jjy>JPe4MoO=h zT>{&?X8ocudxIPs^ zT{zfcLmg!ho?LQ(wJI$?IJ6_hTL+c`9&%>kskVeySeEaHdky()AI}p z9^&ccRXgTe63oB^{AD=JL5G)A1VZnPi3VR%>Hs!9j6J(Z?JqWV^FQ>F*az;e-D-sm zq)5;toGULFhc~?7)H!)GwBapJs7AUWA39Z0;?SW~zvKB~X1?3!!y8-kZVFKE{+<3O zlA3Bv0uNymNgql3p|nJ@3fn?0adRnPZd-22vZE*U4>@Y@+Z@Va9d50w`L-cq=a^An z4>9d!zqBB^!{Bfcx%=ZFh1Jfw1={0Kn_zss`c*V8T z1R2Z5qzKI8Ilim=Ex!EH$aHa1?-c8&l}p~GNipWnDry$DPb=&)+9McN^mF)XEdK~x z9M|qNy$W{ryew;#)LtK&=?p(Adcmy4XTN@`HW1_8u1217o@VWCjVrjlb-%|5($p0qRIrF6(g zd2;|M#on$PC`&dlOtC{lIQ*M*3LWpD=^(-`&nX9!KbAR(ucD5C>SvUqSbDcqEs>IM zq7BGd30WJ2TbcJb&7!>Tb>x?(A4Q2xutTSPO`908uh^v!m<;vDqx9yZ->k@?EL6W( zoFFv}V{aa!pxE1&Pu{JRDP^BoK=11>?8lgKXxw+WLCg=asIp6eum;1+WI!fenME~s zs51jHqs&^ZH5iAwZKzMU%{`G?KEr-+sL@}#MB8h$)$P>xEXNpCx{M^KH$FeQ+&R=d zze`G5VOdPp96scMCOSPa+!^YesjLWt&7?hibf4W3QSZ$Io_cH#*kezQ+mQI%`}?MaRf+A5^17~mwo zduERw?p()e;wFC`WQiZ zw7}P_;`KIChNMwuXkjXUxNoYE#pQbq12qEtvZ!`l%xk0ZW^25g=B4dPwx+@0V=awH zUP1$&=x-P=+pU?)z0+_S&DRt`bwPD!@85mAIZF(0I4jymFv#bi|BAQeL{3U>(MNrf zUz9Io#u)WMsHD%^AVPt6(qeOTFhhuoAe5uAXLYnrm~_a{I9f|Rd`220LOD)fmcNFU z&?(K(s$t3;^=p*A`KKukc%!JwRFw#Ia4{$uAUIK>I*_WQPZPy=eI|Un&F5t{jY6*T z&^}@`7K@BEn(w?$H&}F6``8weR2-#ub<86(M`Li#*GoE$!b%y8ccR!KTxvk*)+Q+Z zY@waXG0-!W9*gUp0R@f36k{(gD#@o0{cniavJ-o~YvfLfeU!p+0e4n>ny+V{I^+o^eKEwV3=LLsw-;NY*A zgPVp@FL>s4`h-azRj=cmLzk9CdAqc47fz};e_FMFNS}JW8)ZsqTXIR%yz~IFJY@_}hnXh!s-Zzf{or(hq-M+wGGaf?fw>mMvEKeAvHLJn!^U zKW{%rsUOY#zd=be@tt zND#Z-p|dqU#3lqAF%U94-OP`*5wa zob2pqrgLp;Uf~4poh?a$cYXkt=vy@#@u$iI>mSr3(Pwr{3|_%ISEkbSy3D^%JQK?M zdfFo7Ypu%KSMcE5S=&0SeEiH&lh@7kBy3LK6(KiMlcXA!+2?<*p?j-aY7{MfW zX}V3IOfTeNalPdVM4vIcTOeP0wd>MX)h-yeKrK@A#Cqjuk%>^uNUVj&rr_GM#lfS> zg7ql4WHo$i*jO#$o9h~QVkced{9!oR+%3zOWzkL0>~K-$cK561qE`8Yhif^4^LMrw z;qvE~_y{I89EI#A%NZZD4mb^@^~G{%dV)4bTVB6Age2ZBEiSg|WM7Th-#+z-Juu6J z-h`}Ks5($K6`C!o%r5|aJ6>Lt#Ch;)I~&*+aTu3j^x)*3lxBp(JiRdbAhE3+uM+Sw z740s|+%DL@q#C{;&z8F>%09AqP#>r`QAt%$9LE@yf5yD)7A#&lW_)%7Qti%Gn5(Am zQ1DJ|mi|Ho2AfH~5>MbdVRpb1X&mu`lR_xt&-2x&P-g2EHO6cEh)#RNkWD+cMz57z zAz7WUgWtW+>bH`z%ll>kZl&(f7+u?%SM^n^rpY99x+0A$fbU)*tt}$`<3Q{W+3EH# z0!+K5ASSVdp$mct`A~!Pk{KJ4H8v9`!9M%Dw(^7RHtSFywkE;*T3{){1Hb(cLT5KWTJ(rdS*i>ACahA*6WY;*yFo45Vl z1yWm<=hgoc`6#Vi8zVtN-V z!IJTBd6#}%Kl}(n9VM^dq^dZI)iwez`?pi@@ID=XvcOmKcBBVuutQWd_1y_^^B|WajylDpxOpe5M#(#7sX_@B^9m;o`q*tn zDlRXc6@MnYucpinaOG-JEV0d-WL{_s@+@eHR-14c!P=WxK7Ge^33>6#30OoC>0>nc z;tXONsfPEg3xRu9Z9W9;=Y~Yf0xcOC)Z_lW!Ldx|j6=@x_fd=?)n(Z33TzA?Pe^-Q zGy8Ygp%msd(_+yldvAB_&acahbFF!tHcW-~R3dAzKuOBO^);F&8*0y@4swnrXxxdB z<73u*Qs8|H7^phyln4ardkFmC6vK|b8u3u#O$5=lRwv=xnx5suwM2L^;m|6bEFTeK zt+8L#PS7e~77wuLy5vZEe@7|miX%|l_+)OJlITCaL73P_3n8y14;lIR0jnl?pK>`T zTzNfR@N}sCdgb`j=;RKqBei$hLsUkvKYqT*B+fJ>IO1dl*Oq=QKGErd)8dVunSKgQTx`x`{O06x2v&s5S!XRHX;bH4VQLbPAP{VtDH0$j4_(WG` zFUSADmRK2pF&>rb7b1!-w{ar?FEke!GkXm4h{jZOB9p%6IdqcPIj$7_-Mb}d!jD%z z{r-MprnBbi&Y!A;ob>Vf%itdI-ClNGWR(nS=0Jr#Fp{)Mg#_~i33mPV)#wMS7q;t? z1CwaHb)l^i&C|l$tB+)wB1kb5D)U3t-qF^mt)1nPEz*)r5k$Q{`Ch3RvAdr#-P&F( z(OXGXTlcFDI(*{Zr=Ux0$%(qpQ!DC3U-?esc)YBcn6R1S6gGm)8?&Q_e;F}IrKRi** zI|(C2>azTs{q=3!zE&k|>c=%DTP$F;9|ZfEu;25-yf*2+pubK>^TDu_>GDNf^(4Hn zN2x$uZ7uZa?tEdFkJ3^8w!q}N;N>I5>K@;*3W*l(u`#Ze1yK)+iU8%;c@9KopSW%o zwjR8f$IX7@PqYT#{;=yQRI$_P%GN$Uidg%idHf1Cd-WijF}T+BaN88GC$)8L<8}W@ z48lF|IUm+>uHS2<>vq2>6}w#{xYyLHMsQxS2(O+HX|HXHwIBOXu_C$2b+y8M#k3Rd zT7r9y%0ZQ*)1?XboGZ72v1{+ibVt}1p{{gj=3(}gx9rK{Pkr!KpVI7E+wmv+;Q2kk zeJy(H4X1-APq_+#^+a83WSg($?z+PMc&N?X!41=@bxi;KcE)6$ZWRZX`-zpSK)qjb zeFp279DpqqX|Kqm%#I?-_(;yCjB8{;iP z1Z8!7c)q$^l-bJKlZ#BfOtdWP;Cjoi>y`**#Tg@WZ3vc0;_t?vxNR8~P3N1!9oPBI zl(wABz^OWi6v~ej`oQ8ajJAD5V;Gf>el>)e`wXIj>xUzI9p$$*oZ;2%XDs`MUN6i~ z5!Pd=5|3rO6Sv9@$VeX;UrnNe<@XAK5xc4j@r>y>5b^8@&(~*;>1)*{DO1n-;7m~6 zl)HK)j${4Q$9VWGpN(Jx41qkMnG~>72-qkoGgUTpG3)7 z1tSyOgFwMQK&btw_#wI^$xopvfr7cNQ_S!Wf)#owu4!R!Oq$fX20e+q^87rB0D@h1 zZ6K|#s@&&%jBvsInm6)KpH+WchC@{A&Y{PrU1gq)TA6v~ZrjZg9KfvS=lAH^;^xc# zWnp~m$Vs5HL-nhiZLN?l!#QRwLyjv8`_b~Vb`LH$7WVTI;91u5L7-5~lfeeTSz?nc z>ec69Ba;;O0vyoD=l1k4S66=a7fz#ZnKR+rq{y9QT~Eef#a#so>tK$~QN>aDExJaO z4ln>h;V_+kM%+}n84}FLID!UXsvIQbAPids7K_geWEC$B&d3nCfpG6p$x$FUP=X$5 zcqD8LOrswXEOT2obyrvo*I8FJ{(g|&3%z<_hf)~SuhwBtYGFoUX<+HU7NE#~A;Wtc zh(~=6gTAVck&;Q2;S9eEL*X|&`4LBMiuuQD#?2oWFpo>rkDV}i@3;SjvHXj0@E?)` z2MF|MvOCDX`fDw4)g+ekVM3x$#j0~NoD?S4KL13BBPq=~z zwwmhmX}7KJ^H<{jB>TkW9mEHUrMp|#9vOwBs;{T8WLp;O(+nr~9Hayea(2wwxJ@^( z8)8aNNtqukO0>M7)Bd&-?brjgO-preww_T7|=?}+h_(3LBda)vqX2JEDwxq9@p+nch2 z(!GF#{u4c?=pW0Lnn}+L-S!f`U&@H?aXp>-)bWi-dS~ywBOvpG%jYNtu8^`+TS*_W z_J9I8`0NH2u8@5>(XLQM1~+n+Rmz)ClB|UuFuq*B&})U)0tx0QJ?aD_lXcTfSt6oc z9Jj6Oa$f_kHoe#2Z(w|=UQZ@RHLz)TPWh%72o=e%bgx{=f?QlfVx7EAL#{-OiYdMby^D zN!ZxY(81i!$=2c5Oe#MiS$%70p}3-~q?{^)u(5@{s5jpLu?qWae6R_9N_+e{!ZSyk!O=;`OyA+Z8j#li&o&SQ{MEzX^-cE6B8tCCL~IOgjm&LK$yn6PZ3Ju_&HoGh zDpfN#ax!y-DiRF*$;bQa0_Fse{rvu1ewKpSeyxGo$k_fre*fCrzpaBff5s6283)vQ z05W!t|4P6H{sRY)adP~m8~(nq0YOk1SfRWt&R@T5KnNKaYK5N|8yHLmVrT#Lg|Kt} z`sHN*17`yQf7Jnyu|n4%P{#pt{%i#%gKz@LIDTp1=h`p-A!AXtRk1OLD$f|YBd832 zweU}#;vXz8XtiJVl-D;k{=<)@%#D63^w$JD|8YejTW6?ofq!uk$Y0ry@(#8}&W6Sg zWVD9*<_@-GKxQC>83-VwHFI*Z<6>d?g_=6(+nJdgIx^cjn9}`mPzXV(T~6kdK=yxNV78y$^mkdH;{8K^tkCSTzt>~uJh{EzVh*f~M}Xv@yQ`H%4eA%NfQ3nfMVW4}PCC;vmI5C}BF{C&JY z4vwE$c>ksYCal`iv6UY{!JDzJIBvh z`8&q;yRSiQ^bg-)1pxkWtg-?)0l)VLHQT?{?`R!%VBcb!5p@b7-g%E|FF(*I3n zDE2cp{tbi17xv%#gIX7Qy8pADlY>6=TJ_XT{2AQCN&=%f%ex*&*1B%%{U^xj+aUZV@qI}yE$-ia2XccO==LG=F3 zeeZpL&-eZJd7k&ZoSd`w+H1`<=a^%Rb^N6zMR9RRa8M`|?yHv~vMAIgHxvq;6B`p= z(Yy4F75;-fRnS1ew>eUCyB-9Y|_RyOvi9A3O*{andf&RoyhPSZ*k zWoKu{Y-ncuUR%>bm)YD(KmHFt2?|ApdL{By-acV{%1-HKJ1N%IW`DeO=x28Z4Hdo7? zbe;Z^nHi{??c?)YRXi&^)9 z+LRQk^|9hh;SVI5+k#2g=zM#9Z_rB4&VBQpzxYVXjrZcki^Yt`*2@H+K7B%=uKQzz z(@GWe^DDfNks<6!c{x>A~Au8x@V`GVQB#vKyP69Nn58s<)eVz?yMAVR{il=CAI0lrC&Izp!BW ztAh|Fq@j`0w(uz-Aqf5*7d5-G;!p9!(Lm*Qy~{~xR1_vRH}~$!AQmb#G}Ijv7h?4D z=g+fqb24*hIe3%hrr%&uVHpENKT-^@mM7EV_@KMGy26W?1?mlIbH=OB3CYNUShd?4 zr>7}CQVJHVt;^@alWSj`pT)3hV~*s%Q`}fP`1@B_Liu(Q#XTg#7`sH$qIboGrdqP;%Z$sH~YrK3c zWt6UmXeS4oL>Dsy1J~1D1P@f64rWSiujUrgaB~x(Qqt0PeqMGH4IyhsGq$ zIc>7Dr^h8Mt*L4ogQ2XjwmmWdXJS|;#)Bp)nlO#+`BtSOji-@2XP*a$hg%~a%C$7m zN+x94R$aov)0ikVM7c*Xy_-MYTQiDgU}S8883>J!5A?Z86wpNJByhSrC{<~@L89ig zQTCgD>$Q{=QCE>fJXdzYOIZEbB@4n}%<3W+t1^mMeeSXXZ|x{J^>HTztJl@!CddbQPecYS@Gw?|^} z*RNlGC!xv7>g`qiY7MSuvukT7KRNFd25El#&@?(qlqs3m?0_g3HNPwMvyy1BWjG`Nzxoo-{nrkh<}hJ|E$2Wh(6ZZiZzWmF3< zc>|s^=JERne%R;d=VJ|S4V|vy2|R?qdlH{%Xi!lIx&~1{`!KuI9bZ&luApr8=Vukn zkAiZq{*J#m!R zMos3woPbS^Yvn3ZmY>%1RCV_)*l_y0r5Y8UKR^pDh>Kh@UuepcdmA z2fSBceIK#1X3N&YLV3bF@-OYRw1|kjc%e{@`H-Dmj`2odKmdJN$STdR`>d=o3pVmH zkoQs2f6q#}1_lO@85$ar&mTZ0lAaz1pMpPYFs^9eKrdCH`ZE-=mIZY=KkQepUPbb@ zJ%9e(&)@&4y!=gwZDTs$&YL(shj}vN(FP6<4wY^f0`v3prPU4mF2|+Kqu(G!rW6)_ z)NT)%g9(f5q|L=_QDPF4lzfmaFD9EELBVe?L@Sl_rQCG#I%-?p7ms`yN{?*302|vU z{wGhq4-SS83=T#vkw3Qb{v!LZ%xo&o&#(UC+{wzu=GLgOhK3O2n3S=xF|pr*JUlV* zk!P00-18HJu9cln6zOcGc$9k&iCt`-Q92E&8BM|?nR0jj^w?SmzNhwc0GOw z1NC1C4h}Y)Z}H!SVkWj|JXWNM;eLFuDb*fAeit=VYA9FM<+|H1is7Cil`J{qazKto zMNUp0xd@A72$h9Hr-Oivn_F>0{r&s*B-~~Yq`O%^oo^8l4Z_rCsn*zj$<56z4S^ak z02#NS^b}rhIhw36FYK%TNX#nC-!2DnurfC{H(w3^q>yT3xCYyr!|soY(MVow=Q*e8 zM15JN^#(6ubk!-ukHFv#X>bE zJHc|ZDKQEP3NhWDMvqGm>FEQI7f>C;!*8^YXJ<8xrm8uidZoX=2Wp|OHW>ctlL4%dj;?OHY!avWw94X` zLQ60ycZ;$5pvzomB!gD08Vnn%u5^_?B$^~<)oS@a<-)?kbW~LCySuwB)=(2UEM|qu z8Z@P)LkG^jKJ~&BJ0P+-xFlh_G4UMLF+H7x%qJj|6<+p7kN%mdTJFsB^#0Z1+-$%w zIyyREN;d&OW!lZSC~lYoDw9q>@eT|O91sX1=To>Z0nij;P<63h*T_f=poQ$?9^ooM z?Y3*3U0rGT0*CI5OiZoTdU|>s@0Y~kwcM?3`h1u=T52Ef zPnu_EWxX`5c6Udi3n6GH{mU0=Wbnl{*4AHG>JL4CSyfH!e*gX**^4DmX{sn7(Z7JV zT2`IF`Y|e{oS|tBdwK~f}@t8Y=5hnX%&P&nosiBqRacUf+E2bH6mW zoRr6$Lnw&txE?JMp$lyd+S(3%)t5^5#S#@2t#-R`P5;ZnZ^3CeAfh`B zL%xE-rQnYN{P+shF)|XRTw#`P&AxSTp!hHpl4F)!rsO;u#KjPRPUMzVm6f3(A$Vv6 z<`xr}Zf7S4v?u`RqGo1h$e{jiZxdd1@)r?SciD@aa48VqijIyJg#vu@AQK9~P?{+I z>QMF#PJ=$7Q>N0$q$J6WiLx7`YpbhbQ#E#qj-kknPpBTjl%Na2B7BC0_Q%J|S1zNu zdi5%+3$zAV|5Tbtyz_v-z*gUou4onpCPl~TNCw4D+;hmu5fn7e&dyoJqXlC4y5;5N zHwg(-xulMcj3If{izF|;-;w0>d~yB?p2B;oa22Q`59bhNeaW&qZeJ&}FN z96cCH{j6n?gv;b*o#P&jxw$zjo&8QXH^Z${LPAcnpGphGr0jY@#3>9naY~AdsgZOP ztwqGFLa<|Zyla^5klwYBl|`5C03gPfIL~ytHum22D|bjqWTZxL&XU04+zg9eSbGGcI@;CR_Ss zf8&+9x_a%*pYgAv4<#fny8(2(b;0ap4sn?Q05j{0pyj;xfCDna5F6pL?n?^`&thX^ z#a2pj&mjp!6gUAGUhPlAf1JqX$l-cwUu`kx*;xx$mi?;N-QxZxab++waP55kYp?vYz)ZDGpk8-e zI!E{Tcq~dfS-^$9c2g=@;Fh|ycs!Scq1s9`NnzbSiI2B;mJ4xq-e$u^5(L;YxVG3J zlwCt87FzWo6i;&gH@wD1cW44+acezah% zcVf7i*X>0S%SYWml@#6>g%ujctIpQC`&-e$zvi5SD{Upd_Q7(OXN-owQ&rm0rtB@}n zd(PPWIt$ttBb5y6Eqwr5(1s`)C0amR$BHdWq~ZPHLqNMjqdQteTpWE509v9#sT((L zL{bSne*E_5ej=Y;>9n8+!6|SlVInlCRqub(N1~;srfN0zSH0JdblRD5yO7wdJD`9J zDrHzLoSFiiYiM2F6Ex|EU49YoC|g=v4S#5xnB>_{+dDX9*OqocMKhf&&;D8CV>Q#! z;kUlAvGP&yoZ$EOMXNYK* z@I0%3NQgol5g{S9KnJ9mQsFfQX66y%mM4K*TDl#f)MA6?)3wBg=58N!| zNWD@ZeIj4pX1Y0DhY>ME7uEBXKq-1OBA?CMc&Uq}VW?7kWmZbgbaJB1xE1wfz3g5> zgKW0E>4uH6a@-hBipgWOsU}Jk36Dj}gsx<=026cCpUVag-YL@q1G0-MxdvObwFbq- z#i`H(KZm$MjiS`-U$#0s z3qOb)A#I6cDvfS6eLx4AcT}rn`v)ZP;wx z!E|olF&jI3t0pbnrK~g1$LBIC%er)aZ7mSM3N;-aHUM|H9E#WNoL`|(Ef_+!xwZ8& zu!Ly}let-dBvFgWlhxJLBv{fT*4=8A7Ej44ETA|T4Tg|%OK$XCz4gYi&o;GPa&`t! zMGSwk4-i?pgU~Bl4tP2u_fON$7+w>DKRk^_8N-rVW5q*JSC@c zsR4BqpDu*lRcLlm(gW}EL}+B<)t0HUOx`k|F6p*k=d)S8iP8XIZ}I;9H%K{Q5fNY5 z1fhC9>=kyf1um%UDE}Ibu$UMQO8$^6R=}ltVx@T#*qx8Q_>=*IJ3Bl7(36dPo3)p; zwY4KlflY|vFud;mY2l^Ftr>r@K5O$oQ0$elukhnL*}ucL&%@7bRoT9$QHR#j0ydL+HU zpQ=*hc2Pf2rGD&~_2WqP*qOzAT~XmZkli*f=$3~G+pgBU|1FvB*p<^!{TkmdPnu3z zUjEB|ayc}HdHb4JC=w0>RLU>vno-zsvKAW?oGAB?AMpVf z3^8kKX`xe6Qlbc)Vi_S(zux$E4`q4UR?;A)TesatigHhOJHLY}(r(B5wYZoHO+ATI zpZsswu!q0Gr5-^$3$&liO2rMw&kQG%s=(F=y>d@kv5$OnJSRQ5Cb|4rTGjj$fV{DC zQ&NN$xhonn>xC~M1kk#rm=}6}R$yVAPq*8ZP2~`#6P`g6cuEjKqo4#kh_}*Ya(18J>{y+su&U!9RYn!)_yV!Ca$MF@Il0}`&S(f)9|k;-Xk*3nTqYA?5p9=fYz5V9yK--1QgLn9eQ5?W>-+>~Ym=3J^B5l93;27~ zu(3!V0PWy|ZwMalWlMLvG3UtRxJ!3>db+hYs(zP|F|T>l3t+0!zVT!@eJ%yrX)*7@ z{QTb^2(VDL8#gmBP%?}Di%ZIdk)pEvBc2-{6BE2c zU;<{V$qNhrk=wcR;n7jk$jI%&`r{m>_wsK6b9?#vVgcg;^~H7;n!HNKJ$j(@2+7Hr zY;jdpRo(1XhpvELaQ_-EE>fm{B=QkKljRAhp)G`*VFbtESx1`mV7kA>AA{9D)oe)c z9k1phw=C9f2iEZ(riZZfAtR7pF^@FSfhPCr6}%vWWoT{r)?CX!otFcF${NTfWGz{m2%QWq^=|o^c3ootDA;2@Cpa3 zuEaF}g1O`_E8&%tL;=X#Z+>12;bI#bo_+@CG;ruT(KkFiti*nwj1(otVk;J%pMEL4 z#Ji*tlB2S+a@4y^Ok|UpQpxmXF$O;?i!04EuXRJa=i%3)%tqaK1HInc8v}Smba%1f zU%=XL^@~zIRa7K`Ya`4u)DIlUQQ}GbcZgWjhGIk|#2Tpb3>>u0%?oX-GiFk)?(QR2q`nv(ZP84?p^SX&&*d7q0pqHkfbM0pP@xls4;A4S-qtxz9tUeB+X z76v-A{`}Y&QHp^2fUczldMH-NGS?{hD`mOMVIhLmc&i4*WKVrRrJ9a)=j9wo9N-HidP8I&W2pSXQy4r0){W*GXcnW%X>wA?8 zxXiiI+fPpp7d|3#0+dd9dy@tvxZ=6ZKluA!fxYDoztXU?-vBO{E%q8)toTB_wWeTM zej;dsmr>p30mJ?Q0oU8jZwx4U$Hv~7cKA(h^0Sgq=#|<5Y~Q(E7%lMEkARSc0*-}& zg?0Dg!z-6BU+(DX`5^w_8xXC^b9;tqpW7>Px|h94YJflTU%&?51)(EC#nQ#PqD+q; zo>n~b#WRXO9gYZ4(~b)XE+4I~*7ZS2V*lwJS>0P5z6#*egoOTd6lyp?GWtp7dgsS~ zrt1Qche_nMK{QU_Sc?q@A6Ua~WY_N*TCFGtPSwkEm10IgdU`wihZU!UoX{i9W{iX< zPPaosLJp7D3N0_rU3B#I(^67|7_s*D_897>1}1aY_mn5w^Q-^(-ePL#%(#FS#`55g zD&xEIYXF}=q^43Mx(1L-gisQiVA?qg_!t;oo4l1(>-%AZhvk;ngR}_=v>e0z!^1x5 z>FEkGWu48yIESC3CRR6&e;MlioD+ z8jI>potp7$n<@OR$(iP6;bH}O)nHSA9IQYJ0z3zWZw}Nzt@o>&^(T@GffWe%WsY~g ziiyO+&sqn$g<4W>GZfuXeeSwMUG+%*ic|P+pZa=%YMZqWKxz1!uKV&EX0&B z=!C*a8*F|7d`-^Xu0=Ku4iO3Wd) z$4T&MjqQepmX;>~?ztba>{_$(kv(ek-yo1qpD@VYj(&4|!eKMxcEx+saoDBz0frlp z?K~jhYiViq0o*LU^KM1=pJ+W%+;zjH^FlEF6q_S7GKa@g{k%7Nh}Bv`d(?pkx{he7S<^ z9`))g1)7brzP^63AbR*3blHhVFsxx$DOwI(40ljc-xy5+%_qlq1`_Oia6!ph!Byd! z(~|brhe;W=n_sYkU!2&!c5-%f_% zPcu0K{ryc)skWeP)PVhc3r`GkQLBdPpm~M!kyY?Yd(a&)im38C{KbIT&bM$)m(3nK zQMa%tQaZ_!1P27H`Nv&2~V5m_Nu^w855%vM@8osRsmD z44NQLp%f|LnVU1p#yMfIN%hN|pWPoiPkiE}uyNpu4&rL5@hBcb(Nt;b=*X{Zp3!&x z_#vM66s9e4!ncdh?vG!YsqWG7aexF%!|^IZS=Y~cmv`$;7KdAN^gF=xwn*}LOS*Mp z+BRRfU7Q{Gef;PP?N5$jJ~l9f#da@K-zNrKM?VZuxf=<0xL3~uT65h*v=GGOSgGL+ z_fJk*D@5MF!Op*q1WnfHdw7P^&e6{AR#e$;-P_7G|Cbv!1=4h#XC_Vk{W7QZvV$(N zP;l2%Pe8nPp>|BU8PX4l%VKv~rmV|(yOoHFCMGu4aJ^#*T6hxUJRhs>sj0f=r*TP1 zNn=gH8Ea3M9macmr50ZEDSSoRm?aQ=h&hcS#@NZF2SgAxEcCk$$k=VLJK0BCEJmN9|wIqhyoB}lqn3%};brKd>4B9)w?v~-a1g}m@MHzG%{<1f! zK7XcRRI4QhMYd0g{m;tELp8yFY$Gh{1%J1InDIau`uiJ->Mr+PYYreEEI=Qwz{`CL z=Q59A1=?VW$C_A+1VM%$Sm#d?IAu5aC$JmnktkUVAz}~H&tM9THx)-3Cxo{}~nQHEtT8A45Ve9_MxY`;8y6bz(msy}E z&~sku0R#vZm@Sxk<8{qRkQ3JX^jZUMf#-nW;OU{{9lD3wrY0tU0t0}rh@Acm8d8zd zf!Vg2%INX#%H1e8C_!>LXQ1gTeboydqtON<6p3JR|KQ*^?<+T2rc*sW?KlE#MA}pL zPw%sK%XoqL%TuY6H4Uu=@rsott^jM!@nNAqXRanEUl5gcrx-qctyU`zBqVA%IXRFm zQUIfd7Z{CUZ z(1Q{$m1yV;xzL3`dlnl6()o>L1GJo%F)*Yd%YBE2JYl*-_jPAyr>q!l`1cNAIt@{# zb2A_<`uou_Fa!cuz$kgJzn|fHb}R!e%M}!;U5K0~gzA8zaKAV5&aXPRi*s)`%y$P{ zTPf3ZPI5E#E}-bk{SXD!IucW`5Ia`<1qeFxya@Y@hKBZQb(LNcvS?zbd%4I3-roYl zMkAWfz@w}2znGxs>u`D=$=z`Romq=V9_ZoOAmtC$*qI~h(kVMJ6wwV}H(?6zyMTy) z851+0y$$pSUYk`Bgj?0u*9Wxm1q3lJb=ccOV9`o{-}(K!e{EgecOdo>GC*|%?Mb#K z1l$vmI|EHk9?;>40Un)4?V&n;{!HjedXhU_jBv%7Qk0hD1qB7jFGhnI!Aj-MfDPwQ zOT3>>^I0#aSdt>j{3*M;?OSLbISl%!(sznscMd_6H4A$Aft4)Dy%YB@Go2HeXfR2- zSP6r&2pcIHCPV-?J(MP z;{9bNz|_SO0(xl(Qi0KUNxJMDA$pN&Qr z*47v(u7YTXToF)w;Lo2wTS{SXyy1&E`-;8zcKm7W<#a3u7CJiV8gVtXq{<)ZucPIc z%*TqJ)?Oeg9r%b4_rtYo*RWA{h>80k7>5g-z)~kRn!VNA+gsRtLI=@kZY~82Sg(Y) zyEgg}7=o7C$B!TPgP{6mzzw$Mye%k`h;oe#o{g228dVB1$oBXgP}TG+hzzn%F^;U% zVo$Q56xh7xok1l-f**`a;n~>_(NduBFr*W9p50;BGx&J{T}J{+8mv_G&Ob2XFdb;= z?=Y$o3#nC_?=AOxfjhF*5JY@gr)g}jS}AaHAfX2a0nmdbfNV$uncr{4%hNLg)1H>b zXsWu*zV|N#Ii%4n75slb_=Ml}GzQfAm!hJ+pVQLH1Ss+x!D?#sX2mxc+C*O0Q=T$| ze&KAP{ey$dt3=FM5|p=YJqN}Pc&z78LB)2&u-tHbJdq9}U07UQJsHxZB$$07doExO zVe16~EtA5w`L$QzE_e+f1&_p>1Lt}l{(v}Ehyw+{67g^#=8;9rVelLs11BbrF8EYd z_BxYFW#|VyaxqB%$Opi=(A?bIqI>6XxwiXeSvIwlL(IABEN5~~$J#B@4)*q0iEd!!1W{dP0%^>Ffhl~MD&5CWSSt*){K7YFphOXUSh>t7{V%~N+((1xv^~-NU7g<|y zM@b(C`?!I4pAP+gTtGlTXLsNOaM#kH=npWOV1ims5s_H+fuNwe$`VkuM$wP${*di~ z=WvBW0}NKMRav;*AJFguCk4%&Kdhw0^z<~`a=8B5&@Z4C;MecHy&n;0ifWC*N_skU zPr<~jo?6=4oCOQMl&;ba{o}wGB5MWK05A%{vO^?GnjQly+XwX!F~HQ;*1m*kghzW5 z73lAu3M^S5%b2$ts0D~9R_%OLGVoWp>H<1qqaP>0K8wm`m&&rZcV0dB^8$njBY0CxY1CE<&S5Io%-a+c%&x=l&XHT3lr{}Ag;K*f0~E`BX2 zI2iG1&#BSoBA#9#emi=5ee3F6sutD_8CY2f5l?wZ$@PYsqeAe@wLu!tfR-LYQ!&SQ z8}L5Z0GokqTAOJ|NkM^Dj@Ya7^O?YF%E47eFXiaS3wvJEzyKS{M!wU|@E4$5K!WoY zp#gRW*QhL7E#=Fzps_Kfn?yuu&^Or(4E=S80+%#gn*%b7Nn0ks)N9CXT3RrAdU}SZ z6&o*{;=7_Czb$9zfS^;l>#qS<+4%3O!IIA27C$MAASB%=&Bt_M8 z*Hl+498MO(&A=CU6ACKl1iPW7WpRukA72gcTI4`?H!ftrv8wl(hvQznV8Vum6dovV z*M*CP1s|lgM{I1uFzg6Nj8X7!VuAgWj+yxdWb7{T-)~Z-k&RjT{x_av0#8%7z#0KG z_X>tM=Q&>0vmfD@fKw8pPTY7P-Uwv{4BaZDw0b8wjz^u!`9Z@4H7pubX|3Ke7J46H4=9ep zii#CKr{BKa$a3V?`R8y#o~*UCwZ(kP6-c|$lO`c`WQeyOY(iAP>Y)g3-jvTzem!&< zJ`Q(n1O~_CtaTMgs((Ig(*d*FIfGwv@gXAOrjDLo^Y`ypo<4o5RHE}rRX@8EN)T0~ z*cvbCI^}6MW$qgsA7STsT{APaRQv#j99V3~#i1|n4UhO^Acq{3Ou>WY0ey2DtIC~R z`v3QV2=e+z{~nqcd+q-Jh(dueWIg~J`2z>;=u;u)Fy%b-zzDZ1_lQ| zx3=aODNsdB6NV}wPAAT2U{9jv;3zHl+Vt;n45yIwpH(*yW|Sw{_*_j$u|S3JLaj&x z4LtJ!kRh5UCu{KDxBmO)+^d3TyEhQ+<3%t@WDOaX8w*crwmtyu{u13T-X7e4&vN9I zKj!5{M?pd8QVrpA*8FEOgNmb3|IKR<>;Cmwy=0aY@OInyY#JFmcaQD9%+6nP$AnF4yxTOIGi}=HbHO>AVpEe8n`4SRs$d%O4 z$xi?K_5VAo^2hNFFmqafvJq=F(1H)dW88sZKt}gh5nMp4Jly|1I+4dn zw*ZS;EfDxGQXpASy6h5y>oKQ9Tw0m{QAW0An~c8S`|obWIsMg32>7^!f?gRD8o_6v zig&Vs(GJL;MkwyNNzXF0&QFi#XBZRr8V~6B@Mhh5Oh3i(}%!q>(z8^K2t2a%hcfn4En_{7gQ5FY6{T$2G912CtLe5gl5f!s8V$u zmR*K?>BGNKxlhx_dq@iE0Dua`R9y*i@jf^bfpPh=Cdems_44_-wDiW9Rw1X#6*b{cFnH zCkcXX0?4r+nAw>4c!ut;rKK%^E)bR-22M>yg#vA_8M+O;Z217NB!DX`e}b*|f77f5 z)3g6)DiHE)WMg3|h&WoOhud&4LJ)>_8LA|>9TuRgc+MJW)yJ30CDzahKaJEkhrwRH}o?fz42FPGyYML80Nfh(- zD?7vw8`e&Jw&S%rCS1mtrC$beda&?t9k5W#fS3?5!b zt244!Qc|MOAKb)&<77Vnr6!I6$VQj1-kt?l9S_(sfJ8tU8yoZR@!f^83l$tNuRH9* zkwSGAOs8lT^%qcsA8EDt8O?a)0Obbz?kT9gnE27*1- z4n`LOI6N0Cj+vq(eE>102~^GUSaDiR2Bcp&=aXNrq8JV&hbG{8`oW#Qe>)`(0Lg2E zT>FTf{Tr}y$Vnk}x3gPdRBMJ*X}R1-osPBv{(Z10Tm{4ko-QNRW!haa;ktl#yFPON(aO?ZSnagk&BL zh8ckO9Hjy0{gx-n7!V>7@gzWqYQ<&CWoiMfG=CuoG&8)~3aM-hj7Fm!_5Y4CNceNo zY`b8ZrNG}SH$~=mZ)kpmd4GVp{7chIlA?U8h})|+W>(J_NA&7&)VrXwQTfNR?Ck6y z(!aI&l|F(?#zO!QW0&*1#k^Bv|S&~sXd3g*Mmot(s zTBIz`=F=}uspWhwiRAFFA)j;GC;Biod$!rTtcn&sh^CUVpgg3&0N^pOS% zlCW(0H34&wFt4IOb@1F5l*nU1ENa-+N$i6 zK2rRPFFv&d@h8+qd-7e0tÐ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 literal 0 HcmV?d00001 diff --git a/docs/img/awkward-0-popularity.svg b/docs/img/awkward-0-popularity.svg new file mode 100644 index 0000000000..0f42ff5be8 --- /dev/null +++ b/docs/img/awkward-0-popularity.svg @@ -0,0 +1,1373 @@ + + + +image/svg+xmlSep 2015 +Jan 2016 +May 2016 +Sep 2016 +Jan 2017 +May 2017 +Sep 2017 +Jan2018 +May 2018 +Sep 2018 +Jan 2019 +May 2019 +Sep 2019 +10 +2 +10 +1 +10 +0 +10 +1 +10 +2 +10 +3 +10 +4 +10 +5 +pip-installs/day, 60-day moving average +pip-installs on MacOS and Windows (not batch jobs) +numpy +scipy +pandas +matplotlib +root-numpy +iminuit +rootpyuprootawkwardcoffea + \ No newline at end of file diff --git a/docs/img/awkward-1-0-layers.pdf b/docs/img/awkward-1-0-layers.pdf index dfac1fc176ee189909f03897a604af9b9e870767..bc3172e5ff926773d62f313fd49a9466a6f8c9ca 100644 GIT binary patch delta 9826 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 Bcmx0d diff --git a/docs/img/awkward-1-0-layers.png b/docs/img/awkward-1-0-layers.png index 00d080a2ad6a825be145498fa0cb8f8a6fb2cfea..20715f64f6ed04b5ca1117426b9a82756ab7b884 100644 GIT binary patch literal 109520 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 P1%LBrhXkDsRPFu;C*5lp literal 103741 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/svg+xmlC++ classes + id="path70" + style="fill:url(#linearGradient68);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 14.547,193.629 h 124.25 v 45.836 H 14.547 Z" />C++ classes + Numba models + id="g76">Numba models + pybind11 of C++ + id="g92">pybind11 of C++ + Single Array class in Python + id="g108">Single Array class in Python + CPU functions + transform="matrix(0.00761599,-1,-1,-0.00761599,0,405.944)" + id="g128">CPU functions + GPU functions + id="g164">GPU functions + inherits from Pandas's ExtensionDtyperegistered as a type in Numbalazy versions may be wrapped as Daskoperates on CPU pointersoperates on GPU pointerslaunches kernels internally + id="text190" + style="font-variant:normal;font-weight:normal;font-size:9px;font-family:'DejaVu Sans';-inkscape-font-specification:DejaVuSans;writing-mode:lr-tb;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none" + transform="scale(1,-1)" + x="191.08656" + y="-332.61389">inherits from Pandas's ExtensionDtyperegistered as a type in Numbalazy versions may be wrapped as Daskoperates on CPU pointersoperates on GPU pointerslaunches kernels internally + Layer 1: + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:12px;line-height:1.25;font-family:sans-serif;text-align:end;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.75" + x="-28.461832" + y="-365.2543" + id="text4669" + transform="scale(1,-1)">Layer 1: + Layer 2: + transform="scale(1,-1)" + id="text4744" + y="-275.67114" + x="-28.461832" + style="font-style:normal;font-weight:normal;font-size:12px;line-height:1.25;font-family:sans-serif;text-align:end;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.75" + xml:space="preserve">Layer 2: + Layer 3: + xml:space="preserve" + style="font-style:normal;font-weight:normal;font-size:12px;line-height:1.25;font-family:sans-serif;text-align:end;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.75" + x="-28.461832" + y="-184.92491" + id="text4748" + transform="scale(1,-1)">Layer 3: + Layer 4: + transform="scale(1,-1)" + id="text4752" + y="-59.530098" + x="-28.461832" + style="font-style:normal;font-weight:normal;font-size:12px;line-height:1.25;font-family:sans-serif;text-align:end;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.75" + xml:space="preserve">Layer 4: + extern "C" interface + id="text58" + style="font-variant:normal;font-weight:normal;font-size:11.99999905px;font-family:'DejaVu Sans';-inkscape-font-specification:DejaVuSans;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" + transform="scale(1,-1)" + x="103.53472" + y="-118.48515">extern "C" interface + \ No newline at end of file diff --git a/docs/img/logo-300px.png b/docs/img/logo-300px.png new file mode 100644 index 0000000000000000000000000000000000000000..9a5a10b6aba7963d0373976d932f6b4dc282d353 GIT binary patch literal 13084 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 literal 0 HcmV?d00001 diff --git a/docs/img/logo-600px.png b/docs/img/logo-600px.png new file mode 100644 index 0000000000000000000000000000000000000000..f6c7302004905f444a340acf37c68005669b6b6d GIT binary patch literal 26635 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 literal 0 HcmV?d00001 diff --git a/docs/img/logo.svg b/docs/img/logo.svg new file mode 100644 index 0000000000..cd5ea20fda --- /dev/null +++ b/docs/img/logo.svg @@ -0,0 +1,152 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/include/awkward/array/NumpyArray.h b/include/awkward/array/NumpyArray.h index 9e62ee4952..02b5ed6454 100644 --- a/include/awkward/array/NumpyArray.h +++ b/include/awkward/array/NumpyArray.h @@ -111,6 +111,7 @@ namespace awkward { void tojson_integer(ToJson& builder) const; template void tojson_real(ToJson& builder) const; + void tojson_string(ToJson& builder) const; private: std::shared_ptr ptr_; diff --git a/include/awkward/array/RawArray.h b/include/awkward/array/RawArray.h index e5e501a030..e0b68b346d 100644 --- a/include/awkward/array/RawArray.h +++ b/include/awkward/array/RawArray.h @@ -184,37 +184,37 @@ namespace awkward { virtual const std::shared_ptr innertype(bool bare) const { if (std::is_same::value) { - return std::shared_ptr(new PrimitiveType(PrimitiveType::float64)); + return std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::float64)); } else if (std::is_same::value) { - return std::shared_ptr(new PrimitiveType(PrimitiveType::float32)); + return std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::float32)); } else if (std::is_same::value) { - return std::shared_ptr(new PrimitiveType(PrimitiveType::int64)); + return std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::int64)); } else if (std::is_same::value) { - return std::shared_ptr(new PrimitiveType(PrimitiveType::uint64)); + return std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::uint64)); } else if (std::is_same::value) { - return std::shared_ptr(new PrimitiveType(PrimitiveType::int32)); + return std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::int32)); } else if (std::is_same::value) { - return std::shared_ptr(new PrimitiveType(PrimitiveType::uint32)); + return std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::uint32)); } else if (std::is_same::value) { - return std::shared_ptr(new PrimitiveType(PrimitiveType::int16)); + return std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::int16)); } else if (std::is_same::value) { - return std::shared_ptr(new PrimitiveType(PrimitiveType::uint16)); + return std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::uint16)); } else if (std::is_same::value) { - return std::shared_ptr(new PrimitiveType(PrimitiveType::int8)); + return std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::int8)); } else if (std::is_same::value) { - return std::shared_ptr(new PrimitiveType(PrimitiveType::uint8)); + return std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::uint8)); } else if (std::is_same::value) { - return std::shared_ptr(new PrimitiveType(PrimitiveType::boolean)); + return std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::boolean)); } else { throw std::invalid_argument(std::string("RawArrayOf<") + typeid(T).name() + std::string("> cannot be expressed as a PrimitiveType")); @@ -233,37 +233,37 @@ namespace awkward { virtual bool accepts(const std::shared_ptr type) { std::shared_ptr check = type.get()->level(); if (std::is_same::value) { - return check.get()->shallow_equal(std::shared_ptr(new PrimitiveType(PrimitiveType::float64))); + return check.get()->equal(std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::float64)), false); } else if (std::is_same::value) { - return check.get()->shallow_equal(std::shared_ptr(new PrimitiveType(PrimitiveType::float32))); + return check.get()->equal(std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::float32)), false); } else if (std::is_same::value) { - return check.get()->shallow_equal(std::shared_ptr(new PrimitiveType(PrimitiveType::int64))); + return check.get()->equal(std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::int64)), false); } else if (std::is_same::value) { - return check.get()->shallow_equal(std::shared_ptr(new PrimitiveType(PrimitiveType::uint64))); + return check.get()->equal(std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::uint64)), false); } else if (std::is_same::value) { - return check.get()->shallow_equal(std::shared_ptr(new PrimitiveType(PrimitiveType::int32))); + return check.get()->equal(std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::int32)), false); } else if (std::is_same::value) { - return check.get()->shallow_equal(std::shared_ptr(new PrimitiveType(PrimitiveType::uint32))); + return check.get()->equal(std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::uint32)), false); } else if (std::is_same::value) { - return check.get()->shallow_equal(std::shared_ptr(new PrimitiveType(PrimitiveType::int16))); + return check.get()->equal(std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::int16)), false); } else if (std::is_same::value) { - return check.get()->shallow_equal(std::shared_ptr(new PrimitiveType(PrimitiveType::uint16))); + return check.get()->equal(std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::uint16)), false); } else if (std::is_same::value) { - return check.get()->shallow_equal(std::shared_ptr(new PrimitiveType(PrimitiveType::int8))); + return check.get()->equal(std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::int8)), false); } else if (std::is_same::value) { - return check.get()->shallow_equal(std::shared_ptr(new PrimitiveType(PrimitiveType::uint8))); + return check.get()->equal(std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::uint8)), false); } else if (std::is_same::value) { - return check.get()->shallow_equal(std::shared_ptr(new PrimitiveType(PrimitiveType::boolean))); + return check.get()->equal(std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::boolean)), false); } else { return false; diff --git a/include/awkward/fillable/BoolFillable.h b/include/awkward/fillable/BoolFillable.h index ea473d4e59..cb0a1fe856 100644 --- a/include/awkward/fillable/BoolFillable.h +++ b/include/awkward/fillable/BoolFillable.h @@ -13,29 +13,28 @@ namespace awkward { public: BoolFillable(const FillableOptions& options, const GrowableBuffer& buffer): options_(options), buffer_(buffer) { } - static BoolFillable* fromempty(const FillableOptions& options) { - return new BoolFillable(options, GrowableBuffer::empty(options)); - } + static const std::shared_ptr fromempty(const FillableOptions& options); + virtual const std::string classname() const { return "BoolFillable"; }; virtual int64_t length() const; virtual void clear(); virtual const std::shared_ptr type() const; virtual const std::shared_ptr snapshot() const; virtual bool active() const; - virtual Fillable* null(); - virtual Fillable* boolean(bool x); - virtual Fillable* integer(int64_t x); - virtual Fillable* real(double x); - virtual Fillable* beginlist(); - virtual Fillable* endlist(); - virtual Fillable* begintuple(int64_t numfields); - virtual Fillable* index(int64_t index); - virtual Fillable* endtuple(); - virtual Fillable* beginrecord(int64_t disambiguator); - virtual Fillable* field_fast(const char* key); - virtual Fillable* field_check(const char* key); - virtual Fillable* endrecord(); + virtual const std::shared_ptr null(); + virtual const std::shared_ptr boolean(bool x); + virtual const std::shared_ptr integer(int64_t x); + virtual const std::shared_ptr real(double x); + virtual const std::shared_ptr string(const char* x, int64_t length, const char* encoding); + virtual const std::shared_ptr beginlist(); + virtual const std::shared_ptr endlist(); + virtual const std::shared_ptr begintuple(int64_t numfields); + virtual const std::shared_ptr index(int64_t index); + virtual const std::shared_ptr endtuple(); + virtual const std::shared_ptr beginrecord(const char* name, bool check); + virtual const std::shared_ptr field(const char* key, bool check); + virtual const std::shared_ptr endrecord(); private: const FillableOptions options_; diff --git a/include/awkward/fillable/Fillable.h b/include/awkward/fillable/Fillable.h index ef51473593..c5a09b50aa 100644 --- a/include/awkward/fillable/Fillable.h +++ b/include/awkward/fillable/Fillable.h @@ -15,26 +15,33 @@ namespace awkward { public: virtual ~Fillable() { } + virtual const std::string classname() const = 0; virtual int64_t length() const = 0; virtual void clear() = 0; virtual const std::shared_ptr type() const = 0; virtual const std::shared_ptr snapshot() const = 0; virtual bool active() const = 0; - virtual Fillable* null() = 0; - virtual Fillable* boolean(bool x) = 0; - virtual Fillable* integer(int64_t x) = 0; - virtual Fillable* real(double x) = 0; - virtual Fillable* beginlist() = 0; - virtual Fillable* endlist() = 0; - virtual Fillable* begintuple(int64_t numfields) = 0; - virtual Fillable* index(int64_t index) = 0; - virtual Fillable* endtuple() = 0; - virtual Fillable* beginrecord(int64_t disambiguator) = 0; - virtual Fillable* field_fast(const char* key) = 0; - virtual Fillable* field_check(const char* key) = 0; - virtual Fillable* endrecord() = 0; - + virtual const std::shared_ptr null() = 0; + virtual const std::shared_ptr boolean(bool x) = 0; + virtual const std::shared_ptr integer(int64_t x) = 0; + virtual const std::shared_ptr real(double x) = 0; + virtual const std::shared_ptr string(const char* x, int64_t length, const char* encoding) = 0; + virtual const std::shared_ptr beginlist() = 0; + virtual const std::shared_ptr endlist() = 0; + virtual const std::shared_ptr begintuple(int64_t numfields) = 0; + virtual const std::shared_ptr index(int64_t index) = 0; + virtual const std::shared_ptr endtuple() = 0; + virtual const std::shared_ptr beginrecord(const char* name, bool check) = 0; + virtual const std::shared_ptr field(const char* key, bool check) = 0; + virtual const std::shared_ptr endrecord() = 0; + + void setthat(const std::shared_ptr& that) { + that_ = that; + } + + protected: + std::shared_ptr that_; }; } diff --git a/include/awkward/fillable/FillableArray.h b/include/awkward/fillable/FillableArray.h index cad70fab88..111c2afe1f 100644 --- a/include/awkward/fillable/FillableArray.h +++ b/include/awkward/fillable/FillableArray.h @@ -30,15 +30,32 @@ namespace awkward { void boolean(bool x); void integer(int64_t x); void real(double x); + void bytestring(const char* x); + void bytestring(const char* x, int64_t length); + void bytestring(const std::string& x) { + bytestring(x.c_str(), (int64_t)x.length()); + } + void string(const char* x); + void string(const char* x, int64_t length); + void string(const std::string& x) { + string(x.c_str(), (int64_t)x.length()); + } void beginlist(); void endlist(); void begintuple(int64_t numfields); void index(int64_t index); void endtuple(); void beginrecord(); - void beginrecord(int64_t disambiguator); + void beginrecord_fast(const char* name); + void beginrecord_check(const char* name); + void beginrecord_check(const std::string& name) { + beginrecord_check(name.c_str()); + } void field_fast(const char* key); void field_check(const char* key); + void field_check(const std::string& key) { + field_check(key.c_str()); + } void endrecord(); template @@ -51,11 +68,16 @@ namespace awkward { } void fill(int64_t x) { integer(x); } void fill(double x) { real(x); } + void fill(const char* x) { bytestring(x); } + void fill(const std::string& x) { bytestring(x.c_str()); } private: - std::shared_ptr fillable_; + void maybeupdate(const std::shared_ptr& tmp); + + static const char* no_encoding; + static const char* utf8_encoding; - void maybeupdate(Fillable* tmp); + std::shared_ptr fillable_; }; } @@ -67,12 +89,18 @@ extern "C" { EXPORT_SYMBOL uint8_t awkward_FillableArray_boolean(void* fillablearray, bool x); EXPORT_SYMBOL uint8_t awkward_FillableArray_integer(void* fillablearray, int64_t x); EXPORT_SYMBOL uint8_t awkward_FillableArray_real(void* fillablearray, double x); + EXPORT_SYMBOL uint8_t awkward_FillableArray_bytestring(void* fillablearray, const char* x); + EXPORT_SYMBOL uint8_t awkward_FillableArray_bytestring_length(void* fillablearray, const char* x, int64_t length); + EXPORT_SYMBOL uint8_t awkward_FillableArray_string(void* fillablearray, const char* x); + EXPORT_SYMBOL uint8_t awkward_FillableArray_string_length(void* fillablearray, const char* x, int64_t length); EXPORT_SYMBOL uint8_t awkward_FillableArray_beginlist(void* fillablearray); EXPORT_SYMBOL uint8_t awkward_FillableArray_endlist(void* fillablearray); EXPORT_SYMBOL uint8_t awkward_FillableArray_begintuple(void* fillablearray, int64_t numfields); EXPORT_SYMBOL uint8_t awkward_FillableArray_index(void* fillablearray, int64_t index); EXPORT_SYMBOL uint8_t awkward_FillableArray_endtuple(void* fillablearray); - EXPORT_SYMBOL uint8_t awkward_FillableArray_beginrecord(void* fillablearray, int64_t disambiguator); + EXPORT_SYMBOL uint8_t awkward_FillableArray_beginrecord(void* fillablearray); + EXPORT_SYMBOL uint8_t awkward_FillableArray_beginrecord_fast(void* fillablearray, const char* name); + EXPORT_SYMBOL uint8_t awkward_FillableArray_beginrecord_check(void* fillablearray, const char* name); EXPORT_SYMBOL uint8_t awkward_FillableArray_field_fast(void* fillablearray, const char* key); EXPORT_SYMBOL uint8_t awkward_FillableArray_field_check(void* fillablearray, const char* key); EXPORT_SYMBOL uint8_t awkward_FillableArray_endrecord(void* fillablearray); diff --git a/include/awkward/fillable/Float64Fillable.h b/include/awkward/fillable/Float64Fillable.h index 2a68b8dbc1..a25a3056df 100644 --- a/include/awkward/fillable/Float64Fillable.h +++ b/include/awkward/fillable/Float64Fillable.h @@ -13,40 +13,29 @@ namespace awkward { public: Float64Fillable(const FillableOptions& options, const GrowableBuffer& buffer): options_(options), buffer_(buffer) { } - static Float64Fillable* fromempty(const FillableOptions& options) { - return new Float64Fillable(options, GrowableBuffer::empty(options)); - } - - static Float64Fillable* fromint64(const FillableOptions& options, GrowableBuffer old) { - GrowableBuffer buffer = GrowableBuffer::empty(options, old.reserved()); - int64_t* oldraw = old.ptr().get(); - double* newraw = buffer.ptr().get(); - for (int64_t i = 0; i < old.length(); i++) { - newraw[i] = (double)oldraw[i]; - } - buffer.set_length(old.length()); - return new Float64Fillable(options, buffer); - } + static const std::shared_ptr fromempty(const FillableOptions& options); + static const std::shared_ptr fromint64(const FillableOptions& options, GrowableBuffer old); + virtual const std::string classname() const { return "Float64Fillable"; }; virtual int64_t length() const; virtual void clear(); virtual const std::shared_ptr type() const; virtual const std::shared_ptr snapshot() const; virtual bool active() const; - virtual Fillable* null(); - virtual Fillable* boolean(bool x); - virtual Fillable* integer(int64_t x); - virtual Fillable* real(double x); - virtual Fillable* beginlist(); - virtual Fillable* endlist(); - virtual Fillable* begintuple(int64_t numfields); - virtual Fillable* index(int64_t index); - virtual Fillable* endtuple(); - virtual Fillable* beginrecord(int64_t disambiguator); - virtual Fillable* field_fast(const char* key); - virtual Fillable* field_check(const char* key); - virtual Fillable* endrecord(); + virtual const std::shared_ptr null(); + virtual const std::shared_ptr boolean(bool x); + virtual const std::shared_ptr integer(int64_t x); + virtual const std::shared_ptr real(double x); + virtual const std::shared_ptr string(const char* x, int64_t length, const char* encoding); + virtual const std::shared_ptr beginlist(); + virtual const std::shared_ptr endlist(); + virtual const std::shared_ptr begintuple(int64_t numfields); + virtual const std::shared_ptr index(int64_t index); + virtual const std::shared_ptr endtuple(); + virtual const std::shared_ptr beginrecord(const char* name, bool check); + virtual const std::shared_ptr field(const char* key, bool check); + virtual const std::shared_ptr endrecord(); private: const FillableOptions options_; diff --git a/include/awkward/fillable/Int64Fillable.h b/include/awkward/fillable/Int64Fillable.h index 7ac1abfb1a..41967a8bc7 100644 --- a/include/awkward/fillable/Int64Fillable.h +++ b/include/awkward/fillable/Int64Fillable.h @@ -13,29 +13,28 @@ namespace awkward { public: Int64Fillable(const FillableOptions& options, const GrowableBuffer& buffer): options_(options), buffer_(buffer) { } - static Int64Fillable* fromempty(const FillableOptions& options) { - return new Int64Fillable(options, GrowableBuffer::empty(options)); - } + static const std::shared_ptr fromempty(const FillableOptions& options); + virtual const std::string classname() const { return "Int64Fillable"; }; virtual int64_t length() const; virtual void clear(); virtual const std::shared_ptr type() const; virtual const std::shared_ptr snapshot() const; virtual bool active() const; - virtual Fillable* null(); - virtual Fillable* boolean(bool x); - virtual Fillable* integer(int64_t x); - virtual Fillable* real(double x); - virtual Fillable* beginlist(); - virtual Fillable* endlist(); - virtual Fillable* begintuple(int64_t numfields); - virtual Fillable* index(int64_t index); - virtual Fillable* endtuple(); - virtual Fillable* beginrecord(int64_t disambiguator); - virtual Fillable* field_fast(const char* key); - virtual Fillable* field_check(const char* key); - virtual Fillable* endrecord(); + virtual const std::shared_ptr null(); + virtual const std::shared_ptr boolean(bool x); + virtual const std::shared_ptr integer(int64_t x); + virtual const std::shared_ptr real(double x); + virtual const std::shared_ptr string(const char* x, int64_t length, const char* encoding); + virtual const std::shared_ptr beginlist(); + virtual const std::shared_ptr endlist(); + virtual const std::shared_ptr begintuple(int64_t numfields); + virtual const std::shared_ptr index(int64_t index); + virtual const std::shared_ptr endtuple(); + virtual const std::shared_ptr beginrecord(const char* name, bool check); + virtual const std::shared_ptr field(const char* key, bool check); + virtual const std::shared_ptr endrecord(); const GrowableBuffer buffer() const { return buffer_; } diff --git a/include/awkward/fillable/ListFillable.h b/include/awkward/fillable/ListFillable.h index bd8ac40cef..60fded2729 100644 --- a/include/awkward/fillable/ListFillable.h +++ b/include/awkward/fillable/ListFillable.h @@ -14,33 +14,30 @@ namespace awkward { class ListFillable: public Fillable { public: - ListFillable(const FillableOptions& options, const GrowableBuffer& offsets, Fillable* content, bool begun): options_(options), offsets_(offsets), content_(std::shared_ptr(content)), begun_(begun) { } + ListFillable(const FillableOptions& options, const GrowableBuffer& offsets, std::shared_ptr content, bool begun): options_(options), offsets_(offsets), content_(std::shared_ptr(content)), begun_(begun) { } - static ListFillable* fromempty(const FillableOptions& options) { - GrowableBuffer offsets = GrowableBuffer::empty(options); - offsets.append(0); - return new ListFillable(options, offsets, UnknownFillable::fromempty(options), false); - } + static const std::shared_ptr fromempty(const FillableOptions& options); + virtual const std::string classname() const { return "ListFillable"; }; virtual int64_t length() const; virtual void clear(); virtual const std::shared_ptr type() const; virtual const std::shared_ptr snapshot() const; virtual bool active() const; - virtual Fillable* null(); - virtual Fillable* boolean(bool x); - virtual Fillable* integer(int64_t x); - virtual Fillable* real(double x); - virtual Fillable* beginlist(); - virtual Fillable* endlist(); - virtual Fillable* begintuple(int64_t numfields); - virtual Fillable* index(int64_t index); - virtual Fillable* endtuple(); - virtual Fillable* beginrecord(int64_t disambiguator); - virtual Fillable* field_fast(const char* key); - virtual Fillable* field_check(const char* key); - virtual Fillable* endrecord(); + virtual const std::shared_ptr null(); + virtual const std::shared_ptr boolean(bool x); + virtual const std::shared_ptr integer(int64_t x); + virtual const std::shared_ptr real(double x); + virtual const std::shared_ptr string(const char* x, int64_t length, const char* encoding); + virtual const std::shared_ptr beginlist(); + virtual const std::shared_ptr endlist(); + virtual const std::shared_ptr begintuple(int64_t numfields); + virtual const std::shared_ptr index(int64_t index); + virtual const std::shared_ptr endtuple(); + virtual const std::shared_ptr beginrecord(const char* name, bool check); + virtual const std::shared_ptr field(const char* key, bool check); + virtual const std::shared_ptr endrecord(); private: const FillableOptions options_; @@ -48,7 +45,7 @@ namespace awkward { std::shared_ptr content_; bool begun_; - Fillable* maybeupdate(Fillable* tmp); + void maybeupdate(const std::shared_ptr& tmp); }; } diff --git a/include/awkward/fillable/OptionFillable.h b/include/awkward/fillable/OptionFillable.h index 68ac3c3606..c3ce89e1df 100644 --- a/include/awkward/fillable/OptionFillable.h +++ b/include/awkward/fillable/OptionFillable.h @@ -13,44 +13,38 @@ namespace awkward { class OptionFillable: public Fillable { public: - OptionFillable(const FillableOptions& options, const GrowableBuffer& offsets, Fillable* content): options_(options), offsets_(offsets), content_(content) { } + OptionFillable(const FillableOptions& options, const GrowableBuffer& offsets, std::shared_ptr content): options_(options), offsets_(offsets), content_(content) { } - static OptionFillable* fromnulls(const FillableOptions& options, int64_t nullcount, Fillable* content) { - GrowableBuffer offsets = GrowableBuffer::full(options, -1, nullcount); - return new OptionFillable(options, offsets, content); - } - - static OptionFillable* fromvalids(const FillableOptions& options, Fillable* content) { - GrowableBuffer offsets = GrowableBuffer::arange(options, content->length()); - return new OptionFillable(options, offsets, content); - } + static const std::shared_ptr fromnulls(const FillableOptions& options, int64_t nullcount, std::shared_ptr content); + static const std::shared_ptr fromvalids(const FillableOptions& options, std::shared_ptr content); + virtual const std::string classname() const { return "OptionFillable"; }; virtual int64_t length() const; virtual void clear(); virtual const std::shared_ptr type() const; virtual const std::shared_ptr snapshot() const; virtual bool active() const; - virtual Fillable* null(); - virtual Fillable* boolean(bool x); - virtual Fillable* integer(int64_t x); - virtual Fillable* real(double x); - virtual Fillable* beginlist(); - virtual Fillable* endlist(); - virtual Fillable* begintuple(int64_t numfields); - virtual Fillable* index(int64_t index); - virtual Fillable* endtuple(); - virtual Fillable* beginrecord(int64_t disambiguator); - virtual Fillable* field_fast(const char* key); - virtual Fillable* field_check(const char* key); - virtual Fillable* endrecord(); + virtual const std::shared_ptr null(); + virtual const std::shared_ptr boolean(bool x); + virtual const std::shared_ptr integer(int64_t x); + virtual const std::shared_ptr real(double x); + virtual const std::shared_ptr string(const char* x, int64_t length, const char* encoding); + virtual const std::shared_ptr beginlist(); + virtual const std::shared_ptr endlist(); + virtual const std::shared_ptr begintuple(int64_t numfields); + virtual const std::shared_ptr index(int64_t index); + virtual const std::shared_ptr endtuple(); + virtual const std::shared_ptr beginrecord(const char* name, bool check); + virtual const std::shared_ptr field(const char* key, bool check); + virtual const std::shared_ptr endrecord(); private: const FillableOptions options_; GrowableBuffer offsets_; std::shared_ptr content_; - void maybeupdate(Fillable* tmp); + void maybeupdate(const std::shared_ptr& tmp); }; } diff --git a/include/awkward/fillable/RecordFillable.h b/include/awkward/fillable/RecordFillable.h index a61d1307b7..2558cabde0 100644 --- a/include/awkward/fillable/RecordFillable.h +++ b/include/awkward/fillable/RecordFillable.h @@ -14,56 +14,60 @@ namespace awkward { class RecordFillable: public Fillable { public: - RecordFillable(const FillableOptions& options, const std::vector>& contents, const std::vector& keys, const std::vector& pointers, int64_t disambiguator, int64_t length, bool begun, int64_t nextindex, int64_t nexttotry) + RecordFillable(const FillableOptions& options, const std::vector>& contents, const std::vector& keys, const std::vector& pointers, const std::string& name, const char* nameptr, int64_t length, bool begun, int64_t nextindex, int64_t nexttotry) : options_(options) , contents_(contents) , keys_(keys) , pointers_(pointers) - , disambiguator_(disambiguator) + , name_(name) + , nameptr_(nameptr) , length_(length) , begun_(begun) , nextindex_(nextindex) , nexttotry_(nexttotry) { } - static RecordFillable* fromempty(const FillableOptions& options) { - return new RecordFillable(options, std::vector>(), std::vector(), std::vector(), 0, -1, false, -1, -1); - } - + static const std::shared_ptr fromempty(const FillableOptions& options); + virtual const std::string classname() const { return "RecordFillable"; }; virtual int64_t length() const; virtual void clear(); virtual const std::shared_ptr type() const; virtual const std::shared_ptr snapshot() const; virtual bool active() const; - virtual Fillable* null(); - virtual Fillable* boolean(bool x); - virtual Fillable* integer(int64_t x); - virtual Fillable* real(double x); - virtual Fillable* beginlist(); - virtual Fillable* endlist(); - virtual Fillable* begintuple(int64_t numfields); - virtual Fillable* index(int64_t index); - virtual Fillable* endtuple(); - virtual Fillable* beginrecord(int64_t disambiguator); - virtual Fillable* field_fast(const char* key); - virtual Fillable* field_check(const char* key); - virtual Fillable* endrecord(); + virtual const std::shared_ptr null(); + virtual const std::shared_ptr boolean(bool x); + virtual const std::shared_ptr integer(int64_t x); + virtual const std::shared_ptr real(double x); + virtual const std::shared_ptr string(const char* x, int64_t length, const char* encoding); + virtual const std::shared_ptr beginlist(); + virtual const std::shared_ptr endlist(); + virtual const std::shared_ptr begintuple(int64_t numfields); + virtual const std::shared_ptr index(int64_t index); + virtual const std::shared_ptr endtuple(); + virtual const std::shared_ptr beginrecord(const char* name, bool check); + virtual const std::shared_ptr field(const char* key, bool check); + virtual const std::shared_ptr endrecord(); - int64_t disambiguator() const { return disambiguator_; } + const std::string name() const { return name_; } + const char* nameptr() const { return nameptr_; } private: + const std::shared_ptr field_fast(const char* key); + const std::shared_ptr field_check(const char* key); + const FillableOptions options_; std::vector> contents_; std::vector keys_; std::vector pointers_; - int64_t disambiguator_; + std::string name_; + const char* nameptr_; int64_t length_; bool begun_; int64_t nextindex_; int64_t nexttotry_; - void maybeupdate(int64_t i, Fillable* tmp); + void maybeupdate(int64_t i, const std::shared_ptr& tmp); }; } diff --git a/include/awkward/fillable/StringFillable.h b/include/awkward/fillable/StringFillable.h new file mode 100644 index 0000000000..7962be0552 --- /dev/null +++ b/include/awkward/fillable/StringFillable.h @@ -0,0 +1,49 @@ +// BSD 3-Clause License; see https://github.com/jpivarski/awkward-1.0/blob/master/LICENSE + +#ifndef AWKWARD_STRINGFILLABLE_H_ +#define AWKWARD_STRINGFILLABLE_H_ + +#include "awkward/cpu-kernels/util.h" +#include "awkward/fillable/FillableOptions.h" +#include "awkward/fillable/GrowableBuffer.h" +#include "awkward/fillable/Fillable.h" + +namespace awkward { + class StringFillable: public Fillable { + public: + StringFillable(const FillableOptions& options, const GrowableBuffer& offsets, GrowableBuffer& content, const char* encoding): options_(options), offsets_(offsets), content_(content), encoding_(encoding) { } + + static const std::shared_ptr fromempty(const FillableOptions& options, const char* encoding); + + virtual const std::string classname() const { return "StringFillable"; }; + virtual int64_t length() const; + virtual void clear(); + virtual const std::shared_ptr type() const; + virtual const std::shared_ptr snapshot() const; + + virtual bool active() const; + virtual const std::shared_ptr null(); + virtual const std::shared_ptr boolean(bool x); + virtual const std::shared_ptr integer(int64_t x); + virtual const std::shared_ptr real(double x); + virtual const std::shared_ptr string(const char* x, int64_t length, const char* encoding); + virtual const std::shared_ptr beginlist(); + virtual const std::shared_ptr endlist(); + virtual const std::shared_ptr begintuple(int64_t numfields); + virtual const std::shared_ptr index(int64_t index); + virtual const std::shared_ptr endtuple(); + virtual const std::shared_ptr beginrecord(const char* name, bool check); + virtual const std::shared_ptr field(const char* key, bool check); + virtual const std::shared_ptr endrecord(); + + const char* encoding() const { return encoding_; } + + private: + const FillableOptions options_; + GrowableBuffer offsets_; + GrowableBuffer content_; + const char* encoding_; + }; +} + +#endif // AWKWARD_STRINGFILLABLE_H_ diff --git a/include/awkward/fillable/TupleFillable.h b/include/awkward/fillable/TupleFillable.h index e2fb11968c..71dd012f2f 100644 --- a/include/awkward/fillable/TupleFillable.h +++ b/include/awkward/fillable/TupleFillable.h @@ -21,29 +21,28 @@ namespace awkward { , begun_(begun) , nextindex_(nextindex) { } - static TupleFillable* fromempty(const FillableOptions& options) { - return new TupleFillable(options, std::vector>(), -1, false, -1); - } + static const std::shared_ptr fromempty(const FillableOptions& options); + virtual const std::string classname() const { return "TupleFillable"; }; virtual int64_t length() const; virtual void clear(); virtual const std::shared_ptr type() const; virtual const std::shared_ptr snapshot() const; virtual bool active() const; - virtual Fillable* null(); - virtual Fillable* boolean(bool x); - virtual Fillable* integer(int64_t x); - virtual Fillable* real(double x); - virtual Fillable* beginlist(); - virtual Fillable* endlist(); - virtual Fillable* begintuple(int64_t numfields); - virtual Fillable* index(int64_t index); - virtual Fillable* endtuple(); - virtual Fillable* beginrecord(int64_t disambiguator); - virtual Fillable* field_fast(const char* key); - virtual Fillable* field_check(const char* key); - virtual Fillable* endrecord(); + virtual const std::shared_ptr null(); + virtual const std::shared_ptr boolean(bool x); + virtual const std::shared_ptr integer(int64_t x); + virtual const std::shared_ptr real(double x); + virtual const std::shared_ptr string(const char* x, int64_t length, const char* encoding); + virtual const std::shared_ptr beginlist(); + virtual const std::shared_ptr endlist(); + virtual const std::shared_ptr begintuple(int64_t numfields); + virtual const std::shared_ptr index(int64_t index); + virtual const std::shared_ptr endtuple(); + virtual const std::shared_ptr beginrecord(const char* name, bool check); + virtual const std::shared_ptr field(const char* key, bool check); + virtual const std::shared_ptr endrecord(); int64_t numfields() const { return (int64_t)contents_.size(); } @@ -54,7 +53,7 @@ namespace awkward { bool begun_; int64_t nextindex_; - void maybeupdate(int64_t i, Fillable* tmp); + void maybeupdate(int64_t i, const std::shared_ptr& tmp); }; } diff --git a/include/awkward/fillable/UnionFillable.h b/include/awkward/fillable/UnionFillable.h index a0ab1e5c66..4a83935000 100644 --- a/include/awkward/fillable/UnionFillable.h +++ b/include/awkward/fillable/UnionFillable.h @@ -18,32 +18,28 @@ namespace awkward { public: UnionFillable(const FillableOptions& options, const GrowableBuffer& types, const GrowableBuffer& offsets, std::vector> contents): options_(options), types_(types), offsets_(offsets), contents_(contents), current_(-1) { } - static UnionFillable* fromsingle(const FillableOptions& options, Fillable* firstcontent) { - GrowableBuffer types = GrowableBuffer::full(options, 0, firstcontent->length()); - GrowableBuffer offsets = GrowableBuffer::arange(options, firstcontent->length()); - std::vector> contents({ std::shared_ptr(firstcontent) }); - return new UnionFillable(options, types, offsets, contents); - } + static const std::shared_ptr fromsingle(const FillableOptions& options, const std::shared_ptr firstcontent); + virtual const std::string classname() const { return "UnionFillable"; }; virtual int64_t length() const; virtual void clear(); virtual const std::shared_ptr type() const; virtual const std::shared_ptr snapshot() const; virtual bool active() const; - virtual Fillable* null(); - virtual Fillable* boolean(bool x); - virtual Fillable* integer(int64_t x); - virtual Fillable* real(double x); - virtual Fillable* beginlist(); - virtual Fillable* endlist(); - virtual Fillable* begintuple(int64_t numfields); - virtual Fillable* index(int64_t index); - virtual Fillable* endtuple(); - virtual Fillable* beginrecord(int64_t disambiguator); - virtual Fillable* field_fast(const char* key); - virtual Fillable* field_check(const char* key); - virtual Fillable* endrecord(); + virtual const std::shared_ptr null(); + virtual const std::shared_ptr boolean(bool x); + virtual const std::shared_ptr integer(int64_t x); + virtual const std::shared_ptr real(double x); + virtual const std::shared_ptr string(const char* x, int64_t length, const char* encoding); + virtual const std::shared_ptr beginlist(); + virtual const std::shared_ptr endlist(); + virtual const std::shared_ptr begintuple(int64_t numfields); + virtual const std::shared_ptr index(int64_t index); + virtual const std::shared_ptr endtuple(); + virtual const std::shared_ptr beginrecord(const char* name, bool check); + virtual const std::shared_ptr field(const char* key, bool check); + virtual const std::shared_ptr endrecord(); private: const FillableOptions options_; diff --git a/include/awkward/fillable/UnknownFillable.h b/include/awkward/fillable/UnknownFillable.h index 0da621800b..f050bc26ee 100644 --- a/include/awkward/fillable/UnknownFillable.h +++ b/include/awkward/fillable/UnknownFillable.h @@ -14,29 +14,28 @@ namespace awkward { public: UnknownFillable(const FillableOptions& options, int64_t nullcount): options_(options), nullcount_(nullcount) { } - static UnknownFillable* fromempty(const FillableOptions& options) { - return new UnknownFillable(options, 0); - } + static const std::shared_ptr fromempty(const FillableOptions& options); + virtual const std::string classname() const { return "UnknownFillable"; }; virtual int64_t length() const; virtual void clear(); virtual const std::shared_ptr type() const; virtual const std::shared_ptr snapshot() const; virtual bool active() const; - virtual Fillable* null(); - virtual Fillable* boolean(bool x); - virtual Fillable* integer(int64_t x); - virtual Fillable* real(double x); - virtual Fillable* beginlist(); - virtual Fillable* endlist(); - virtual Fillable* begintuple(int64_t numfields); - virtual Fillable* index(int64_t index); - virtual Fillable* endtuple(); - virtual Fillable* beginrecord(int64_t disambiguator); - virtual Fillable* field_fast(const char* key); - virtual Fillable* field_check(const char* key); - virtual Fillable* endrecord(); + virtual const std::shared_ptr null(); + virtual const std::shared_ptr boolean(bool x); + virtual const std::shared_ptr integer(int64_t x); + virtual const std::shared_ptr real(double x); + virtual const std::shared_ptr string(const char* x, int64_t length, const char* encoding); + virtual const std::shared_ptr beginlist(); + virtual const std::shared_ptr endlist(); + virtual const std::shared_ptr begintuple(int64_t numfields); + virtual const std::shared_ptr index(int64_t index); + virtual const std::shared_ptr endtuple(); + virtual const std::shared_ptr beginrecord(const char* name, bool check); + virtual const std::shared_ptr field(const char* key, bool check); + virtual const std::shared_ptr endrecord(); private: const FillableOptions options_; diff --git a/include/awkward/io/json.h b/include/awkward/io/json.h index 2510ee39b2..7f28f914e0 100644 --- a/include/awkward/io/json.h +++ b/include/awkward/io/json.h @@ -32,12 +32,12 @@ namespace awkward { virtual void boolean(bool x) = 0; virtual void integer(int64_t x) = 0; virtual void real(double x) = 0; + virtual void string(const char* x, int64_t length) = 0; virtual void beginlist() = 0; virtual void endlist() = 0; - virtual void beginrec() = 0; - virtual void endrec() = 0; - virtual void fieldkey(const char* x) = 0; - virtual void string(const char* x) = 0; + virtual void beginrecord() = 0; + virtual void field(const char* x) = 0; + virtual void endrecord() = 0; }; class ToJsonString: public ToJson { @@ -52,12 +52,12 @@ namespace awkward { virtual void boolean(bool x) { writer_.Bool(x); } virtual void integer(int64_t x) { writer_.Int64(x); } virtual void real(double x) { writer_.Double(x); } + virtual void string(const char* x, int64_t length) { writer_.String(x, (rj::SizeType)length); } virtual void beginlist() { writer_.StartArray(); } virtual void endlist() { writer_.EndArray(); } - virtual void beginrec() { writer_.StartObject(); } - virtual void endrec() { writer_.EndObject(); } - virtual void fieldkey(const char* x) { writer_.Key(x); } - virtual void string(const char* x) { writer_.String(x); } + virtual void beginrecord() { writer_.StartObject(); } + virtual void field(const char* x) { writer_.Key(x); } + virtual void endrecord() { writer_.EndObject(); } std::string tostring() { return std::string(buffer_.GetString()); @@ -80,12 +80,12 @@ namespace awkward { virtual void boolean(bool x) { writer_.Bool(x); } virtual void integer(int64_t x) { writer_.Int64(x); } virtual void real(double x) { writer_.Double(x); } + virtual void string(const char* x, int64_t length) { writer_.String(x, (rj::SizeType)length); } virtual void beginlist() { writer_.StartArray(); } virtual void endlist() { writer_.EndArray(); } - virtual void beginrec() { writer_.StartObject(); } - virtual void endrec() { writer_.EndObject(); } - virtual void fieldkey(const char* x) { writer_.Key(x); } - virtual void string(const char* x) { writer_.String(x); } + virtual void beginrecord() { writer_.StartObject(); } + virtual void field(const char* x) { writer_.Key(x); } + virtual void endrecord() { writer_.EndObject(); } std::string tostring() { return std::string(buffer_.GetString()); @@ -108,12 +108,12 @@ namespace awkward { virtual void boolean(bool x) { writer_.Bool(x); } virtual void integer(int64_t x) { writer_.Int64(x); } virtual void real(double x) { writer_.Double(x); } + virtual void string(const char* x, int64_t length) { writer_.String(x, (rj::SizeType)length); } virtual void beginlist() { writer_.StartArray(); } virtual void endlist() { writer_.EndArray(); } - virtual void beginrec() { writer_.StartObject(); } - virtual void endrec() { writer_.EndObject(); } - virtual void fieldkey(const char* x) { writer_.Key(x); } - virtual void string(const char* x) { writer_.String(x); } + virtual void beginrecord() { writer_.StartObject(); } + virtual void field(const char* x) { writer_.Key(x); } + virtual void endrecord() { writer_.EndObject(); } private: std::shared_ptr buffer_; @@ -133,12 +133,12 @@ namespace awkward { virtual void boolean(bool x) { writer_.Bool(x); } virtual void integer(int64_t x) { writer_.Int64(x); } virtual void real(double x) { writer_.Double(x); } + virtual void string(const char* x, int64_t length) { writer_.String(x, (rj::SizeType)length); } virtual void beginlist() { writer_.StartArray(); } virtual void endlist() { writer_.EndArray(); } - virtual void beginrec() { writer_.StartObject(); } - virtual void endrec() { writer_.EndObject(); } - virtual void fieldkey(const char* x) { writer_.Key(x); } - virtual void string(const char* x) { writer_.String(x); } + virtual void beginrecord() { writer_.StartObject(); } + virtual void field(const char* x) { writer_.Key(x); } + virtual void endrecord() { writer_.EndObject(); } private: std::shared_ptr buffer_; @@ -149,3 +149,5 @@ namespace awkward { } #endif // AWKWARD_IO_JSON_H_ + +// , rj::UTF8<>, rj::UTF8<>, rj::CrtAllocator<>, rj::kWriteNanAndInfFlag, rj::UTF8<>, rj::UTF8<>, rj::CrtAllocator<>, rj::kWriteNanAndInfFlag, rj::UTF8<>, rj::UTF8<>, rj::CrtAllocator<>, rj::kWriteNanAndInfFlag, rj::UTF8<>, rj::UTF8<>, rj::CrtAllocator<>, rj::kWriteNanAndInfFlag diff --git a/include/awkward/type/ArrayType.h b/include/awkward/type/ArrayType.h index d735939b68..e0dd32aa2b 100644 --- a/include/awkward/type/ArrayType.h +++ b/include/awkward/type/ArrayType.h @@ -8,12 +8,14 @@ namespace awkward { class ArrayType: public Type { public: - ArrayType(const std::shared_ptr type, int64_t length): type_(type), length_(length) { } + ArrayType(const Parameters& parameters, const std::shared_ptr type, int64_t length) + : Type(parameters) + , type_(type) + , length_(length) { } virtual std::string tostring_part(std::string indent, std::string pre, std::string post) const; virtual const std::shared_ptr shallow_copy() const; - virtual bool shallow_equal(const std::shared_ptr other) const; - virtual bool equal(const std::shared_ptr other) const; + virtual bool equal(const std::shared_ptr other, bool check_parameters) const; virtual std::shared_ptr nolength() const; virtual std::shared_ptr level() const; virtual std::shared_ptr inner() const; diff --git a/include/awkward/type/DressedType.h b/include/awkward/type/DressedType.h deleted file mode 100644 index dc099830ef..0000000000 --- a/include/awkward/type/DressedType.h +++ /dev/null @@ -1,115 +0,0 @@ -// BSD 3-Clause License; see https://github.com/jpivarski/awkward-1.0/blob/master/LICENSE - -#ifndef AWKWARD_DRESSEDTYPE_H_ -#define AWKWARD_DRESSEDTYPE_H_ - -#include - -#include "awkward/type/Type.h" - -namespace awkward { - template - class DressParameters { - public: - virtual const std::vector keys() const = 0; - virtual const T get(const std::string& key) const = 0; - virtual const std::string get_string(const std::string& key) const = 0; - virtual bool equal(const DressParameters& other) const = 0; - }; - - template - class Dress { - public: - virtual const std::string name() const = 0; - virtual const std::string typestr(std::shared_ptr baretype, const DressParameters& parameters) const = 0; - virtual bool equal(const Dress& other) const = 0; - }; - - template - class DressedType: public Type { - public: - DressedType(const std::shared_ptr type, const D& dress, const P& parameters): type_(type), dress_(dress), parameters_(parameters) { } - - virtual std::string tostring_part(std::string indent, std::string pre, std::string post) const { - std::string outstr = dress_.typestr(type_, parameters_); - if (outstr.size() != 0) { - return outstr; - } - else { - std::stringstream out; - out << indent << pre << "dress[" << type_.get()->tostring_part(indent, "", "") << ", " << util::quote(dress_.name(), false); - for (auto key : parameters_.keys()) { - out << ", " << key << "=" << parameters_.get_string(key); - } - out << "]"; - return out.str(); - } - } - virtual const std::shared_ptr shallow_copy() const { - return std::shared_ptr(new DressedType(type_, dress_, parameters_)); - } - virtual bool shallow_equal(const std::shared_ptr other) const { - if (DressedType* raw = dynamic_cast*>(other.get())) { - D otherdress = raw->dress(); - if (!dress_.equal(otherdress)) { - return false; - } - P otherparam = raw->parameters(); - if (!parameters_.equal(otherparam)) { - return false; - } - return true; - } - else { - return false; - } - } - virtual bool equal(const std::shared_ptr other) const { - if (!shallow_equal(other)) { - return false; - } - return type_.get()->equal(dynamic_cast*>(other.get())->type()); - } - virtual std::shared_ptr level() const { - return type_.get()->level(); - } - virtual std::shared_ptr inner() const { - return type_.get()->inner(); - } - virtual std::shared_ptr inner(const std::string& key) const { - return type_.get()->inner(key); - } - virtual int64_t numfields() const { - return type_.get()->numfields(); - } - virtual int64_t fieldindex(const std::string& key) const { - return type_.get()->fieldindex(key); - } - virtual const std::string key(int64_t fieldindex) const { - return type_.get()->key(fieldindex); - } - virtual bool haskey(const std::string& key) const { - return type_.get()->haskey(key); - } - virtual const std::vector keyaliases(int64_t fieldindex) const { - return type_.get()->keyaliases(fieldindex); - } - virtual const std::vector keyaliases(const std::string& key) const { - return type_.get()->keyaliases(key); - } - virtual const std::vector keys() const { - return type_.get()->keys(); - } - - const std::shared_ptr type() const { return type_; }; - const D dress() const { return dress_; }; - const P parameters() const { return parameters_; } - - private: - const std::shared_ptr type_; - const D dress_; - const P parameters_; - }; -} - -#endif // AWKWARD_DRESSEDTYPE_H_ diff --git a/include/awkward/type/ListType.h b/include/awkward/type/ListType.h index b062fc8978..fb568914fd 100644 --- a/include/awkward/type/ListType.h +++ b/include/awkward/type/ListType.h @@ -8,12 +8,13 @@ namespace awkward { class ListType: public Type { public: - ListType(const std::shared_ptr type): type_(type) { } + ListType(const Parameters& parameters, const std::shared_ptr type) + : Type(parameters) + , type_(type) { } virtual std::string tostring_part(std::string indent, std::string pre, std::string post) const; virtual const std::shared_ptr shallow_copy() const; - virtual bool shallow_equal(const std::shared_ptr other) const; - virtual bool equal(const std::shared_ptr other) const; + virtual bool equal(const std::shared_ptr other, bool check_parameters) const; virtual std::shared_ptr level() const; virtual std::shared_ptr inner() const; virtual std::shared_ptr inner(const std::string& key) const; diff --git a/include/awkward/type/OptionType.h b/include/awkward/type/OptionType.h index df563a91ff..adfd2a2c1a 100644 --- a/include/awkward/type/OptionType.h +++ b/include/awkward/type/OptionType.h @@ -8,12 +8,13 @@ namespace awkward { class OptionType: public Type { public: - OptionType(const std::shared_ptr type): type_(type) { } + OptionType(const Parameters& parameters, const std::shared_ptr type) + : Type(parameters) + , type_(type) { } virtual std::string tostring_part(std::string indent, std::string pre, std::string post) const; virtual const std::shared_ptr shallow_copy() const; - virtual bool shallow_equal(const std::shared_ptr other) const; - virtual bool equal(const std::shared_ptr other) const; + virtual bool equal(const std::shared_ptr other, bool check_parameters) const; virtual std::shared_ptr level() const; virtual std::shared_ptr inner() const; virtual std::shared_ptr inner(const std::string& key) const; diff --git a/include/awkward/type/PrimitiveType.h b/include/awkward/type/PrimitiveType.h index 322c82787d..ff165648ee 100644 --- a/include/awkward/type/PrimitiveType.h +++ b/include/awkward/type/PrimitiveType.h @@ -23,12 +23,13 @@ namespace awkward { numtypes }; - PrimitiveType(DType dtype): dtype_(dtype) { } + PrimitiveType(const Parameters& parameters, DType dtype) + : Type(parameters) + , dtype_(dtype) { } virtual std::string tostring_part(std::string indent, std::string pre, std::string post) const; virtual const std::shared_ptr shallow_copy() const; - virtual bool shallow_equal(const std::shared_ptr other) const; - virtual bool equal(const std::shared_ptr other) const; + virtual bool equal(const std::shared_ptr other, bool check_parameters) const; virtual std::shared_ptr level() const; virtual std::shared_ptr inner() const; virtual std::shared_ptr inner(const std::string& key) const; diff --git a/include/awkward/type/RecordType.h b/include/awkward/type/RecordType.h index c858f624ba..f19e45547d 100644 --- a/include/awkward/type/RecordType.h +++ b/include/awkward/type/RecordType.h @@ -15,12 +15,14 @@ namespace awkward { typedef std::unordered_map Lookup; typedef std::vector ReverseLookup; - RecordType(const std::vector>& types, const std::shared_ptr& lookup, const std::shared_ptr& reverselookup) - : types_(types) + RecordType(const Parameters& parameters, const std::vector>& types, const std::shared_ptr& lookup, const std::shared_ptr& reverselookup) + : Type(parameters) + , types_(types) , lookup_(lookup) , reverselookup_(reverselookup) { } - RecordType(const std::vector>& types) - : types_(types) + RecordType(const Parameters& parameters, const std::vector>& types) + : Type(parameters) + , types_(types) , lookup_(nullptr) , reverselookup_(nullptr) { } @@ -30,8 +32,7 @@ namespace awkward { virtual std::string tostring_part(std::string indent, std::string pre, std::string post) const; virtual const std::shared_ptr shallow_copy() const; - virtual bool shallow_equal(const std::shared_ptr other) const; - virtual bool equal(const std::shared_ptr other) const; + virtual bool equal(const std::shared_ptr other, bool check_parameters) const; virtual std::shared_ptr level() const; virtual std::shared_ptr inner() const; virtual std::shared_ptr inner(const std::string& key) const; diff --git a/include/awkward/type/RegularType.h b/include/awkward/type/RegularType.h index 612eb0c82f..9f8af20713 100644 --- a/include/awkward/type/RegularType.h +++ b/include/awkward/type/RegularType.h @@ -10,12 +10,14 @@ namespace awkward { class RegularType: public Type { public: - RegularType(const std::shared_ptr type, int64_t size): type_(type), size_(size) { } + RegularType(const Parameters& parameters, const std::shared_ptr type, int64_t size) + : Type(parameters) + , type_(type) + , size_(size) { } virtual std::string tostring_part(std::string indent, std::string pre, std::string post) const; virtual const std::shared_ptr shallow_copy() const; - virtual bool shallow_equal(const std::shared_ptr other) const; - virtual bool equal(const std::shared_ptr other) const; + virtual bool equal(const std::shared_ptr other, bool check_parameters) const; virtual std::shared_ptr level() const; virtual std::shared_ptr inner() const; virtual std::shared_ptr inner(const std::string& key) const; diff --git a/include/awkward/type/Type.h b/include/awkward/type/Type.h index 26d848eab1..bc6875c024 100644 --- a/include/awkward/type/Type.h +++ b/include/awkward/type/Type.h @@ -5,20 +5,23 @@ #include #include +#include #include "awkward/cpu-kernels/util.h" namespace awkward { class Type { public: + typedef std::map Parameters; + + Type(const Parameters& parameters): parameters_(parameters) { } virtual ~Type() { } static std::shared_ptr none() { return std::shared_ptr(nullptr); } virtual std::string tostring_part(std::string indent, std::string pre, std::string post) const = 0; virtual const std::shared_ptr shallow_copy() const = 0; - virtual bool shallow_equal(const std::shared_ptr other) const = 0; - virtual bool equal(const std::shared_ptr other) const = 0; + virtual bool equal(const std::shared_ptr other, bool check_parameters) const = 0; virtual std::shared_ptr nolength() const; virtual std::shared_ptr level() const = 0; virtual std::shared_ptr inner() const = 0; @@ -31,8 +34,38 @@ namespace awkward { virtual const std::vector keyaliases(const std::string& key) const = 0; virtual const std::vector keys() const = 0; - std::string tostring() const { return tostring_part("", "", ""); }; + const Parameters parameters() const { + return parameters_; + } + void setparameters(const Parameters& parameters) { + parameters_ = parameters; + } + std::string parameter(const std::string& key) { + return parameters_[key]; + } + void setparameter(const std::string& key, const std::string& value) { + parameters_[key] = value; + } + bool parameter_equals(const std::string& key, const std::string& value) { + auto item = parameters_.find(key); + if (item == parameters_.end()) { + return false; + } + else { + return item->second == value; + } + } + std::string tostring() const { + return tostring_part("", "", ""); + }; const std::string compare(std::shared_ptr supertype); + + protected: + bool equal_parameters(const Parameters& other) const; + bool get_typestr(std::string& output) const; + const std::string string_parameters() const; + + Parameters parameters_; }; } diff --git a/include/awkward/type/UnionType.h b/include/awkward/type/UnionType.h index 5439cfc943..0b63a0b274 100644 --- a/include/awkward/type/UnionType.h +++ b/include/awkward/type/UnionType.h @@ -10,12 +10,11 @@ namespace awkward { class UnionType: public Type { public: - UnionType(const std::vector>& types): types_(types) { } + UnionType(const Parameters& parameters, const std::vector>& types): Type(parameters), types_(types) { } virtual std::string tostring_part(std::string indent, std::string pre, std::string post) const; virtual const std::shared_ptr shallow_copy() const; - virtual bool shallow_equal(const std::shared_ptr other) const; - virtual bool equal(const std::shared_ptr other) const; + virtual bool equal(const std::shared_ptr other, bool check_parameters) const; virtual std::shared_ptr level() const; virtual std::shared_ptr inner() const; virtual std::shared_ptr inner(const std::string& key) const; diff --git a/include/awkward/type/UnknownType.h b/include/awkward/type/UnknownType.h index e51549a10b..272657c653 100644 --- a/include/awkward/type/UnknownType.h +++ b/include/awkward/type/UnknownType.h @@ -8,12 +8,11 @@ namespace awkward { class UnknownType: public Type { public: - UnknownType() { } + UnknownType(const Parameters& parameters): Type(parameters) { } virtual std::string tostring_part(std::string indent, std::string pre, std::string post) const; virtual const std::shared_ptr shallow_copy() const; - virtual bool shallow_equal(const std::shared_ptr other) const; - virtual bool equal(const std::shared_ptr other) const; + virtual bool equal(const std::shared_ptr other, bool check_parameters) const; virtual std::shared_ptr level() const; virtual std::shared_ptr inner() const; virtual std::shared_ptr inner(const std::string& key) const; diff --git a/src/libawkward/Content.cpp b/src/libawkward/Content.cpp index 808b3b985d..bfca83ddd6 100644 --- a/src/libawkward/Content.cpp +++ b/src/libawkward/Content.cpp @@ -22,11 +22,11 @@ namespace awkward { return innertype(false); } else { - return std::shared_ptr(new ArrayType(innertype(false), length())); + return std::shared_ptr(new ArrayType(Type::Parameters(), innertype(false), length())); } } else { - return std::shared_ptr(new ArrayType(type_, length())); + return std::shared_ptr(new ArrayType(Type::Parameters(), type_, length())); } } @@ -50,7 +50,7 @@ namespace awkward { return innertype(true); } else { - return std::shared_ptr(new ArrayType(innertype(true), length())); + return std::shared_ptr(new ArrayType(Type::Parameters(), innertype(true), length())); } } diff --git a/src/libawkward/array/EmptyArray.cpp b/src/libawkward/array/EmptyArray.cpp index 7f1308d508..f4dbf4fcc3 100644 --- a/src/libawkward/array/EmptyArray.cpp +++ b/src/libawkward/array/EmptyArray.cpp @@ -46,7 +46,7 @@ namespace awkward { } const std::shared_ptr EmptyArray::innertype(bool bare) const { - return std::shared_ptr(new UnknownType()); + return std::shared_ptr(new UnknownType(Type::Parameters())); } void EmptyArray::settype_part(const std::shared_ptr type) { @@ -54,13 +54,12 @@ namespace awkward { type_ = type; } else { - throw std::invalid_argument(std::string("provided type is incompatible with array: ") + ArrayType(type, length()).compare(baretype())); + throw std::invalid_argument(std::string("provided type is incompatible with array: ") + ArrayType(Type::Parameters(), type, length()).compare(baretype())); } } bool EmptyArray::accepts(const std::shared_ptr type) { - const std::shared_ptr model(new UnknownType()); - return type.get()->level().get()->shallow_equal(model); + return dynamic_cast(type.get()->level().get()) != nullptr; } int64_t EmptyArray::length() const { diff --git a/src/libawkward/array/ListArray.cpp b/src/libawkward/array/ListArray.cpp index 4059fa3165..7100d24b2e 100644 --- a/src/libawkward/array/ListArray.cpp +++ b/src/libawkward/array/ListArray.cpp @@ -167,10 +167,10 @@ namespace awkward { template const std::shared_ptr ListArrayOf::innertype(bool bare) const { if (bare || content_.get()->isbare()) { - return std::shared_ptr(new ListType(content_.get()->innertype(bare))); + return std::shared_ptr(new ListType(Type::Parameters(), content_.get()->innertype(bare))); } else { - return std::shared_ptr(new ListType(content_.get()->type().get()->nolength())); + return std::shared_ptr(new ListType(Type::Parameters(), content_.get()->type().get()->nolength())); } } @@ -181,14 +181,13 @@ namespace awkward { type_ = type; } else { - throw std::invalid_argument(std::string("provided type is incompatible with array: ") + ArrayType(type, length()).compare(baretype())); + throw std::invalid_argument(std::string("provided type is incompatible with array: ") + ArrayType(Type::Parameters(), type, length()).compare(baretype())); } } template bool ListArrayOf::accepts(const std::shared_ptr type) { - const std::shared_ptr model(new ListType(std::shared_ptr(new UnknownType()))); - return type.get()->level().get()->shallow_equal(model); + return dynamic_cast(type.get()->level().get()) != nullptr; } template diff --git a/src/libawkward/array/ListOffsetArray.cpp b/src/libawkward/array/ListOffsetArray.cpp index 1d0d6720be..4810e15570 100644 --- a/src/libawkward/array/ListOffsetArray.cpp +++ b/src/libawkward/array/ListOffsetArray.cpp @@ -170,10 +170,10 @@ namespace awkward { template const std::shared_ptr ListOffsetArrayOf::innertype(bool bare) const { if (bare || content_.get()->isbare()) { - return std::shared_ptr(new ListType(content_.get()->innertype(bare))); + return std::shared_ptr(new ListType(Type::Parameters(), content_.get()->innertype(bare))); } else { - return std::shared_ptr(new ListType(content_.get()->type().get()->nolength())); + return std::shared_ptr(new ListType(Type::Parameters(), content_.get()->type().get()->nolength())); } } @@ -184,14 +184,13 @@ namespace awkward { type_ = type; } else { - throw std::invalid_argument(std::string("provided type is incompatible with array: ") + ArrayType(type, length()).compare(baretype())); + throw std::invalid_argument(std::string("provided type is incompatible with array: ") + ArrayType(Type::Parameters(), type, length()).compare(baretype())); } } template bool ListOffsetArrayOf::accepts(const std::shared_ptr type) { - const std::shared_ptr model(new ListType(std::shared_ptr(new UnknownType()))); - return type.get()->level().get()->shallow_equal(model); + return dynamic_cast(type.get()->level().get()) != nullptr; } template diff --git a/src/libawkward/array/NumpyArray.cpp b/src/libawkward/array/NumpyArray.cpp index b0c1f7e1d9..484ebfd1c8 100644 --- a/src/libawkward/array/NumpyArray.cpp +++ b/src/libawkward/array/NumpyArray.cpp @@ -214,7 +214,10 @@ namespace awkward { } void NumpyArray::tojson_part(ToJson& builder) const { - if (format_.compare("d") == 0) { + if (type_.get() != nullptr && type_.get()->parameter_equals("__class__", "\"char\"")) { + tojson_string(builder); + } + else if (format_.compare("d") == 0) { tojson_real(builder); } else if (format_.compare("f") == 0) { @@ -249,16 +252,16 @@ namespace awkward { tojson_integer(builder); } else if (format_.compare("h") == 0) { - tojson_real(builder); + tojson_integer(builder); } else if (format_.compare("H") == 0) { - tojson_real(builder); + tojson_integer(builder); } else if (format_.compare("b") == 0) { - tojson_real(builder); + tojson_integer(builder); } else if (format_.compare("B") == 0) { - tojson_real(builder); + tojson_integer(builder); } else if (format_.compare("?") == 0) { tojson_boolean(builder); @@ -271,53 +274,53 @@ namespace awkward { const std::shared_ptr NumpyArray::innertype(bool bare) const { if (ndim() == 1) { if (format_.compare("d") == 0) { - return std::shared_ptr(new PrimitiveType(PrimitiveType::float64)); + return std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::float64)); } else if (format_.compare("f") == 0) { - return std::shared_ptr(new PrimitiveType(PrimitiveType::float32)); + return std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::float32)); } #ifdef _MSC_VER else if (format_.compare("q") == 0) { #else else if (format_.compare("l") == 0) { #endif - return std::shared_ptr(new PrimitiveType(PrimitiveType::int64)); + return std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::int64)); } #ifdef _MSC_VER else if (format_.compare("Q") == 0) { #else else if (format_.compare("L") == 0) { #endif - return std::shared_ptr(new PrimitiveType(PrimitiveType::uint64)); + return std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::uint64)); } #ifdef _MSC_VER else if (format_.compare("l") == 0) { #else else if (format_.compare("i") == 0) { #endif - return std::shared_ptr(new PrimitiveType(PrimitiveType::int32)); + return std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::int32)); } #ifdef _MSC_VER else if (format_.compare("L") == 0) { #else else if (format_.compare("I") == 0) { #endif - return std::shared_ptr(new PrimitiveType(PrimitiveType::uint32)); + return std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::uint32)); } else if (format_.compare("h") == 0) { - return std::shared_ptr(new PrimitiveType(PrimitiveType::int16)); + return std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::int16)); } else if (format_.compare("H") == 0) { - return std::shared_ptr(new PrimitiveType(PrimitiveType::uint16)); + return std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::uint16)); } else if (format_.compare("b") == 0) { - return std::shared_ptr(new PrimitiveType(PrimitiveType::int8)); + return std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::int8)); } else if (format_.compare("B") == 0 || format_.compare("c") == 0) { - return std::shared_ptr(new PrimitiveType(PrimitiveType::uint8)); + return std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::uint8)); } else if (format_.compare("?") == 0) { - return std::shared_ptr(new PrimitiveType(PrimitiveType::boolean)); + return std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::boolean)); } else { throw std::invalid_argument(std::string("Numpy format \"") + format_ + std::string("\" cannot be expressed as a PrimitiveType")); @@ -327,7 +330,7 @@ namespace awkward { NumpyArray tmp(id_, type_, ptr_, std::vector({ 1 }), std::vector({ itemsize_ }), byteoffset_, itemsize_, format_); std::shared_ptr out = tmp.innertype(bare); for (ssize_t i = shape_.size() - 1; i > 0; i--) { - out = std::shared_ptr(new RegularType(out, (int64_t)shape_[i])); + out = std::shared_ptr(new RegularType(Type::Parameters(), out, (int64_t)shape_[i])); } return out; } @@ -339,15 +342,15 @@ namespace awkward { return innertype(false); } else { - return std::shared_ptr(new ArrayType(innertype(false), length())); + return std::shared_ptr(new ArrayType(Type::Parameters(), innertype(false), length())); } } else { std::shared_ptr out = type_; for (ssize_t i = shape_.size() - 1; i > 0; i--) { - out = std::shared_ptr(new RegularType(out, (int64_t)shape_[i])); + out = std::shared_ptr(new RegularType(Type::Parameters(), out, (int64_t)shape_[i])); } - return std::shared_ptr(new ArrayType(out, length())); + return std::shared_ptr(new ArrayType(Type::Parameters(), out, length())); } } @@ -360,68 +363,82 @@ namespace awkward { type_ = t; } else { - throw std::invalid_argument(std::string("provided type is incompatible with array: ") + ArrayType(type, length()).compare(baretype())); + throw std::invalid_argument(std::string("provided type is incompatible with array: ") + ArrayType(Type::Parameters(), type, length()).compare(baretype())); } } bool NumpyArray::accepts(const std::shared_ptr type) { - std::shared_ptr model; - if (format_.compare("d") == 0) { - model = std::shared_ptr(new PrimitiveType(PrimitiveType::float64)); - } - else if (format_.compare("f") == 0) { - model = std::shared_ptr(new PrimitiveType(PrimitiveType::float32)); + std::shared_ptr test = type->level(); + for (size_t i = 1; i < shape_.size(); i++) { + if (RegularType* raw = dynamic_cast(test.get())) { + if (raw->size() == (int64_t)shape_[i]) { + test = raw->inner()->level(); + } + else { + return false; + } + } + else { + return false; + } } + if (PrimitiveType* raw = dynamic_cast(test.get())) { + if (format_.compare("d") == 0) { + return raw->dtype() == PrimitiveType::float64; + } + else if (format_.compare("f") == 0) { + return raw->dtype() == PrimitiveType::float32; + } #ifdef _MSC_VER - else if (format_.compare("q") == 0) { + else if (format_.compare("q") == 0) { #else - else if (format_.compare("l") == 0) { + else if (format_.compare("l") == 0) { #endif - model = std::shared_ptr(new PrimitiveType(PrimitiveType::int64)); - } + return raw->dtype() == PrimitiveType::int64; + } #ifdef _MSC_VER - else if (format_.compare("Q") == 0) { + else if (format_.compare("Q") == 0) { #else - else if (format_.compare("L") == 0) { + else if (format_.compare("L") == 0) { #endif - model = std::shared_ptr(new PrimitiveType(PrimitiveType::uint64)); - } + return raw->dtype() == PrimitiveType::uint64; + } #ifdef _MSC_VER - else if (format_.compare("l") == 0) { + else if (format_.compare("l") == 0) { #else - else if (format_.compare("i") == 0) { + else if (format_.compare("i") == 0) { #endif - model = std::shared_ptr(new PrimitiveType(PrimitiveType::int32)); - } + return raw->dtype() == PrimitiveType::int32; + } #ifdef _MSC_VER - else if (format_.compare("L") == 0) { + else if (format_.compare("L") == 0) { #else - else if (format_.compare("I") == 0) { + else if (format_.compare("I") == 0) { #endif - model = std::shared_ptr(new PrimitiveType(PrimitiveType::uint32)); - } - else if (format_.compare("h") == 0) { - model = std::shared_ptr(new PrimitiveType(PrimitiveType::int16)); - } - else if (format_.compare("H") == 0) { - model = std::shared_ptr(new PrimitiveType(PrimitiveType::uint16)); - } - else if (format_.compare("b") == 0) { - model = std::shared_ptr(new PrimitiveType(PrimitiveType::int8)); - } - else if (format_.compare("B") == 0 || format_.compare("c") == 0) { - model = std::shared_ptr(new PrimitiveType(PrimitiveType::uint8)); - } - else if (format_.compare("?") == 0) { - model = std::shared_ptr(new PrimitiveType(PrimitiveType::boolean)); + return raw->dtype() == PrimitiveType::uint32; + } + else if (format_.compare("h") == 0) { + return raw->dtype() == PrimitiveType::int16; + } + else if (format_.compare("H") == 0) { + return raw->dtype() == PrimitiveType::uint16; + } + else if (format_.compare("b") == 0) { + return raw->dtype() == PrimitiveType::int8; + } + else if (format_.compare("B") == 0 || format_.compare("c") == 0) { + return raw->dtype() == PrimitiveType::uint8; + } + else if (format_.compare("?") == 0) { + return raw->dtype() == PrimitiveType::boolean; + } + else { + return false; + } } else { return false; } - for (size_t i = shape_.size() - 1; i > 0; i--) { - model = std::shared_ptr(new RegularType(model, shape_[i])); - } - return type.get()->level().get()->shallow_equal(model); } int64_t NumpyArray::length() const { @@ -1156,4 +1173,25 @@ namespace awkward { } } + void NumpyArray::tojson_string(ToJson& builder) const { + if (ndim() == 0) { + char* array = reinterpret_cast(byteptr()); + builder.string(array, 1); + } + else if (ndim() == 1) { + char* array = reinterpret_cast(byteptr()); + builder.string(array, length()); + } + else { + const std::vector shape(shape_.begin() + 1, shape_.end()); + const std::vector strides(strides_.begin() + 1, strides_.end()); + builder.beginlist(); + for (int64_t i = 0; i < length(); i++) { + ssize_t byteoffset = byteoffset_ + strides_[0]*((ssize_t)i); + NumpyArray numpy(Identity::none(), Type::none(), ptr_, shape, strides, byteoffset, itemsize_, format_); + numpy.tojson_string(builder); + } + builder.endlist(); + } + } } diff --git a/src/libawkward/array/Record.cpp b/src/libawkward/array/Record.cpp index 307f1f5442..8ab68640eb 100644 --- a/src/libawkward/array/Record.cpp +++ b/src/libawkward/array/Record.cpp @@ -58,12 +58,12 @@ namespace awkward { } } std::vector> contents = array_.contents(); - builder.beginrec(); + builder.beginrecord(); for (size_t j = 0; j < cols; j++) { - builder.fieldkey(keys.get()->at(j).c_str()); + builder.field(keys.get()->at(j).c_str()); contents[j].get()->getitem_at_nowrap(at_).get()->tojson_part(builder); } - builder.endrec(); + builder.endrecord(); } const std::shared_ptr Record::innertype(bool bare) const { diff --git a/src/libawkward/array/RecordArray.cpp b/src/libawkward/array/RecordArray.cpp index 805f2deac3..72258cd8e0 100644 --- a/src/libawkward/array/RecordArray.cpp +++ b/src/libawkward/array/RecordArray.cpp @@ -108,12 +108,12 @@ namespace awkward { } builder.beginlist(); for (int64_t i = 0; i < rows; i++) { - builder.beginrec(); + builder.beginrecord(); for (size_t j = 0; j < cols; j++) { - builder.fieldkey(keys.get()->at(j).c_str()); + builder.field(keys.get()->at(j).c_str()); contents_[j].get()->getitem_at_nowrap(i).get()->tojson_part(builder); } - builder.endrec(); + builder.endrecord(); } builder.endlist(); } @@ -123,7 +123,7 @@ namespace awkward { for (auto item : contents_) { types.push_back(item.get()->innertype(bare)); } - return std::shared_ptr(new RecordType(types, lookup_, reverselookup_)); + return std::shared_ptr(new RecordType(Type::Parameters(), types, lookup_, reverselookup_)); } void RecordArray::settype_part(const std::shared_ptr type) { @@ -143,7 +143,7 @@ namespace awkward { type_ = type; } else { - throw std::invalid_argument(std::string("provided type is incompatible with array: ") + ArrayType(type, length()).compare(baretype())); + throw std::invalid_argument(std::string("provided type is incompatible with array: ") + ArrayType(Type::Parameters(), type, length()).compare(baretype())); } } diff --git a/src/libawkward/array/RegularArray.cpp b/src/libawkward/array/RegularArray.cpp index 17cdf32fab..09efd3b799 100644 --- a/src/libawkward/array/RegularArray.cpp +++ b/src/libawkward/array/RegularArray.cpp @@ -106,10 +106,10 @@ namespace awkward { const std::shared_ptr RegularArray::innertype(bool bare) const { if (bare || content_.get()->isbare()) { - return std::shared_ptr(new RegularType(content_.get()->innertype(bare), size_)); + return std::shared_ptr(new RegularType(Type::Parameters(), content_.get()->innertype(bare), size_)); } else { - return std::shared_ptr(new RegularType(content_.get()->type().get()->nolength(), size_)); + return std::shared_ptr(new RegularType(Type::Parameters(), content_.get()->type().get()->nolength(), size_)); } } @@ -119,13 +119,17 @@ namespace awkward { type_ = type; } else { - throw std::invalid_argument(std::string("provided type is incompatible with array: ") + ArrayType(type, length()).compare(baretype())); + throw std::invalid_argument(std::string("provided type is incompatible with array: ") + ArrayType(Type::Parameters(), type, length()).compare(baretype())); } } bool RegularArray::accepts(const std::shared_ptr type) { - const std::shared_ptr model(new RegularType(std::shared_ptr(new UnknownType()), size_)); - return type.get()->level().get()->shallow_equal(model); + if (RegularType* raw = dynamic_cast(type.get()->level().get())) { + return raw->size() == size_; + } + else { + return false; + } } int64_t RegularArray::length() const { @@ -303,7 +307,7 @@ namespace awkward { std::shared_ptr outtype = Type::none(); if (type_.get() != nullptr) { RegularType* raw = dynamic_cast(type_.get()); - outtype = std::shared_ptr(new RegularType(raw->type(), nextsize)); + outtype = std::shared_ptr(new RegularType(Type::Parameters(), raw->type(), nextsize)); } if (advanced.length() == 0) { diff --git a/src/libawkward/fillable/BoolFillable.cpp b/src/libawkward/fillable/BoolFillable.cpp index 7b6e172a3d..6b39f16799 100644 --- a/src/libawkward/fillable/BoolFillable.cpp +++ b/src/libawkward/fillable/BoolFillable.cpp @@ -9,6 +9,12 @@ #include "awkward/fillable/BoolFillable.h" namespace awkward { + const std::shared_ptr BoolFillable::fromempty(const FillableOptions& options) { + std::shared_ptr out(new BoolFillable(options, GrowableBuffer::empty(options))); + out.get()->setthat(out); + return out; + } + int64_t BoolFillable::length() const { return buffer_.length(); } @@ -18,118 +24,83 @@ namespace awkward { } const std::shared_ptr BoolFillable::type() const { - return std::shared_ptr(new PrimitiveType(PrimitiveType::boolean)); + return std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::boolean)); } const std::shared_ptr BoolFillable::snapshot() const { std::vector shape = { (ssize_t)buffer_.length() }; std::vector strides = { (ssize_t)sizeof(bool) }; - return std::shared_ptr(new NumpyArray(Identity::none(), Type::none(), buffer_.ptr(), shape, strides, 0, sizeof(bool), "?")); // FIXME: Type::none() + return std::shared_ptr(new NumpyArray(Identity::none(), Type::none(), buffer_.ptr(), shape, strides, 0, sizeof(bool), "?")); } bool BoolFillable::active() const { return false; } - Fillable* BoolFillable::null() { - Fillable* out = OptionFillable::fromvalids(options_, this); - try { - out->null(); - } - catch (...) { - delete out; - throw; - } + const std::shared_ptr BoolFillable::null() { + std::shared_ptr out = OptionFillable::fromvalids(options_, that_); + out.get()->null(); return out; } - Fillable* BoolFillable::boolean(bool x) { + const std::shared_ptr BoolFillable::boolean(bool x) { buffer_.append(x); - return this; - } - - Fillable* BoolFillable::integer(int64_t x) { - Fillable* out = UnionFillable::fromsingle(options_, this); - try { - out->integer(x); - } - catch (...) { - delete out; - throw; - } + return that_; + } + + const std::shared_ptr BoolFillable::integer(int64_t x) { + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->integer(x); return out; } - Fillable* BoolFillable::real(double x) { - Fillable* out = UnionFillable::fromsingle(options_, this); - try { - out->real(x); - } - catch (...) { - delete out; - throw; - } + const std::shared_ptr BoolFillable::real(double x) { + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->real(x); return out; } - Fillable* BoolFillable::beginlist() { - Fillable* out = UnionFillable::fromsingle(options_, this); - try { - out->beginlist(); - } - catch (...) { - delete out; - throw; - } + const std::shared_ptr BoolFillable::string(const char* x, int64_t length, const char* encoding) { + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->string(x, length, encoding); return out; } - Fillable* BoolFillable::endlist() { + const std::shared_ptr BoolFillable::beginlist() { + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->beginlist(); + return out; + } + + const std::shared_ptr BoolFillable::endlist() { throw std::invalid_argument("called 'endlist' without 'beginlist' at the same level before it"); } - Fillable* BoolFillable::begintuple(int64_t numfields) { - Fillable* out = UnionFillable::fromsingle(options_, this); - try { - out->begintuple(numfields); - } - catch (...) { - delete out; - throw; - } + const std::shared_ptr BoolFillable::begintuple(int64_t numfields) { + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->begintuple(numfields); return out; } - Fillable* BoolFillable::index(int64_t index) { + const std::shared_ptr BoolFillable::index(int64_t index) { throw std::invalid_argument("called 'index' without 'begintuple' at the same level before it"); } - Fillable* BoolFillable::endtuple() { + const std::shared_ptr BoolFillable::endtuple() { throw std::invalid_argument("called 'endtuple' without 'begintuple' at the same level before it"); } - Fillable* BoolFillable::beginrecord(int64_t disambiguator) { - Fillable* out = UnionFillable::fromsingle(options_, this); - try { - out->beginrecord(disambiguator); - } - catch (...) { - delete out; - throw; - } + const std::shared_ptr BoolFillable::beginrecord(const char* name, bool check) { + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->beginrecord(name, check); return out; } - Fillable* BoolFillable::field_fast(const char* key) { - throw std::invalid_argument("called 'field_fast' without 'beginrecord' at the same level before it"); + const std::shared_ptr BoolFillable::field(const char* key, bool check) { + throw std::invalid_argument("called 'field' without 'beginrecord' at the same level before it"); } - Fillable* BoolFillable::field_check(const char* key) { - throw std::invalid_argument("called 'field_check' without 'beginrecord' at the same level before it"); - } - - Fillable* BoolFillable::endrecord() { + const std::shared_ptr BoolFillable::endrecord() { throw std::invalid_argument("called 'endrecord' without 'beginrecord' at the same level before it"); } - } diff --git a/src/libawkward/fillable/FillableArray.cpp b/src/libawkward/fillable/FillableArray.cpp index c91eebeade..014407b00a 100644 --- a/src/libawkward/fillable/FillableArray.cpp +++ b/src/libawkward/fillable/FillableArray.cpp @@ -22,7 +22,7 @@ namespace awkward { } const std::shared_ptr FillableArray::type() const { - return std::shared_ptr(new ArrayType(fillable_.get()->type(), fillable_.get()->length())); + return std::shared_ptr(new ArrayType(Type::Parameters(), fillable_.get()->type(), fillable_.get()->length())); } const std::shared_ptr FillableArray::snapshot() const { @@ -65,13 +65,29 @@ namespace awkward { maybeupdate(fillable_.get()->real(x)); } + void FillableArray::bytestring(const char* x) { + maybeupdate(fillable_.get()->string(x, -1, no_encoding)); + } + + void FillableArray::bytestring(const char* x, int64_t length) { + maybeupdate(fillable_.get()->string(x, length, no_encoding)); + } + + void FillableArray::string(const char* x) { + maybeupdate(fillable_.get()->string(x, -1, utf8_encoding)); + } + + void FillableArray::string(const char* x, int64_t length) { + maybeupdate(fillable_.get()->string(x, length, utf8_encoding)); + } + void FillableArray::beginlist() { maybeupdate(fillable_.get()->beginlist()); } void FillableArray::endlist() { - Fillable* tmp = fillable_.get()->endlist(); - if (tmp == nullptr) { + std::shared_ptr tmp = fillable_.get()->endlist(); + if (tmp.get() == nullptr) { throw std::invalid_argument("endlist doesn't match a corresponding beginlist"); } maybeupdate(tmp); @@ -90,30 +106,37 @@ namespace awkward { } void FillableArray::beginrecord() { - beginrecord(0); + beginrecord_fast(nullptr); } - void FillableArray::beginrecord(int64_t disambiguator) { - maybeupdate(fillable_.get()->beginrecord(disambiguator)); + void FillableArray::beginrecord_fast(const char* name) { + maybeupdate(fillable_.get()->beginrecord(name, false)); + } + + void FillableArray::beginrecord_check(const char* name) { + maybeupdate(fillable_.get()->beginrecord(name, true)); } void FillableArray::field_fast(const char* key) { - maybeupdate(fillable_.get()->field_fast(key)); + maybeupdate(fillable_.get()->field(key, false)); } void FillableArray::field_check(const char* key) { - maybeupdate(fillable_.get()->field_check(key)); + maybeupdate(fillable_.get()->field(key, true)); } void FillableArray::endrecord() { maybeupdate(fillable_.get()->endrecord()); } - void FillableArray::maybeupdate(Fillable* tmp) { - if (tmp != fillable_.get() && tmp != nullptr) { - fillable_ = std::shared_ptr(tmp); + void FillableArray::maybeupdate(const std::shared_ptr& tmp) { + if (tmp.get() != fillable_.get()) { + fillable_ = tmp; } } + + const char* FillableArray::no_encoding = nullptr; + const char* FillableArray::utf8_encoding = "utf-8"; } uint8_t awkward_FillableArray_length(void* fillablearray, int64_t* result) { @@ -182,6 +205,50 @@ uint8_t awkward_FillableArray_real(void* fillablearray, double x) { return 0; } +uint8_t awkward_FillableArray_bytestring(void* fillablearray, const char* x) { + awkward::FillableArray* obj = reinterpret_cast(fillablearray); + try { + obj->bytestring(x); + } + catch (...) { + return 1; + } + return 0; +} + +uint8_t awkward_FillableArray_bytestring_length(void* fillablearray, const char* x, int64_t length) { + awkward::FillableArray* obj = reinterpret_cast(fillablearray); + try { + obj->bytestring(x, length); + } + catch (...) { + return 1; + } + return 0; +} + +uint8_t awkward_FillableArray_string(void* fillablearray, const char* x) { + awkward::FillableArray* obj = reinterpret_cast(fillablearray); + try { + obj->string(x); + } + catch (...) { + return 1; + } + return 0; +} + +uint8_t awkward_FillableArray_string_length(void* fillablearray, const char* x, int64_t length) { + awkward::FillableArray* obj = reinterpret_cast(fillablearray); + try { + obj->string(x, length); + } + catch (...) { + return 1; + } + return 0; +} + uint8_t awkward_FillableArray_beginlist(void* fillablearray) { awkward::FillableArray* obj = reinterpret_cast(fillablearray); try { @@ -237,10 +304,32 @@ uint8_t awkward_FillableArray_endtuple(void* fillablearray) { return 0; } -uint8_t awkward_FillableArray_beginrecord(void* fillablearray, int64_t disambiguator) { +uint8_t awkward_FillableArray_beginrecord(void* fillablearray) { + awkward::FillableArray* obj = reinterpret_cast(fillablearray); + try { + obj->beginrecord(); + } + catch (...) { + return 1; + } + return 0; +} + +uint8_t awkward_FillableArray_beginrecord_fast(void* fillablearray, const char* name) { + awkward::FillableArray* obj = reinterpret_cast(fillablearray); + try { + obj->beginrecord_fast(name); + } + catch (...) { + return 1; + } + return 0; +} + +uint8_t awkward_FillableArray_beginrecord_check(void* fillablearray, const char* name) { awkward::FillableArray* obj = reinterpret_cast(fillablearray); try { - obj->beginrecord(disambiguator); + obj->beginrecord_check(name); } catch (...) { return 1; diff --git a/src/libawkward/fillable/Float64Fillable.cpp b/src/libawkward/fillable/Float64Fillable.cpp index eed05d6cd5..70395eb8bb 100644 --- a/src/libawkward/fillable/Float64Fillable.cpp +++ b/src/libawkward/fillable/Float64Fillable.cpp @@ -9,6 +9,25 @@ #include "awkward/fillable/Float64Fillable.h" namespace awkward { + const std::shared_ptr Float64Fillable::fromempty(const FillableOptions& options) { + std::shared_ptr out(new Float64Fillable(options, GrowableBuffer::empty(options))); + out.get()->setthat(out); + return out; + } + + const std::shared_ptr Float64Fillable::fromint64(const FillableOptions& options, GrowableBuffer old) { + GrowableBuffer buffer = GrowableBuffer::empty(options, old.reserved()); + int64_t* oldraw = old.ptr().get(); + double* newraw = buffer.ptr().get(); + for (int64_t i = 0; i < old.length(); i++) { + newraw[i] = (double)oldraw[i]; + } + buffer.set_length(old.length()); + std::shared_ptr out(new Float64Fillable(options, buffer)); + out.get()->setthat(out); + return out; + } + int64_t Float64Fillable::length() const { return buffer_.length(); } @@ -18,111 +37,82 @@ namespace awkward { } const std::shared_ptr Float64Fillable::type() const { - return std::shared_ptr(new PrimitiveType(PrimitiveType::float64)); + return std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::float64)); } const std::shared_ptr Float64Fillable::snapshot() const { std::vector shape = { (ssize_t)buffer_.length() }; std::vector strides = { (ssize_t)sizeof(double) }; - return std::shared_ptr(new NumpyArray(Identity::none(), Type::none(), buffer_.ptr(), shape, strides, 0, sizeof(double), "d")); // FIXME: Type::none() + return std::shared_ptr(new NumpyArray(Identity::none(), Type::none(), buffer_.ptr(), shape, strides, 0, sizeof(double), "d")); } bool Float64Fillable::active() const { return false; } - Fillable* Float64Fillable::null() { - Fillable* out = OptionFillable::fromvalids(options_, this); - try { - out->null(); - } - catch (...) { - delete out; - throw; - } + const std::shared_ptr Float64Fillable::null() { + std::shared_ptr out = OptionFillable::fromvalids(options_, that_); + out.get()->null(); return out; } - Fillable* Float64Fillable::boolean(bool x) { - Fillable* out = UnionFillable::fromsingle(options_, this); - try { - out->boolean(x); - } - catch (...) { - delete out; - throw; - } + const std::shared_ptr Float64Fillable::boolean(bool x) { + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->boolean(x); return out; } - Fillable* Float64Fillable::integer(int64_t x) { + const std::shared_ptr Float64Fillable::integer(int64_t x) { buffer_.append((double)x); - return this; + return that_; } - Fillable* Float64Fillable::real(double x) { + const std::shared_ptr Float64Fillable::real(double x) { buffer_.append(x); - return this; + return that_; } - Fillable* Float64Fillable::beginlist() { - Fillable* out = UnionFillable::fromsingle(options_, this); - try { - out->beginlist(); - } - catch (...) { - delete out; - throw; - } + const std::shared_ptr Float64Fillable::string(const char* x, int64_t length, const char* encoding) { + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->string(x, length, encoding); + return out; + } + + const std::shared_ptr Float64Fillable::beginlist() { + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->beginlist(); return out; } - Fillable* Float64Fillable::endlist() { + const std::shared_ptr Float64Fillable::endlist() { throw std::invalid_argument("called 'endlist' without 'beginlist' at the same level before it"); } - Fillable* Float64Fillable::begintuple(int64_t numfields) { - Fillable* out = UnionFillable::fromsingle(options_, this); - try { - out->begintuple(numfields); - } - catch (...) { - delete out; - throw; - } + const std::shared_ptr Float64Fillable::begintuple(int64_t numfields) { + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->begintuple(numfields); return out; } - Fillable* Float64Fillable::index(int64_t index) { + const std::shared_ptr Float64Fillable::index(int64_t index) { throw std::invalid_argument("called 'index' without 'begintuple' at the same level before it"); } - Fillable* Float64Fillable::endtuple() { + const std::shared_ptr Float64Fillable::endtuple() { throw std::invalid_argument("called 'endtuple' without 'begintuple' at the same level before it"); } - Fillable* Float64Fillable::beginrecord(int64_t disambiguator) { - Fillable* out = UnionFillable::fromsingle(options_, this); - try { - out->beginrecord(disambiguator); - } - catch (...) { - delete out; - throw; - } + const std::shared_ptr Float64Fillable::beginrecord(const char* name, bool check) { + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->beginrecord(name, check); return out; } - Fillable* Float64Fillable::field_fast(const char* key) { - throw std::invalid_argument("called 'field_fast' without 'beginrecord' at the same level before it"); + const std::shared_ptr Float64Fillable::field(const char* key, bool check) { + throw std::invalid_argument("called 'field' without 'beginrecord' at the same level before it"); } - Fillable* Float64Fillable::field_check(const char* key) { - throw std::invalid_argument("called 'field_check' without 'beginrecord' at the same level before it"); - } - - Fillable* Float64Fillable::endrecord() { + const std::shared_ptr Float64Fillable::endrecord() { throw std::invalid_argument("called 'endrecord' without 'beginrecord' at the same level before it"); } - } diff --git a/src/libawkward/fillable/Int64Fillable.cpp b/src/libawkward/fillable/Int64Fillable.cpp index d84ec216a7..2e48988ff6 100644 --- a/src/libawkward/fillable/Int64Fillable.cpp +++ b/src/libawkward/fillable/Int64Fillable.cpp @@ -10,6 +10,12 @@ #include "awkward/fillable/Int64Fillable.h" namespace awkward { + const std::shared_ptr Int64Fillable::fromempty(const FillableOptions& options) { + std::shared_ptr out(new Int64Fillable(options, GrowableBuffer::empty(options))); + out.get()->setthat(out); + return out; + } + int64_t Int64Fillable::length() const { return buffer_.length(); } @@ -19,16 +25,16 @@ namespace awkward { } const std::shared_ptr Int64Fillable::type() const { - return std::shared_ptr(new PrimitiveType(PrimitiveType::int64)); + return std::shared_ptr(new PrimitiveType(Type::Parameters(), PrimitiveType::int64)); } const std::shared_ptr Int64Fillable::snapshot() const { std::vector shape = { (ssize_t)buffer_.length() }; std::vector strides = { (ssize_t)sizeof(int64_t) }; #ifdef _MSC_VER - return std::shared_ptr(new NumpyArray(Identity::none(), Type::none(), buffer_.ptr(), shape, strides, 0, sizeof(int64_t), "q")); // FIXME: Type::none() + return std::shared_ptr(new NumpyArray(Identity::none(), Type::none(), buffer_.ptr(), shape, strides, 0, sizeof(int64_t), "q")); #else - return std::shared_ptr(new NumpyArray(Identity::none(), Type::none(), buffer_.ptr(), shape, strides, 0, sizeof(int64_t), "l")); // FIXME: Type::none() + return std::shared_ptr(new NumpyArray(Identity::none(), Type::none(), buffer_.ptr(), shape, strides, 0, sizeof(int64_t), "l")); #endif } @@ -36,105 +42,70 @@ namespace awkward { return false; } - Fillable* Int64Fillable::null() { - Fillable* out = OptionFillable::fromvalids(options_, this); - try { - out->null(); - } - catch (...) { - delete out; - throw; - } + const std::shared_ptr Int64Fillable::null() { + std::shared_ptr out = OptionFillable::fromvalids(options_, that_); + out.get()->null(); return out; } - Fillable* Int64Fillable::boolean(bool x) { - Fillable* out = UnionFillable::fromsingle(options_, this); - try { - out->boolean(x); - } - catch (...) { - delete out; - throw; - } + const std::shared_ptr Int64Fillable::boolean(bool x) { + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->boolean(x); return out; } - Fillable* Int64Fillable::integer(int64_t x) { + const std::shared_ptr Int64Fillable::integer(int64_t x) { buffer_.append(x); - return this; - } - - Fillable* Int64Fillable::real(double x) { - Float64Fillable* out = Float64Fillable::fromint64(options_, buffer_); - try { - out->real(x); - } - catch (...) { - delete out; - throw; - } + return that_; + } + + const std::shared_ptr Int64Fillable::real(double x) { + std::shared_ptr out = Float64Fillable::fromint64(options_, buffer_); + out.get()->real(x); return out; } - Fillable* Int64Fillable::beginlist() { - Fillable* out = UnionFillable::fromsingle(options_, this); - try { - out->beginlist(); - } - catch (...) { - delete out; - throw; - } + const std::shared_ptr Int64Fillable::string(const char* x, int64_t length, const char* encoding) { + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->string(x, length, encoding); return out; } - Fillable* Int64Fillable::endlist() { + const std::shared_ptr Int64Fillable::beginlist() { + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->beginlist(); + return out; + } + + const std::shared_ptr Int64Fillable::endlist() { throw std::invalid_argument("called 'endlist' without 'beginlist' at the same level before it"); } - Fillable* Int64Fillable::begintuple(int64_t numfields) { - Fillable* out = UnionFillable::fromsingle(options_, this); - try { - out->begintuple(numfields); - } - catch (...) { - delete out; - throw; - } + const std::shared_ptr Int64Fillable::begintuple(int64_t numfields) { + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->begintuple(numfields); return out; } - Fillable* Int64Fillable::index(int64_t index) { + const std::shared_ptr Int64Fillable::index(int64_t index) { throw std::invalid_argument("called 'index' without 'begintuple' at the same level before it"); } - Fillable* Int64Fillable::endtuple() { + const std::shared_ptr Int64Fillable::endtuple() { throw std::invalid_argument("called 'endtuple' without 'begintuple' at the same level before it"); } - Fillable* Int64Fillable::beginrecord(int64_t disambiguator) { - Fillable* out = UnionFillable::fromsingle(options_, this); - try { - out->beginrecord(disambiguator); - } - catch (...) { - delete out; - throw; - } + const std::shared_ptr Int64Fillable::beginrecord(const char* name, bool check) { + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->beginrecord(name, check); return out; } - Fillable* Int64Fillable::field_fast(const char* key) { - throw std::invalid_argument("called 'field_fast' without 'beginrecord' at the same level before it"); + const std::shared_ptr Int64Fillable::field(const char* key, bool check) { + throw std::invalid_argument("called 'field' without 'beginrecord' at the same level before it"); } - Fillable* Int64Fillable::field_check(const char* key) { - throw std::invalid_argument("called 'field_check' without 'beginrecord' at the same level before it"); - } - - Fillable* Int64Fillable::endrecord() { + const std::shared_ptr Int64Fillable::endrecord() { throw std::invalid_argument("called 'endrecord' without 'beginrecord' at the same level before it"); } - } diff --git a/src/libawkward/fillable/ListFillable.cpp b/src/libawkward/fillable/ListFillable.cpp index 641c6a6b8a..81bea2053d 100644 --- a/src/libawkward/fillable/ListFillable.cpp +++ b/src/libawkward/fillable/ListFillable.cpp @@ -12,111 +12,108 @@ #include "awkward/fillable/ListFillable.h" namespace awkward { + const std::shared_ptr ListFillable::fromempty(const FillableOptions& options) { + GrowableBuffer offsets = GrowableBuffer::empty(options); + offsets.append(0); + std::shared_ptr out(new ListFillable(options, offsets, UnknownFillable::fromempty(options), false)); + out.get()->setthat(out); + return out; + } + int64_t ListFillable::length() const { return offsets_.length() - 1; } void ListFillable::clear() { offsets_.clear(); + offsets_.append(0); content_.get()->clear(); } const std::shared_ptr ListFillable::type() const { - return std::shared_ptr(new ListType(content_.get()->type())); + return std::shared_ptr(new ListType(Type::Parameters(), content_.get()->type())); } const std::shared_ptr ListFillable::snapshot() const { Index64 offsets(offsets_.ptr(), 0, offsets_.length()); - return std::shared_ptr(new ListOffsetArray64(Identity::none(), Type::none(), offsets, content_.get()->snapshot())); // FIXME: Type::none() + return std::shared_ptr(new ListOffsetArray64(Identity::none(), Type::none(), offsets, content_.get()->snapshot())); } bool ListFillable::active() const { return begun_; } - Fillable* ListFillable::null() { + const std::shared_ptr ListFillable::null() { if (!begun_) { - Fillable* out = OptionFillable::fromvalids(options_, this); - try { - out->null(); - } - catch (...) { - delete out; - throw; - } + std::shared_ptr out = OptionFillable::fromvalids(options_, that_); + out.get()->null(); return out; } else { maybeupdate(content_.get()->null()); - return this; + return that_; } } - Fillable* ListFillable::boolean(bool x) { + const std::shared_ptr ListFillable::boolean(bool x) { if (!begun_) { - Fillable* out = UnionFillable::fromsingle(options_, this); - try { - out->boolean(x); - } - catch (...) { - delete out; - throw; - } + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->boolean(x); return out; } else { maybeupdate(content_.get()->boolean(x)); - return this; + return that_; } } - Fillable* ListFillable::integer(int64_t x) { + const std::shared_ptr ListFillable::integer(int64_t x) { if (!begun_) { - Fillable* out = UnionFillable::fromsingle(options_, this); - try { - out->integer(x); - } - catch (...) { - delete out; - throw; - } + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->integer(x); return out; } else { maybeupdate(content_.get()->integer(x)); - return this; + return that_; } } - Fillable* ListFillable::real(double x) { + const std::shared_ptr ListFillable::real(double x) { if (!begun_) { - Fillable* out = UnionFillable::fromsingle(options_, this); - try { - out->real(x); - } - catch (...) { - delete out; - throw; - } + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->real(x); return out; } else { maybeupdate(content_.get()->real(x)); - return this; + return that_; } } - Fillable* ListFillable::beginlist() { + const std::shared_ptr ListFillable::string(const char* x, int64_t length, const char* encoding) { + if (!begun_) { + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->string(x, length, encoding); + return out; + } + else { + maybeupdate(content_.get()->string(x, length, encoding)); + return that_; + } + } + + const std::shared_ptr ListFillable::beginlist() { if (!begun_) { begun_ = true; } else { maybeupdate(content_.get()->beginlist()); } - return this; + return that_; } - Fillable* ListFillable::endlist() { + const std::shared_ptr ListFillable::endlist() { if (!begun_) { throw std::invalid_argument("called 'endlist' without 'beginlist' at the same level before it"); } @@ -127,99 +124,76 @@ namespace awkward { else { maybeupdate(content_.get()->endlist()); } - return this; + return that_; } - Fillable* ListFillable::begintuple(int64_t numfields) { + const std::shared_ptr ListFillable::begintuple(int64_t numfields) { if (!begun_) { - Fillable* out = UnionFillable::fromsingle(options_, this); - try { - out->begintuple(numfields); - } - catch (...) { - delete out; - throw; - } + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->begintuple(numfields); return out; } else { maybeupdate(content_.get()->begintuple(numfields)); - return this; + return that_; } } - Fillable* ListFillable::index(int64_t index) { + const std::shared_ptr ListFillable::index(int64_t index) { if (!begun_) { throw std::invalid_argument("called 'index' without 'begintuple' at the same level before it"); } else { content_.get()->index(index); - return this; + return that_; } } - Fillable* ListFillable::endtuple() { + const std::shared_ptr ListFillable::endtuple() { if (!begun_) { throw std::invalid_argument("called 'endtuple' without 'begintuple' at the same level before it"); } else { content_.get()->endtuple(); - return this; + return that_; } } - Fillable* ListFillable::beginrecord(int64_t disambiguator) { + const std::shared_ptr ListFillable::beginrecord(const char* name, bool check) { if (!begun_) { - Fillable* out = UnionFillable::fromsingle(options_, this); - try { - out->beginrecord(disambiguator); - } - catch (...) { - delete out; - throw; - } + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->beginrecord(name, check); return out; } else { - maybeupdate(content_.get()->beginrecord(disambiguator)); - return this; - } - } - - Fillable* ListFillable::field_fast(const char* key) { - if (!begun_) { - throw std::invalid_argument("called 'field_fast' without 'beginrecord' at the same level before it"); - } - else { - content_.get()->field_fast(key); - return this; + maybeupdate(content_.get()->beginrecord(name, check)); + return that_; } } - Fillable* ListFillable::field_check(const char* key) { + const std::shared_ptr ListFillable::field(const char* key, bool check) { if (!begun_) { - throw std::invalid_argument("called 'field_check' without 'beginrecord' at the same level before it"); + throw std::invalid_argument("called 'field' without 'beginrecord' at the same level before it"); } else { - content_.get()->field_check(key); - return this; + content_.get()->field(key, check); + return that_; } } - Fillable* ListFillable::endrecord() { + const std::shared_ptr ListFillable::endrecord() { if (!begun_) { throw std::invalid_argument("called 'endrecord' without 'beginrecord' at the same level before it"); } else { content_.get()->endrecord(); - return this; + return that_; } } - Fillable* ListFillable::maybeupdate(Fillable* tmp) { - if (tmp != content_.get()) { - content_ = std::shared_ptr(tmp); + void ListFillable::maybeupdate(const std::shared_ptr& tmp) { + if (tmp.get() != content_.get()) { + content_ = tmp; } - return this; } } diff --git a/src/libawkward/fillable/OptionFillable.cpp b/src/libawkward/fillable/OptionFillable.cpp index f0780604c5..c8e6c9ac97 100644 --- a/src/libawkward/fillable/OptionFillable.cpp +++ b/src/libawkward/fillable/OptionFillable.cpp @@ -9,6 +9,20 @@ #include "awkward/fillable/OptionFillable.h" namespace awkward { + const std::shared_ptr OptionFillable::fromnulls(const FillableOptions& options, int64_t nullcount, std::shared_ptr content) { + GrowableBuffer offsets = GrowableBuffer::full(options, -1, nullcount); + std::shared_ptr out(new OptionFillable(options, offsets, content)); + out.get()->setthat(out); + return out; + } + + const std::shared_ptr OptionFillable::fromvalids(const FillableOptions& options, std::shared_ptr content) { + GrowableBuffer offsets = GrowableBuffer::arange(options, content->length()); + std::shared_ptr out(new OptionFillable(options, offsets, content)); + out.get()->setthat(out); + return out; + } + int64_t OptionFillable::length() const { return offsets_.length(); } @@ -20,7 +34,7 @@ namespace awkward { const std::shared_ptr OptionFillable::type() const { Index64 offsets(offsets_.ptr(), 0, offsets_.length()); - return std::shared_ptr(new OptionType(content_.get()->type())); + return std::shared_ptr(new OptionType(Type::Parameters(), content_.get()->type())); } const std::shared_ptr OptionFillable::snapshot() const { @@ -31,17 +45,17 @@ namespace awkward { return content_.get()->active(); } - Fillable* OptionFillable::null() { + const std::shared_ptr OptionFillable::null() { if (!content_.get()->active()) { offsets_.append(-1); } else { content_.get()->null(); } - return this; + return that_; } - Fillable* OptionFillable::boolean(bool x) { + const std::shared_ptr OptionFillable::boolean(bool x) { if (!content_.get()->active()) { int64_t length = content_.get()->length(); maybeupdate(content_.get()->boolean(x)); @@ -50,10 +64,10 @@ namespace awkward { else { content_.get()->boolean(x); } - return this; + return that_; } - Fillable* OptionFillable::integer(int64_t x) { + const std::shared_ptr OptionFillable::integer(int64_t x) { if (!content_.get()->active()) { int64_t length = content_.get()->length(); maybeupdate(content_.get()->integer(x)); @@ -62,10 +76,10 @@ namespace awkward { else { content_.get()->integer(x); } - return this; + return that_; } - Fillable* OptionFillable::real(double x) { + const std::shared_ptr OptionFillable::real(double x) { if (!content_.get()->active()) { int64_t length = content_.get()->length(); maybeupdate(content_.get()->real(x)); @@ -74,20 +88,32 @@ namespace awkward { else { content_.get()->real(x); } - return this; + return that_; + } + + const std::shared_ptr OptionFillable::string(const char* x, int64_t length, const char* encoding) { + if (!content_.get()->active()) { + int64_t len = content_.get()->length(); + maybeupdate(content_.get()->string(x, length, encoding)); + offsets_.append(len); + } + else { + content_.get()->string(x, length, encoding); + } + return that_; } - Fillable* OptionFillable::beginlist() { + const std::shared_ptr OptionFillable::beginlist() { if (!content_.get()->active()) { maybeupdate(content_.get()->beginlist()); } else { content_.get()->beginlist(); } - return this; + return that_; } - Fillable* OptionFillable::endlist() { + const std::shared_ptr OptionFillable::endlist() { if (!content_.get()->active()) { throw std::invalid_argument("called 'endlist' without 'beginlist' at the same level before it"); } @@ -98,30 +124,30 @@ namespace awkward { offsets_.append(length); } } - return this; + return that_; } - Fillable* OptionFillable::begintuple(int64_t numfields) { + const std::shared_ptr OptionFillable::begintuple(int64_t numfields) { if (!content_.get()->active()) { maybeupdate(content_.get()->begintuple(numfields)); } else { content_.get()->begintuple(numfields); } - return this; + return that_; } - Fillable* OptionFillable::index(int64_t index) { + const std::shared_ptr OptionFillable::index(int64_t index) { if (!content_.get()->active()) { throw std::invalid_argument("called 'index' without 'begintuple' at the same level before it"); } else { content_.get()->index(index); } - return this; + return that_; } - Fillable* OptionFillable::endtuple() { + const std::shared_ptr OptionFillable::endtuple() { if (!content_.get()->active()) { throw std::invalid_argument("called 'endtuple' without 'begintuple' at the same level before it"); } @@ -132,40 +158,30 @@ namespace awkward { offsets_.append(length); } } - return this; - } - - Fillable* OptionFillable::beginrecord(int64_t disambiguator) { - if (!content_.get()->active()) { - maybeupdate(content_.get()->beginrecord(disambiguator)); - } - else { - content_.get()->beginrecord(disambiguator); - } - return this; + return that_; } - Fillable* OptionFillable::field_fast(const char* key) { + const std::shared_ptr OptionFillable::beginrecord(const char* name, bool check) { if (!content_.get()->active()) { - throw std::invalid_argument("called 'field_fast' without 'beginrecord' at the same level before it"); + maybeupdate(content_.get()->beginrecord(name, check)); } else { - content_.get()->field_fast(key); + content_.get()->beginrecord(name, check); } - return this; + return that_; } - Fillable* OptionFillable::field_check(const char* key) { + const std::shared_ptr OptionFillable::field(const char* key, bool check) { if (!content_.get()->active()) { - throw std::invalid_argument("called 'field_check' without 'beginrecord' at the same level before it"); + throw std::invalid_argument("called 'field' without 'beginrecord' at the same level before it"); } else { - content_.get()->field_check(key); + content_.get()->field(key, check); } - return this; + return that_; } - Fillable* OptionFillable::endrecord() { + const std::shared_ptr OptionFillable::endrecord() { if (!content_.get()->active()) { throw std::invalid_argument("called 'endrecord' without 'beginrecord' at the same level before it"); } @@ -176,12 +192,12 @@ namespace awkward { offsets_.append(length); } } - return this; + return that_; } - void OptionFillable::maybeupdate(Fillable* tmp) { - if (tmp != content_.get()) { - content_ = std::shared_ptr(tmp); + void OptionFillable::maybeupdate(const std::shared_ptr& tmp) { + if (tmp.get() != content_.get()) { + content_ = tmp; } } } diff --git a/src/libawkward/fillable/RecordFillable.cpp b/src/libawkward/fillable/RecordFillable.cpp index 9d5b0b77c9..acc2dc42a4 100644 --- a/src/libawkward/fillable/RecordFillable.cpp +++ b/src/libawkward/fillable/RecordFillable.cpp @@ -17,6 +17,12 @@ #include "awkward/fillable/RecordFillable.h" namespace awkward { + const std::shared_ptr RecordFillable::fromempty(const FillableOptions& options) { + std::shared_ptr out(new RecordFillable(options, std::vector>(), std::vector(), std::vector(), "", nullptr, -1, false, -1, -1)); + out.get()->setthat(out); + return out; + } + int64_t RecordFillable::length() const { return length_; } @@ -27,7 +33,8 @@ namespace awkward { } keys_.clear(); pointers_.clear(); - disambiguator_ = 0; + name_ = ""; + nameptr_ = nullptr; length_ = -1; begun_ = false; nextindex_ = -1; @@ -36,7 +43,7 @@ namespace awkward { const std::shared_ptr RecordFillable::type() const { if (length_ == -1) { - return std::shared_ptr(new UnknownType); + return std::shared_ptr(new UnknownType(Type::Parameters())); } else { std::vector> types; @@ -47,17 +54,27 @@ namespace awkward { (*lookup.get())[keys_[i]] = i; reverselookup.get()->push_back(keys_[i]); } - return std::shared_ptr(new RecordType(types, lookup, reverselookup)); - return std::shared_ptr(new RecordType(types)); + Type::Parameters parameters; + if (nameptr_ != nullptr) { + parameters["__class__"] = util::quote(name_, true); + } + return std::shared_ptr(new RecordType(parameters, types, lookup, reverselookup)); + return std::shared_ptr(new RecordType(parameters, types)); } } const std::shared_ptr RecordFillable::snapshot() const { if (length_ == -1) { - return std::shared_ptr(new EmptyArray(Identity::none(), Type::none())); // FIXME: Type::none() + return std::shared_ptr(new EmptyArray(Identity::none(), Type::none())); } else if (contents_.size() == 0) { - return std::shared_ptr(new RecordArray(Identity::none(), Type::none(), length_, false)); // FIXME: Type::none() + std::shared_ptr out(new RecordArray(Identity::none(), Type::none(), length_, false)); + if (nameptr_ != nullptr) { + std::shared_ptr type = out.get()->type(); + type.get()->nolength().get()->setparameter("__class__", util::quote(name_, true)); + out.get()->settype(type); + } + return out; } else { std::vector> contents; @@ -68,7 +85,13 @@ namespace awkward { (*lookup.get())[keys_[i]] = i; reverselookup.get()->push_back(keys_[i]); } - return std::shared_ptr(new RecordArray(Identity::none(), Type::none(), contents, lookup, reverselookup)); // FIXME: Type::none() + std::shared_ptr out(new RecordArray(Identity::none(), Type::none(), contents, lookup, reverselookup)); + if (nameptr_ != nullptr) { + std::shared_ptr type = out.get()->type(); + type.get()->nolength().get()->setparameter("__class__", util::quote(name_, true)); + out.get()->settype(type); + } + return out; } } @@ -76,16 +99,10 @@ namespace awkward { return begun_; } - Fillable* RecordFillable::null() { + const std::shared_ptr RecordFillable::null() { if (!begun_) { - Fillable* out = OptionFillable::fromvalids(options_, this); - try { - out->null(); - } - catch (...) { - delete out; - throw; - } + std::shared_ptr out = OptionFillable::fromvalids(options_, that_); + out.get()->null(); return out; } else if (nextindex_ == -1) { @@ -97,19 +114,13 @@ namespace awkward { else { contents_[(size_t)nextindex_].get()->null(); } - return this; + return that_; } - Fillable* RecordFillable::boolean(bool x) { + const std::shared_ptr RecordFillable::boolean(bool x) { if (!begun_) { - Fillable* out = UnionFillable::fromsingle(options_, this); - try { - out->boolean(x); - } - catch (...) { - delete out; - throw; - } + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->boolean(x); return out; } else if (nextindex_ == -1) { @@ -121,19 +132,13 @@ namespace awkward { else { contents_[(size_t)nextindex_].get()->boolean(x); } - return this; + return that_; } - Fillable* RecordFillable::integer(int64_t x) { + const std::shared_ptr RecordFillable::integer(int64_t x) { if (!begun_) { - Fillable* out = UnionFillable::fromsingle(options_, this); - try { - out->integer(x); - } - catch (...) { - delete out; - throw; - } + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->integer(x); return out; } else if (nextindex_ == -1) { @@ -145,19 +150,13 @@ namespace awkward { else { contents_[(size_t)nextindex_].get()->integer(x); } - return this; + return that_; } - Fillable* RecordFillable::real(double x) { + const std::shared_ptr RecordFillable::real(double x) { if (!begun_) { - Fillable* out = UnionFillable::fromsingle(options_, this); - try { - out->real(x); - } - catch (...) { - delete out; - throw; - } + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->real(x); return out; } else if (nextindex_ == -1) { @@ -169,19 +168,31 @@ namespace awkward { else { contents_[(size_t)nextindex_].get()->real(x); } - return this; + return that_; } - Fillable* RecordFillable::beginlist() { + const std::shared_ptr RecordFillable::string(const char* x, int64_t length, const char* encoding) { if (!begun_) { - Fillable* out = UnionFillable::fromsingle(options_, this); - try { - out->beginlist(); - } - catch (...) { - delete out; - throw; - } + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->string(x, length, encoding); + return out; + } + else if (nextindex_ == -1) { + throw std::invalid_argument("called 'string' immediately after 'beginrecord'; needs 'index' or 'endrecord'"); + } + else if (!contents_[(size_t)nextindex_].get()->active()) { + maybeupdate(nextindex_, contents_[(size_t)nextindex_].get()->string(x, length, encoding)); + } + else { + contents_[(size_t)nextindex_].get()->string(x, length, encoding); + } + return that_; + } + + const std::shared_ptr RecordFillable::beginlist() { + if (!begun_) { + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->beginlist(); return out; } else if (nextindex_ == -1) { @@ -193,10 +204,10 @@ namespace awkward { else { contents_[(size_t)nextindex_].get()->beginlist(); } - return this; + return that_; } - Fillable* RecordFillable::endlist() { + const std::shared_ptr RecordFillable::endlist() { if (!begun_) { throw std::invalid_argument("called 'endlist' without 'beginlist' at the same level before it"); } @@ -206,19 +217,13 @@ namespace awkward { else { contents_[(size_t)nextindex_].get()->endlist(); } - return this; + return that_; } - Fillable* RecordFillable::begintuple(int64_t numfields) { + const std::shared_ptr RecordFillable::begintuple(int64_t numfields) { if (!begun_) { - Fillable* out = UnionFillable::fromsingle(options_, this); - try { - out->begintuple(numfields); - } - catch (...) { - delete out; - throw; - } + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->begintuple(numfields); return out; } else if (nextindex_ == -1) { @@ -230,10 +235,10 @@ namespace awkward { else { contents_[(size_t)nextindex_].get()->begintuple(numfields); } - return this; + return that_; } - Fillable* RecordFillable::index(int64_t index) { + const std::shared_ptr RecordFillable::index(int64_t index) { if (!begun_) { throw std::invalid_argument("called 'index' without 'begintuple' at the same level before it"); } @@ -243,10 +248,10 @@ namespace awkward { else { contents_[(size_t)nextindex_].get()->index(index); } - return this; + return that_; } - Fillable* RecordFillable::endtuple() { + const std::shared_ptr RecordFillable::endtuple() { if (!begun_) { throw std::invalid_argument("called 'endtuple' without 'begintuple' at the same level before it"); } @@ -256,46 +261,55 @@ namespace awkward { else { contents_[(size_t)nextindex_].get()->endtuple(); } - return this; + return that_; } - Fillable* RecordFillable::beginrecord(int64_t disambiguator) { + const std::shared_ptr RecordFillable::beginrecord(const char* name, bool check) { if (length_ == -1) { - disambiguator_ = disambiguator; + if (name == nullptr) { + name_ = std::string(""); + } + else { + name_ = std::string(name); + } + nameptr_ = name; length_ = 0; } - if (!begun_ && disambiguator == disambiguator_) { + if (!begun_ && ((check && name_ == name) || (!check && nameptr_ == name))) { begun_ = true; nextindex_ = -1; nexttotry_ = 0; } else if (!begun_) { - Fillable* out = UnionFillable::fromsingle(options_, this); - try { - out->beginrecord(disambiguator); - } - catch (...) { - delete out; - throw; - } + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->beginrecord(name, check); return out; } else if (nextindex_ == -1) { throw std::invalid_argument("called 'beginrecord' immediately after 'beginrecord'; needs 'field_fast', 'field_check', or 'endrecord'"); } else if (!contents_[(size_t)nextindex_].get()->active()) { - maybeupdate(nextindex_, contents_[(size_t)nextindex_].get()->beginrecord(disambiguator)); + maybeupdate(nextindex_, contents_[(size_t)nextindex_].get()->beginrecord(name, check)); + } + else { + contents_[(size_t)nextindex_].get()->beginrecord(name, check); + } + return that_; + } + + const std::shared_ptr RecordFillable::field(const char* key, bool check) { + if (check) { + return field_check(key); } else { - contents_[(size_t)nextindex_].get()->beginrecord(disambiguator); + return field_fast(key); } - return this; } - Fillable* RecordFillable::field_fast(const char* key) { + const std::shared_ptr RecordFillable::field_fast(const char* key) { if (!begun_) { - throw std::invalid_argument("called 'field_fast' without 'beginrecord' at the same level before it"); + throw std::invalid_argument("called 'field' without 'beginrecord' at the same level before it"); } else if (nextindex_ == -1 || !contents_[(size_t)nextindex_].get()->active()) { int64_t wrap_around = (int64_t)pointers_.size(); @@ -310,31 +324,31 @@ namespace awkward { if (pointers_[(size_t)i] == key) { nextindex_ = i; nexttotry_ = i + 1; - return this; + return that_; } i++; } while (i != nexttotry_); nextindex_ = wrap_around; nexttotry_ = 0; if (length_ == 0) { - contents_.push_back(std::shared_ptr(UnknownFillable::fromempty(options_))); + contents_.push_back(UnknownFillable::fromempty(options_)); } else { - contents_.push_back(std::shared_ptr(OptionFillable::fromnulls(options_, length_, UnknownFillable::fromempty(options_)))); + contents_.push_back(OptionFillable::fromnulls(options_, length_, UnknownFillable::fromempty(options_))); } keys_.push_back(std::string(key)); pointers_.push_back(key); - return this; + return that_; } else { - contents_[(size_t)nextindex_].get()->field_fast(key); - return this; + contents_[(size_t)nextindex_].get()->field(key, false); + return that_; } } - Fillable* RecordFillable::field_check(const char* key) { + const std::shared_ptr RecordFillable::field_check(const char* key) { if (!begun_) { - throw std::invalid_argument("called 'field_check' without 'beginrecord' at the same level before it"); + throw std::invalid_argument("called 'field' without 'beginrecord' at the same level before it"); } else if (nextindex_ == -1 || !contents_[(size_t)nextindex_].get()->active()) { int64_t wrap_around = (int64_t)keys_.size(); @@ -349,29 +363,29 @@ namespace awkward { if (keys_[(size_t)i].compare(key) == 0) { nextindex_ = i; nexttotry_ = i + 1; - return this; + return that_; } i++; } while (i != nexttotry_); nextindex_ = wrap_around; nexttotry_ = 0; if (length_ == 0) { - contents_.push_back(std::shared_ptr(UnknownFillable::fromempty(options_))); + contents_.push_back(UnknownFillable::fromempty(options_)); } else { - contents_.push_back(std::shared_ptr(OptionFillable::fromnulls(options_, length_, UnknownFillable::fromempty(options_)))); + contents_.push_back(OptionFillable::fromnulls(options_, length_, UnknownFillable::fromempty(options_))); } keys_.push_back(std::string(key)); pointers_.push_back(nullptr); - return this; + return that_; } else { - contents_[(size_t)nextindex_].get()->field_check(key); - return this; + contents_[(size_t)nextindex_].get()->field(key, true); + return that_; } } - Fillable* RecordFillable::endrecord() { + const std::shared_ptr RecordFillable::endrecord() { if (!begun_) { throw std::invalid_argument("called 'endrecord' without 'beginrecord' at the same level before it"); } @@ -392,13 +406,12 @@ namespace awkward { else { contents_[(size_t)nextindex_].get()->endrecord(); } - return this; + return that_; } - void RecordFillable::maybeupdate(int64_t i, Fillable* tmp) { - if (tmp != contents_[(size_t)i].get()) { - contents_[(size_t)i] = std::shared_ptr(tmp); + void RecordFillable::maybeupdate(int64_t i, const std::shared_ptr& tmp) { + if (tmp.get() != contents_[(size_t)i].get()) { + contents_[(size_t)i] = tmp; } } - } diff --git a/src/libawkward/fillable/StringFillable.cpp b/src/libawkward/fillable/StringFillable.cpp new file mode 100644 index 0000000000..378a490aaf --- /dev/null +++ b/src/libawkward/fillable/StringFillable.cpp @@ -0,0 +1,154 @@ +// BSD 3-Clause License; see https://github.com/jpivarski/awkward-1.0/blob/master/LICENSE + +#include "awkward/Identity.h" +#include "awkward/array/NumpyArray.h" +#include "awkward/array/ListOffsetArray.h" +#include "awkward/type/PrimitiveType.h" +#include "awkward/type/ListType.h" +#include "awkward/fillable/OptionFillable.h" +#include "awkward/fillable/UnionFillable.h" + +#include "awkward/fillable/StringFillable.h" + +namespace awkward { + const std::shared_ptr StringFillable::fromempty(const FillableOptions& options, const char* encoding) { + GrowableBuffer offsets = GrowableBuffer::empty(options); + offsets.append(0); + GrowableBuffer content = GrowableBuffer::empty(options); + std::shared_ptr out(new StringFillable(options, offsets, content, encoding)); + out.get()->setthat(out); + return out; + } + + int64_t StringFillable::length() const { + return offsets_.length() - 1; + } + + void StringFillable::clear() { + offsets_.clear(); + offsets_.append(0); + content_.clear(); + } + + const std::shared_ptr StringFillable::type() const { + Type::Parameters char_parameters; + char_parameters["__class__"] = std::string("\"char\""); + + Type::Parameters string_parameters; + string_parameters["__class__"] = std::string("\"string\""); + + if (encoding_ == nullptr) { + char_parameters["__str__"] = std::string("\"byte\""); + char_parameters["encoding"] = std::string("null"); + string_parameters["__str__"] = std::string("\"bytes\""); + } + else { + std::string quoted = util::quote(encoding_, true); + std::string slashquoted = std::string("\\\"") + quoted.substr(1, quoted.length() - 2) + std::string("\\\""); + if (std::string(encoding_) == std::string("utf-8")) { + char_parameters["__str__"] = std::string("\"utf8\""); + string_parameters["__str__"] = std::string("\"string\""); + } + else { + char_parameters["__str__"] = std::string("\"char[") + slashquoted + std::string("]\""); + string_parameters["__str__"] = std::string("\"string[") + slashquoted + std::string("]\""); + } + char_parameters["encoding"] = std::string(quoted); + } + + return std::shared_ptr(new ListType(string_parameters, std::shared_ptr(new PrimitiveType(char_parameters, PrimitiveType::uint8)))); + } + + const std::shared_ptr StringFillable::snapshot() const { + std::shared_ptr stringtype = type(); + + Index64 offsets(offsets_.ptr(), 0, offsets_.length()); + + std::vector shape = { (ssize_t)content_.length() }; + std::vector strides = { (ssize_t)sizeof(uint8_t) }; + std::shared_ptr content(new NumpyArray(Identity::none(), stringtype.get()->inner(), content_.ptr(), shape, strides, 0, sizeof(uint8_t), "B")); + + return std::shared_ptr(new ListOffsetArray64(Identity::none(), stringtype, offsets, content)); + } + + bool StringFillable::active() const { + return false; + } + + const std::shared_ptr StringFillable::null() { + std::shared_ptr out = OptionFillable::fromvalids(options_, that_); + out.get()->null(); + return out; + } + + const std::shared_ptr StringFillable::boolean(bool x) { + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->boolean(x); + return out; + } + + const std::shared_ptr StringFillable::integer(int64_t x) { + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->integer(x); + return out; + } + + const std::shared_ptr StringFillable::real(double x) { + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->real(x); + return out; + } + + const std::shared_ptr StringFillable::string(const char* x, int64_t length, const char* encoding) { + if (length < 0) { + for (int64_t i = 0; x[i] != 0; i++) { + content_.append((uint8_t)x[i]); + } + } + else { + for (int64_t i = 0; i < length; i++) { + content_.append((uint8_t)x[i]); + } + } + offsets_.append(content_.length()); + return that_; + } + + const std::shared_ptr StringFillable::beginlist() { + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->beginlist(); + return out; + } + + const std::shared_ptr StringFillable::endlist() { + throw std::invalid_argument("called 'endlist' without 'beginlist' at the same level before it"); + } + + const std::shared_ptr StringFillable::begintuple(int64_t numfields) { + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->begintuple(numfields); + return out; + } + + const std::shared_ptr StringFillable::index(int64_t index) { + throw std::invalid_argument("called 'index' without 'begintuple' at the same level before it"); + } + + const std::shared_ptr StringFillable::endtuple() { + throw std::invalid_argument("called 'endtuple' without 'begintuple' at the same level before it"); + } + + const std::shared_ptr StringFillable::beginrecord(const char* name, bool check) { + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->beginrecord(name, check); + return out; + } + + const std::shared_ptr StringFillable::field(const char* key, bool check) { + throw std::invalid_argument("called 'field' without 'beginrecord' at the same level before it"); + } + + const std::shared_ptr StringFillable::endrecord() { + throw std::invalid_argument("called 'endrecord' without 'beginrecord' at the same level before it"); + } +} diff --git a/src/libawkward/fillable/TupleFillable.cpp b/src/libawkward/fillable/TupleFillable.cpp index 67537a77b0..ff8b09b76a 100644 --- a/src/libawkward/fillable/TupleFillable.cpp +++ b/src/libawkward/fillable/TupleFillable.cpp @@ -14,6 +14,12 @@ #include "awkward/fillable/TupleFillable.h" namespace awkward { + const std::shared_ptr TupleFillable::fromempty(const FillableOptions& options) { + std::shared_ptr out(new TupleFillable(options, std::vector>(), -1, false, -1)); + out.get()->setthat(out); + return out; + } + int64_t TupleFillable::length() const { return length_; } @@ -29,30 +35,30 @@ namespace awkward { const std::shared_ptr TupleFillable::type() const { if (length_ == -1) { - return std::shared_ptr(new UnknownType); + return std::shared_ptr(new UnknownType(Type::Parameters())); } else { std::vector> types; for (auto content : contents_) { types.push_back(content.get()->type()); } - return std::shared_ptr(new RecordType(types)); + return std::shared_ptr(new RecordType(Type::Parameters(), types)); } } const std::shared_ptr TupleFillable::snapshot() const { if (length_ == -1) { - return std::shared_ptr(new EmptyArray(Identity::none(), Type::none())); // FIXME: Type::none() + return std::shared_ptr(new EmptyArray(Identity::none(), Type::none())); } else if (contents_.size() == 0) { - return std::shared_ptr(new RecordArray(Identity::none(), Type::none(), length_, true)); // FIXME: Type::none() + return std::shared_ptr(new RecordArray(Identity::none(), Type::none(), length_, true)); } else { std::vector> contents; for (auto content : contents_) { contents.push_back(content.get()->snapshot()); } - return std::shared_ptr(new RecordArray(Identity::none(), Type::none(), contents)); // FIXME: Type::none() + return std::shared_ptr(new RecordArray(Identity::none(), Type::none(), contents)); } } @@ -60,16 +66,10 @@ namespace awkward { return begun_; } - Fillable* TupleFillable::null() { + const std::shared_ptr TupleFillable::null() { if (!begun_) { - Fillable* out = OptionFillable::fromvalids(options_, this); - try { - out->null(); - } - catch (...) { - delete out; - throw; - } + std::shared_ptr out = OptionFillable::fromvalids(options_, that_); + out.get()->null(); return out; } else if (nextindex_ == -1) { @@ -81,19 +81,13 @@ namespace awkward { else { contents_[(size_t)nextindex_].get()->null(); } - return this; + return that_; } - Fillable* TupleFillable::boolean(bool x) { + const std::shared_ptr TupleFillable::boolean(bool x) { if (!begun_) { - Fillable* out = UnionFillable::fromsingle(options_, this); - try { - out->boolean(x); - } - catch (...) { - delete out; - throw; - } + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->boolean(x); return out; } else if (nextindex_ == -1) { @@ -105,19 +99,13 @@ namespace awkward { else { contents_[(size_t)nextindex_].get()->boolean(x); } - return this; + return that_; } - Fillable* TupleFillable::integer(int64_t x) { + const std::shared_ptr TupleFillable::integer(int64_t x) { if (!begun_) { - Fillable* out = UnionFillable::fromsingle(options_, this); - try { - out->integer(x); - } - catch (...) { - delete out; - throw; - } + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->integer(x); return out; } else if (nextindex_ == -1) { @@ -129,19 +117,13 @@ namespace awkward { else { contents_[(size_t)nextindex_].get()->integer(x); } - return this; + return that_; } - Fillable* TupleFillable::real(double x) { + const std::shared_ptr TupleFillable::real(double x) { if (!begun_) { - Fillable* out = UnionFillable::fromsingle(options_, this); - try { - out->real(x); - } - catch (...) { - delete out; - throw; - } + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->real(x); return out; } else if (nextindex_ == -1) { @@ -153,19 +135,31 @@ namespace awkward { else { contents_[(size_t)nextindex_].get()->real(x); } - return this; + return that_; } - Fillable* TupleFillable::beginlist() { + const std::shared_ptr TupleFillable::string(const char* x, int64_t length, const char* encoding) { if (!begun_) { - Fillable* out = UnionFillable::fromsingle(options_, this); - try { - out->beginlist(); - } - catch (...) { - delete out; - throw; - } + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->string(x, length, encoding); + return out; + } + else if (nextindex_ == -1) { + throw std::invalid_argument("called 'string' immediately after 'begintuple'; needs 'index' or 'endtuple'"); + } + else if (!contents_[(size_t)nextindex_].get()->active()) { + maybeupdate(nextindex_, contents_[(size_t)nextindex_].get()->string(x, length, encoding)); + } + else { + contents_[(size_t)nextindex_].get()->string(x, length, encoding); + } + return that_; + } + + const std::shared_ptr TupleFillable::beginlist() { + if (!begun_) { + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->beginlist(); return out; } else if (nextindex_ == -1) { @@ -177,10 +171,10 @@ namespace awkward { else { contents_[(size_t)nextindex_].get()->beginlist(); } - return this; + return that_; } - Fillable* TupleFillable::endlist() { + const std::shared_ptr TupleFillable::endlist() { if (!begun_) { throw std::invalid_argument("called 'endlist' without 'beginlist' at the same level before it"); } @@ -190,10 +184,10 @@ namespace awkward { else { contents_[(size_t)nextindex_].get()->endlist(); } - return this; + return that_; } - Fillable* TupleFillable::begintuple(int64_t numfields) { + const std::shared_ptr TupleFillable::begintuple(int64_t numfields) { if (length_ == -1) { for (int64_t i = 0; i < numfields; i++) { contents_.push_back(std::shared_ptr(UnknownFillable::fromempty(options_))); @@ -206,14 +200,8 @@ namespace awkward { nextindex_ = -1; } else if (!begun_) { - Fillable* out = UnionFillable::fromsingle(options_, this); - try { - out->begintuple(numfields); - } - catch (...) { - delete out; - throw; - } + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->begintuple(numfields); return out; } else if (nextindex_ == -1) { @@ -225,10 +213,10 @@ namespace awkward { else { contents_[(size_t)nextindex_].get()->begintuple(numfields); } - return this; + return that_; } - Fillable* TupleFillable::index(int64_t index) { + const std::shared_ptr TupleFillable::index(int64_t index) { if (!begun_) { throw std::invalid_argument("called 'index' without 'begintuple' at the same level before it"); } @@ -238,10 +226,10 @@ namespace awkward { else { contents_[(size_t)nextindex_].get()->index(index); } - return this; + return that_; } - Fillable* TupleFillable::endtuple() { + const std::shared_ptr TupleFillable::endtuple() { if (!begun_) { throw std::invalid_argument("called 'endtuple' without 'begintuple' at the same level before it"); } @@ -262,34 +250,28 @@ namespace awkward { else { contents_[(size_t)nextindex_].get()->endtuple(); } - return this; + return that_; } - Fillable* TupleFillable::beginrecord(int64_t disambiguator) { + const std::shared_ptr TupleFillable::beginrecord(const char* name, bool check) { if (!begun_) { - Fillable* out = UnionFillable::fromsingle(options_, this); - try { - out->beginrecord(disambiguator); - } - catch (...) { - delete out; - throw; - } + std::shared_ptr out = UnionFillable::fromsingle(options_, that_); + out.get()->beginrecord(name, check); return out; } else if (nextindex_ == -1) { throw std::invalid_argument("called 'beginrecord' immediately after 'begintuple'; needs 'index' or 'endtuple'"); } else if (!contents_[(size_t)nextindex_].get()->active()) { - maybeupdate(nextindex_, contents_[(size_t)nextindex_].get()->beginrecord(disambiguator)); + maybeupdate(nextindex_, contents_[(size_t)nextindex_].get()->beginrecord(name, check)); } else { - contents_[(size_t)nextindex_].get()->beginrecord(disambiguator); + contents_[(size_t)nextindex_].get()->beginrecord(name, check); } - return this; + return that_; } - Fillable* TupleFillable::field_fast(const char* key) { + const std::shared_ptr TupleFillable::field(const char* key, bool check) { if (!begun_) { throw std::invalid_argument("called 'field_fast' without 'beginrecord' at the same level before it"); } @@ -297,25 +279,12 @@ namespace awkward { throw std::invalid_argument("called 'field_fast' immediately after 'begintuple'; needs 'index' or 'endtuple' and then 'beginrecord'"); } else { - contents_[(size_t)nextindex_].get()->field_fast(key); - } - return this; - } - - Fillable* TupleFillable::field_check(const char* key) { - if (!begun_) { - throw std::invalid_argument("called 'field_check' without 'beginrecord' at the same level before it"); - } - else if (nextindex_ == -1) { - throw std::invalid_argument("called 'field_check' immediately after 'begintuple'; needs 'index' or 'endtuple' and then 'beginrecord'"); - } - else { - contents_[(size_t)nextindex_].get()->field_check(key); + contents_[(size_t)nextindex_].get()->field(key, check); } - return this; + return that_; } - Fillable* TupleFillable::endrecord() { + const std::shared_ptr TupleFillable::endrecord() { if (!begun_) { throw std::invalid_argument("called 'endrecord' without 'beginrecord' at the same level before it"); } @@ -325,12 +294,12 @@ namespace awkward { else { contents_[(size_t)nextindex_].get()->endrecord(); } - return this; + return that_; } - void TupleFillable::maybeupdate(int64_t i, Fillable* tmp) { - if (tmp != contents_[(size_t)i].get()) { - contents_[(size_t)i] = std::shared_ptr(tmp); + void TupleFillable::maybeupdate(int64_t i, const std::shared_ptr& tmp) { + if (tmp.get() != contents_[(size_t)i].get()) { + contents_[(size_t)i] = tmp; } } } diff --git a/src/libawkward/fillable/UnionFillable.cpp b/src/libawkward/fillable/UnionFillable.cpp index f6f0364d5f..e45c15e594 100644 --- a/src/libawkward/fillable/UnionFillable.cpp +++ b/src/libawkward/fillable/UnionFillable.cpp @@ -9,6 +9,7 @@ #include "awkward/fillable/BoolFillable.h" #include "awkward/fillable/Int64Fillable.h" #include "awkward/fillable/Float64Fillable.h" +#include "awkward/fillable/StringFillable.h" #include "awkward/fillable/ListFillable.h" #include "awkward/fillable/TupleFillable.h" #include "awkward/fillable/RecordFillable.h" @@ -16,6 +17,15 @@ #include "awkward/fillable/UnionFillable.h" namespace awkward { + const std::shared_ptr UnionFillable::fromsingle(const FillableOptions& options, const std::shared_ptr firstcontent) { + GrowableBuffer types = GrowableBuffer::full(options, 0, firstcontent->length()); + GrowableBuffer offsets = GrowableBuffer::arange(options, firstcontent->length()); + std::vector> contents({ firstcontent }); + std::shared_ptr out(new UnionFillable(options, types, offsets, contents)); + out.get()->setthat(out); + return out; + } + int64_t UnionFillable::length() const { return types_.length(); } @@ -33,7 +43,7 @@ namespace awkward { for (auto x : contents_) { types.push_back(x.get()->type()); } - return std::shared_ptr(new UnionType(types)); + return std::shared_ptr(new UnionType(Type::Parameters(), types)); } const std::shared_ptr UnionFillable::snapshot() const { @@ -43,143 +53,165 @@ namespace awkward { } bool UnionFillable::active() const { - throw std::runtime_error("FIXME: UnionFillable::active"); + return current_ != -1; } - Fillable* UnionFillable::null() { + const std::shared_ptr UnionFillable::null() { if (current_ == -1) { - Fillable* out = OptionFillable::fromvalids(options_, this); - try { - out->null(); - } - catch (...) { - delete out; - throw; - } + std::shared_ptr out = OptionFillable::fromvalids(options_, that_); + out.get()->null(); return out; } else { contents_[(size_t)current_].get()->null(); - return this; + return that_; } } - Fillable* UnionFillable::boolean(bool x) { + const std::shared_ptr UnionFillable::boolean(bool x) { if (current_ == -1) { - Fillable* tofill = nullptr; + std::shared_ptr tofill(nullptr); int8_t i = 0; for (auto content : contents_) { if (dynamic_cast(content.get()) != nullptr) { - tofill = content.get(); + tofill = content; break; } i++; } - if (tofill == nullptr) { + if (tofill.get() == nullptr) { tofill = BoolFillable::fromempty(options_); - contents_.push_back(std::shared_ptr(tofill)); + contents_.push_back(tofill); } - int64_t length = tofill->length(); - tofill->boolean(x); + int64_t length = tofill.get()->length(); + tofill.get()->boolean(x); types_.append(i); offsets_.append(length); } else { contents_[(size_t)current_].get()->boolean(x); } - return this; + return that_; } - Fillable* UnionFillable::integer(int64_t x) { + const std::shared_ptr UnionFillable::integer(int64_t x) { if (current_ == -1) { - Fillable* tofill = nullptr; + std::shared_ptr tofill(nullptr); int8_t i = 0; for (auto content : contents_) { if (dynamic_cast(content.get()) != nullptr) { - tofill = content.get(); + tofill = content; break; } i++; } - if (tofill == nullptr) { + if (tofill.get() == nullptr) { tofill = Int64Fillable::fromempty(options_); - contents_.push_back(std::shared_ptr(tofill)); + contents_.push_back(tofill); } - int64_t length = tofill->length(); - tofill->integer(x); + int64_t length = tofill.get()->length(); + tofill.get()->integer(x); types_.append(i); offsets_.append(length); } else { contents_[(size_t)current_].get()->integer(x); } - return this; + return that_; } - Fillable* UnionFillable::real(double x) { + const std::shared_ptr UnionFillable::real(double x) { if (current_ == -1) { - Fillable* tofill = nullptr; + std::shared_ptr tofill(nullptr); int8_t i = 0; for (auto content : contents_) { if (dynamic_cast(content.get()) != nullptr) { - tofill = content.get(); + tofill = content; break; } i++; } - if (tofill == nullptr) { + if (tofill.get() == nullptr) { i = 0; for (auto content : contents_) { if (dynamic_cast(content.get()) != nullptr) { - tofill = content.get(); + tofill = content; break; } i++; } - if (tofill != nullptr) { - tofill = Float64Fillable::fromint64(options_, dynamic_cast(tofill)->buffer()); - contents_[(size_t)i] = std::shared_ptr(tofill); + if (tofill.get() != nullptr) { + tofill = Float64Fillable::fromint64(options_, dynamic_cast(tofill.get())->buffer()); + contents_[(size_t)i] = tofill; } else { tofill = Float64Fillable::fromempty(options_); - contents_.push_back(std::shared_ptr(tofill)); + contents_.push_back(tofill); } } - int64_t length = tofill->length(); - tofill->real(x); + int64_t length = tofill.get()->length(); + tofill.get()->real(x); types_.append(i); offsets_.append(length); } else { contents_[(size_t)current_].get()->real(x); } - return this; + return that_; + } + + const std::shared_ptr UnionFillable::string(const char* x, int64_t length, const char* encoding) { + if (current_ == -1) { + std::shared_ptr tofill(nullptr); + int8_t i = 0; + for (auto content : contents_) { + if (StringFillable* raw = dynamic_cast(content.get())) { + if (raw->encoding() == encoding) { + tofill = content; + break; + } + } + i++; + } + if (tofill.get() == nullptr) { + tofill = StringFillable::fromempty(options_, encoding); + contents_.push_back(tofill); + } + int64_t len = tofill.get()->length(); + tofill.get()->string(x, length, encoding); + types_.append(i); + offsets_.append(len); + } + else { + contents_[(size_t)current_].get()->string(x, length, encoding); + } + return that_; } - Fillable* UnionFillable::beginlist() { + const std::shared_ptr UnionFillable::beginlist() { if (current_ == -1) { - Fillable* tofill = nullptr; + std::shared_ptr tofill(nullptr); int8_t i = 0; for (auto content : contents_) { if (dynamic_cast(content.get()) != nullptr) { - tofill = content.get(); + tofill = content; break; } i++; } - if (tofill == nullptr) { + if (tofill.get() == nullptr) { tofill = ListFillable::fromempty(options_); - contents_.push_back(std::shared_ptr(tofill)); + contents_.push_back(tofill); } tofill->beginlist(); } else { contents_[(size_t)current_].get()->beginlist(); } - return this; + return that_; } - Fillable* UnionFillable::endlist() { + const std::shared_ptr UnionFillable::endlist() { if (current_ == -1) { throw std::invalid_argument("called 'endlist' without 'beginlist' at the same level before it"); } @@ -192,25 +224,25 @@ namespace awkward { current_ = -1; } } - return this; + return that_; } - Fillable* UnionFillable::begintuple(int64_t numfields) { + const std::shared_ptr UnionFillable::begintuple(int64_t numfields) { if (current_ == -1) { - Fillable* tofill = nullptr; + std::shared_ptr tofill(nullptr); int8_t i = 0; for (auto content : contents_) { if (TupleFillable* raw = dynamic_cast(content.get())) { if (raw->length() == -1 || raw->numfields() == numfields) { - tofill = content.get(); + tofill = content; break; } } i++; } - if (tofill == nullptr) { + if (tofill.get() == nullptr) { tofill = TupleFillable::fromempty(options_); - contents_.push_back(std::shared_ptr(tofill)); + contents_.push_back(tofill); } tofill->begintuple(numfields); current_ = i; @@ -218,20 +250,20 @@ namespace awkward { else { contents_[(size_t)current_].get()->begintuple(numfields); } - return this; + return that_; } - Fillable* UnionFillable::index(int64_t index) { + const std::shared_ptr UnionFillable::index(int64_t index) { if (current_ == -1) { throw std::invalid_argument("called 'index' without 'begintuple' at the same level before it"); } else { contents_[(size_t)current_].get()->index(index); } - return this; + return that_; } - Fillable* UnionFillable::endtuple() { + const std::shared_ptr UnionFillable::endtuple() { if (current_ == -1) { throw std::invalid_argument("called 'endtuple' without 'begintuple' at the same level before it"); } @@ -244,56 +276,46 @@ namespace awkward { current_ = -1; } } - return this; + return that_; } - Fillable* UnionFillable::beginrecord(int64_t disambiguator) { + const std::shared_ptr UnionFillable::beginrecord(const char* name, bool check) { if (current_ == -1) { - Fillable* tofill = nullptr; + std::shared_ptr tofill(nullptr); int8_t i = 0; for (auto content : contents_) { if (RecordFillable* raw = dynamic_cast(content.get())) { - if (raw->length() == -1 || raw->disambiguator() == disambiguator) { - tofill = content.get(); + if (raw->length() == -1 || ((check && raw->name() == name) || (!check && raw->nameptr() == name))) { + tofill = content; break; } } i++; } - if (tofill == nullptr) { + if (tofill.get() == nullptr) { tofill = RecordFillable::fromempty(options_); - contents_.push_back(std::shared_ptr(tofill)); + contents_.push_back(tofill); } - tofill->beginrecord(disambiguator); + tofill->beginrecord(name, check); current_ = i; } else { - contents_[(size_t)current_].get()->beginrecord(disambiguator); + contents_[(size_t)current_].get()->beginrecord(name, check); } - return this; + return that_; } - Fillable* UnionFillable::field_fast(const char* key) { + const std::shared_ptr UnionFillable::field(const char* key, bool check) { if (current_ == -1) { - throw std::invalid_argument("called 'field_fast' without 'beginrecord' at the same level before it"); + throw std::invalid_argument("called 'field' without 'beginrecord' at the same level before it"); } else { - contents_[(size_t)current_].get()->field_fast(key); + contents_[(size_t)current_].get()->field(key, check); } - return this; + return that_; } - Fillable* UnionFillable::field_check(const char* key) { - if (current_ == -1) { - throw std::invalid_argument("called 'field_check' without 'beginrecord' at the same level before it"); - } - else { - contents_[(size_t)current_].get()->field_check(key); - } - return this; - } - - Fillable* UnionFillable::endrecord() { + const std::shared_ptr UnionFillable::endrecord() { if (current_ == -1) { throw std::invalid_argument("called 'endrecord' without 'beginrecord' at the same level before it"); } @@ -306,7 +328,6 @@ namespace awkward { current_ = -1; } } - return this; + return that_; } - } diff --git a/src/libawkward/fillable/UnknownFillable.cpp b/src/libawkward/fillable/UnknownFillable.cpp index d75c0cd2bf..4cc19b0e89 100644 --- a/src/libawkward/fillable/UnknownFillable.cpp +++ b/src/libawkward/fillable/UnknownFillable.cpp @@ -10,6 +10,7 @@ #include "awkward/fillable/BoolFillable.h" #include "awkward/fillable/Int64Fillable.h" #include "awkward/fillable/Float64Fillable.h" +#include "awkward/fillable/StringFillable.h" #include "awkward/fillable/ListFillable.h" #include "awkward/fillable/TupleFillable.h" #include "awkward/fillable/RecordFillable.h" @@ -17,6 +18,12 @@ #include "awkward/fillable/UnknownFillable.h" namespace awkward { + const std::shared_ptr UnknownFillable::fromempty(const FillableOptions& options) { + std::shared_ptr out(new UnknownFillable(options, 0)); + out.get()->setthat(out); + return out; + } + int64_t UnknownFillable::length() const { return nullcount_; } @@ -26,12 +33,12 @@ namespace awkward { } const std::shared_ptr UnknownFillable::type() const { - return std::shared_ptr(new UnknownType); + return std::shared_ptr(new UnknownType(Type::Parameters())); } const std::shared_ptr UnknownFillable::snapshot() const { if (nullcount_ == 0) { - return std::shared_ptr(new EmptyArray(Identity::none(), Type::none())); // FIXME: Type::none() + return std::shared_ptr(new EmptyArray(Identity::none(), Type::none())); } else { throw std::runtime_error("UnknownFillable::snapshot() needs OptionArray"); @@ -42,123 +49,91 @@ namespace awkward { return false; } - Fillable* UnknownFillable::null() { + const std::shared_ptr UnknownFillable::null() { nullcount_++; - return this; + return that_; } - Fillable* UnknownFillable::boolean(bool x) { - Fillable* out = BoolFillable::fromempty(options_); + const std::shared_ptr UnknownFillable::boolean(bool x) { + std::shared_ptr out = BoolFillable::fromempty(options_); if (nullcount_ != 0) { out = OptionFillable::fromnulls(options_, nullcount_, out); } - try { - out->boolean(x); - } - catch (...) { - delete out; - throw; - } + out.get()->boolean(x); return out; } - Fillable* UnknownFillable::integer(int64_t x) { - Fillable* out = Int64Fillable::fromempty(options_); + const std::shared_ptr UnknownFillable::integer(int64_t x) { + std::shared_ptr out = Int64Fillable::fromempty(options_); if (nullcount_ != 0) { out = OptionFillable::fromnulls(options_, nullcount_, out); } - try { - out->integer(x); - } - catch (...) { - delete out; - throw; - } + out.get()->integer(x); return out; } - Fillable* UnknownFillable::real(double x) { - Fillable* out = Float64Fillable::fromempty(options_); + const std::shared_ptr UnknownFillable::real(double x) { + std::shared_ptr out = Float64Fillable::fromempty(options_); if (nullcount_ != 0) { out = OptionFillable::fromnulls(options_, nullcount_, out); } - try { - out->real(x); - } - catch (...) { - delete out; - throw; - } + out.get()->real(x); return out; } - Fillable* UnknownFillable::beginlist() { - Fillable* out = ListFillable::fromempty(options_); + const std::shared_ptr UnknownFillable::string(const char* x, int64_t length, const char* encoding) { + std::shared_ptr out = StringFillable::fromempty(options_, encoding); if (nullcount_ != 0) { out = OptionFillable::fromnulls(options_, nullcount_, out); } - try { - out->beginlist(); - } - catch (...) { - delete out; - throw; + out.get()->string(x, length, encoding); + return out; + } + + const std::shared_ptr UnknownFillable::beginlist() { + std::shared_ptr out = ListFillable::fromempty(options_); + if (nullcount_ != 0) { + out = OptionFillable::fromnulls(options_, nullcount_, out); } + out.get()->beginlist(); return out; } - Fillable* UnknownFillable::endlist() { + const std::shared_ptr UnknownFillable::endlist() { throw std::invalid_argument("called 'endlist' without 'beginlist' at the same level before it"); } - Fillable* UnknownFillable::begintuple(int64_t numfields) { - Fillable* out = TupleFillable::fromempty(options_); + const std::shared_ptr UnknownFillable::begintuple(int64_t numfields) { + std::shared_ptr out = TupleFillable::fromempty(options_); if (nullcount_ != 0) { out = OptionFillable::fromnulls(options_, nullcount_, out); } - try { - out->begintuple(numfields); - } - catch (...) { - delete out; - throw; - } + out.get()->begintuple(numfields); return out; } - Fillable* UnknownFillable::index(int64_t index) { + const std::shared_ptr UnknownFillable::index(int64_t index) { throw std::invalid_argument("called 'index' without 'begintuple' at the same level before it"); } - Fillable* UnknownFillable::endtuple() { + const std::shared_ptr UnknownFillable::endtuple() { throw std::invalid_argument("called 'endtuple' without 'begintuple' at the same level before it"); } - Fillable* UnknownFillable::beginrecord(int64_t disambiguator) { - Fillable* out = RecordFillable::fromempty(options_); + const std::shared_ptr UnknownFillable::beginrecord(const char* name, bool check) { + std::shared_ptr out = RecordFillable::fromempty(options_); if (nullcount_ != 0) { out = OptionFillable::fromnulls(options_, nullcount_, out); } - try { - out->beginrecord(disambiguator); - } - catch (...) { - delete out; - throw; - } + out.get()->beginrecord(name, check); return out; } - Fillable* UnknownFillable::field_fast(const char* key) { - throw std::invalid_argument("called 'field_fast' without 'beginrecord' at the same level before it"); + const std::shared_ptr UnknownFillable::field(const char* key, bool check) { + throw std::invalid_argument("called 'field' without 'beginrecord' at the same level before it"); } - Fillable* UnknownFillable::field_check(const char* key) { - throw std::invalid_argument("called 'field_check' without 'beginrecord' at the same level before it"); - } - - Fillable* UnknownFillable::endrecord() { + const std::shared_ptr UnknownFillable::endrecord() { throw std::invalid_argument("called 'endrecord' without 'beginrecord' at the same level before it"); } - } diff --git a/src/libawkward/io/json.cpp b/src/libawkward/io/json.cpp index 72003ff35f..b141fe2d1e 100644 --- a/src/libawkward/io/json.cpp +++ b/src/libawkward/io/json.cpp @@ -22,6 +22,11 @@ namespace awkward { bool Uint64(uint64_t x) { array_.integer((int64_t)x); return true; } bool Double(double x) { array_.real(x); return true; } + bool String(const char* str, rj::SizeType length, bool copy) { + array_.string(str, (int64_t)length); + return true; + } + bool StartArray() { if (depth_ != 0) { array_.beginlist(); @@ -50,10 +55,6 @@ namespace awkward { return true; } - bool String(const char* str, rj::SizeType length, bool copy) { - throw std::runtime_error("not implemented: Handler::String"); - } - private: FillableArray array_; int64_t depth_; diff --git a/src/libawkward/io/root.cpp b/src/libawkward/io/root.cpp index c8b7c0096f..f5ffabbe80 100644 --- a/src/libawkward/io/root.cpp +++ b/src/libawkward/io/root.cpp @@ -66,10 +66,10 @@ namespace awkward { std::vector shape = { (ssize_t)bytepos_tocopy.length() }; std::vector strides = { (ssize_t)itemsize }; - std::shared_ptr out(new NumpyArray(Identity::none(), Type::none(), ptr, shape, strides, 0, (ssize_t)itemsize, format)); // FIXME: Type::none() + std::shared_ptr out(new NumpyArray(Identity::none(), Type::none(), ptr, shape, strides, 0, (ssize_t)itemsize, format)); for (int64_t i = depth - 1; i >= 0; i--) { - out = std::shared_ptr(new ListOffsetArray64(Identity::none(), Type::none(), levels[(size_t)i].toindex(), out)); // FIXME: Type::none() + out = std::shared_ptr(new ListOffsetArray64(Identity::none(), Type::none(), levels[(size_t)i].toindex(), out)); } return out; } diff --git a/src/libawkward/type/ArrayType.cpp b/src/libawkward/type/ArrayType.cpp index f3f61ab166..4ed95d16f6 100644 --- a/src/libawkward/type/ArrayType.cpp +++ b/src/libawkward/type/ArrayType.cpp @@ -6,20 +6,24 @@ namespace awkward { std::string ArrayType::tostring_part(std::string indent, std::string pre, std::string post) const { + std::string typestr; + if (get_typestr(typestr)) { + return typestr; + } + return indent + pre + std::to_string(length_) + " * " + type_.get()->tostring_part(indent, "", "") + post; } const std::shared_ptr ArrayType::shallow_copy() const { - return std::shared_ptr(new ArrayType(type_, length_)); - } - - bool ArrayType::shallow_equal(const std::shared_ptr other) const { - return (dynamic_cast(other.get()) != nullptr); + return std::shared_ptr(new ArrayType(parameters_, type_, length_)); } - bool ArrayType::equal(const std::shared_ptr other) const { + bool ArrayType::equal(const std::shared_ptr other, bool check_parameters) const { if (ArrayType* t = dynamic_cast(other.get())) { - return length_ == t->length_ && type_.get()->equal(t->type_); + if (check_parameters && !equal_parameters(other.get()->parameters())) { + return false; + } + return length_ == t->length_ && type_.get()->equal(t->type_, check_parameters); } else { return false; diff --git a/src/libawkward/type/ListType.cpp b/src/libawkward/type/ListType.cpp index e152a03fa5..08f0e25a13 100644 --- a/src/libawkward/type/ListType.cpp +++ b/src/libawkward/type/ListType.cpp @@ -1,6 +1,7 @@ // BSD 3-Clause License; see https://github.com/jpivarski/awkward-1.0/blob/master/LICENSE #include +#include #include "awkward/type/UnknownType.h" #include "awkward/type/OptionType.h" @@ -9,20 +10,31 @@ namespace awkward { std::string ListType::tostring_part(std::string indent, std::string pre, std::string post) const { - return indent + pre + "var * " + type().get()->tostring_part(indent, "", "") + post; - } + std::string typestr; + if (get_typestr(typestr)) { + return typestr; + } - const std::shared_ptr ListType::shallow_copy() const { - return std::shared_ptr(new ListType(type_)); + std::stringstream out; + if (parameters_.size() == 0) { + out << indent << pre << "var * " << type_.get()->tostring_part(indent, "", "") << post; + } + else { + out << indent << pre << "[var * " << type_.get()->tostring_part(indent, "", "") << ", " << string_parameters() << "]" << post; + } + return out.str(); } - bool ListType::shallow_equal(const std::shared_ptr other) const { - return (dynamic_cast(other.get()) != nullptr); + const std::shared_ptr ListType::shallow_copy() const { + return std::shared_ptr(new ListType(parameters_, type_)); } - bool ListType::equal(const std::shared_ptr other) const { + bool ListType::equal(const std::shared_ptr other, bool check_parameters) const { if (ListType* t = dynamic_cast(other.get())) { - return type().get()->equal(t->type()); + if (check_parameters && !equal_parameters(other.get()->parameters())) { + return false; + } + return type().get()->equal(t->type(), check_parameters); } else { return false; diff --git a/src/libawkward/type/OptionType.cpp b/src/libawkward/type/OptionType.cpp index 0eb9d35bbd..0831624b73 100644 --- a/src/libawkward/type/OptionType.cpp +++ b/src/libawkward/type/OptionType.cpp @@ -1,6 +1,7 @@ // BSD 3-Clause License; see https://github.com/jpivarski/awkward-1.0/blob/master/LICENSE #include +#include #include "awkward/type/UnknownType.h" #include "awkward/type/ListType.h" @@ -10,26 +11,37 @@ namespace awkward { std::string OptionType::tostring_part(std::string indent, std::string pre, std::string post) const { - if (dynamic_cast(type_.get()) != nullptr || - dynamic_cast(type_.get()) != nullptr) { - return indent + pre + "option[" + type().get()->tostring_part(indent, "", "") + "]" + post; + std::string typestr; + if (get_typestr(typestr)) { + return typestr; + } + + std::stringstream out; + if (parameters_.size() == 0) { + if (dynamic_cast(type_.get()) != nullptr || + dynamic_cast(type_.get()) != nullptr) { + out << indent << pre << "option[" << type_.get()->tostring_part(indent, "", "") << "]" << post; + } + else { + out << indent << pre << "?" << type_.get()->tostring_part("", "", "") << post; + } } else { - return indent + pre + "?" + type_.get()->tostring_part("", "", "") + post; + out << indent << pre << "option[" << type_.get()->tostring_part(indent, "", "") << ", " << string_parameters() << "]" << post; } + return out.str(); } const std::shared_ptr OptionType::shallow_copy() const { - return std::shared_ptr(new OptionType(type_)); - } - - bool OptionType::shallow_equal(const std::shared_ptr other) const { - return (dynamic_cast(other.get()) != nullptr); + return std::shared_ptr(new OptionType(parameters_, type_)); } - bool OptionType::equal(const std::shared_ptr other) const { + bool OptionType::equal(const std::shared_ptr other, bool check_parameters) const { if (OptionType* t = dynamic_cast(other.get())) { - return type().get()->equal(t->type()); + if (check_parameters && !equal_parameters(other.get()->parameters())) { + return false; + } + return type().get()->equal(t->type(), check_parameters); } else { return false; diff --git a/src/libawkward/type/PrimitiveType.cpp b/src/libawkward/type/PrimitiveType.cpp index 6e9b82ec2c..5164a5c00d 100644 --- a/src/libawkward/type/PrimitiveType.cpp +++ b/src/libawkward/type/PrimitiveType.cpp @@ -1,6 +1,7 @@ // BSD 3-Clause License; see https://github.com/jpivarski/awkward-1.0/blob/master/LICENSE #include +#include #include "awkward/type/UnknownType.h" #include "awkward/type/OptionType.h" @@ -9,6 +10,12 @@ namespace awkward { std::string PrimitiveType::tostring_part(std::string indent, std::string pre, std::string post) const { + std::string typestr; + if (get_typestr(typestr)) { + return typestr; + } + + std::stringstream out; std::string s; switch (dtype_) { case boolean: s = "bool"; break; @@ -24,19 +31,24 @@ namespace awkward { case float64: s = "float64"; break; default: assert(dtype_ < numtypes); } - return indent + pre + s + post; + if (parameters_.size() == 0) { + out << indent << pre << s << post; + } + else { + out << indent << pre << s << "[" << string_parameters() << "]" << post; + } + return out.str(); } const std::shared_ptr PrimitiveType::shallow_copy() const { - return std::shared_ptr(new PrimitiveType(dtype_)); - } - - bool PrimitiveType::shallow_equal(const std::shared_ptr other) const { - return equal(other); + return std::shared_ptr(new PrimitiveType(parameters_, dtype_)); } - bool PrimitiveType::equal(const std::shared_ptr other) const { + bool PrimitiveType::equal(const std::shared_ptr other, bool check_parameters) const { if (PrimitiveType* t = dynamic_cast(other.get())) { + if (check_parameters && !equal_parameters(other.get()->parameters())) { + return false; + } return dtype_ == t->dtype_; } else { diff --git a/src/libawkward/type/RecordType.cpp b/src/libawkward/type/RecordType.cpp index 06cd20c0ee..3c1d6e98d7 100644 --- a/src/libawkward/type/RecordType.cpp +++ b/src/libawkward/type/RecordType.cpp @@ -11,72 +11,75 @@ namespace awkward { std::string RecordType::tostring_part(std::string indent, std::string pre, std::string post) const { + std::string typestr; + if (get_typestr(typestr)) { + return typestr; + } + std::stringstream out; - if (reverselookup_.get() == nullptr) { - out << "("; - for (size_t j = 0; j < types_.size(); j++) { - if (j != 0) { - out << ", "; + if (parameters_.size() == 0) { + if (reverselookup_.get() == nullptr) { + out << "("; + for (size_t j = 0; j < types_.size(); j++) { + if (j != 0) { + out << ", "; + } + out << types_[j].get()->tostring_part("", "", ""); } - out << types_[j].get()->tostring_part("", "", ""); + out << ")"; } - out << ")"; - } - else { - out << "{"; - for (size_t j = 0; j < types_.size(); j++) { - if (j != 0) { - out << ", "; + else { + out << "{"; + for (size_t j = 0; j < types_.size(); j++) { + if (j != 0) { + out << ", "; + } + out << util::quote(reverselookup_.get()->at(j), true) << ": "; + out << types_[j].get()->tostring_part("", "", ""); } - out << util::quote(reverselookup_.get()->at(j), false) << ": "; - out << types_[j].get()->tostring_part("", "", ""); + out << "}"; } - out << "}"; } - return out.str(); - } - - const std::shared_ptr RecordType::shallow_copy() const { - return std::shared_ptr(new RecordType(types_, lookup_, reverselookup_)); - } - - bool RecordType::shallow_equal(const std::shared_ptr other) const { - if (RecordType* t = dynamic_cast(other.get())) { - if (numfields() != t->numfields()) { - return false; - } + else { if (reverselookup_.get() == nullptr) { - if (t->reverselookup().get() != nullptr) { - return false; + out << "tuple[["; + for (size_t j = 0; j < types_.size(); j++) { + if (j != 0) { + out << ", "; + } + out << types_[j].get()->tostring_part("", "", ""); } - return true; } else { - if (t->reverselookup().get() == nullptr) { - return false; - } - if (lookup_.get()->size() != t->lookup().get()->size()) { - return false; - } - for (auto pair : *lookup_.get()) { - int64_t otherindex; - try { - otherindex = (int64_t)t->lookup().get()->at(pair.first); + out << "struct[["; + for (size_t j = 0; j < types_.size(); j++) { + if (j != 0) { + out << ", "; } - catch (std::out_of_range err) { - return false; + out << util::quote(reverselookup_.get()->at(j), true); + } + out << "], ["; + for (size_t j = 0; j < types_.size(); j++) { + if (j != 0) { + out << ", "; } + out << types_[j].get()->tostring_part("", "", ""); } - return true; } + out << "], " << string_parameters() << "]"; } - else { - return false; - } + return out.str(); } - bool RecordType::equal(const std::shared_ptr other) const { + const std::shared_ptr RecordType::shallow_copy() const { + return std::shared_ptr(new RecordType(parameters_, types_, lookup_, reverselookup_)); + } + + bool RecordType::equal(const std::shared_ptr other, bool check_parameters) const { if (RecordType* t = dynamic_cast(other.get())) { + if (check_parameters && !equal_parameters(other.get()->parameters())) { + return false; + } if (numfields() != t->numfields()) { return false; } @@ -85,7 +88,7 @@ namespace awkward { return false; } for (int64_t j = 0; j < numfields(); j++) { - if (!field(j).get()->equal(t->field(j))) { + if (!field(j).get()->equal(t->field(j), check_parameters)) { return false; } } @@ -106,7 +109,7 @@ namespace awkward { catch (std::out_of_range err) { return false; } - if (!field((int64_t)pair.second).get()->equal(t->field(otherindex))) { + if (!field((int64_t)pair.second).get()->equal(t->field(otherindex), check_parameters)) { return false; } } diff --git a/src/libawkward/type/RegularType.cpp b/src/libawkward/type/RegularType.cpp index 1cef549b7e..9683b285d7 100644 --- a/src/libawkward/type/RegularType.cpp +++ b/src/libawkward/type/RegularType.cpp @@ -1,6 +1,7 @@ // BSD 3-Clause License; see https://github.com/jpivarski/awkward-1.0/blob/master/LICENSE #include +#include #include "awkward/type/UnknownType.h" #include "awkward/type/OptionType.h" @@ -9,25 +10,31 @@ namespace awkward { std::string RegularType::tostring_part(std::string indent, std::string pre, std::string post) const { - return indent + pre + std::to_string(size_) + std::string(" * ") + type_.get()->tostring_part(indent, "", "") + post; - } - - const std::shared_ptr RegularType::shallow_copy() const { - return std::shared_ptr(new RegularType(type_, size_)); - } + std::string typestr; + if (get_typestr(typestr)) { + return typestr; + } - bool RegularType::shallow_equal(const std::shared_ptr other) const { - if (RegularType* t = dynamic_cast(other.get())) { - return size() == t->size(); + std::stringstream out; + if (parameters_.size() == 0) { + out << indent << pre << size_ << " * " << type_.get()->tostring_part(indent, "", "") << post; } else { - return false; + out << indent << pre << "[" << size_ << " * " << type_.get()->tostring_part(indent, "", "") << ", " << string_parameters() << "]" << post; } + return out.str(); + } + + const std::shared_ptr RegularType::shallow_copy() const { + return std::shared_ptr(new RegularType(parameters_, type_, size_)); } - bool RegularType::equal(const std::shared_ptr other) const { + bool RegularType::equal(const std::shared_ptr other, bool check_parameters) const { if (RegularType* t = dynamic_cast(other.get())) { - return size() == t->size() && type().get()->equal(t->type()); + if (check_parameters && !equal_parameters(other.get()->parameters())) { + return false; + } + return size() == t->size() && type().get()->equal(t->type(), check_parameters); } else { return false; diff --git a/src/libawkward/type/Type.cpp b/src/libawkward/type/Type.cpp index 3413158273..73269c9d11 100644 --- a/src/libawkward/type/Type.cpp +++ b/src/libawkward/type/Type.cpp @@ -1,9 +1,16 @@ // BSD 3-Clause License; see https://github.com/jpivarski/awkward-1.0/blob/master/LICENSE #include +#include + +#include "rapidjson/document.h" + +#include "awkward/util.h" #include "awkward/type/Type.h" +namespace rj = rapidjson; + namespace awkward { std::shared_ptr Type::nolength() const { return shallow_copy(); @@ -13,4 +20,52 @@ namespace awkward { // FIXME: better side-by-side comparison return tostring() + std::string(" versus ") + supertype.get()->tostring(); } + + bool Type::equal_parameters(const Type::Parameters& other) const { + if (parameters_.size() != other.size()) { + return false; + } + for (auto pair : parameters_) { + auto other_value = other.find(pair.first); + if (other_value == other.end()) { + return false; + } + rj::Document mine; + rj::Document yours; + mine.Parse(pair.second.c_str()); + yours.Parse(other_value->second.c_str()); + if (mine != yours) { + return false; + } + } + return true; + } + + bool Type::get_typestr(std::string& output) const { + auto typestr = parameters_.find(std::string("__str__")); + if (typestr != parameters_.end()) { + rj::Document mine; + mine.Parse(typestr->second.c_str()); + if (mine.IsString()) { + output = std::string(mine.GetString()); + return true; + } + } + return false; + } + + const std::string Type::string_parameters() const { + std::stringstream out; + out << "parameters={"; + bool first = true; + for (auto pair : parameters_) { + if (!first) { + out << ", "; + } + out << util::quote(pair.first, true) << ": " << pair.second; + first = false; + } + out << "}"; + return out.str(); + } } diff --git a/src/libawkward/type/UnionType.cpp b/src/libawkward/type/UnionType.cpp index ef7da54df6..560a99a82b 100644 --- a/src/libawkward/type/UnionType.cpp +++ b/src/libawkward/type/UnionType.cpp @@ -10,6 +10,11 @@ namespace awkward { std::string UnionType::tostring_part(std::string indent, std::string pre, std::string post) const { + std::string typestr; + if (get_typestr(typestr)) { + return typestr; + } + std::stringstream out; out << indent << pre << "union["; for (int64_t i = 0; i < numtypes(); i++) { @@ -18,38 +23,27 @@ namespace awkward { } out << type(i).get()->tostring_part(indent, "", ""); } + if (parameters_.size() != 0) { + out << ", " << string_parameters(); + } out << "]" << post; return out.str(); } const std::shared_ptr UnionType::shallow_copy() const { - return std::shared_ptr(new UnionType(types_)); + return std::shared_ptr(new UnionType(parameters_, types_)); } - bool UnionType::shallow_equal(const std::shared_ptr other) const { + bool UnionType::equal(const std::shared_ptr other, bool check_parameters) const { if (UnionType* t = dynamic_cast(other.get())) { - if (types_.size() != t->types_.size()) { + if (check_parameters && !equal_parameters(other.get()->parameters())) { return false; } - for (size_t i = 0; i < types_.size(); i++) { - if (!types_[i].get()->shallow_equal(t->types_[i])) { - return false; - } - } - return true; - } - else { - return false; - } - } - - bool UnionType::equal(const std::shared_ptr other) const { - if (UnionType* t = dynamic_cast(other.get())) { if (types_.size() != t->types_.size()) { return false; } for (size_t i = 0; i < types_.size(); i++) { - if (!types_[i].get()->equal(t->types_[i])) { + if (!types_[i].get()->equal(t->types_[i], check_parameters)) { return false; } } @@ -69,7 +63,7 @@ namespace awkward { for (auto t : types_) { types.push_back(t.get()->level()); } - return std::shared_ptr(new UnionType(types)); + return std::shared_ptr(new UnionType(Type::Parameters(), types)); } std::shared_ptr UnionType::inner() const { diff --git a/src/libawkward/type/UnknownType.cpp b/src/libawkward/type/UnknownType.cpp index 8432c2f486..dae16d03ab 100644 --- a/src/libawkward/type/UnknownType.cpp +++ b/src/libawkward/type/UnknownType.cpp @@ -1,24 +1,36 @@ // BSD 3-Clause License; see https://github.com/jpivarski/awkward-1.0/blob/master/LICENSE #include +#include #include "awkward/type/UnknownType.h" namespace awkward { std::string UnknownType::tostring_part(std::string indent, std::string pre, std::string post) const { - return indent + pre + "unknown" + post; - } + std::string typestr; + if (get_typestr(typestr)) { + return typestr; + } - const std::shared_ptr UnknownType::shallow_copy() const { - return std::shared_ptr(new UnknownType()); + std::stringstream out; + if (parameters_.size() == 0) { + out << indent << pre << "unknown" << post; + } + else { + out << indent << pre << "unknown[" << string_parameters() << "]" << post; + } + return out.str(); } - bool UnknownType::shallow_equal(const std::shared_ptr other) const { - return equal(other); + const std::shared_ptr UnknownType::shallow_copy() const { + return std::shared_ptr(new UnknownType(parameters_)); } - bool UnknownType::equal(const std::shared_ptr other) const { + bool UnknownType::equal(const std::shared_ptr other, bool check_parameters) const { if (UnknownType* t = dynamic_cast(other.get())) { + if (check_parameters && !equal_parameters(other.get()->parameters())) { + return false; + } return true; } else { diff --git a/src/pyawkward.cpp b/src/pyawkward.cpp index 774981c570..11137811e1 100644 --- a/src/pyawkward.cpp +++ b/src/pyawkward.cpp @@ -22,7 +22,6 @@ #include "awkward/fillable/FillableOptions.h" #include "awkward/fillable/FillableArray.h" #include "awkward/type/Type.h" -#include "awkward/type/DressedType.h" #include "awkward/type/ArrayType.h" #include "awkward/type/UnknownType.h" #include "awkward/type/PrimitiveType.h" @@ -50,102 +49,20 @@ class pyobject_deleter { PyObject* pyobj_; }; -class PyDressParameters: public ak::DressParameters { -public: - PyDressParameters(const py::dict& pydict): pydict_(pydict) { } - - py::dict pydict() const { return pydict_; } - - virtual const std::vector keys() const { - std::vector out; - for (auto pair : pydict_) { - out.push_back(pair.first.cast()); - } - return out; - } - - virtual const py::object get(const std::string& key) const { - py::str pykey(PyUnicode_DecodeUTF8(key.data(), key.length(), "surrogateescape")); - return pydict_[pykey]; - } - - virtual const std::string get_string(const std::string& key) const { - return get(key).attr("__repr__")().cast(); - } - - virtual bool equal(const ak::DressParameters& other) const { - if (const PyDressParameters* raw = dynamic_cast(&other)) { - return pydict_.attr("__eq__")(raw->pydict()).cast(); - } - else { - return false; - } - } - -private: - py::dict pydict_; -}; - -class PyDress: public ak::Dress { -public: - PyDress(const py::object& pyclass): pyclass_(pyclass) { } - - py::object pyclass() const { return pyclass_; } - - virtual const std::string name() const { - std::string out; - if (py::hasattr(pyclass_, "__module__")) { - out = pyclass_.attr("__module__").cast() + std::string("."); - } - if (py::hasattr(pyclass_, "__qualname__")) { - out = out + pyclass_.attr("__qualname__").cast(); - } - else if (py::hasattr(pyclass_, "__name__")) { - out = out + pyclass_.attr("__name__").cast(); - } - else { - out = out + std::string(""); - } - return out; - } - - virtual const std::string typestr(std::shared_ptr baretype, const ak::DressParameters& parameters) const { - if (const PyDressParameters* raw = dynamic_cast(¶meters)) { - if (py::hasattr(pyclass_, "typestr")) { - return pyclass_.attr("typestr")(py::cast(baretype.get()), raw->pydict()).cast(); - } - } - return std::string(); - } - - virtual bool equal(const ak::Dress& other) const { - if (const PyDress* raw = dynamic_cast(&other)) { - return pyclass_.is(raw->pyclass()); - } - else { - return false; - } - } - -private: - py::object pyclass_; -}; - py::class_> make_Type(py::handle m, std::string name) { return (py::class_>(m, name.c_str()) + .def("__eq__", [](std::shared_ptr self, std::shared_ptr other) -> bool { + return self.get()->equal(other, true); + }) .def("__ne__", [](std::shared_ptr self, std::shared_ptr other) -> bool { - return !self.get()->equal(other); + return !self.get()->equal(other, true); }) ); } -typedef ak::DressedType PyDressedType; py::object box(std::shared_ptr t) { - if (PyDressedType* raw = dynamic_cast(t.get())) { - return py::cast(*raw); - } - else if (ak::ArrayType* raw = dynamic_cast(t.get())) { + if (ak::ArrayType* raw = dynamic_cast(t.get())) { return py::cast(*raw); } else if (ak::ListType* raw = dynamic_cast(t.get())) { @@ -241,10 +158,6 @@ py::object box(std::shared_ptr id) { } std::shared_ptr unbox_type(py::handle obj) { - try { - return obj.cast()->shallow_copy(); - } - catch (py::cast_error err) { } try { return obj.cast()->shallow_copy(); } @@ -754,6 +667,12 @@ void fillable_fill(ak::FillableArray& self, py::handle obj) { else if (py::isinstance(obj)) { self.real(obj.cast()); } + else if (py::isinstance(obj)) { + self.bytestring(obj.cast()); + } + else if (py::isinstance(obj)) { + self.string(obj.cast()); + } else if (py::isinstance(obj)) { py::tuple tup = obj.cast(); self.begintuple(tup.size()); @@ -765,7 +684,7 @@ void fillable_fill(ak::FillableArray& self, py::handle obj) { } else if (py::isinstance(obj)) { py::dict dict = obj.cast(); - self.beginrecord(dict.size()); + self.beginrecord(); for (auto pair : dict) { if (!py::isinstance(pair.first)) { throw std::invalid_argument("keys of dicts in 'fromiter' must all be strings"); @@ -776,7 +695,6 @@ void fillable_fill(ak::FillableArray& self, py::handle obj) { } self.endrecord(); } - // FIXME: strings else if (py::isinstance(obj)) { py::iterable seq = obj.cast(); self.beginlist(); @@ -811,15 +729,29 @@ py::class_ make_FillableArray(py::handle m, std::string name) .def("boolean", &ak::FillableArray::boolean) .def("integer", &ak::FillableArray::integer) .def("real", &ak::FillableArray::real) + .def("bytestring", [](ak::FillableArray& self, py::bytes x) -> void { + self.bytestring(x.cast()); + }) + .def("string", [](ak::FillableArray& self, py::str x) -> void { + self.string(x.cast()); + }) .def("beginlist", &ak::FillableArray::beginlist) .def("endlist", &ak::FillableArray::endlist) .def("begintuple", &ak::FillableArray::begintuple) .def("index", &ak::FillableArray::index) .def("endtuple", &ak::FillableArray::endtuple) - .def("beginrecord", [](ak::FillableArray& self, int64_t disambiguator) -> void { - self.beginrecord(disambiguator); - }, py::arg("disambiguator") = 0) - .def("field", &ak::FillableArray::field_check) + .def("beginrecord", [](ak::FillableArray& self, py::object name) -> void { + if (name.is(py::none())) { + self.beginrecord(); + } + else { + std::string cppname = name.cast(); + self.beginrecord_check(cppname.c_str()); + } + }, py::arg("name") = py::none()) + .def("field", [](ak::FillableArray& self, const std::string& x) -> void { + self.field_check(x); + }) .def("endrecord", &ak::FillableArray::endrecord) .def("fill", &fillable_fill) ); @@ -842,10 +774,49 @@ py::dict emptydict(T& self) { return py::dict(); } +ak::Type::Parameters dict2parameters(py::object in) { + ak::Type::Parameters out; + if (in.is(py::none())) { + // None is equivalent to an empty dict + } + else if (py::isinstance(in)) { + for (auto pair : in.cast()) { + std::string key = pair.first.cast(); + py::object value = py::module::import("json").attr("dumps")(pair.second); + out[key] = value.cast(); + } + } + else { + throw std::invalid_argument("type parameters must be a dict (or None)"); + } + return out; +} + +py::dict parameters2dict(const ak::Type::Parameters& in) { + py::dict out; + for (auto pair : in) { + std::string cppkey = pair.first; + std::string cppvalue = pair.second; + py::str pykey(PyUnicode_DecodeUTF8(cppkey.data(), cppkey.length(), "surrogateescape")); + py::str pyvalue(PyUnicode_DecodeUTF8(cppvalue.data(), cppvalue.length(), "surrogateescape")); + out[pykey] = py::module::import("json").attr("loads")(pyvalue); + } + return out; +} + +template +py::dict getparameters(T& self) { + return parameters2dict(self.parameters()); +} + +template +void setparameters(T& self, py::object parameters) { + self.setparameters(dict2parameters(parameters)); +} + template py::class_ type_methods(py::class_, ak::Type>& x) { return x.def("__repr__", &T::tostring) - .def("__eq__", &T::equal) .def("nolength", &T::nolength) .def("level", &T::level) .def("inner", &inner) @@ -864,94 +835,76 @@ py::class_ type_methods(py::class_, ak::Type> ; } -py::class_, ak::Type> make_DressedType(py::handle m, std::string name) { - return type_methods(py::class_, ak::Type>(m, name.c_str()) - .def(py::init([](std::shared_ptr type, py::object dress, py::kwargs kwargs) -> PyDressedType { - kwargs = py::module::import("copy").attr("deepcopy")(kwargs); - return PyDressedType(type, PyDress(dress), PyDressParameters(kwargs)); - })) - .def_property_readonly("type", &PyDressedType::type) - .def_property_readonly("dress", [](PyDressedType& self) -> py::object { - return self.dress().pyclass(); - }) - .def_property_readonly("parameters", [](PyDressedType& self) -> py::dict { - return self.parameters().pydict(); - }) - .def(py::pickle([](const PyDressedType& self) { - return py::make_tuple(self.type(), self.dress().pyclass(), self.parameters().pydict()); - }, [](py::tuple state) { - return PyDressedType(unbox_type(state[0]), PyDress(state[1]), PyDressParameters(state[2])); - })) - - ); -} - py::class_, ak::Type> make_ArrayType(py::handle m, std::string name) { return type_methods(py::class_, ak::Type>(m, name.c_str()) - .def(py::init, int64_t>()) + .def(py::init([](std::shared_ptr type, int64_t length, py::object parameters) -> ak::ArrayType { + return ak::ArrayType(dict2parameters(parameters), type, length); + }), py::arg("type"), py::arg("length"), py::arg("parameters") = py::none()) .def_property_readonly("type", &ak::ArrayType::type) .def_property_readonly("length", &ak::ArrayType::length) - .def_property_readonly("parameters", &emptydict) + .def_property("parameters", &getparameters, &setparameters) .def(py::pickle([](const ak::ArrayType& self) { - return py::make_tuple(box(self.type()), py::cast(self.length())); + return py::make_tuple(parameters2dict(self.parameters()), box(self.type()), py::cast(self.length())); }, [](py::tuple state) { - return ak::ArrayType(unbox_type(state[0]), state[1].cast()); + return ak::ArrayType(dict2parameters(state[0]), unbox_type(state[1]), state[2].cast()); })) ); } py::class_, ak::Type> make_UnknownType(py::handle m, std::string name) { return type_methods(py::class_, ak::Type>(m, name.c_str()) - .def(py::init<>()) - .def_property_readonly("parameters", &emptydict) + .def(py::init([](py::object parameters) -> ak::UnknownType { + return ak::UnknownType(dict2parameters(parameters)); + }), py::arg("parameters") = py::none()) + .def_property("parameters", &getparameters, &setparameters) .def(py::pickle([](const ak::UnknownType& self) { - return py::make_tuple(); + return py::make_tuple(parameters2dict(self.parameters())); }, [](py::tuple state) { - return ak::UnknownType(); + return ak::UnknownType(dict2parameters(state[0])); })) ); } py::class_, ak::Type> make_PrimitiveType(py::handle m, std::string name) { return type_methods(py::class_, ak::Type>(m, name.c_str()) - .def(py::init([](std::string dtype) -> ak::PrimitiveType { + .def(py::init([](std::string dtype, py::object parameters) -> ak::PrimitiveType { if (dtype == std::string("bool")) { - return ak::PrimitiveType(ak::PrimitiveType::boolean); + return ak::PrimitiveType(dict2parameters(parameters), ak::PrimitiveType::boolean); } else if (dtype == std::string("int8")) { - return ak::PrimitiveType(ak::PrimitiveType::int8); + return ak::PrimitiveType(dict2parameters(parameters), ak::PrimitiveType::int8); } else if (dtype == std::string("int16")) { - return ak::PrimitiveType(ak::PrimitiveType::int16); + return ak::PrimitiveType(dict2parameters(parameters), ak::PrimitiveType::int16); } else if (dtype == std::string("int32")) { - return ak::PrimitiveType(ak::PrimitiveType::int32); + return ak::PrimitiveType(dict2parameters(parameters), ak::PrimitiveType::int32); } else if (dtype == std::string("int64")) { - return ak::PrimitiveType(ak::PrimitiveType::int64); + return ak::PrimitiveType(dict2parameters(parameters), ak::PrimitiveType::int64); } else if (dtype == std::string("uint8")) { - return ak::PrimitiveType(ak::PrimitiveType::uint8); + return ak::PrimitiveType(dict2parameters(parameters), ak::PrimitiveType::uint8); } else if (dtype == std::string("uint16")) { - return ak::PrimitiveType(ak::PrimitiveType::uint16); + return ak::PrimitiveType(dict2parameters(parameters), ak::PrimitiveType::uint16); } else if (dtype == std::string("uint32")) { - return ak::PrimitiveType(ak::PrimitiveType::uint32); + return ak::PrimitiveType(dict2parameters(parameters), ak::PrimitiveType::uint32); } else if (dtype == std::string("uint64")) { - return ak::PrimitiveType(ak::PrimitiveType::uint64); + return ak::PrimitiveType(dict2parameters(parameters), ak::PrimitiveType::uint64); } else if (dtype == std::string("float32")) { - return ak::PrimitiveType(ak::PrimitiveType::float32); + return ak::PrimitiveType(dict2parameters(parameters), ak::PrimitiveType::float32); } else if (dtype == std::string("float64")) { - return ak::PrimitiveType(ak::PrimitiveType::float64); + return ak::PrimitiveType(dict2parameters(parameters), ak::PrimitiveType::float64); } else { throw std::invalid_argument(std::string("unrecognized primitive type: ") + dtype); } - })) + }), py::arg("dtype"), py::arg("parameters") = py::none()) .def_property_readonly("dtype", [](ak::PrimitiveType& self) -> std::string { switch (self.dtype()) { case ak::PrimitiveType::boolean: return std::string("bool"); @@ -969,64 +922,70 @@ py::class_, ak::Type> make throw std::invalid_argument(std::string("unrecognized primitive type: ") + std::to_string(self.dtype())); } }) - .def_property_readonly("parameters", &emptydict) + .def_property("parameters", &getparameters, &setparameters) .def(py::pickle([](const ak::PrimitiveType& self) { - return py::make_tuple(py::cast((int64_t)self.dtype())); + return py::make_tuple(parameters2dict(self.parameters()), py::cast((int64_t)self.dtype())); }, [](py::tuple state) { - return ak::PrimitiveType((ak::PrimitiveType::DType)state[0].cast()); + return ak::PrimitiveType(dict2parameters(state[0]), (ak::PrimitiveType::DType)state[1].cast()); })) ); } py::class_, ak::Type> make_RegularType(py::handle m, std::string name) { return type_methods(py::class_, ak::Type>(m, name.c_str()) - .def(py::init, int64_t>()) + .def(py::init([](std::shared_ptr type, int64_t size, py::object parameters) -> ak::RegularType { + return ak::RegularType(dict2parameters(parameters), type, size); + }), py::arg("type"), py::arg("size"), py::arg("parameters") = py::none()) .def_property_readonly("type", &ak::RegularType::type) .def_property_readonly("size", &ak::RegularType::size) - .def_property_readonly("parameters", &emptydict) + .def_property("parameters", &getparameters, &setparameters) .def(py::pickle([](const ak::RegularType& self) { - return py::make_tuple(box(self.type()), py::cast(self.size())); + return py::make_tuple(parameters2dict(self.parameters()), box(self.type()), py::cast(self.size())); }, [](py::tuple state) { - return ak::RegularType(unbox_type(state[0]), state[1].cast()); + return ak::RegularType(dict2parameters(state[0]), unbox_type(state[1]), state[2].cast()); })) ); } py::class_, ak::Type> make_ListType(py::handle m, std::string name) { return type_methods(py::class_, ak::Type>(m, name.c_str()) - .def(py::init>()) + .def(py::init([](std::shared_ptr type, py::object parameters) -> ak::ListType { + return ak::ListType(dict2parameters(parameters), type); + }), py::arg("type"), py::arg("parameters") = py::none()) .def_property_readonly("type", &ak::ListType::type) - .def_property_readonly("parameters", &emptydict) + .def_property("parameters", &getparameters, &setparameters) .def(py::pickle([](const ak::ListType& self) { - return py::make_tuple(box(self.type())); + return py::make_tuple(parameters2dict(self.parameters()), box(self.type())); }, [](py::tuple state) { - return ak::ListType(unbox_type(state[0])); + return ak::ListType(dict2parameters(state[0]), unbox_type(state[1])); })) ); } py::class_, ak::Type> make_OptionType(py::handle m, std::string name) { return type_methods(py::class_, ak::Type>(m, name.c_str()) - .def(py::init>()) + .def(py::init([](std::shared_ptr type, py::object parameters) -> ak::OptionType { + return ak::OptionType(dict2parameters(parameters), type); + }), py::arg("type"), py::arg("parameters") = py::none()) .def_property_readonly("type", &ak::OptionType::type) - .def_property_readonly("parameters", &emptydict) + .def_property("parameters", &getparameters, &setparameters) .def(py::pickle([](const ak::OptionType& self) { - return py::make_tuple(box(self.type())); + return py::make_tuple(parameters2dict(self.parameters()), box(self.type())); }, [](py::tuple state) { - return ak::OptionType(unbox_type(state[0])); + return ak::OptionType(dict2parameters(state[0]), unbox_type(state[1])); })) ); } py::class_, ak::Type> make_UnionType(py::handle m, std::string name) { return type_methods(py::class_, ak::Type>(m, name.c_str()) - .def(py::init([](py::args args) -> ak::UnionType { - std::vector> types; - for (auto x : args) { - types.push_back(unbox_type(x)); + .def(py::init([](py::iterable types, py::object parameters) -> ak::UnionType { + std::vector> out; + for (auto x : types) { + out.push_back(unbox_type(x)); } - return ak::UnionType(types); - })) + return ak::UnionType(dict2parameters(parameters), out); + }), py::arg("types"), py::arg("parameters") = py::none()) .def_property_readonly("numtypes", &ak::UnionType::numtypes) .def_property_readonly("types", [](ak::UnionType& self) -> py::tuple { py::tuple types((size_t)self.numtypes()); @@ -1036,44 +995,23 @@ py::class_, ak::Type> make_UnionTy return types; }) .def("type", &ak::UnionType::type) - .def_property_readonly("parameters", &emptydict) + .def_property("parameters", &getparameters, &setparameters) .def(py::pickle([](const ak::UnionType& self) { py::tuple types((size_t)self.numtypes()); for (int64_t i = 0; i < self.numtypes(); i++) { types[(size_t)i] = box(self.type(i)); } - return py::make_tuple(types); + return py::make_tuple(parameters2dict(self.parameters()), types); }, [](py::tuple state) { std::vector> types; - for (auto x : state[0]) { + for (auto x : state[1]) { types.push_back(unbox_type(x)); } - return ak::UnionType(types); + return ak::UnionType(dict2parameters(state[0]), types); })) ); } -ak::RecordType tuple2recordtype(py::tuple args) { - std::vector> types; - for (auto x : args) { - types.push_back(unbox_type(x)); - } - return ak::RecordType(types, std::shared_ptr(nullptr), std::shared_ptr(nullptr)); -} - -ak::RecordType dict2recordtype(py::dict kwargs) { - std::shared_ptr lookup(new ak::RecordType::Lookup); - std::shared_ptr reverselookup(new ak::RecordType::ReverseLookup); - std::vector> types; - for (auto x : kwargs) { - std::string key = x.first.cast(); - (*lookup.get())[key] = types.size(); - reverselookup.get()->push_back(key); - types.push_back(unbox_type(x.second)); - } - return ak::RecordType(types, lookup, reverselookup); -} - template py::object lookup(const T& self) { std::shared_ptr lookup = self.lookup(); @@ -1140,19 +1078,26 @@ void from_lookup(std::shared_ptr lookup, std::shared_ptr reverselookup, py py::class_, ak::Type> make_RecordType(py::handle m, std::string name) { return type_methods(py::class_, ak::Type>(m, name.c_str()) - .def(py::init([](py::tuple singlearg) -> ak::RecordType { - return tuple2recordtype(singlearg); - })) - .def(py::init([](py::dict singlearg) -> ak::RecordType { - return dict2recordtype(singlearg); - })) - .def(py::init([](py::args args) -> ak::RecordType { - return tuple2recordtype(args); - })) - .def(py::init([](py::kwargs kwargs) -> ak::RecordType { - return dict2recordtype(kwargs); - })) - .def_static("from_lookup", [](py::iterable types, py::dict pylookup, py::object pyreverselookup) -> ak::RecordType { + .def(py::init([](py::tuple types, py::object parameters) -> ak::RecordType { + std::vector> out; + for (auto x : types) { + out.push_back(unbox_type(x)); + } + return ak::RecordType(dict2parameters(parameters), out, std::shared_ptr(nullptr), std::shared_ptr(nullptr)); + }), py::arg("types"), py::arg("parameters") = py::none()) + .def(py::init([](py::dict types, py::object parameters) -> ak::RecordType { + std::shared_ptr lookup(new ak::RecordType::Lookup); + std::shared_ptr reverselookup(new ak::RecordType::ReverseLookup); + std::vector> out; + for (auto x : types) { + std::string key = x.first.cast(); + (*lookup.get())[key] = out.size(); + reverselookup.get()->push_back(key); + out.push_back(unbox_type(x.second)); + } + return ak::RecordType(dict2parameters(parameters), out, lookup, reverselookup); + }), py::arg("types"), py::arg("parameters") = py::none()) + .def_static("from_lookup", [](py::iterable types, py::dict pylookup, py::object pyreverselookup, py::object parameters) -> ak::RecordType { std::vector> out; for (auto x : types) { out.push_back(unbox_type(x)); @@ -1160,8 +1105,8 @@ py::class_, ak::Type> make_Recor std::shared_ptr lookup(new ak::RecordType::Lookup); std::shared_ptr reverselookup(new ak::RecordType::ReverseLookup); from_lookup(lookup, reverselookup, pylookup, pyreverselookup, (int64_t)out.size()); - return ak::RecordType(out, lookup, reverselookup); - }, py::arg("types"), py::arg("lookup"), py::arg("reverselookup") = py::none()) + return ak::RecordType(dict2parameters(parameters), out, lookup, reverselookup); + }, py::arg("types"), py::arg("lookup"), py::arg("reverselookup") = py::none(), py::arg("parameters") = py::none()) .def("__getitem__", [](ak::RecordType& self, int64_t fieldindex) -> py::object { return box(self.field(fieldindex)); }) @@ -1203,22 +1148,22 @@ py::class_, ak::Type> make_Recor }) .def_property_readonly("lookup", &lookup) .def_property_readonly("reverselookup", &reverselookup) - .def_property_readonly("parameters", &emptydict) + .def_property("parameters", &getparameters, &setparameters) .def(py::pickle([](const ak::RecordType& self) { py::tuple fields((size_t)self.numfields()); for (int64_t i = 0; i < self.numfields(); i++) { fields[(size_t)i] = box(self.field(i)); } - return py::make_tuple(fields, lookup(self), reverselookup(self)); + return py::make_tuple(parameters2dict(self.parameters()), fields, lookup(self), reverselookup(self)); }, [](py::tuple state) { std::vector> fields; - for (auto x : state[0]) { + for (auto x : state[1]) { fields.push_back(unbox_type(x)); } std::shared_ptr lookup(new ak::RecordType::Lookup); std::shared_ptr reverselookup(new ak::RecordType::ReverseLookup); - from_lookup(lookup, reverselookup, state[1].cast(), state[2], (int64_t)fields.size()); - return ak::RecordType(fields, lookup, reverselookup); + from_lookup(lookup, reverselookup, state[2].cast(), state[3], (int64_t)fields.size()); + return ak::RecordType(dict2parameters(state[0]), fields, lookup, reverselookup); })) ); } @@ -1590,7 +1535,6 @@ PYBIND11_MODULE(layout, m) { make_FillableArray(m, "FillableArray"); make_Type(m, "Type"); - make_DressedType(m, "DressedType"); make_ArrayType(m, "ArrayType"); make_PrimitiveType(m, "PrimitiveType"); make_RegularType(m, "RegularType"); diff --git a/tests/test_PR018_fromiter_fillable.py b/tests/test_PR018_fromiter_fillable.py index dc252677ad..efa67d2c1d 100644 --- a/tests/test_PR018_fromiter_fillable.py +++ b/tests/test_PR018_fromiter_fillable.py @@ -12,7 +12,7 @@ def test_types(): t0 = awkward1.layout.UnknownType() t1 = awkward1.layout.PrimitiveType("int32") t2 = awkward1.layout.OptionType(t1) - t3 = awkward1.layout.UnionType(t1, awkward1.layout.PrimitiveType("float64")) + t3 = awkward1.layout.UnionType((t1, awkward1.layout.PrimitiveType("float64"))) t4 = awkward1.layout.ListType(t1) t4b = awkward1.layout.ListType(awkward1.layout.PrimitiveType("int32")) t5 = awkward1.layout.ListType(t4) diff --git a/tests/test_PR025_record_array.py b/tests/test_PR025_record_array.py index 75cbf7da81..7626521b46 100644 --- a/tests/test_PR025_record_array.py +++ b/tests/test_PR025_record_array.py @@ -101,32 +101,32 @@ def test_type(): assert str(awkward1.typeof(recordarray)) == '5 * (int64, var * float64)' assert recordarray.lookup is None - assert awkward1.typeof(recordarray) == awkward1.layout.ArrayType(awkward1.layout.RecordType( + assert awkward1.typeof(recordarray) == awkward1.layout.ArrayType(awkward1.layout.RecordType(( awkward1.layout.PrimitiveType("int64"), - awkward1.layout.ListType(awkward1.layout.PrimitiveType("float64"))), 5) + awkward1.layout.ListType(awkward1.layout.PrimitiveType("float64")))), 5) assert awkward1.typeof(recordarray[2]) == awkward1.layout.RecordType( - awkward1.layout.PrimitiveType("int64"), - awkward1.layout.ListType(awkward1.layout.PrimitiveType("float64"))) + (awkward1.layout.PrimitiveType("int64"), + awkward1.layout.ListType(awkward1.layout.PrimitiveType("float64")))) recordarray.setkey(0, "one") recordarray.setkey(1, "two") - assert str(awkward1.typeof(recordarray)) in ("5 * {'one': int64, 'two': var * float64}", "5 * {'two': var * float64, 'one': int64}") + assert str(awkward1.typeof(recordarray)) in ('5 * {"one": int64, "two": var * float64}', '5 * {"two": var * float64, "one": int64}') assert recordarray.lookup == {"one": 0, "two": 1} assert str(awkward1.layout.RecordType( - awkward1.layout.PrimitiveType("int32"), - awkward1.layout.PrimitiveType("float64"))) == '(int32, float64)' + (awkward1.layout.PrimitiveType("int32"), + awkward1.layout.PrimitiveType("float64")))) == '(int32, float64)' assert str(awkward1.layout.RecordType( - one=awkward1.layout.PrimitiveType("int32"), - two=awkward1.layout.PrimitiveType("float64"))) in ("{'one': int32, 'two': float64}", "{'two': float64, 'one': int32}") + {"one": awkward1.layout.PrimitiveType("int32"), + "two": awkward1.layout.PrimitiveType("float64")})) in ('{"one": int32, "two": float64}', '{"two": float64, "one": int32}') - assert awkward1.typeof(recordarray) == awkward1.layout.ArrayType(awkward1.layout.RecordType( - one=awkward1.layout.PrimitiveType("int64"), - two=awkward1.layout.ListType(awkward1.layout.PrimitiveType("float64"))), 5) - assert awkward1.typeof(recordarray[2]) == awkward1.layout.RecordType( - one=awkward1.layout.PrimitiveType("int64"), - two=awkward1.layout.ListType(awkward1.layout.PrimitiveType("float64"))) + assert awkward1.typeof(recordarray) == awkward1.layout.ArrayType(awkward1.layout.RecordType({ + "one": awkward1.layout.PrimitiveType("int64"), + "two": awkward1.layout.ListType(awkward1.layout.PrimitiveType("float64"))}), 5) + assert awkward1.typeof(recordarray[2]) == awkward1.layout.RecordType({ + "one": awkward1.layout.PrimitiveType("int64"), + "two": awkward1.layout.ListType(awkward1.layout.PrimitiveType("float64"))}) def test_getitem(): assert str(awkward1.layout.Slice((1, 2, [3], "four", ["five", "six"], slice(7, 8, 9)))) == '[array([1]), array([2]), array([3]), "four", ["five", "six"], 7:8:9]' @@ -372,7 +372,7 @@ def test_fillable_record(): fillable.real(3.3) fillable.endrecord() - assert str(fillable.type) == "3 * {'one': int64, 'two': float64}" + assert str(fillable.type) == '3 * {"one": int64, "two": float64}' assert awkward1.tolist(fillable.snapshot()) == [{"one": 1, "two": 1.1}, {"one": 2, "two": 2.2}, {"one": 3, "two": 3.3}] def test_fromiter(): diff --git a/tests/test_PR028_add_dressed_types.py b/tests/test_PR028_add_dressed_types.py index 2aceb70160..0e1a7f348d 100644 --- a/tests/test_PR028_add_dressed_types.py +++ b/tests/test_PR028_add_dressed_types.py @@ -27,41 +27,12 @@ def test_highlevel(): assert str(b) == "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ... 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]" c = awkward1.Array('[{"one": 3.14, "two": [1.1, 2.2]}, {"one": 99.9, "two": [-3.1415926]}]') - assert repr(c) == "" + assert repr(c) == "" assert str(c) == "[{one: 3.14, two: [1.1, 2.2]}, {one: 99.9, two: [-3.14]}]" class Dummy(awkward1.highlevel.Array): pass -def test_dress(): - dressed0 = awkward1.layout.DressedType(awkward1.layout.PrimitiveType("float64"), Dummy, one=1, two=2) - assert repr(dressed0) in ("dress[float64, 'tests.test_PR028_add_dressed_types.Dummy', one=1, two=2]", "dress[float64, 'tests.test_PR028_add_dressed_types.Dummy', two=2, one=1]") - - pyclass = awkward1.behavior.string.CharBehavior - inner = awkward1.layout.PrimitiveType("uint8") - - baseline = sys.getrefcount(pyclass) - assert (sys.getrefcount(pyclass), sys.getrefcount(inner)) == (baseline, 2) - dressed1 = awkward1.layout.DressedType(inner, pyclass, encoding="utf-8") - assert (sys.getrefcount(pyclass), sys.getrefcount(inner)) == (baseline + 1, 2) - dressed2 = awkward1.layout.DressedType(inner, pyclass, encoding="utf-8") - assert (sys.getrefcount(pyclass), sys.getrefcount(inner)) == (baseline + 2, 2) - dressed3 = awkward1.layout.DressedType(inner, pyclass) - assert (sys.getrefcount(pyclass), sys.getrefcount(inner)) == (baseline + 3, 2) - - assert repr(dressed1) == "utf8" - assert repr(dressed3) == "char" - assert dressed1 == dressed2 - assert dressed1 != dressed3 - - assert (sys.getrefcount(pyclass), sys.getrefcount(inner)) == (baseline + 3, 2) - del dressed1 - assert (sys.getrefcount(pyclass), sys.getrefcount(inner)) == (baseline + 2, 2) - del dressed2 - assert (sys.getrefcount(pyclass), sys.getrefcount(inner)) == (baseline + 1, 2) - del dressed3 - assert (sys.getrefcount(pyclass), sys.getrefcount(inner)) == (baseline, 2) - def test_string1(): a = awkward1.Array(numpy.array([ord(x) for x in "hey there"], dtype=numpy.uint8)) a.__class__ = awkward1.behavior.string.CharBehavior @@ -114,10 +85,10 @@ def test_accepts(): content = awkward1.layout.NumpyArray(numpy.array([1.1, 2.2, 3.3, 4.4, 5.5], dtype=numpy.float64)) listoffsetarray = awkward1.layout.ListOffsetArray64(awkward1.layout.Index64(numpy.array([0, 3, 3, 5])), content) - dressed1 = awkward1.layout.DressedType(awkward1.layout.ListType(awkward1.layout.PrimitiveType("float64")), Dummy) + dressed1 = awkward1.layout.ListType(awkward1.layout.PrimitiveType("float64"), {"__class__": "Dummy"}) listoffsetarray.type = dressed1 - dressed2 = awkward1.layout.DressedType(awkward1.layout.PrimitiveType("float64"), Dummy) + dressed2 = awkward1.layout.PrimitiveType("float64", {"__class__": "Dummy"}) with pytest.raises(ValueError): listoffsetarray.type = dressed2 @@ -129,13 +100,13 @@ def typestr(baretype, parameters): def test_type_propagation(): array = awkward1.Array([[{"one": 1, "two": [1.0, 1.1]}, {"one": 2, "two": [2.0]}, {"one": 3, "two": [3.0, 3.1, 3.2]}], [], [{"one": 4, "two": []}, {"one": 5, "two": [5.0, 5.1, 5.2, 5.3]}]]) assert awkward1.tolist(array) == [[{"one": 1, "two": [1.0, 1.1]}, {"one": 2, "two": [2.0]}, {"one": 3, "two": [3.0, 3.1, 3.2]}], [], [{"one": 4, "two": []}, {"one": 5, "two": [5.0, 5.1, 5.2, 5.3]}]] - assert repr(array.type) in ("3 * var * {'one': int64, 'two': var * float64}", "3 * var * {'two': var * float64, 'one': int64}") + assert repr(array.type) in ('3 * var * {"one": int64, "two": var * float64}', '3 * var * {"two": var * float64, "one": int64}') - dfloat64 = awkward1.layout.DressedType(awkward1.layout.PrimitiveType("float64"), D) - dvarfloat64 = awkward1.layout.DressedType(awkward1.layout.ListType(dfloat64), D) - dint64 = awkward1.layout.DressedType(awkward1.layout.PrimitiveType("int64"), D) - drec = awkward1.layout.DressedType(awkward1.layout.RecordType(collections.OrderedDict([("one", dint64), ("two", dvarfloat64)])), D) - dvarrec = awkward1.layout.DressedType(awkward1.layout.ListType(drec), D) + dfloat64 = awkward1.layout.PrimitiveType("float64", {"__class__": "D", "__str__": "D[float64]"}) + dvarfloat64 = awkward1.layout.ListType(dfloat64, {"__class__": "D", "__str__": "D[var * D[float64]]"}) + dint64 = awkward1.layout.PrimitiveType("int64", {"__class__": "D", "__str__": "D[int64]"}) + drec = awkward1.layout.RecordType(collections.OrderedDict([("one", dint64), ("two", dvarfloat64)]), {"__class__": "D", "__str__": "D[{\"one\": D[int64], \"two\": D[var * D[float64]]}]"}) + dvarrec = awkward1.layout.ListType(drec, {"__class__": "D", "__str__": "D[var * D[{\"one\": D[int64], \"two\": D[var * D[float64]]}]]"}) array.layout.type = awkward1.layout.ArrayType(dvarrec, 3) assert array.layout.type == awkward1.layout.ArrayType(dvarrec, 3) diff --git a/tests/test_PR030_recordarray_in_numba.cpp b/tests/test_PR030_recordarray_in_numba.cpp new file mode 100644 index 0000000000..23f735265c --- /dev/null +++ b/tests/test_PR030_recordarray_in_numba.cpp @@ -0,0 +1,48 @@ +// BSD 3-Clause License; see https://github.com/jpivarski/awkward-1.0/blob/master/LICENSE + +#include +#include + +#include "awkward/Slice.h" +#include "awkward/fillable/FillableArray.h" +#include "awkward/fillable/FillableOptions.h" + +namespace ak = awkward; + +int main(int, char**) +{ + + // create fillable array + ak::FillableArray myarray(ak::FillableOptions(1024, 2.0)); + + // populate fillable array with lists + myarray.beginlist(); + //myarray.boolean(true); + myarray.integer(1); + myarray.real(1.1); + myarray.endlist(); + + myarray.beginlist(); + //myarray.boolean(false); + myarray.integer(2); + myarray.real(2.2); + myarray.endlist(); + + myarray.beginlist(); + //myarray.boolean(true); + myarray.integer(3); + myarray.real(3.3); + myarray.endlist(); + + // take a snapshot + //std::shared_ptr array = builder.snapshot(); + + // saving to compare fillable array to std vector + //std::vector>> vector = + //{{{true, 1, 1.1}, {false, 2, 2.2}, {true, 3, 3.3}}, {}, {}, {}}; + + + return 0; +} + + diff --git a/tests/test_PR031_types_in_numba.py b/tests/test_PR031_types_in_numba.py index 91facab142..32c8510ade 100644 --- a/tests/test_PR031_types_in_numba.py +++ b/tests/test_PR031_types_in_numba.py @@ -41,8 +41,8 @@ def test_pickle(): t = awkward1.layout.ListType(awkward1.layout.PrimitiveType("int32")); assert pickle.loads(pickle.dumps(t)) == t t = awkward1.layout.RegularType(awkward1.layout.PrimitiveType("int32"), 5); assert pickle.loads(pickle.dumps(t)) == t t = awkward1.layout.OptionType(awkward1.layout.PrimitiveType("int32")); assert pickle.loads(pickle.dumps(t)) == t - t = awkward1.layout.UnionType(awkward1.layout.PrimitiveType("int32"), awkward1.layout.PrimitiveType("float64")); assert pickle.loads(pickle.dumps(t)) == t - t = awkward1.layout.RecordType(one=awkward1.layout.PrimitiveType("int32"), two=awkward1.layout.PrimitiveType("float64")); assert pickle.loads(pickle.dumps(t)) == t + t = awkward1.layout.UnionType((awkward1.layout.PrimitiveType("int32"), awkward1.layout.PrimitiveType("float64"))); assert pickle.loads(pickle.dumps(t)) == t + t = awkward1.layout.RecordType({"one": awkward1.layout.PrimitiveType("int32"), "two": awkward1.layout.PrimitiveType("float64")}); assert pickle.loads(pickle.dumps(t)) == t def test_boxing(): @numba.njit @@ -89,11 +89,11 @@ def f2(q): f1(t) assert f2(t) == t - t = awkward1.layout.UnionType(awkward1.layout.PrimitiveType("int32"), awkward1.layout.PrimitiveType("float64")) + t = awkward1.layout.UnionType((awkward1.layout.PrimitiveType("int32"), awkward1.layout.PrimitiveType("float64"))) f1(t) assert f2(t) == t - t = awkward1.layout.RecordType(one=awkward1.layout.PrimitiveType("int32"), two=awkward1.layout.PrimitiveType("float64")) + t = awkward1.layout.RecordType({"one": awkward1.layout.PrimitiveType("int32"), "two": awkward1.layout.PrimitiveType("float64")}) f1(t) assert f2(t) == t @@ -104,7 +104,7 @@ def typestr(baretype, parameters): def test_numpyarray(): array1 = awkward1.layout.NumpyArray(numpy.arange(2*3*5, dtype=numpy.int64).reshape(2, 3, 5)) - dint64 = awkward1.layout.DressedType(awkward1.layout.PrimitiveType("int64"), D) + dint64 = awkward1.layout.PrimitiveType("int64", {"__class__": "D", "__str__": "D[int64]"}) array1.type = awkward1.layout.ArrayType(awkward1.layout.RegularType(awkward1.layout.RegularType(dint64, 5), 3), 2) @numba.njit @@ -121,7 +121,7 @@ def f1(q): def test_regulararray(): array1 = awkward1.layout.RegularArray(awkward1.layout.NumpyArray(numpy.arange(10, dtype=numpy.int64)), 5) - dregint64 = awkward1.layout.DressedType(awkward1.layout.RegularType(awkward1.layout.PrimitiveType("int64"), 5), D) + dregint64 = awkward1.layout.RegularType(awkward1.layout.PrimitiveType("int64"), 5, {"__class__": "D", "__str__": "D[5 * int64]"}) array1.type = awkward1.layout.ArrayType(dregint64, 2) @numba.njit @@ -135,7 +135,7 @@ def f1(q): def test_listoffsetarray(): array1 = awkward1.layout.ListOffsetArray64(awkward1.layout.Index64(numpy.array([0, 3, 3, 5], dtype=numpy.int64)), awkward1.layout.NumpyArray(numpy.array([1, 2, 3, 4, 5], dtype=numpy.int64))) - dvarint64 = awkward1.layout.DressedType(awkward1.layout.ListType(awkward1.layout.PrimitiveType("int64")), D) + dvarint64 = awkward1.layout.ListType(awkward1.layout.PrimitiveType("int64"), {"__class__": "D", "__str__": "D[var * int64]"}) array1.type = awkward1.layout.ArrayType(dvarint64, 3) @numba.njit @@ -149,7 +149,7 @@ def f1(q): def test_listarray(): array1 = awkward1.layout.ListArray64(awkward1.layout.Index64(numpy.array([0, 3, 3], dtype=numpy.int64)), awkward1.layout.Index64(numpy.array([3, 3, 5], dtype=numpy.int64)), awkward1.layout.NumpyArray(numpy.array([1, 2, 3, 4, 5], dtype=numpy.int64))) - dvarint64 = awkward1.layout.DressedType(awkward1.layout.ListType(awkward1.layout.PrimitiveType("int64")), D) + dvarint64 = awkward1.layout.ListType(awkward1.layout.PrimitiveType("int64"), {"__class__": "D", "__str__": "D[var * int64]"}) array1.type = awkward1.layout.ArrayType(dvarint64, 3) @numba.njit @@ -163,7 +163,7 @@ def f1(q): def test_recordarray(): array1 = awkward1.Array([{"one": 1, "two": 1.1}, {"one": 2, "two": 2.2}, {"one": 3, "two": 3.3}]).layout - dvarrec = awkward1.layout.DressedType(array1.type.nolength(), D) + dvarrec = awkward1.layout.RecordType({"one": awkward1.layout.PrimitiveType("int64"), "two": awkward1.layout.PrimitiveType("float64")}, {"__class__": "D", "__str__": "D[{\"one\": int64, \"two\": float64}]"}) array1.type = awkward1.layout.ArrayType(dvarrec, 3) @numba.njit @@ -172,8 +172,8 @@ def f1(q): array2 = f1(array1) - assert repr(array2.baretype) in ("3 * {'one': int64, 'two': float64}", "3 * {'two': float64, 'one': int64}") - assert repr(array2.type) in ("3 * D[{'one': int64, 'two': float64}]", "3 * D[{'two': float64, 'one': int64}]") + assert repr(array2.baretype) in ('3 * {"one": int64, "two": float64}', '3 * {"two": float64, "one": int64}') + assert repr(array2.type) in ('3 * D[{"one": int64, "two": float64}]', '3 * D[{"two": float64, "one": int64}]') - assert repr(array2[0].baretype) in ("{'one': int64, 'two': float64}", "{'two': float64, 'one': int64}") - assert repr(array2[0].type) in ("D[{'one': int64, 'two': float64}]", "D[{'two': float64, 'one': int64}]") + assert repr(array2[0].baretype) in ('{"one": int64, "two": float64}', '{"two": float64, "one": int64}') + assert repr(array2[0].type) in ('D[{"one": int64, "two": float64}]', 'D[{"two": float64, "one": int64}]') diff --git a/tests/test_PR032_replace_dressedtype.py b/tests/test_PR032_replace_dressedtype.py new file mode 100644 index 0000000000..93c2f7a450 --- /dev/null +++ b/tests/test_PR032_replace_dressedtype.py @@ -0,0 +1,231 @@ +# BSD 3-Clause License; see https://github.com/jpivarski/awkward-1.0/blob/master/LICENSE + +import sys +import itertools +import pickle + +import pytest +import numpy + +import awkward1 + +py27 = (sys.version_info[0] < 3) + +def test_types_with_parameters(): + t = awkward1.layout.UnknownType() + assert t.parameters == {} + t.parameters = {"key": ["val", "ue"]} + assert t.parameters == {"key": ["val", "ue"]} + t = awkward1.layout.UnknownType(parameters={"key": ["val", "ue"]}) + assert t.parameters == {"key": ["val", "ue"]} + + t = awkward1.layout.PrimitiveType("int32", parameters={"key": ["val", "ue"]}); assert t.parameters == {"key": ["val", "ue"]} + t = awkward1.layout.PrimitiveType("float64", parameters={"key": ["val", "ue"]}); assert t.parameters == {"key": ["val", "ue"]} + t = awkward1.layout.ArrayType(awkward1.layout.PrimitiveType("int32"), 100, parameters={"key": ["val", "ue"]}); assert t.parameters == {"key": ["val", "ue"]} + t = awkward1.layout.ListType(awkward1.layout.PrimitiveType("int32"), parameters={"key": ["val", "ue"]}); assert t.parameters == {"key": ["val", "ue"]} + t = awkward1.layout.RegularType(awkward1.layout.PrimitiveType("int32"), 5, parameters={"key": ["val", "ue"]}); assert t.parameters == {"key": ["val", "ue"]} + t = awkward1.layout.OptionType(awkward1.layout.PrimitiveType("int32"), parameters={"key": ["val", "ue"]}); assert t.parameters == {"key": ["val", "ue"]} + t = awkward1.layout.UnionType((awkward1.layout.PrimitiveType("int32"), awkward1.layout.PrimitiveType("float64")), parameters={"key": ["val", "ue"]}); assert t.parameters == {"key": ["val", "ue"]} + t = awkward1.layout.RecordType({"one": awkward1.layout.PrimitiveType("int32"), "two": awkward1.layout.PrimitiveType("float64")}, parameters={"key": ["val", "ue"]}); assert t.parameters == {"key": ["val", "ue"]} + + t = awkward1.layout.UnknownType(parameters={"key1": ["val", "ue"], "key2": u"one \u2192 two"}) + assert t.parameters == {"key2": u"one \u2192 two", "key1": ["val", "ue"]} + + assert t == awkward1.layout.UnknownType(parameters={"key2": u"one \u2192 two", "key1": ["val", "ue"]}) + assert t != awkward1.layout.UnknownType(parameters={"key": ["val", "ue"]}) + +def test_dress(): + class Dummy(awkward1.highlevel.Array): + def __repr__(self): + return "".format(str(self)) + ns = {"Dummy": Dummy} + + t = awkward1.layout.PrimitiveType("float64", {"__class__": "Dummy"}) + x = awkward1.layout.NumpyArray(numpy.array([1.1, 2.2, 3.3, 4.4, 5.5]), type=t) + a = awkward1.Array(x, namespace=ns) + assert repr(a) == "" + + x2 = awkward1.layout.ListOffsetArray64(awkward1.layout.Index64(numpy.array([0, 3, 3, 5], dtype=numpy.int64)), x) + a2 = awkward1.Array(x2, namespace=ns) + assert repr(a2) == ", ... ] type='3 * var * float64[parameters={\"__cl...'>" + assert repr(a2[0]) == "" + assert repr(a2[1]) == "" + assert repr(a2[2]) == "" + +def test_typestr(): + t = awkward1.layout.PrimitiveType("float64", {"__str__": "something"}) + t2 = awkward1.layout.ListType(t) + + assert repr(t) == "something" + assert repr(t2) == "var * something" + +def test_record_name(): + fillable = awkward1.FillableArray() + + fillable.beginrecord("Dummy") + fillable.field("one") + fillable.integer(1) + fillable.field("two") + fillable.real(1.1) + fillable.endrecord() + + fillable.beginrecord("Dummy") + fillable.field("two") + fillable.real(2.2) + fillable.field("one") + fillable.integer(2) + fillable.endrecord() + + a = fillable.snapshot() + assert repr(a.type) == '2 * struct[["one", "two"], [int64, float64], parameters={"__class__": "Dummy"}]' + assert a.type.nolength().parameters == {"__class__": "Dummy"} + +def test_fillable_string(): + fillable = awkward1.FillableArray() + + fillable.bytestring(b"one") + fillable.bytestring(b"two") + fillable.bytestring(b"three") + + a = fillable.snapshot() + if py27: + assert str(a) == "['one', 'two', 'three']" + else: + assert str(a) == "[b'one', b'two', b'three']" + assert awkward1.tolist(a) == [b'one', b'two', b'three'] + assert awkward1.tojson(a) == '["one","two","three"]' + if py27: + assert repr(a) == "" + else: + assert repr(a) == "" + assert repr(a.type) == "3 * bytes" + + fillable = awkward1.FillableArray() + + fillable.string("one") + fillable.string("two") + fillable.string("three") + + a = fillable.snapshot() + if py27: + assert str(a) == "[u'one', u'two', u'three']" + else: + assert str(a) == "['one', 'two', 'three']" + assert awkward1.tolist(a) == ['one', 'two', 'three'] + assert awkward1.tojson(a) == '["one","two","three"]' + if py27: + assert repr(a) == "" + else: + assert repr(a) == "" + assert repr(a.type) == "3 * string" + + fillable = awkward1.FillableArray() + + fillable.beginlist() + fillable.string("one") + fillable.string("two") + fillable.string("three") + fillable.endlist() + + fillable.beginlist() + fillable.endlist() + + fillable.beginlist() + fillable.string("four") + fillable.string("five") + fillable.endlist() + + a = fillable.snapshot() + if py27: + assert str(a) == "[[u'one', u'two', u'three'], [], [u'four', u'five']]" + else: + assert str(a) == "[['one', 'two', 'three'], [], ['four', 'five']]" + assert awkward1.tolist(a) == [['one', 'two', 'three'], [], ['four', 'five']] + assert awkward1.tojson(a) == '[["one","two","three"],[],["four","five"]]' + assert repr(a.type) == "3 * var * string" + +def test_fromiter_fromjson(): + assert awkward1.tolist(awkward1.fromiter(["one", "two", "three"])) == ["one", "two", "three"] + assert awkward1.tolist(awkward1.fromiter([["one", "two", "three"], [], ["four", "five"]])) == [["one", "two", "three"], [], ["four", "five"]] + + assert awkward1.tolist(awkward1.fromjson('["one", "two", "three"]')) == ["one", "two", "three"] + assert awkward1.tolist(awkward1.fromjson('[["one", "two", "three"], [], ["four", "five"]]')) == [["one", "two", "three"], [], ["four", "five"]] + +numba = pytest.importorskip("numba") + +def test_record_name_numba(): + @numba.njit + def f1(fillable): + fillable.beginrecord("Dummy") + fillable.field("one") + fillable.integer(1) + fillable.field("two") + fillable.real(1.1) + fillable.endrecord() + + fillable.beginrecord("Dummy") + fillable.field("two") + fillable.real(2.2) + fillable.field("one") + fillable.integer(2) + fillable.endrecord() + + fillable = awkward1.layout.FillableArray() + f1(fillable) + + a = fillable.snapshot() + assert repr(a.type) == '2 * struct[["one", "two"], [int64, float64], parameters={"__class__": "Dummy"}]' + assert a.type.nolength().parameters == {"__class__": "Dummy"} + +def test_boxing(): + @numba.njit + def f1(q): + return 3.14 + + @numba.njit + def f2(q): + return q + + t = awkward1.layout.UnknownType(parameters={"one": 1, "two": 2}) + f1(t) + assert f2(t) == t + + t = awkward1.layout.PrimitiveType("int32", parameters={"one": 1, "two": 2}) + f1(t) + assert f2(t) == t + + t = awkward1.layout.PrimitiveType("float64", parameters={"one": 1, "two": 2}) + f1(t) + assert f2(t) == t + + t = awkward1.layout.ListType(awkward1.layout.ListType(awkward1.layout.PrimitiveType("int32"), parameters={"one": 1, "two": 2})) + f1(t) + assert f2(t) == t + + t = awkward1.layout.ListType(awkward1.layout.ListType(awkward1.layout.PrimitiveType("int32")), parameters={"one": 1, "two": 2}) + f1(t) + assert f2(t) == t + + t = awkward1.layout.RegularType(awkward1.layout.ListType(awkward1.layout.PrimitiveType("int32")), 5, parameters={"one": 1, "two": 2}) + f1(t) + assert f2(t) == t + + t = awkward1.layout.OptionType(awkward1.layout.PrimitiveType("int32"), parameters={"one": 1, "two": 2}) + f1(t) + assert f2(t) == t + + t = awkward1.layout.OptionType(awkward1.layout.ListType(awkward1.layout.PrimitiveType("int32")), parameters={"one": 1, "two": 2}) + f1(t) + assert f2(t) == t + + t = awkward1.layout.UnionType((awkward1.layout.PrimitiveType("int32"), awkward1.layout.PrimitiveType("float64")), parameters={"one": 1, "two": 2}) + f1(t) + assert f2(t) == t + + t = awkward1.layout.RecordType((awkward1.layout.PrimitiveType("int32"), awkward1.layout.PrimitiveType("float64")), parameters={"one": 1, "two": 2}) + f1(t) + assert f2(t) == t + + t = awkward1.layout.RecordType({"one": awkward1.layout.PrimitiveType("int32"), "two": awkward1.layout.PrimitiveType("float64")}, parameters={"one": 1, "two": 2}) + f1(t) + assert f2(t) == t