Skip to content

Commit e390940

Browse files
committed
Add test for std::set
1 parent a91c84c commit e390940

File tree

12 files changed

+375
-0
lines changed

12 files changed

+375
-0
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
*.json
22
*.root
3+
4+
# Ignore files related to dictionary generation
5+
*.pcm
6+
Nested*.cxx

types/README.md

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

33
* [`fundamental`](fundamental): fundamental column types
44
* [`optional`](optional): `std::optional` with different element types
5+
* [`set`](set): `std::set` with all `[Split]Index{32,64}` column types
56
* [`string`](string): `std::string` with all `[Split]Index{32,64}` column types
67
* [`unique_ptr`](unique_ptr): `std::unique_ptr` with different element types
78
* [`variant`](variant): `std::variant` with `Switch` column type

types/set/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# `std::set`
2+
3+
* [`fundamental`](fundamental): `std::set<std::int32_t>`
4+
* [`nested`](nested): `std::set<std::set<std::int32_t>>`

types/set/fundamental/README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# `std::set<std::int32_t>`
2+
3+
## Fields
4+
5+
* `[Split]Index{32,64}`
6+
7+
with the corresponding column type for the offset column of the collection parent field.
8+
All child fields use the default column encoding `Int32`.
9+
10+
## Entries
11+
12+
1. Single-element sets, with ascending values
13+
2. Empty sets
14+
3. Increasing number of elements in the set:
15+
one element in the first field, two elements in the second field, etc.

types/set/fundamental/read.C

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
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 <ostream>
10+
#include <set>
11+
#include <string>
12+
#include <string_view>
13+
14+
using Set = std::set<std::int32_t>;
15+
16+
static void PrintSetValue(const REntry &entry, std::string_view name,
17+
std::ostream &os, bool last = false) {
18+
Set &value = *entry.GetPtr<Set>(name);
19+
os << " \"" << name << "\": [";
20+
bool first = true;
21+
for (auto element : value) {
22+
if (first) {
23+
first = false;
24+
} else {
25+
os << ",";
26+
}
27+
os << "\n " << element;
28+
}
29+
if (!value.empty()) {
30+
os << "\n ";
31+
}
32+
os << "]";
33+
if (!last) {
34+
os << ",";
35+
}
36+
os << "\n";
37+
}
38+
39+
void read(std::string_view input = "types.set.fundamental.root",
40+
std::string_view output = "types.set.fundamental.json") {
41+
std::ofstream os(std::string{output});
42+
os << "[\n";
43+
44+
auto reader = RNTupleReader::Open("ntpl", input);
45+
auto &entry = reader->GetModel().GetDefaultEntry();
46+
bool first = true;
47+
for (auto index : *reader) {
48+
reader->LoadEntry(index);
49+
50+
if (first) {
51+
first = false;
52+
} else {
53+
os << ",\n";
54+
}
55+
os << " {\n";
56+
57+
PrintSetValue(entry, "Index32", os);
58+
PrintSetValue(entry, "Index64", os);
59+
PrintSetValue(entry, "SplitIndex32", os);
60+
PrintSetValue(entry, "SplitIndex64", os, /*last=*/true);
61+
62+
os << " }";
63+
// Newline is intentionally missing, may need to print a comma before the
64+
// next entry.
65+
}
66+
os << "\n";
67+
os << "]\n";
68+
}

