Skip to content

Commit cd8fbb4

Browse files
pcanalCopilot
andauthored
Update how type information is passed from Phlex to FORM (#252)
* Switch product from type_index to type_info * Switch FORM from type_index to type_info * FORM: Remove type_map * FORM: Demangle type_info before printing name * FORM: Add more information to exception msg --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 5a46fa3 commit cd8fbb4

19 files changed

+138
-157
lines changed

form/form/form.cpp

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22

33
#include "form.hpp"
44

5+
#include <stdexcept>
6+
#include <typeinfo>
7+
58
namespace form::experimental {
69

7-
form_interface::form_interface(std::shared_ptr<product_type_names> tm,
8-
config::output_item_config const& output_config,
10+
form_interface::form_interface(config::output_item_config const& output_config,
911
config::tech_setting_config const& tech_config) :
10-
m_pers(nullptr), m_type_map(tm)
12+
m_pers(nullptr)
1113
{
1214
for (auto const& item : output_config.getItems()) {
1315
m_product_to_config.emplace(item.product_name,
@@ -30,12 +32,10 @@ namespace form::experimental {
3032
throw std::runtime_error("No configuration found for product: " + pb.label);
3133
}
3234

33-
std::string const type = m_type_map->names[pb.type];
34-
35-
std::map<std::string, std::string> products = {{pb.label, type}};
35+
std::map<std::string, std::type_info const*> products = {{pb.label, pb.type}};
3636
m_pers->createContainers(creator, products);
3737

38-
m_pers->registerWrite(creator, pb.label, pb.data, type);
38+
m_pers->registerWrite(creator, pb.label, pb.data, *pb.type);
3939

4040
m_pers->commitOutput(creator, segment_id);
4141
}
@@ -54,18 +54,16 @@ namespace form::experimental {
5454
}
5555

5656
// FIXME: Really only needed on first call
57-
std::map<std::string, std::string> product_types;
57+
std::map<std::string, std::type_info const*> product_types;
5858
for (auto const& pb : products) {
59-
std::string const& type = m_type_map->names[pb.type];
60-
product_types.insert(std::make_pair(pb.label, type));
59+
product_types.insert(std::make_pair(pb.label, pb.type));
6160
}
6261

6362
m_pers->createContainers(creator, product_types);
6463

6564
for (auto const& pb : products) {
66-
std::string const& type = m_type_map->names[pb.type];
6765
// FIXME: We could consider checking id to be identical for all product bases here
68-
m_pers->registerWrite(creator, pb.label, pb.data, type);
66+
m_pers->registerWrite(creator, pb.label, pb.data, *pb.type);
6967
}
7068

7169
m_pers->commitOutput(creator, segment_id);
@@ -81,8 +79,6 @@ namespace form::experimental {
8179
throw std::runtime_error("No configuration found for product: " + pb.label);
8280
}
8381

84-
std::string type = m_type_map->names[pb.type];
85-
86-
m_pers->read(creator, pb.label, segment_id, &pb.data, type);
82+
m_pers->read(creator, pb.label, segment_id, &pb.data, *pb.type);
8783
}
8884
}

form/form/form.hpp

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,20 @@
99
#include <map>
1010
#include <memory>
1111
#include <string>
12-
#include <typeindex>
13-
#include <unordered_map>
12+
#include <typeinfo>
1413
#include <vector>
1514

1615
namespace form::experimental {
1716

18-
struct product_type_names {
19-
std::unordered_map<std::type_index, std::string> names;
20-
};
21-
2217
struct product_with_name {
2318
std::string label;
2419
void const* data;
25-
std::type_index type;
20+
std::type_info const* type;
2621
};
2722

2823
class form_interface {
2924
public:
30-
form_interface(std::shared_ptr<product_type_names> tm,
31-
config::output_item_config const& output_config,
25+
form_interface(config::output_item_config const& output_config,
3226
config::tech_setting_config const& tech_config);
3327
~form_interface() = default;
3428

@@ -46,7 +40,6 @@ namespace form::experimental {
4640

4741
private:
4842
std::unique_ptr<form::detail::experimental::IPersistence> m_pers;
49-
std::shared_ptr<product_type_names> m_type_map;
5043
std::map<std::string, form::experimental::config::PersistenceItem> m_product_to_config;
5144
};
5245
}

form/form_module.cpp

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,10 @@ namespace {
1414

1515
class FormOutputModule {
1616
public:
17-
FormOutputModule(std::shared_ptr<form::experimental::product_type_names> type_map,
18-
std::string output_file,
17+
FormOutputModule(std::string output_file,
1918
int technology,
2019
std::vector<std::string> const& products_to_save) :
21-
m_type_map(type_map), m_output_file(std::move(output_file)), m_technology(technology)
20+
m_output_file(std::move(output_file)), m_technology(technology)
2221
{
2322
std::cout << "FormOutputModule initialized\n";
2423
std::cout << " Output file: " << m_output_file << "\n";
@@ -39,8 +38,7 @@ namespace {
3938
}
4039

4140
// Initialize FORM interface
42-
m_form_interface =
43-
std::make_unique<form::experimental::form_interface>(type_map, output_cfg, tech_cfg);
41+
m_form_interface = std::make_unique<form::experimental::form_interface>(output_cfg, tech_cfg);
4442
}
4543

4644
// This method is called by Phlex - signature must be: void(product_store const&)
@@ -82,7 +80,7 @@ namespace {
8280
// Create FORM product with metadata
8381
products.emplace_back(product_name, // label, from map key
8482
product_ptr->address(), // data, from phlex product_base
85-
product_ptr->type() // type, from phlex product_base
83+
&product_ptr->type() // type, from phlex product_base
8684
);
8785
}
8886

@@ -96,7 +94,6 @@ namespace {
9694
}
9795

9896
private:
99-
std::shared_ptr<form::experimental::product_type_names> m_type_map;
10097
std::string m_output_file;
10198
int m_technology;
10299
std::unique_ptr<form::experimental::form_interface> m_form_interface;
@@ -108,19 +105,6 @@ PHLEX_REGISTER_ALGORITHMS(m, config)
108105
{
109106
std::cout << "Registering FORM output module...\n";
110107

111-
// Create type map
112-
auto type_map = std::make_shared<form::experimental::product_type_names>();
113-
114-
// Register some fundamental type for simple products
115-
type_map->names[std::type_index(typeid(int))] = "int";
116-
type_map->names[std::type_index(typeid(long))] = "long";
117-
type_map->names[std::type_index(typeid(float))] = "float";
118-
type_map->names[std::type_index(typeid(double))] = "double";
119-
type_map->names[std::type_index(typeid(std::vector<int>))] = "std::vector<int>";
120-
type_map->names[std::type_index(typeid(std::vector<long>))] = "std::vector<long>";
121-
type_map->names[std::type_index(typeid(std::vector<float>))] = "std::vector<float>";
122-
type_map->names[std::type_index(typeid(std::vector<double>))] = "std::vector<double>";
123-
124108
// Extract configuration from Phlex config
125109
std::string output_file = config.get<std::string>("output_file", "output.root");
126110
std::string tech_string = config.get<std::string>("technology", "ROOT_TTREE");
@@ -146,7 +130,7 @@ PHLEX_REGISTER_ALGORITHMS(m, config)
146130

147131
// Phlex needs an OBJECT
148132
// Create the FORM output module
149-
auto form_output = m.make<FormOutputModule>(type_map, output_file, technology, products_to_save);
133+
auto form_output = m.make<FormOutputModule>(output_file, technology, products_to_save);
150134

151135
// Phlex needs a MEMBER FUNCTION to call
152136
// Register the callback that Phlex will invoke

form/persistence/ipersistence.hpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <map>
77
#include <memory>
88
#include <string>
9+
#include <typeinfo>
910

1011
namespace form::experimental::config {
1112
class output_item_config;
@@ -26,18 +27,18 @@ namespace form::detail::experimental {
2627
form::experimental::config::output_item_config const& outputItems) = 0;
2728

2829
virtual void createContainers(std::string const& creator,
29-
std::map<std::string, std::string> const& products) = 0;
30+
std::map<std::string, std::type_info const*> const& products) = 0;
3031
virtual void registerWrite(std::string const& creator,
3132
std::string const& label,
3233
void const* data,
33-
std::string const& type) = 0;
34+
std::type_info const& type) = 0;
3435
virtual void commitOutput(std::string const& creator, std::string const& id) = 0;
3536

3637
virtual void read(std::string const& creator,
3738
std::string const& label,
3839
std::string const& id,
3940
void const** data,
40-
std::string& type) = 0;
41+
std::type_info const& type) = 0;
4142
};
4243

4344
std::unique_ptr<IPersistence> createPersistence();

form/persistence/persistence.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
#include <algorithm>
66
#include <cstring>
7+
#include <stdexcept>
8+
#include <string>
9+
#include <typeinfo>
710
#include <utility>
811

912
using namespace form::detail::experimental;
@@ -31,21 +34,21 @@ void Persistence::configureOutputItems(
3134
}
3235

3336
void Persistence::createContainers(std::string const& creator,
34-
std::map<std::string, std::string> const& products)
37+
std::map<std::string, std::type_info const*> const& products)
3538
{
36-
std::map<std::unique_ptr<Placement>, std::string> containers;
39+
std::map<std::unique_ptr<Placement>, std::type_info const*> containers;
3740
for (auto const& [label, type] : products) {
3841
containers.insert(std::make_pair(getPlacement(creator, label), type));
3942
}
40-
containers.insert(std::make_pair(getPlacement(creator, "index"), "std::string"));
43+
containers.insert(std::make_pair(getPlacement(creator, "index"), &typeid(std::string)));
4144
m_store->createContainers(containers, m_tech_settings);
4245
return;
4346
}
4447

4548
void Persistence::registerWrite(std::string const& creator,
4649
std::string const& label,
4750
void const* data,
48-
std::string const& type)
51+
std::type_info const& type)
4952
{
5053
std::unique_ptr<Placement> plcmnt = getPlacement(creator, label);
5154
m_store->fillContainer(*plcmnt, data, type);
@@ -55,7 +58,7 @@ void Persistence::registerWrite(std::string const& creator,
5558
void Persistence::commitOutput(std::string const& creator, std::string const& id)
5659
{
5760
std::unique_ptr<Placement> plcmnt = getPlacement(creator, "index");
58-
m_store->fillContainer(*plcmnt, &id, "std::string");
61+
m_store->fillContainer(*plcmnt, &id, typeid(std::string));
5962
m_store->commitContainers(*plcmnt);
6063
return;
6164
}
@@ -64,7 +67,7 @@ void Persistence::read(std::string const& creator,
6467
std::string const& label,
6568
std::string const& id,
6669
void const** data,
67-
std::string& type)
70+
std::type_info const& type)
6871
{
6972
std::unique_ptr<Token> token = getToken(creator, label, id);
7073
m_store->readContainer(*token, data, type, m_tech_settings);

form/persistence/persistence.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,18 @@ namespace form::detail::experimental {
3232
form::experimental::config::output_item_config const& output_items) override;
3333

3434
void createContainers(std::string const& creator,
35-
std::map<std::string, std::string> const& products) override;
35+
std::map<std::string, std::type_info const*> const& products) override;
3636
void registerWrite(std::string const& creator,
3737
std::string const& label,
3838
void const* data,
39-
std::string const& type) override;
39+
std::type_info const& type) override;
4040
void commitOutput(std::string const& creator, std::string const& id) override;
4141

4242
void read(std::string const& creator,
4343
std::string const& label,
4444
std::string const& id,
4545
void const** data,
46-
std::string& type) override;
46+
std::type_info const& type) override;
4747

4848
private:
4949
std::unique_ptr<Placement> getPlacement(std::string const& creator, std::string const& label);

form/root_storage/root_tbranch_container.cpp

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,28 @@
55
#include "root_ttree_container.hpp"
66

77
#include "TBranch.h"
8+
#include "TClassEdit.h"
89
#include "TFile.h"
910
#include "TLeaf.h"
1011
#include "TTree.h"
1112

1213
#include <unordered_map>
1314

1415
namespace {
16+
// Return the demangled type name
17+
std::string DemangleName(std::type_info const& type)
18+
{
19+
int errorCode;
20+
// The TClassEdit version works on both linux and Windows.
21+
char* demangledName = TClassEdit::DemangleTypeIdName(type, errorCode);
22+
if (errorCode != 0) {
23+
// NOTE: Instead of throwing, we could return the mangled name as a fallback.
24+
throw std::runtime_error("Failed to demangle type name");
25+
}
26+
std::string result(demangledName);
27+
std::free(demangledName);
28+
return result;
29+
}
1530
//Type name conversion based on https://root.cern.ch/doc/master/classTTree.html#ac1fa9466ce018d4aa739b357f981c615
1631
//An empty leaf list defaults to Float_t
1732
std::unordered_map<std::string, std::string> typeNameToLeafList = {{"int", "/I"},
@@ -63,16 +78,18 @@ void ROOT_TBranch_ContainerImp::setParent(std::shared_ptr<IStorage_Container> pa
6378
return;
6479
}
6580

66-
void ROOT_TBranch_ContainerImp::setupWrite(std::string const& type)
81+
void ROOT_TBranch_ContainerImp::setupWrite(std::type_info const& type)
6782
{
6883
if (m_tree == nullptr) {
6984
throw std::runtime_error("ROOT_TBranch_ContainerImp::setupWrite no tree found");
7085
}
7186

72-
auto dictInfo = TDictionary::GetDictionary(type.c_str());
87+
auto dictInfo = TDictionary::GetDictionary(type);
7388
if (m_branch == nullptr) {
7489
if (!dictInfo) {
75-
throw std::runtime_error("ROOT_TBranch_ContainerImp::setupWrite unsupported type: " + type);
90+
throw std::runtime_error(
91+
std::string{"ROOT_TBranch_ContainerImp::setupWrite unsupported type: "} +
92+
DemangleName(type));
7693
}
7794
if (dictInfo->Property() & EProperty::kIsFundamental) {
7895
m_branch = m_tree->Branch(col_name().c_str(),
@@ -117,7 +134,7 @@ void ROOT_TBranch_ContainerImp::commit()
117134
return;
118135
}
119136

120-
bool ROOT_TBranch_ContainerImp::read(int id, void const** data, std::string& type)
137+
bool ROOT_TBranch_ContainerImp::read(int id, void const** data, std::type_info const& type)
121138
{
122139
if (m_tfile == nullptr) {
123140
throw std::runtime_error("ROOT_TBranch_ContainerImp::read no file attached");
@@ -138,23 +155,34 @@ bool ROOT_TBranch_ContainerImp::read(int id, void const** data, std::string& typ
138155
return false;
139156

140157
void* branchBuffer = nullptr;
141-
auto dictInfo = TClass::GetClass(type.c_str());
158+
auto dictInfo = TDictionary::GetDictionary(type);
142159
int branchStatus = 0;
143-
if (dictInfo) {
144-
branchBuffer = dictInfo->New();
145-
branchStatus = m_tree->SetBranchAddress(
146-
col_name().c_str(), &branchBuffer, TClass::GetClass(type.c_str()), EDataType::kOther_t, true);
147-
} else {
148-
//Assume this is a fundamental type like int or double
149-
auto fundInfo = static_cast<TDataType*>(TDictionary::GetDictionary(type.c_str()));
160+
if (!dictInfo) {
161+
throw std::runtime_error(std::string{"ROOT_TBranch_ContainerImp::read unsupported type: "} +
162+
DemangleName(type));
163+
}
164+
165+
if (dictInfo->Property() & EProperty::kIsFundamental) {
166+
auto fundInfo = static_cast<TDataType*>(dictInfo);
150167
branchBuffer = new char[fundInfo->Size()];
151168
branchStatus = m_tree->SetBranchAddress(
152169
col_name().c_str(), &branchBuffer, nullptr, EDataType(fundInfo->GetType()), true);
170+
} else {
171+
auto klass = TClass::GetClass(type);
172+
if (!klass) {
173+
throw std::runtime_error(std::string{"ROOT_TBranch_ContainerImp::read missing TClass"} +
174+
" (col_name='" + col_name() + "', type='" + DemangleName(type) +
175+
"')");
176+
}
177+
branchBuffer = klass->New();
178+
branchStatus =
179+
m_tree->SetBranchAddress(col_name().c_str(), &branchBuffer, klass, EDataType::kOther_t, true);
153180
}
154181

155182
if (branchStatus < 0) {
156183
throw std::runtime_error(
157-
"ROOT_TBranch_ContainerImp::read SetBranchAddress() failed with error code " +
184+
std::string{"ROOT_TBranch_ContainerImp::read SetBranchAddress() failed"} + " (col_name='" +
185+
col_name() + "', type='" + DemangleName(type) + "')" + " with error code " +
158186
std::to_string(branchStatus));
159187
}
160188

0 commit comments

Comments
 (0)