Skip to content

Commit 34d6347

Browse files
committed
groot/rdict: proper handling of 'This' streamers
'This' streamers are used to extract the type argument of templates. e.g.: class MyVector: public std::vector<Foo> {...}; would be encoded as a TStreamerInfo named 'MyVector' and an element named "This" with a title "<Foo> Used to call ...". This technique seems to be used to properly extract 'Foo'. This seems to be also applied for other containers. (vector, deque, ...)
1 parent 0a85f50 commit 34d6347

File tree

3 files changed

+84
-22
lines changed

3 files changed

+84
-22
lines changed

groot/rdict/rwstreamer_test.go

+18
Original file line numberDiff line numberDiff line change
@@ -3252,6 +3252,24 @@ func TestRWStream(t *testing.T) {
32523252
},
32533253
},
32543254
},
3255+
{
3256+
name: "rmeta-stl-vector<set<int>>",
3257+
ptr: &struct {
3258+
F [][]int32
3259+
}{[][]int32{{1}, {2, 3}}},
3260+
si: &StreamerInfo{
3261+
named: *rbase.NewNamed("T", "T"),
3262+
objarr: rcont.NewObjArray(),
3263+
elems: []rbytes.StreamerElement{
3264+
NewCxxStreamerSTL(Element{
3265+
Name: *rbase.NewNamed("This", "Used to call the proper TStreamerInfo case"),
3266+
Type: rmeta.STL,
3267+
MaxIdx: [5]int32{0, 0, 0, 0, 0},
3268+
EName: "vector<set<int> >",
3269+
}.New(), rmeta.STLvector, rmeta.Object),
3270+
},
3271+
},
3272+
},
32553273
} {
32563274
t.Run(tc.name, func(t *testing.T) {
32573275
if tc.skip {

groot/rdict/type.go

+38-6
Original file line numberDiff line numberDiff line change
@@ -194,10 +194,19 @@ func TypeFromSE(ctx rbytes.StreamerInfoContext, se rbytes.StreamerElement) (refl
194194
case rmeta.STLvector, rmeta.STLlist, rmeta.STLdeque:
195195
var (
196196
ct = se.ContainedType()
197-
ename = rmeta.CxxTemplateFrom(se.TypeName()).Args[0]
198197
typevers = int16(-1)
199-
elt, err = typeFromTypeName(ctx, ename, typevers, ct, se, 1)
198+
ename string
200199
)
200+
switch {
201+
case hasThisHandling(se):
202+
ename = se.Title()
203+
ename = ename[:strings.Index(ename, "> Used to call the proper TStreamerInfo case")+1]
204+
ename = strings.TrimSpace(ename)
205+
ename = rmeta.CxxTemplateFrom("Type" + ename).Args[0]
206+
default:
207+
ename = rmeta.CxxTemplateFrom(se.TypeName()).Args[0]
208+
}
209+
elt, err := typeFromTypeName(ctx, ename, typevers, ct, se, 1)
201210
if err != nil {
202211
return nil, fmt.Errorf("rdict: could not create type for %q: %w", se.TypeName(), err)
203212
}
@@ -208,8 +217,17 @@ func TypeFromSE(ctx rbytes.StreamerInfoContext, se rbytes.StreamerElement) (refl
208217
ct = se.ContainedType()
209218
typename = se.TypeName()
210219
typevers = int16(-1)
211-
kname = rmeta.CxxTemplateFrom(se.TypeName()).Args[0]
220+
kname string
212221
)
222+
switch {
223+
case hasThisHandling(se):
224+
kname = se.Title()
225+
kname = kname[:strings.Index(kname, "> Used to call the proper TStreamerInfo case")+1]
226+
kname = strings.TrimSpace(kname)
227+
kname = rmeta.CxxTemplateFrom("Type" + kname).Args[0]
228+
default:
229+
kname = rmeta.CxxTemplateFrom(typename).Args[0]
230+
}
213231

214232
key, err := typeFromTypeName(ctx, kname, typevers, ct, se, 1)
215233
if err != nil {
@@ -224,10 +242,20 @@ func TypeFromSE(ctx rbytes.StreamerInfoContext, se rbytes.StreamerElement) (refl
224242
ct = se.ContainedType()
225243
typename = se.TypeName()
226244
typevers = int16(-1)
227-
enames = rmeta.CxxTemplateFrom(se.TypeName()).Args
228-
kname = enames[0]
229-
vname = enames[1]
245+
enames []string
230246
)
247+
switch {
248+
case hasThisHandling(se):
249+
ename := se.Title()
250+
ename = ename[1:] // drop leading '<'
251+
ename = ename[:strings.Index(ename, "> Used to call the proper TStreamerInfo case")]
252+
ename = strings.TrimSpace(ename)
253+
enames = rmeta.CxxTemplateFrom(ename).Args
254+
default:
255+
enames = rmeta.CxxTemplateFrom(typename).Args
256+
}
257+
kname := enames[0]
258+
vname := enames[1]
231259

232260
key, err := typeFromTypeName(ctx, kname, typevers, ct, se, 1)
233261
if err != nil {
@@ -560,3 +588,7 @@ func hasStdPrefix(typename string, ps ...string) bool {
560588
}
561589
return false
562590
}
591+
592+
func hasThisHandling(se rbytes.StreamerElement) bool {
593+
return se.Name() == "This" && strings.HasPrefix(se.Title(), "<")
594+
}

groot/rdict/type_test.go

+28-16
Original file line numberDiff line numberDiff line change
@@ -204,11 +204,23 @@ func TestTypeFromSI(t *testing.T) {
204204
ROOT_second float32 `groot:"second"`
205205
})(nil)).Elem(),
206206
},
207+
{
208+
name: "vector<int>",
209+
si: rdict.NewCxxStreamerInfo("vector<int>", 1, 0, []rbytes.StreamerElement{
210+
rdict.NewCxxStreamerSTL(rdict.Element{
211+
Name: *rbase.NewNamed("This", "<int> Used to call the proper TStreamerInfo case"),
212+
Type: rmeta.Streamer,
213+
Size: 48,
214+
EName: "vector<int>",
215+
}.New(), rmeta.STLvector, rmeta.Object),
216+
}),
217+
want: reflect.TypeOf((*[]int32)(nil)).Elem(),
218+
},
207219
{
208220
name: "list<int>",
209221
si: rdict.NewCxxStreamerInfo("list<int>", 1, 0, []rbytes.StreamerElement{
210222
rdict.NewCxxStreamerSTL(rdict.Element{
211-
Name: *rbase.NewNamed("This", ""),
223+
Name: *rbase.NewNamed("This", "<int> Used to call the proper TStreamerInfo case"),
212224
Type: rmeta.Streamer,
213225
Size: 48,
214226
EName: "list<int>",
@@ -220,7 +232,7 @@ func TestTypeFromSI(t *testing.T) {
220232
name: "deque<int>",
221233
si: rdict.NewCxxStreamerInfo("deque<int>", 1, 0, []rbytes.StreamerElement{
222234
rdict.NewCxxStreamerSTL(rdict.Element{
223-
Name: *rbase.NewNamed("This", ""),
235+
Name: *rbase.NewNamed("This", "<int> Used to call the proper TStreamerInfo case"),
224236
Type: rmeta.Streamer,
225237
Size: 48,
226238
EName: "deque<int>",
@@ -232,7 +244,7 @@ func TestTypeFromSI(t *testing.T) {
232244
name: "set<int>",
233245
si: rdict.NewCxxStreamerInfo("set<int>", 1, 0, []rbytes.StreamerElement{
234246
rdict.NewCxxStreamerSTL(rdict.Element{
235-
Name: *rbase.NewNamed("This", ""),
247+
Name: *rbase.NewNamed("This", "<int> Used to call the proper TStreamerInfo case"),
236248
Type: rmeta.Streamer,
237249
Size: 48,
238250
EName: "set<int>",
@@ -244,7 +256,7 @@ func TestTypeFromSI(t *testing.T) {
244256
name: "multiset<int>",
245257
si: rdict.NewCxxStreamerInfo("multiset<int>", 1, 0, []rbytes.StreamerElement{
246258
rdict.NewCxxStreamerSTL(rdict.Element{
247-
Name: *rbase.NewNamed("This", ""),
259+
Name: *rbase.NewNamed("This", "<int> Used to call the proper TStreamerInfo case"),
248260
Type: rmeta.Streamer,
249261
Size: 48,
250262
EName: "set<int>",
@@ -256,7 +268,7 @@ func TestTypeFromSI(t *testing.T) {
256268
name: "unordered_set<int>",
257269
si: rdict.NewCxxStreamerInfo("unordered_set<int>", 1, 0, []rbytes.StreamerElement{
258270
rdict.NewCxxStreamerSTL(rdict.Element{
259-
Name: *rbase.NewNamed("This", ""),
271+
Name: *rbase.NewNamed("This", "<int> Used to call the proper TStreamerInfo case"),
260272
Type: rmeta.Streamer,
261273
Size: 48,
262274
EName: "unordered_set<int>",
@@ -268,7 +280,7 @@ func TestTypeFromSI(t *testing.T) {
268280
name: "unordered_multiset<int>",
269281
si: rdict.NewCxxStreamerInfo("unordered_multiset<int>", 1, 0, []rbytes.StreamerElement{
270282
rdict.NewCxxStreamerSTL(rdict.Element{
271-
Name: *rbase.NewNamed("This", ""),
283+
Name: *rbase.NewNamed("This", "<int> Used to call the proper TStreamerInfo case"),
272284
Type: rmeta.Streamer,
273285
Size: 48,
274286
EName: "unordered_multiset<int>",
@@ -280,7 +292,7 @@ func TestTypeFromSI(t *testing.T) {
280292
name: "map<int,float>",
281293
si: rdict.NewCxxStreamerInfo("map<int,float>", 1, 0, []rbytes.StreamerElement{
282294
rdict.NewCxxStreamerSTL(rdict.Element{
283-
Name: *rbase.NewNamed("This", ""),
295+
Name: *rbase.NewNamed("This", "<pair<int,float>> Used to call the proper TStreamerInfo case"),
284296
Type: rmeta.Streamer,
285297
Size: 48,
286298
EName: "map<int,float>",
@@ -292,7 +304,7 @@ func TestTypeFromSI(t *testing.T) {
292304
name: "multimap<int,float>",
293305
si: rdict.NewCxxStreamerInfo("multimap<int,float>", 1, 0, []rbytes.StreamerElement{
294306
rdict.NewCxxStreamerSTL(rdict.Element{
295-
Name: *rbase.NewNamed("This", ""),
307+
Name: *rbase.NewNamed("This", "<pair<int,float>> Used to call the proper TStreamerInfo case"),
296308
Type: rmeta.Streamer,
297309
Size: 48,
298310
EName: "multimap<int,float>",
@@ -304,7 +316,7 @@ func TestTypeFromSI(t *testing.T) {
304316
name: "unordered_map<int,float>",
305317
si: rdict.NewCxxStreamerInfo("unordered_map<int,float>", 1, 0, []rbytes.StreamerElement{
306318
rdict.NewCxxStreamerSTL(rdict.Element{
307-
Name: *rbase.NewNamed("This", ""),
319+
Name: *rbase.NewNamed("This", "<pair<int,float>> Used to call the proper TStreamerInfo case"),
308320
Type: rmeta.Streamer,
309321
Size: 48,
310322
EName: "unordered_map<int,float>",
@@ -316,7 +328,7 @@ func TestTypeFromSI(t *testing.T) {
316328
name: "unordered_multimap<int,float>",
317329
si: rdict.NewCxxStreamerInfo("unordered_multimap<int,float>", 1, 0, []rbytes.StreamerElement{
318330
rdict.NewCxxStreamerSTL(rdict.Element{
319-
Name: *rbase.NewNamed("This", ""),
331+
Name: *rbase.NewNamed("This", "<pair<int,float>> Used to call the proper TStreamerInfo case"),
320332
Type: rmeta.Streamer,
321333
Size: 48,
322334
EName: "unordered_multimap<int,float>",
@@ -328,7 +340,7 @@ func TestTypeFromSI(t *testing.T) {
328340
name: "map<int,string>",
329341
si: rdict.NewCxxStreamerInfo("map<int,string>", 1, 0, []rbytes.StreamerElement{
330342
rdict.NewCxxStreamerSTL(rdict.Element{
331-
Name: *rbase.NewNamed("This", ""),
343+
Name: *rbase.NewNamed("This", "<pair<int,string>> Used to call the proper TStreamerInfo case"),
332344
Type: rmeta.Streamer,
333345
Size: 48,
334346
EName: "map<int,string>",
@@ -340,7 +352,7 @@ func TestTypeFromSI(t *testing.T) {
340352
name: "map<int,TNamed>",
341353
si: rdict.NewCxxStreamerInfo("map<int,TNamed>", 1, 0, []rbytes.StreamerElement{
342354
rdict.NewCxxStreamerSTL(rdict.Element{
343-
Name: *rbase.NewNamed("This", ""),
355+
Name: *rbase.NewNamed("This", "<pair<int,TNamed>> Used to call the proper TStreamerInfo case"),
344356
Type: rmeta.Streamer,
345357
Size: 48,
346358
EName: "map<int,TNamed>",
@@ -352,7 +364,7 @@ func TestTypeFromSI(t *testing.T) {
352364
name: "map<TNamed,int>",
353365
si: rdict.NewCxxStreamerInfo("map<TNamed,int>", 1, 0, []rbytes.StreamerElement{
354366
rdict.NewCxxStreamerSTL(rdict.Element{
355-
Name: *rbase.NewNamed("This", ""),
367+
Name: *rbase.NewNamed("This", "<pair<TNamed,int>> Used to call the proper TStreamerInfo case"),
356368
Type: rmeta.Streamer,
357369
Size: 48,
358370
EName: "map<TNamed,int>",
@@ -364,7 +376,7 @@ func TestTypeFromSI(t *testing.T) {
364376
name: "map<int,vector<TNamed> >",
365377
si: rdict.NewCxxStreamerInfo("map<int,vector<TNamed> >", 1, 0, []rbytes.StreamerElement{
366378
rdict.NewCxxStreamerSTL(rdict.Element{
367-
Name: *rbase.NewNamed("This", ""),
379+
Name: *rbase.NewNamed("This", "<pair<int,vector<TNamed> >> Used to call the proper TStreamerInfo case"),
368380
Type: rmeta.Streamer,
369381
Size: 48,
370382
EName: "map<int,vector<TNamed> >",
@@ -376,7 +388,7 @@ func TestTypeFromSI(t *testing.T) {
376388
name: "map<int,vector<string> >",
377389
si: rdict.NewCxxStreamerInfo("map<int,vector<string> >", 1, 0, []rbytes.StreamerElement{
378390
rdict.NewCxxStreamerSTL(rdict.Element{
379-
Name: *rbase.NewNamed("This", ""),
391+
Name: *rbase.NewNamed("This", "<pair<int,vector<string> >> Used to call the proper TStreamerInfo case"),
380392
Type: rmeta.Streamer,
381393
Size: 48,
382394
EName: "map<int,vector<string> >",
@@ -388,7 +400,7 @@ func TestTypeFromSI(t *testing.T) {
388400
name: "map<int,map<int,vector<string> > >",
389401
si: rdict.NewCxxStreamerInfo("map<int,map<int,vector<string> > >", 1, 0, []rbytes.StreamerElement{
390402
rdict.NewCxxStreamerSTL(rdict.Element{
391-
Name: *rbase.NewNamed("This", ""),
403+
Name: *rbase.NewNamed("This", "<pair<int,map<int,vector<string> > >> Used to call the proper TStreamerInfo case"),
392404
Type: rmeta.Streamer,
393405
Size: 48,
394406
EName: "map<int,map<int,vector<string> > >",

0 commit comments

Comments
 (0)