@@ -66,6 +66,50 @@ bool IsUserClass(const std::string &typeName)
66
66
return typeName.rfind (" std::" , 0 ) != 0 && typeName.rfind (" ROOT::VecOps::RVec<" , 0 ) != 0 ;
67
67
}
68
68
69
+ // / Parse a type name of the form `T[n][m]...` and return the base type `T` and a vector that contains,
70
+ // / in order, the declared size for each dimension, e.g. for `unsigned char[1][2][3]` it returns the tuple
71
+ // / `{"unsigned char", {1, 2, 3}}`. Extra whitespace in `typeName` should be removed before calling this function.
72
+ // /
73
+ // / If `typeName` is not an array type, it returns a tuple `{T, {}}`. On error, it returns a default-constructed tuple.
74
+ std::tuple<std::string, std::vector<std::size_t >> ParseArrayType (const std::string &typeName)
75
+ {
76
+ std::vector<std::size_t > sizeVec;
77
+
78
+ // Only parse outer array definition, i.e. the right `]` should be at the end of the type name
79
+ std::string prefix{typeName};
80
+ while (prefix.back () == ' ]' ) {
81
+ auto posRBrace = prefix.size () - 1 ;
82
+ auto posLBrace = prefix.rfind (' [' , posRBrace);
83
+ if (posLBrace == std::string_view::npos) {
84
+ throw ROOT::RException (R__FAIL (std::string (" invalid array type: " ) + typeName));
85
+ }
86
+ if (posRBrace - posLBrace <= 1 ) {
87
+ throw ROOT::RException (R__FAIL (std::string (" invalid array type: " ) + typeName));
88
+ }
89
+
90
+ const std::size_t size =
91
+ ROOT::Internal::ParseUIntTypeToken (prefix.substr (posLBrace + 1 , posRBrace - posLBrace - 1 ));
92
+ if (size == 0 ) {
93
+ throw ROOT::RException (R__FAIL (std::string (" invalid array size: " ) + typeName));
94
+ }
95
+
96
+ sizeVec.insert (sizeVec.begin (), size);
97
+ prefix.resize (posLBrace);
98
+ }
99
+ return std::make_tuple (prefix, sizeVec);
100
+ }
101
+
102
+ // / Assembles a (nested) std::array<> based type based on the dimensions retrieved from ParseArrayType(). Returns
103
+ // / baseType if there are no dimensions.
104
+ std::string GetStandardArrayType (const std::string &baseType, const std::vector<std::size_t > &dimensions)
105
+ {
106
+ std::string typeName = baseType;
107
+ for (auto i = dimensions.rbegin (), iEnd = dimensions.rend (); i != iEnd; ++i) {
108
+ typeName = " std::array<" + typeName + " ," + std::to_string (*i) + " >" ;
109
+ }
110
+ return typeName;
111
+ }
112
+
69
113
// Recursively normalizes a template argument using the regular type name normalizer F as a helper.
70
114
template <typename F>
71
115
std::string GetNormalizedTemplateArg (const std::string &arg, bool keepQualifier, F fnTypeNormalizer)
@@ -85,7 +129,7 @@ std::string GetNormalizedTemplateArg(const std::string &arg, bool keepQualifier,
85
129
// strips the qualifier.
86
130
// Demangled names may have the CV qualifiers suffixed and not prefixed (but const always before volatile).
87
131
// Note that in the latter case, we may have the CV qualifiers before array brackets, e.g. `int const[2]`.
88
- const auto [base, _] = ROOT::Internal:: ParseArrayType (arg);
132
+ const auto [base, _] = ParseArrayType (arg);
89
133
if (base.rfind (" const " , 0 ) == 0 || base.rfind (" volatile const " , 0 ) == 0 ||
90
134
base.find (" const" , base.length () - 6 ) != std::string::npos ||
91
135
base.find (" const volatile" , base.length () - 15 ) != std::string::npos) {
@@ -336,7 +380,7 @@ void NormalizeTemplateArguments(std::string &templatedTypeName, int maxTemplateA
336
380
// Given a type name normalized by ROOT Meta, return the type name normalized according to the RNTuple rules.
337
381
std::string GetRenormalizedMetaTypeName (const std::string &metaNormalizedName)
338
382
{
339
- const std::string canonicalTypePrefix{ ROOT::Internal::GetCanonicalTypePrefix (metaNormalizedName)} ;
383
+ const auto canonicalTypePrefix = ROOT::Internal::GetCanonicalTypePrefix (metaNormalizedName);
340
384
// RNTuple resolves Double32_t for the normalized type name but keeps Double32_t for the type alias
341
385
// (also in template parameters)
342
386
if (canonicalTypePrefix == " Double32_t" )
@@ -357,14 +401,16 @@ std::string GetRenormalizedMetaTypeName(const std::string &metaNormalizedName)
357
401
// RNTuple rules.
358
402
std::string GetRenormalizedDemangledTypeName (const std::string &demangledName, bool renormalizeStdString)
359
403
{
360
- std::string canonicalTypePrefix{demangledName};
404
+ std::string tn{demangledName};
405
+ RemoveSpaceBefore (tn, ' [' );
406
+ auto [canonicalTypePrefix, dimensions] = ParseArrayType (tn);
361
407
RemoveCVQualifiers (canonicalTypePrefix);
362
408
RemoveLeadingKeyword (canonicalTypePrefix);
363
409
MapIntegerType (canonicalTypePrefix);
364
410
365
411
if (canonicalTypePrefix.find (' <' ) == std::string::npos) {
366
412
// If there are no templates, the function is done.
367
- return canonicalTypePrefix;
413
+ return GetStandardArrayType ( canonicalTypePrefix, dimensions) ;
368
414
}
369
415
RemoveSpaceBefore (canonicalTypePrefix, ' >' );
370
416
RemoveSpaceAfter (canonicalTypePrefix, ' ,' );
@@ -396,15 +442,21 @@ std::string GetRenormalizedDemangledTypeName(const std::string &demangledName, b
396
442
RenormalizeStdString (normName);
397
443
}
398
444
399
- return normName;
445
+ return GetStandardArrayType ( normName, dimensions) ;
400
446
}
401
447
402
448
} // namespace
403
449
404
450
std::string ROOT::Internal::GetCanonicalTypePrefix (const std::string &typeName)
405
451
{
406
- // Remove outer cv qualifiers
407
- std::string canonicalType{TClassEdit::CleanType (typeName.c_str (), /* mode=*/ 1 )};
452
+ // Remove outer cv qualifiers and extra white spaces
453
+ const std::string cleanedType = TClassEdit::CleanType (typeName.c_str (), /* mode=*/ 1 );
454
+
455
+ // Can happen when called from RFieldBase::Create() and is caught there
456
+ if (cleanedType.empty ())
457
+ return " " ;
458
+
459
+ auto [canonicalType, dimensions] = ParseArrayType (cleanedType);
408
460
409
461
RemoveLeadingKeyword (canonicalType);
410
462
if (canonicalType.substr (0 , 2 ) == " ::" ) {
@@ -456,7 +508,7 @@ std::string ROOT::Internal::GetCanonicalTypePrefix(const std::string &typeName)
456
508
457
509
MapIntegerType (canonicalType);
458
510
459
- return canonicalType;
511
+ return GetStandardArrayType ( canonicalType, dimensions) ;
460
512
}
461
513
462
514
std::string ROOT::Internal::GetRenormalizedTypeName (const std::type_info &ti)
@@ -474,9 +526,9 @@ std::string ROOT::Internal::GetNormalizedUnresolvedTypeName(const std::string &o
474
526
const TClassEdit::EModType modType = static_cast <TClassEdit::EModType>(
475
527
TClassEdit::kDropStlDefault | TClassEdit::kDropComparator | TClassEdit::kDropHash );
476
528
TClassEdit::TSplitType splitname (origName.c_str (), modType);
477
- std::string canonicalTypePrefix ;
478
- splitname.ShortType (canonicalTypePrefix , modType);
479
- canonicalTypePrefix = GetCanonicalTypePrefix (canonicalTypePrefix );
529
+ std::string shortType ;
530
+ splitname.ShortType (shortType , modType);
531
+ const auto canonicalTypePrefix = GetCanonicalTypePrefix (shortType );
480
532
481
533
if (canonicalTypePrefix.find (' <' ) == std::string::npos) {
482
534
// If there are no templates, the function is done.
@@ -620,30 +672,6 @@ ROOT::Internal::ERNTupleSerializationMode ROOT::Internal::GetRNTupleSerializatio
620
672
}
621
673
}
622
674
623
- std::tuple<std::string, std::vector<std::size_t >> ROOT::Internal::ParseArrayType (const std::string &typeName)
624
- {
625
- std::vector<std::size_t > sizeVec;
626
-
627
- // Only parse outer array definition, i.e. the right `]` should be at the end of the type name
628
- std::string prefix{typeName};
629
- while (prefix.back () == ' ]' ) {
630
- auto posRBrace = prefix.size () - 1 ;
631
- auto posLBrace = prefix.rfind (' [' , posRBrace);
632
- if (posLBrace == std::string_view::npos) {
633
- throw RException (R__FAIL (std::string (" invalid array type: " ) + typeName));
634
- }
635
-
636
- const std::size_t size = ParseUIntTypeToken (prefix.substr (posLBrace + 1 , posRBrace - posLBrace - 1 ));
637
- if (size == 0 ) {
638
- throw RException (R__FAIL (std::string (" invalid array size: " ) + typeName));
639
- }
640
-
641
- sizeVec.insert (sizeVec.begin (), size);
642
- prefix.resize (posLBrace);
643
- }
644
- return std::make_tuple (prefix, sizeVec);
645
- }
646
-
647
675
std::vector<std::string> ROOT::Internal::TokenizeTypeList (std::string_view templateType, std::size_t maxArgs)
648
676
{
649
677
std::vector<std::string> result;
0 commit comments