types/set/fundamental/write.C

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
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 <set>
16+
#include <string_view>
17+
18+
using Set = std::set<std::int32_t>;
19+
20+
static std::shared_ptr<Set> MakeSetField(RNTupleModel &model,
21+
std::string_view name,
22+
EColumnType indexType) {
23+
auto field = std::make_unique<RField<Set>>(name);
24+
field->SetColumnRepresentatives({{indexType}});
25+
model.AddField(std::move(field));
26+
return model.GetDefaultEntry().GetPtr<Set>(name);
27+
}
28+
29+
void write(std::string_view filename = "types.set.fundamental.root") {
30+
auto model = RNTupleModel::Create();
31+
32+
// Non-split index encoding
33+
auto Index32 = MakeSetField(*model, "Index32", EColumnType::kIndex32);
34+
auto Index64 = MakeSetField(*model, "Index64", EColumnType::kIndex64);
35+
36+
// Split index encoding
37+
auto SplitIndex32 =
38+
MakeSetField(*model, "SplitIndex32", EColumnType::kSplitIndex32);
39+
auto SplitIndex64 =
40+
MakeSetField(*model, "SplitIndex64", EColumnType::kSplitIndex64);
41+
42+
RNTupleWriteOptions options;
43+
options.SetCompression(0);
44+
auto writer =
45+
RNTupleWriter::Recreate(std::move(model), "ntpl", filename, options);
46+
47+
// First entry: single-element sets, with ascending values
48+
*Index32 = {1};
49+
*Index64 = {2};
50+
*SplitIndex32 = {3};
51+
*SplitIndex64 = {4};
52+
writer->Fill();
53+
54+
// Second entry: empty sets
55+
*Index32 = {};
56+
*Index64 = {};
57+
*SplitIndex32 = {};
58+
*SplitIndex64 = {};
59+
writer->Fill();
60+
61+
// Third entry: increasing number of elements in the set
62+
*Index32 = {1};
63+
*Index64 = {2, 3};
64+
*SplitIndex32 = {4, 5, 6};
65+
*SplitIndex64 = {7, 8, 9, 10};
66+
writer->Fill();
67+
}

types/set/nested/LinkDef.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#include <cstdint>
2+
#include <set>
3+
4+
#ifdef __CLING__
5+
#pragma link C++ class std::set<std::set<std::int32_t>>+;
6+
#endif

types/set/nested/Makefile

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
CXX=g++
2+
CXXFLAGS_ROOT=$(shell root-config --cflags)
3+
ifeq ($(CXXFLAGS_ROOT),)
4+
$(error cannot find root-config: make sure to source thisroot.sh)
5+
endif
6+
CXXFLAGS=-Wall $(CXXFLAGS_ROOT)
7+
LDFLAGS=$(shell root-config --libs)
8+
9+
.PHONY: all clean
10+
11+
all: NestedSet.cxx libNestedSet.so
12+
13+
NestedSet.cxx: NestedSet.hxx LinkDef.h
14+
rootcling -f $@ $^
15+
16+
libNestedSet.so: NestedSet.cxx
17+
$(CXX) -shared -fPIC -o $@ $^ $(CXXFLAGS) $(LDFLAGS)
18+
19+
clean:
20+
rm -f NestedSet.cxx NestedSet_rdict.pcm libNestedSet.so

types/set/nested/NestedSet.hxx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#pragma once
2+
3+
#include <cstdint>
4+
#include <set>

types/set/nested/README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# `std::set<std::set<std::int32_t>>`
2+
3+
## Fields
4+
5+
* `[Split]Index{32,64}`
6+
7+
with the corresponding column type for the offset column of the two collection parent fields.
8+
All child fields use the default column encoding `Int32`.
9+
10+
## Entries
11+
12+
1. Single-element sets, with ascending values
13+
2. Empty sets
14+
3. Increasing number of elements in the outer set, with arbitrary lengths of the inner sets
15+
16+
## Dictionaries
17+
18+
These tests require ROOT dictionaries, which can be generated with the provided `Makefile` in this directory. This will create a `libNestedSet` shared object.

