diff --git a/types/README.md b/types/README.md index 3b76e6a..0c6525a 100644 --- a/types/README.md +++ b/types/README.md @@ -1,5 +1,8 @@ # Types + * [`array`](array): `std::array` + * [`atomic`](atomic): `std::atomic` + * [`bitset`](bitset): `std::bitset` * [`fundamental`](fundamental): fundamental column types * [`multiset`](multiset): `std::multiset` with all `[Split]Index{32,64}` column types * [`optional`](optional): `std::optional` with different element types diff --git a/types/array/README.md b/types/array/README.md new file mode 100644 index 0000000..2ab1c16 --- /dev/null +++ b/types/array/README.md @@ -0,0 +1,16 @@ +# `std::array` + +## Fields + + * `Array_Int32`: `std::array` + * `Array_Array`: `std::array, 3>>` + * `Array_String`: `std::array` + * `Array_Variant`: `std::array, 2>` + * `Array_Vector`: `std::array, 2>` + +with the default column types. + +## Entries + +1. Simple values +2. Zero / empty values diff --git a/types/array/read.C b/types/array/read.C new file mode 100644 index 0000000..6c0a72a --- /dev/null +++ b/types/array/read.C @@ -0,0 +1,140 @@ +#include +#include + +using ROOT::Experimental::REntry; +using ROOT::Experimental::RNTupleReader; + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using ArrayInt32 = std::array; +using Variant = std::variant; +using VectorInt32 = std::vector; + +template static void PrintValue(const T &value, std::ostream &os); + +template <> void PrintValue(const std::int32_t &value, std::ostream &os) { + os << value; +} + +template <> void PrintValue(const std::string &value, std::ostream &os) { + os << "\"" << value << "\""; +} + +template <> void PrintValue(const Variant &value, std::ostream &os) { + if (value.index() == 0) { + PrintValue(std::get(value), os); + } else if (value.index() == 1) { + PrintValue(std::get(value), os); + } +} + +template <> void PrintValue(const VectorInt32 &value, std::ostream &os) { + os << "["; + bool first = true; + for (auto element : value) { + if (first) { + first = false; + } else { + os << ","; + } + os << "\n " << element; + } + if (!value.empty()) { + os << "\n "; + } + os << "]"; +} + +template +static void PrintArrayValue(const REntry &entry, std::string_view name, + std::ostream &os, bool last = false) { + auto &value = *entry.GetPtr>(name); + os << " \"" << name << "\": ["; + bool first = true; + for (auto &&element : value) { + if (first) { + first = false; + } else { + os << ","; + } + os << "\n "; + PrintValue(element, os); + } + os << "\n"; + os << " ]"; + if (!last) { + os << ","; + } + os << "\n"; +} + +static void PrintArrayArrayValue(const REntry &entry, std::string_view name, + std::ostream &os, bool last = false) { + auto &value = *entry.GetPtr, 3>>(name); + os << " \"" << name << "\": ["; + bool first = true; + for (auto &&element : value) { + if (first) { + first = false; + } else { + os << ","; + } + os << "\n ["; + bool innerFirst = true; + for (auto &&i : element) { + if (innerFirst) { + innerFirst = false; + } else { + os << ","; + } + os << "\n " << i; + } + os << "\n ]"; + } + os << "\n"; + os << " ]"; + if (!last) { + os << ","; + } + os << "\n"; +} + +void read(std::string_view input = "types.array.root", + std::string_view output = "types.array.json") { + std::ofstream os(std::string{output}); + os << "[\n"; + + auto reader = RNTupleReader::Open("ntpl", input); + auto &entry = reader->GetModel().GetDefaultEntry(); + bool first = true; + for (auto index : *reader) { + reader->LoadEntry(index); + + if (first) { + first = false; + } else { + os << ",\n"; + } + os << " {\n"; + + PrintArrayValue(entry, "Array_Int32", os); + PrintArrayArrayValue(entry, "Array_Array", os); + PrintArrayValue(entry, "Array_String", os); + PrintArrayValue(entry, "Array_Variant", os); + PrintArrayValue(entry, "Array_Vector", os, /*last=*/true); + + os << " }"; + // Newline is intentionally missing, may need to print a comma before the + // next entry. + } + os << "\n"; + os << "]\n"; +} diff --git a/types/array/write.C b/types/array/write.C new file mode 100644 index 0000000..68be78d --- /dev/null +++ b/types/array/write.C @@ -0,0 +1,54 @@ +#include +#include +#include + +using ROOT::Experimental::RNTupleModel; +using ROOT::Experimental::RNTupleWriteOptions; +using ROOT::Experimental::RNTupleWriter; + +#include +#include +#include +#include +#include +#include +#include +#include + +using ArrayInt32 = std::array; +using Variant = std::variant; +using VectorInt32 = std::vector; + +void write(std::string_view filename = "types.array.root") { + auto model = RNTupleModel::Create(); + + auto Array_Int32 = model->MakeField("Array_Int32"); + auto Array_Array = model->MakeField>("Array_Array"); + auto Array_String = + model->MakeField>("Array_String"); + auto Array_Variant = + model->MakeField>("Array_Variant"); + auto Array_Vector = + model->MakeField>("Array_Vector"); + + RNTupleWriteOptions options; + options.SetCompression(0); + auto writer = + RNTupleWriter::Recreate(std::move(model), "ntpl", filename, options); + + // First entry: simple values + *Array_Int32 = {1, 2}; + *Array_Array = {ArrayInt32{3, 4}, ArrayInt32{5, 6}, ArrayInt32{7, 8}}; + *Array_String = {"ijk", "lmn"}; + *Array_Vector = {VectorInt32{15, 16, 17}, VectorInt32{17, 18}}; + *Array_Variant = {19, "uvw"}; + writer->Fill(); + + // Second entry: zero / empty values + *Array_Int32 = {0, 0}; + *Array_Array = {ArrayInt32{0, 0}, ArrayInt32{0, 0}, ArrayInt32{0, 0}}; + *Array_String = {"", ""}; + *Array_Vector = {VectorInt32{}, VectorInt32{}}; + *Array_Variant = {0, ""}; + writer->Fill(); +} diff --git a/types/atomic/README.md b/types/atomic/README.md new file mode 100644 index 0000000..ee0f9bf --- /dev/null +++ b/types/atomic/README.md @@ -0,0 +1,16 @@ +# `std::atomic` + +## Fields + + * `Bit` + * `Byte` + * `Char` + * `[U]Int{8,16,32,64}` + * `Real{32,64}` + +with the corresponding column types. + +## Entries + +1. Ascending values +2. Zero values diff --git a/types/atomic/read.C b/types/atomic/read.C new file mode 100644 index 0000000..4cafc1c --- /dev/null +++ b/types/atomic/read.C @@ -0,0 +1,82 @@ +#include +#include + +using ROOT::Experimental::REntry; +using ROOT::Experimental::RNTupleReader; + +#include +#include // for std::byte +#include +#include +#include +#include +#include + +template +static void PrintIntegerValue(const REntry &entry, std::string_view name, + std::ostream &os, bool last = false) { + T value = *entry.GetPtr>(name); + os << " \"" << name << "\": "; + // We want to print the integer value even if it is a character; use the unary + // + operator (https://stackoverflow.com/a/28414758). + os << +value; + if (!last) { + os << ","; + } + os << "\n"; +} + +template +static void PrintRealValue(const REntry &entry, std::string_view name, + std::ostream &os, bool last = false) { + T value = *entry.GetPtr>(name); + os << " \"" << name << "\": \"" << value << "\""; + if (!last) { + os << ","; + } + os << "\n"; +} + +void read(std::string_view input = "types.atomic.root", + std::string_view output = "types.atomic.json") { + std::ofstream os(std::string{output}); + // Print floating-point numbers as hexadecimal literals. + os << std::hexfloat; + os << "[\n"; + + auto reader = RNTupleReader::Open("ntpl", input); + auto &entry = reader->GetModel().GetDefaultEntry(); + bool first = true; + for (auto index : *reader) { + reader->LoadEntry(index); + + if (first) { + first = false; + } else { + os << ",\n"; + } + os << " {\n"; + + PrintIntegerValue(entry, "Bit", os); + os << " \"Byte\": "; + os << std::to_integer(*entry.GetPtr>("Byte")); + os << ",\n"; + PrintIntegerValue(entry, "Char", os); + PrintIntegerValue(entry, "Int8", os); + PrintIntegerValue(entry, "UInt8", os); + PrintIntegerValue(entry, "Int16", os); + PrintIntegerValue(entry, "UInt16", os); + PrintIntegerValue(entry, "Int32", os); + PrintIntegerValue(entry, "UInt32", os); + PrintIntegerValue(entry, "Int64", os); + PrintIntegerValue(entry, "UInt64", os); + PrintRealValue(entry, "Real32", os); + PrintRealValue(entry, "Real64", os, /*last=*/true); + + os << " }"; + // Newline is intentionally missing, may need to print a comma before the + // next entry. + } + os << "\n"; + os << "]\n"; +} diff --git a/types/atomic/write.C b/types/atomic/write.C new file mode 100644 index 0000000..aaaab14 --- /dev/null +++ b/types/atomic/write.C @@ -0,0 +1,76 @@ +#include +#include +#include + +using ROOT::Experimental::RNTupleModel; +using ROOT::Experimental::RNTupleWriteOptions; +using ROOT::Experimental::RNTupleWriter; + +#include +#include // for std::byte +#include +#include +#include + +template +static std::shared_ptr> MakeAtomicField(RNTupleModel &model, + std::string_view name) { + return model.MakeField>(name); +} + +void write(std::string_view filename = "types.atomic.root") { + auto model = RNTupleModel::Create(); + + auto Bit = MakeAtomicField(*model, "Bit"); + auto Byte = MakeAtomicField(*model, "Byte"); + auto Char = MakeAtomicField(*model, "Char"); + + auto Int8 = MakeAtomicField(*model, "Int8"); + auto UInt8 = MakeAtomicField(*model, "UInt8"); + auto Int16 = MakeAtomicField(*model, "Int16"); + auto UInt16 = MakeAtomicField(*model, "UInt16"); + auto Int32 = MakeAtomicField(*model, "Int32"); + auto UInt32 = MakeAtomicField(*model, "UInt32"); + auto Int64 = MakeAtomicField(*model, "Int64"); + auto UInt64 = MakeAtomicField(*model, "UInt64"); + + auto Real32 = MakeAtomicField(*model, "Real32"); + auto Real64 = MakeAtomicField(*model, "Real64"); + + RNTupleWriteOptions options; + options.SetCompression(0); + auto writer = + RNTupleWriter::Recreate(std::move(model), "ntpl", filename, options); + + // First entry: ascending values + *Bit = 1; + *Byte = std::byte{2}; + *Char = 3; + *Int8 = 4; + *UInt8 = 5; + *Int16 = 6; + *UInt16 = 7; + *Int32 = 8; + *UInt32 = 9; + *Int64 = 10; + *UInt64 = 11; + *Real32 = 12.0f; + *Real64 = 13.0; + writer->Fill(); + + // Second entry: zero values + *Bit = 0; + *Byte = std::byte{0}; + *Char = 0; + *Int8 = 0; + *UInt8 = 0; + *Int16 = 0; + *UInt16 = 0; + *Int32 = 0; + *UInt32 = 0; + *Int64 = 0; + *UInt64 = 0; + *Real32 = 0; + *Real64 = 0; + writer->Fill(); +} diff --git a/types/bitset/README.md b/types/bitset/README.md new file mode 100644 index 0000000..90a99b7 --- /dev/null +++ b/types/bitset/README.md @@ -0,0 +1,15 @@ +# `std::bitset` + +## Fields + + * `Bitset1`: `std::bitset<1>` + * `Bitset64`: `std::bitset<64>` + * `Bitset65`: `std::bitset<65>` + +with the default column types. + +## Entries + +1. Ascending bits set +2. All bits set +3. All bits unset diff --git a/types/bitset/read.C b/types/bitset/read.C new file mode 100644 index 0000000..2000714 --- /dev/null +++ b/types/bitset/read.C @@ -0,0 +1,53 @@ +#include +#include + +using ROOT::Experimental::REntry; +using ROOT::Experimental::RNTupleReader; + +#include +#include +#include +#include +#include +#include + +template +static void PrintBitsetValue(const REntry &entry, std::string_view name, + std::ostream &os, bool last = false) { + auto &value = *entry.GetPtr>(name); + os << " \"" << name << "\": \"" << value.to_string() << "\""; + if (!last) { + os << ","; + } + os << "\n"; +} + +void read(std::string_view input = "types.bitset.root", + std::string_view output = "types.bitset.json") { + std::ofstream os(std::string{output}); + os << "[\n"; + + auto reader = RNTupleReader::Open("ntpl", input); + auto &entry = reader->GetModel().GetDefaultEntry(); + bool first = true; + for (auto index : *reader) { + reader->LoadEntry(index); + + if (first) { + first = false; + } else { + os << ",\n"; + } + os << " {\n"; + + PrintBitsetValue<1>(entry, "Bitset1", os); + PrintBitsetValue<64>(entry, "Bitset64", os); + PrintBitsetValue<65>(entry, "Bitset65", os, /*last=*/true); + + os << " }"; + // Newline is intentionally missing, may need to print a comma before the + // next entry. + } + os << "\n"; + os << "]\n"; +} diff --git a/types/bitset/write.C b/types/bitset/write.C new file mode 100644 index 0000000..3e81e23 --- /dev/null +++ b/types/bitset/write.C @@ -0,0 +1,42 @@ +#include +#include +#include + +using ROOT::Experimental::RNTupleModel; +using ROOT::Experimental::RNTupleWriteOptions; +using ROOT::Experimental::RNTupleWriter; + +#include +#include +#include + +void write(std::string_view filename = "types.bitset.root") { + auto model = RNTupleModel::Create(); + + auto Bitset1 = model->MakeField>("Bitset1"); + auto Bitset64 = model->MakeField>("Bitset64"); + auto Bitset65 = model->MakeField>("Bitset65"); + + RNTupleWriteOptions options; + options.SetCompression(0); + auto writer = + RNTupleWriter::Recreate(std::move(model), "ntpl", filename, options); + + // First entry: ascending bits set + Bitset1->set(0); + Bitset64->set(1); + Bitset65->set(2); + writer->Fill(); + + // Second entry: all bits set + Bitset1->set(); + Bitset64->set(); + Bitset65->set(); + writer->Fill(); + + // Third entry: no bits set + Bitset1->reset(); + Bitset64->reset(); + Bitset65->reset(); + writer->Fill(); +}