23
23
#include " openPMD/IO/AbstractIOHandler.hpp"
24
24
#include " openPMD/IO/Access.hpp"
25
25
#include " openPMD/IO/IOTask.hpp"
26
+ #include " openPMD/RecordComponent.hpp"
26
27
#include " openPMD/backend/Attributable.hpp"
27
28
29
+ #include < deque>
30
+ #include < memory>
31
+
28
32
namespace openPMD
29
33
{
30
34
namespace internal
@@ -33,9 +37,25 @@ namespace internal
33
37
{
34
38
return paths.find (name) != paths.end ();
35
39
}
40
+
41
+ CustomHierarchyData::CustomHierarchyData ()
42
+ {
43
+ /*
44
+ * m_embeddeddatasets should point to the same instance of Attributable
45
+ * Can only use a non-owning pointer in here in order to avoid shared
46
+ * pointer cycles.
47
+ * When handing this object out to users, we create a copy that has a
48
+ * proper owning pointer (see CustomHierarchy::datasets()).
49
+ */
50
+ m_embeddedDatasets.Attributable ::setData (
51
+ std::shared_ptr<AttributableData>(this , [](auto const *) {}));
52
+ }
36
53
} // namespace internal
37
54
38
- CustomHierarchy::CustomHierarchy () = default ;
55
+ CustomHierarchy::CustomHierarchy ()
56
+ {
57
+ setData (std::make_shared<Data_t>());
58
+ }
39
59
CustomHierarchy::CustomHierarchy (NoInit) : Container_t(NoInit())
40
60
{}
41
61
@@ -49,7 +69,10 @@ void CustomHierarchy::read(internal::MeshesParticlesPath const &mpp)
49
69
Attributable::readAttributes (ReadMode::FullyReread);
50
70
Parameter<Operation::LIST_PATHS> pList;
51
71
IOHandler ()->enqueue (IOTask (this , pList));
72
+ Parameter<Operation::LIST_DATASETS> dList;
73
+ IOHandler ()->enqueue (IOTask (this , dList));
52
74
IOHandler ()->flush (internal::defaultFlushParams);
75
+ std::deque<std::string> constantComponentsPushback;
53
76
for (auto const &path : *pList.paths )
54
77
{
55
78
if (mpp.ignore (path))
@@ -61,6 +84,39 @@ void CustomHierarchy::read(internal::MeshesParticlesPath const &mpp)
61
84
auto subpath = this ->operator [](path);
62
85
IOHandler ()->enqueue (IOTask (&subpath, pOpen));
63
86
subpath.read (mpp);
87
+ if (subpath.size () == 0 && subpath.containsAttribute (" shape" ) &&
88
+ subpath.containsAttribute (" value" ))
89
+ {
90
+ // This is not a group, but a constant record component
91
+ // Writable::~Writable() will deal with removing this from the
92
+ // backend again.
93
+ std::cout << " IS CONSTANT COMPONENT: " << path << std::endl;
94
+ constantComponentsPushback.push_back (path);
95
+ container ().erase (path);
96
+ }
97
+ }
98
+ auto &data = get ();
99
+ for (auto const &path : *dList.datasets )
100
+ {
101
+ auto &rc = data.m_embeddedDatasets [path];
102
+ Parameter<Operation::OPEN_DATASET> dOpen;
103
+ dOpen.name = path;
104
+ IOHandler ()->enqueue (IOTask (&rc, dOpen));
105
+ IOHandler ()->flush (internal::defaultFlushParams);
106
+ rc.written () = false ;
107
+ rc.resetDataset (Dataset (*dOpen.dtype , *dOpen.extent ));
108
+ rc.written () = true ;
109
+ rc.read ();
110
+ }
111
+
112
+ for (auto const &path : constantComponentsPushback)
113
+ {
114
+ auto &rc = data.m_embeddedDatasets [path];
115
+ Parameter<Operation::OPEN_PATH> pOpen;
116
+ pOpen.path = path;
117
+ IOHandler ()->enqueue (IOTask (&rc, pOpen));
118
+ rc.get ().m_isConstant = true ;
119
+ rc.read ();
64
120
}
65
121
}
66
122
@@ -82,6 +138,17 @@ void CustomHierarchy::flush(
82
138
}
83
139
subpath.flush (name, flushParams);
84
140
}
141
+ for (auto &[name, dataset] : get ().m_embeddedDatasets )
142
+ {
143
+ dataset.flush (name, flushParams);
144
+ }
85
145
flushAttributes (flushParams);
86
146
}
147
+
148
+ Container<RecordComponent> CustomHierarchy::datasets ()
149
+ {
150
+ Container<RecordComponent> res = get ().m_embeddedDatasets ;
151
+ res.Attributable ::setData (m_customHierarchyData);
152
+ return res;
153
+ }
87
154
} // namespace openPMD
0 commit comments