types/set/nested/read.C

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#include <ROOT/REntry.hxx>
2+
#include <ROOT/RNTupleReader.hxx>
3+
4+
using ROOT::Experimental::REntry;
5+
using ROOT::Experimental::RNTupleReader;
6+
7+
#include <TSystem.h>
8+
9+
#include <cstdint>
10+
#include <filesystem>
11+
#include <fstream>
12+
#include <ostream>
13+
#include <set>
14+
#include <string>
15+
#include <string_view>
16+
17+
using Set = std::set<std::set<std::int32_t>>;
18+
19+
static void PrintNestedSetValue(const REntry &entry, std::string_view name,
20+
std::ostream &os, bool last = false) {
21+
Set &value = *entry.GetPtr<Set>(name);
22+
os << " \"" << name << "\": [";
23+
bool outerFirst = true;
24+
for (auto inner : value) {
25+
if (outerFirst) {
26+
outerFirst = false;
27+
} else {
28+
os << ",";
29+
}
30+
os << "\n [";
31+
bool innerFirst = true;
32+
for (auto element : inner) {
33+
if (innerFirst) {
34+
innerFirst = false;
35+
} else {
36+
os << ",";
37+
}
38+
os << "\n " << element;
39+
}
40+
if (!inner.empty()) {
41+
os << "\n ";
42+
}
43+
os << "]";
44+
}
45+
if (!value.empty()) {
46+
os << "\n ";
47+
}
48+
os << "]";
49+
if (!last) {
50+
os << ",";
51+
}
52+
os << "\n";
53+
}
54+
55+
void read(std::string_view input = "types.set.nested.root",
56+
std::string_view output = "types.set.nested.json") {
57+
if (!std::filesystem::exists("libNestedSet.so")) {
58+
throw std::runtime_error("could not find the required ROOT dictionaries, "
59+
"please make sure to run `make` first");
60+
}
61+
62+
gSystem->Load("libNestedSet");
63+
std::ofstream os(std::string{output});
64+
os << "[\n";
65+
66+
auto reader = RNTupleReader::Open("ntpl", input);
67+
auto &entry = reader->GetModel().GetDefaultEntry();
68+
bool first = true;
69+
for (auto index : *reader) {
70+
reader->LoadEntry(index);
71+
72+
if (first) {
73+
first = false;
74+
} else {
75+
os << ",\n";
76+
}
77+
os << " {\n";
78+
79+
PrintNestedSetValue(entry, "Index32", os);
80+
PrintNestedSetValue(entry, "Index64", os);
81+
PrintNestedSetValue(entry, "SplitIndex32", os);
82+
PrintNestedSetValue(entry, "SplitIndex64", os, /*last=*/true);
83+
84+
os << " }";
85+
// Newline is intentionally missing, may need to print a comma before the
86+
// next entry.
87+
}
88+
os << "\n";
89+
os << "]\n";
90+
}

types/set/nested/write.C

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
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 <TSystem.h>
14+
15+
#include <cstdint>
16+
#include <filesystem>
17+
#include <memory>
18+
#include <set>
19+
#include <string_view>
20+
21+
using Set = std::set<std::set<std::int32_t>>;
22+
23+
static std::shared_ptr<Set> MakeSetField(RNTupleModel &model,
24+
std::string_view name,
25+
EColumnType indexType) {
26+
auto field = std::make_unique<RField<Set>>(name);
27+
field->SetColumnRepresentatives({{indexType}});
28+
field->GetSubFields()[0]->SetColumnRepresentatives({{indexType}});
29+
model.AddField(std::move(field));
30+
return model.GetDefaultEntry().GetPtr<Set>(name);
31+
}
32+
33+
void write(std::string_view filename = "types.set.nested.root") {
34+
if (!std::filesystem::exists("libNestedSet.so")) {
35+
throw std::runtime_error("could not find the required ROOT dictionaries, "
36+
"please make sure to run `make` first");
37+
}
38+
39+
gSystem->Load("libNestedSet");
40+
41+
auto model = RNTupleModel::Create();
42+
43+
// Non-split index encoding
44+
auto Index32 = MakeSetField(*model, "Index32", EColumnType::kIndex32);
45+
auto Index64 = MakeSetField(*model, "Index64", EColumnType::kIndex64);
46+
47+
// Split index encoding
48+
auto SplitIndex32 =
49+
MakeSetField(*model, "SplitIndex32", EColumnType::kSplitIndex32);
50+
auto SplitIndex64 =
51+
MakeSetField(*model, "SplitIndex64", EColumnType::kSplitIndex64);
52+
53+
RNTupleWriteOptions options;
54+
options.SetCompression(0);
55+
auto writer =
56+
RNTupleWriter::Recreate(std::move(model), "ntpl", filename, options);
57+
58+
// First entry: single-element sets, with ascending values
59+
*Index32 = {{1}};
60+
*Index64 = {{2}};
61+
*SplitIndex32 = {{3}};
62+
*SplitIndex64 = {{4}};
63+
writer->Fill();
64+
65+
// Second entry: empty sets
66+
*Index32 = {};
67+
*Index64 = {};
68+
*SplitIndex32 = {};
69+
*SplitIndex64 = {};
70+
writer->Fill();
71+
72+
// Third entry: increasing number of elements in the set
73+
*Index32 = {{1}};
74+
*Index64 = {{}, {2, 3}};
75+
*SplitIndex32 = {{}, {4}, {5, 6}};
76+
*SplitIndex64 = {{}, {7, 8, 9}, {10}, {11, 12}};
77+
writer->Fill();
78+
}

0 commit comments

Comments
 (0)