Skip to content

Commit ac3ae05

Browse files
committed
Add test for user-defined enums
Closes #12
1 parent 7b1d4ae commit ac3ae05

7 files changed

Lines changed: 211 additions & 0 deletions

File tree

types/user/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
# User-defined Types
22

33
* [`class`]: user-defined class(es)
4+
* [`enum`]: user-defined enum(s)

types/user/enum/LinkDef.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#ifdef __CLING__
2+
#pragma link C++ enum EnumInt8+;
3+
#pragma link C++ enum EnumUInt8+;
4+
#pragma link C++ enum EnumInt16+;
5+
#pragma link C++ enum EnumUInt16+;
6+
#pragma link C++ enum EnumInt32+;
7+
#pragma link C++ enum EnumUInt32+;
8+
#pragma link C++ enum EnumInt64+;
9+
#pragma link C++ enum EnumUInt64+;
10+
#endif

types/user/enum/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: UserEnum.cxx libUserEnum.so
12+
13+
UserEnum.cxx: UserEnum.hxx LinkDef.h
14+
rootcling -f $@ $^
15+
16+
libUserEnum.so: UserEnum.cxx
17+
$(CXX) -shared -fPIC -o $@ $^ $(CXXFLAGS) $(LDFLAGS)
18+
19+
clean:
20+
rm -f UserEnum.cxx UserEnum_rdict.pcm libUserEnum.so

types/user/enum/README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# User-defined enum(s)
2+
3+
## Fields
4+
5+
* `Enum[U]Int{8,16,32,64}`
6+
7+
with the default column types.
8+
9+
## Entries
10+
11+
1. Simple values
12+
2. Zero values

types/user/enum/UserEnum.hxx

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#pragma once
2+
3+
#include <cstdint>
4+
5+
enum class EnumInt8 : std::int8_t {
6+
Zero = 0,
7+
Simple = 1,
8+
};
9+
10+
enum class EnumUInt8 : std::uint8_t {
11+
Zero = 0,
12+
Simple = 2,
13+
};
14+
15+
enum class EnumInt16 : std::int16_t {
16+
Zero = 0,
17+
Simple = 3,
18+
};
19+
20+
enum class EnumUInt16 : std::uint16_t {
21+
Zero = 0,
22+
Simple = 4,
23+
};
24+
25+
enum class EnumInt32 : std::int32_t {
26+
Zero = 0,
27+
Simple = 5,
28+
};
29+
30+
enum class EnumUInt32 : std::uint32_t {
31+
Zero = 0,
32+
Simple = 6,
33+
};
34+
35+
enum class EnumInt64 : std::int64_t {
36+
Zero = 0,
37+
Simple = 7,
38+
};
39+
40+
enum class EnumUInt64 : std::uint64_t {
41+
Zero = 0,
42+
Simple = 8,
43+
};

types/user/enum/read.C

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
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 <string>
11+
#include <string_view>
12+
#include <type_traits>
13+
14+
#include "UserEnum.hxx"
15+
16+
template <typename T>
17+
static void PrintEnumValue(const REntry &entry, std::string_view name,
18+
std::ostream &os, bool last = false) {
19+
T value = *entry.GetPtr<T>(name);
20+
os << " \"" << name << "\": ";
21+
// We want to print the integer value even if it is a character; use the unary
22+
// + operator (https://stackoverflow.com/a/28414758).
23+
os << +static_cast<std::underlying_type_t<T>>(value);
24+
if (!last) {
25+
os << ",";
26+
}
27+
os << "\n";
28+
}
29+
30+
void read(std::string_view input = "types.user.enum.root",
31+
std::string_view output = "types.user.enum.json") {
32+
if (gSystem->Load("libUserEnum") == -1)
33+
throw std::runtime_error("could not find the required ROOT dictionaries, "
34+
"please make sure to run `make` first");
35+
36+
std::ofstream os(std::string{output});
37+
os << "[\n";
38+
39+
auto reader = RNTupleReader::Open("ntpl", input);
40+
auto &entry = reader->GetModel().GetDefaultEntry();
41+
bool first = true;
42+
for (auto index : *reader) {
43+
reader->LoadEntry(index);
44+
45+
if (first) {
46+
first = false;
47+
} else {
48+
os << ",\n";
49+
}
50+
os << " {\n";
51+
52+
PrintEnumValue<EnumInt8>(entry, "EnumInt8", os);
53+
PrintEnumValue<EnumUInt8>(entry, "EnumUInt8", os);
54+
PrintEnumValue<EnumInt16>(entry, "EnumInt16", os);
55+
PrintEnumValue<EnumUInt16>(entry, "EnumUInt16", os);
56+
PrintEnumValue<EnumInt32>(entry, "EnumInt32", os);
57+
PrintEnumValue<EnumUInt32>(entry, "EnumUInt32", os);
58+
PrintEnumValue<EnumInt64>(entry, "EnumInt64", os);
59+
PrintEnumValue<EnumUInt64>(entry, "EnumUInt64", os, /*last=*/true);
60+
61+
os << " }";
62+
// Newline is intentionally missing, may need to print a comma before the
63+
// next entry.
64+
}
65+
os << "\n";
66+
os << "]\n";
67+
}

