Skip to content

Commit 214168e

Browse files
committed
Add test for std::optional
Closes #15
1 parent ce8a39a commit 214168e

File tree

4 files changed

+241
-0
lines changed

4 files changed

+241
-0
lines changed

types/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Types
22

33
* [`fundamental`](fundamental): fundamental column types
4+
* [`optional`](optional): `std::optional` with different element types
45
* [`string`](string): `std::string` with all `[Split]Index{32,64}` column types
56
* [`variant`](variant): `std::variant` with `Switch` column type
67
* [`vector`](vector): `std::vector` with all `[Split]Index{32,64}` column types

types/optional/README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# `std::optional`
2+
3+
## Fields
4+
5+
* `[Split]Index{32,64}`: `std::optional<std::int32_t>`
6+
* with the corresponding column type for the first (principal) column
7+
* `String`: `std::optional<std::string>`
8+
* `Variant`: `std::optional<std::variant<std::int32_t, std::string>>`
9+
* `VectorInt32`: `std::optional<std::vector<std::int32_t>>`
10+
* `VectorOpt`: `std::vector<std::optional<std::int32_t>>>`
11+
12+
with otherwise the default column types.
13+
14+
## Entries
15+
16+
1. Simple values
17+
2. No value
18+
3. Zero / empty values

types/optional/read.C

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
#include <ROOT/REntry.hxx>
2+
#include <ROOT/RNTupleReader.hxx>
3+
4+
using ROOT::Experimental::REntry;
5+
using ROOT::Experimental::RNTupleReader;
6+
7+
#include <cstdint>
8+
#include <fstream>
9+
#include <optional>
10+
#include <ostream>
11+
#include <string>
12+
#include <string_view>
13+
#include <variant>
14+
#include <vector>
15+
16+
using VariantTy = std::variant<std::int32_t, std::string>;
17+
using VectorInt32Ty = std::vector<std::int32_t>;
18+
19+
template <typename T> static void PrintValue(const T &value, std::ostream &os);
20+
21+
template <> void PrintValue(const std::int32_t &value, std::ostream &os) {
22+
os << value;
23+
}
24+
25+
template <> void PrintValue(const std::string &value, std::ostream &os) {
26+
os << "\"" << value << "\"";
27+
}
28+
29+
template <> void PrintValue(const VariantTy &value, std::ostream &os) {
30+
if (value.index() == 0) {
31+
PrintValue(std::get<std::int32_t>(value), os);
32+
} else if (value.index() == 1) {
33+
PrintValue(std::get<std::string>(value), os);
34+
}
35+
}
36+
37+
template <> void PrintValue(const VectorInt32Ty &value, std::ostream &os) {
38+
os << "[";
39+
bool first = true;
40+
for (auto element : value) {
41+
if (first) {
42+
first = false;
43+
} else {
44+
os << ",";
45+
}
46+
os << "\n " << element;
47+
}
48+
if (!value.empty()) {
49+
os << "\n ";
50+
}
51+
os << "]";
52+
}
53+
54+
template <typename T>
55+
static void PrintOptionalValue(const REntry &entry, std::string_view name,
56+
std::ostream &os, bool last = false) {
57+
auto &value = *entry.GetPtr<std::optional<T>>(name);
58+
os << " \"" << name << "\": ";
59+
if (!value.has_value()) {
60+
os << "null";
61+
} else {
62+
PrintValue(*value, os);
63+
}
64+
if (!last) {
65+
os << ",";
66+
}
67+
os << "\n";
68+
}
69+
70+
static void PrintVectorOptValue(const REntry &entry, std::string_view name,
71+
std::ostream &os, bool last = false) {
72+
auto &value = *entry.GetPtr<std::vector<std::optional<std::int32_t>>>(name);
73+
os << " \"" << name << "\": [";
74+
bool first = true;
75+
for (auto &&element : value) {
76+
if (first) {
77+
first = false;
78+
} else {
79+
os << ",";
80+
}
81+
os << "\n ";
82+
if (!element.has_value()) {
83+
os << "null";
84+
} else {
85+
os << *element;
86+
}
87+
}
88+
if (!value.empty()) {
89+
os << "\n ";
90+
}
91+
os << "]";
92+
if (!last) {
93+
os << ",";
94+
}
95+
os << "\n";
96+
}
97+
98+
void read(std::string_view input = "types.optional.root",
99+
std::string_view output = "types.optional.json") {
100+
std::ofstream os(std::string{output});
101+
os << "[\n";
102+
103+
auto reader = RNTupleReader::Open("ntpl", input);
104+
auto &entry = reader->GetModel().GetDefaultEntry();
105+
bool first = true;
106+
for (auto index : *reader) {
107+
reader->LoadEntry(index);
108+
109+
if (first) {
110+
first = false;
111+
} else {
112+
os << ",\n";
113+
}
114+
os << " {\n";
115+
116+
PrintOptionalValue<std::int32_t>(entry, "Index32", os);
117+
PrintOptionalValue<std::int32_t>(entry, "Index64", os);
118+
PrintOptionalValue<std::int32_t>(entry, "SplitIndex32", os);
119+
PrintOptionalValue<std::int32_t>(entry, "SplitIndex64", os);
120+
PrintOptionalValue<std::string>(entry, "String", os);
121+
PrintOptionalValue<VariantTy>(entry, "Variant", os);
122+
PrintOptionalValue<VectorInt32Ty>(entry, "VectorInt32", os);
123+
PrintVectorOptValue(entry, "VectorOpt", os, /*last=*/true);
124+
125+
os << " }";
126+
// Newline is intentionally missing, may need to print a comma before the
127+
// next entry.
128+
}
129+
os << "\n";
130+
os << "]\n";
131+
}