types/user/enum/write.C

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#include <ROOT/RNTupleModel.hxx>
2+
#include <ROOT/RNTupleWriteOptions.hxx>
3+
#include <ROOT/RNTupleWriter.hxx>
4+
5+
using ROOT::Experimental::RNTupleModel;
6+
using ROOT::Experimental::RNTupleWriteOptions;
7+
using ROOT::Experimental::RNTupleWriter;
8+
9+
#include <TSystem.h>
10+
11+
#include <string_view>
12+
13+
#include "UserEnum.hxx"
14+
15+
void write(std::string_view filename = "types.user.enum.root") {
16+
if (gSystem->Load("libUserEnum") == -1)
17+
throw std::runtime_error("could not find the required ROOT dictionaries, "
18+
"please make sure to run `make` first");
19+
20+
auto model = RNTupleModel::Create();
21+
22+
// TODO: enums with bool underlying type are possible since ROOT 6.38
23+
auto EInt8 = model->MakeField<EnumInt8>("EnumInt8");
24+
auto EUInt8 = model->MakeField<EnumUInt8>("EnumUInt8");
25+
auto EInt16 = model->MakeField<EnumInt16>("EnumInt16");
26+
auto EUInt16 = model->MakeField<EnumUInt16>("EnumUInt16");
27+
auto EInt32 = model->MakeField<EnumInt32>("EnumInt32");
28+
auto EUInt32 = model->MakeField<EnumUInt32>("EnumUInt32");
29+
auto EInt64 = model->MakeField<EnumInt64>("EnumInt64");
30+
auto EUInt64 = model->MakeField<EnumUInt64>("EnumUInt64");
31+
32+
RNTupleWriteOptions options;
33+
options.SetCompression(0);
34+
auto writer =
35+
RNTupleWriter::Recreate(std::move(model), "ntpl", filename, options);
36+
37+
// First entry: simple values
38+
*EInt8 = EnumInt8::Simple; // = 1;
39+
*EUInt8 = EnumUInt8::Simple; // = 2;
40+
*EInt16 = EnumInt16::Simple; // = 3;
41+
*EUInt16 = EnumUInt16::Simple; // = 4;
42+
*EInt32 = EnumInt32::Simple; // = 5;
43+
*EUInt32 = EnumUInt32::Simple; // = 6;
44+
*EInt64 = EnumInt64::Simple; // = 7;
45+
*EUInt64 = EnumUInt64::Simple; // = 8;
46+
writer->Fill();
47+
48+
// Second entry: zero values
49+
*EInt8 = EnumInt8::Zero;
50+
*EUInt8 = EnumUInt8::Zero;
51+
*EInt16 = EnumInt16::Zero;
52+
*EUInt16 = EnumUInt16::Zero;
53+
*EInt32 = EnumInt32::Zero;
54+
*EUInt32 = EnumUInt32::Zero;
55+
*EInt64 = EnumInt64::Zero;
56+
*EUInt64 = EnumUInt64::Zero;
57+
writer->Fill();
58+
}

0 commit comments

Comments
 (0)