types/optional/write.C

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
#include <ROOT/RField.hxx>
2+
#include <ROOT/RNTupleModel.hxx>
3+
#include <ROOT/RNTupleUtil.hxx>
4+
#include <ROOT/RNTupleWriteOptions.hxx>
5+
#include <ROOT/RNTupleWriter.hxx>
6+
7+
using ROOT::Experimental::EColumnType;
8+
using ROOT::Experimental::RField;
9+
using ROOT::Experimental::RNTupleModel;
10+
using ROOT::Experimental::RNTupleWriteOptions;
11+
using ROOT::Experimental::RNTupleWriter;
12+
13+
#include <cstdint>
14+
#include <memory>
15+
#include <optional>
16+
#include <string>
17+
#include <string_view>
18+
#include <variant>
19+
#include <vector>
20+
21+
using OptInt32Ty = std::optional<std::int32_t>;
22+
using VariantTy = std::variant<std::int32_t, std::string>;
23+
using VectorInt32Ty = std::vector<std::int32_t>;
24+
25+
static std::shared_ptr<OptInt32Ty> MakeIntField(RNTupleModel &model,
26+
std::string_view name,
27+
EColumnType indexType) {
28+
auto field = std::make_unique<RField<OptInt32Ty>>(name);
29+
field->SetColumnRepresentatives({{indexType}});
30+
model.AddField(std::move(field));
31+
return model.GetDefaultEntry().GetPtr<OptInt32Ty>(name);
32+
}
33+
34+
void write(std::string_view filename = "types.optional.root") {
35+
auto model = RNTupleModel::Create();
36+
37+
// Non-split index encoding
38+
auto Index32 = MakeIntField(*model, "Index32", EColumnType::kIndex32);
39+
auto Index64 = MakeIntField(*model, "Index64", EColumnType::kIndex64);
40+
41+
// Split index encoding
42+
auto SplitIndex32 =
43+
MakeIntField(*model, "SplitIndex32", EColumnType::kSplitIndex32);
44+
auto SplitIndex64 =
45+
MakeIntField(*model, "SplitIndex64", EColumnType::kSplitIndex64);
46+
47+
auto String = model->MakeField<std::optional<std::string>>("String");
48+
auto Variant = model->MakeField<std::optional<VariantTy>>("Variant");
49+
auto VectorInt32 =
50+
model->MakeField<std::optional<VectorInt32Ty>>("VectorInt32");
51+
auto VectorOpt =
52+
model->MakeField<std::vector<std::optional<std::int32_t>>>("VectorOpt");
53+
54+
RNTupleWriteOptions options;
55+
options.SetCompression(0);
56+
auto writer =
57+
RNTupleWriter::Recreate(std::move(model), "ntpl", filename, options);
58+
59+
// First entry: simple values
60+
*Index32 = 1;
61+
*Index64 = 2;
62+
*SplitIndex32 = 3;
63+
*SplitIndex64 = 4;
64+
*String = "abc";
65+
*Variant = "def";
66+
*VectorInt32 = {1, 2, 3};
67+
*VectorOpt = {4, 5, 6};
68+
writer->Fill();
69+
70+
// Second entry: no value
71+
Index32->reset();
72+
Index64->reset();
73+
SplitIndex32->reset();
74+
SplitIndex64->reset();
75+
String->reset();
76+
Variant->reset();
77+
VectorInt32->reset();
78+
*VectorOpt = {{}};
79+
writer->Fill();
80+
81+
// Third entry: zero / empty value
82+
*Index32 = 0;
83+
*Index64 = 0;
84+
*SplitIndex32 = 0;
85+
*SplitIndex64 = 0;
86+
*String = "";
87+
*Variant = 0;
88+
*VectorInt32 = VectorInt32Ty{};
89+
*VectorOpt = {};
90+
writer->Fill();
91+
}

0 commit comments

Comments
 (0)