23 ClassImp(TSchemaRule);
28 static Bool_t IsIrrelevantCharacter(
char c)
30 return (c ==
' ' || c ==
'\n' || c ==
'\t');
33 static void AdvanceOverIrrelevantCharacter(
const char*& str)
35 while (IsIrrelevantCharacter(*str)) {
42 static Bool_t IsCodeEquivalent(
const TString& lhs,
const TString& rhs)
44 Bool_t result = kTRUE;
47 const char null =
'\0';
48 const char* left = lhs.Data();
49 const char* right = rhs.Data();
50 Bool_t literal =
false;
52 AdvanceOverIrrelevantCharacter(left);
53 AdvanceOverIrrelevantCharacter(right);
55 while (*left != null || *right != null) {
57 if (!literal && IsIrrelevantCharacter(*left) && IsIrrelevantCharacter(*right)) {
58 AdvanceOverIrrelevantCharacter(left);
59 AdvanceOverIrrelevantCharacter(right);
63 if (*left == null || *right == null) {
64 AdvanceOverIrrelevantCharacter(left);
65 AdvanceOverIrrelevantCharacter(right);
66 result = (*left == null && *right == null);
70 if (*left != *right) {
90 TSchemaRule::TSchemaRule(): fVersionVect( 0 ), fChecksumVect( 0 ),
91 fTargetVect( 0 ), fSourceVect( 0 ),
92 fIncludeVect( 0 ), fEmbed( kTRUE ),
93 fReadFuncPtr( 0 ), fReadRawFuncPtr( 0 ),
101 TSchemaRule::~TSchemaRule()
104 delete fChecksumVect;
113 TSchemaRule::TSchemaRule(
const TSchemaRule& rhs ): TObject( rhs ),
114 fVersionVect( 0 ), fChecksumVect( 0 ),
115 fTargetVect( 0 ), fSourceVect( 0 ),
116 fIncludeVect( 0 ), fEmbed( kTRUE ),
117 fReadFuncPtr( 0 ), fReadRawFuncPtr( 0 ),
126 TSchemaRule& TSchemaRule::operator = (
const TSchemaRule& rhs )
129 fVersion = rhs.fVersion;
130 fChecksum = rhs.fChecksum;
131 fSourceClass = rhs.fSourceClass;
132 fTarget = rhs.fTarget;
133 fSource = rhs.fSource;
134 fInclude = rhs.fInclude;
137 fReadFuncPtr = rhs.fReadFuncPtr;
138 fReadRawFuncPtr = rhs.fReadRawFuncPtr;
139 fRuleType = rhs.fRuleType;
140 fAttributes = rhs.fAttributes;
148 Bool_t TSchemaRule::operator == (
const TSchemaRule& rhs )
const
151 Bool_t result = ( fVersion == rhs.fVersion
152 && fChecksum == rhs.fChecksum
153 && fSourceClass == rhs.fSourceClass
154 && fTargetClass == rhs.fTargetClass
155 && fSource == rhs.fSource
156 && fTarget == rhs.fTarget
157 && fInclude == rhs.fInclude
158 && IsCodeEquivalent(fCode, rhs.fCode)
159 && fEmbed == rhs.fEmbed
160 && fRuleType == rhs.fRuleType
161 && fAttributes == rhs.fAttributes );
163 ( (fReadRawFuncPtr != rhs.fReadRawFuncPtr && fReadRawFuncPtr != 0 && rhs.fReadRawFuncPtr != 0)
164 || (fReadFuncPtr != rhs.fReadFuncPtr && fReadFuncPtr != 0 && rhs.fReadFuncPtr != 0) ) )
178 void TSchemaRule::ls(Option_t *targetname)
const
180 TROOT::IndentLevel();
181 std::cout <<
"Schema Evolution Rule: ";
182 if (fRuleType==kReadRule) std::cout <<
"read ";
183 else if (fRuleType==kReadRawRule) std::cout <<
"readraw ";
185 TROOT::IncreaseDirLevel();
186 TROOT::IndentLevel();
187 std::cout <<
"sourceClass=\"" << fSourceClass <<
"\" ";
188 if (fVersion.Length()) std::cout <<
"version=\"" << fVersion <<
"\" ";
189 if (fChecksum.Length()) std::cout <<
"checksum=\"" << fChecksum <<
"\" ";
190 if (targetname && targetname[0]) std::cout <<
"targetClass=\"" << targetname <<
"\" ";
191 else std::cout <<
"targetClass\"" << fTargetClass <<
"\" ";
193 TROOT::IndentLevel();
194 std::cout <<
"source=\"" << fSource <<
"\" ";
195 std::cout <<
"target=\"" << fTarget <<
"\" ";
197 if (fInclude.Length()) {
198 TROOT::IndentLevel();
199 std::cout <<
"include=\"" << fInclude <<
"\" " <<
"\n";
201 if (fAttributes.Length()) {
202 TROOT::IndentLevel();
203 std::cout <<
"attributes=\"" << fAttributes <<
"\"" <<
"\n";
205 if (fCode.Length()) {
206 TROOT::IndentLevel();
207 std::cout <<
"code=\"{" << fCode <<
"}\" "
210 TROOT::DecreaseDirLevel();
219 void TSchemaRule::AsString(TString &out,
const char *options)
const
221 TString opt(options);
223 Bool_t shortform = opt.Contains(
's');
224 Bool_t xmlform = opt.Contains(
'x');
235 if (fRuleType==kReadRule) { out +=
"read "; end =
"</read>"; }
236 else if (fRuleType==kReadRawRule) { out +=
"readraw "; end =
"</readraw>"; }
237 else { out +=
"-- "; end =
"-->"; }
240 if (!shortform || fRuleType!=kReadRule) {
242 if (fRuleType==kReadRule) out +=
"read ";
243 else if (fRuleType==kReadRawRule) out +=
"readraw ";
247 if (!shortform || (fSourceClass != fTargetClass) ) {
248 out +=
"sourceClass=\"" + fSourceClass +
"\" ";
249 out +=
"targetClass=\"" + fTargetClass +
"\" ";
251 out += fSourceClass +
" ";
253 if (shortform && fTarget == fSource) {
254 out += fSource +
" ";
256 if (!shortform || (fVersion !=
"[1-]")) {
257 if (fVersion.Length()) out +=
"version=\"" + fVersion +
"\" ";
259 if (fChecksum.Length()) out +=
"checksum=\"" + fChecksum +
"\" ";
260 if (!shortform || fTarget != fSource) {
261 out +=
"source=\"" + fSource +
"\" ";
262 out +=
"target=\"" + fTarget +
"\" ";
264 if (fInclude.Length()) out +=
"include=\"" + fInclude +
"\" ";
265 if (fAttributes.Length()) out +=
"attributes=\"" + fAttributes +
"\" ";
270 if (fCode.Length()) {
271 out +=
"\n<![CDATA[ { " + fCode +
" ]]>\n ";
272 }
else if (fReadFuncPtr) {
275 }
else if (fReadRawFuncPtr) {
280 if (fCode.Length()) {
281 out +=
"code=\"{" + fCode +
"}\" ";
282 }
else if (fReadFuncPtr) {
285 }
else if (fReadRawFuncPtr) {
298 void TSchemaRule::Clear(
const char * )
302 fSourceClass.Clear();
311 delete fVersionVect; fVersionVect = 0;
312 delete fChecksumVect; fChecksumVect = 0;
313 delete fTargetVect; fTargetVect = 0;
314 delete fSourceVect; fSourceVect = 0;
315 delete fIncludeVect; fIncludeVect = 0;
322 Bool_t TSchemaRule::SetFromRule(
const char *rule )
328 ROOT::Internal::MembersMap_t rule_values;
330 std::string error_string;
331 if( !ROOT::ParseRule(rule, rule_values, error_string) ) {
332 Error(
"SetFromRule",
"The rule (%s) is invalid: %s",rule,error_string.c_str());
335 ROOT::Internal::MembersMap_t::const_iterator it1;
337 it1 = rule_values.find(
"type" );
338 if( it1 != rule_values.end() ) {
339 if (it1->second ==
"read" || it1->second ==
"Read") {
340 SetRuleType( TSchemaRule::kReadRule );
341 }
else if (it1->second ==
"readraw" || it1->second ==
"ReadRaw") {
342 SetRuleType( TSchemaRule::kReadRawRule );
344 SetRuleType( TSchemaRule::kNone );
348 SetRuleType( TSchemaRule::kReadRule );
350 it1 = rule_values.find(
"targetClass" );
351 if( it1 != rule_values.end() ) SetTargetClass( it1->second );
352 it1 = rule_values.find(
"sourceClass" );
353 if( it1 != rule_values.end() ) SetSourceClass( it1->second );
354 it1 = rule_values.find(
"target" );
355 if( it1 != rule_values.end() ) SetTarget( it1->second );
356 it1 = rule_values.find(
"source" );
357 if( it1 != rule_values.end() ) SetSource( it1->second );
358 it1 = rule_values.find(
"version" );
359 if( it1 != rule_values.end() ) SetVersion( it1->second );
360 it1 = rule_values.find(
"checksum" );
361 if( it1 != rule_values.end() ) SetChecksum( it1->second );
362 it1 = rule_values.find(
"embed" );
363 if( it1 != rule_values.end() ) SetEmbed( it1->second ==
"false" ?
false :
true );
364 it1 = rule_values.find(
"include" );
365 if( it1 != rule_values.end() ) SetInclude( it1->second );
366 it1 = rule_values.find(
"attributes" );
367 if( it1 != rule_values.end() ) SetAttributes( it1->second );
368 it1 = rule_values.find(
"code" );
369 if( it1 != rule_values.end() ) SetCode( it1->second );
382 Bool_t TSchemaRule::SetVersion(
const TString& version )
385 Bool_t ret = ProcessVersion( version );
394 const char *TSchemaRule::GetVersion()
const
403 Bool_t TSchemaRule::TestVersion( Int_t version )
const
409 ProcessVersion( fVersion );
415 std::vector<std::pair<Int_t, Int_t> >::iterator it;
416 for( it = fVersionVect->begin(); it != fVersionVect->end(); ++it ) {
417 if( version >= it->first && version <= it->second )
426 Bool_t TSchemaRule::SetChecksum(
const TString& checksum )
429 Bool_t ret = ProcessChecksum( checksum );
431 fChecksum = checksum;
438 Bool_t TSchemaRule::TestChecksum( UInt_t checksum )
const
440 if( fChecksum ==
"" )
444 ProcessChecksum( fChecksum );
446 std::vector<UInt_t>::iterator it;
447 for( it = fChecksumVect->begin(); it != fChecksumVect->end(); ++it ) {
448 if( checksum == *it )
457 void TSchemaRule::SetSourceClass(
const TString& classname )
459 std::string normalizedName;
460 TClassEdit::GetNormalizedName(normalizedName, classname);
461 fSourceClass = normalizedName;
467 const char *TSchemaRule::GetSourceClass()
const
475 void TSchemaRule::SetTargetClass(
const TString& classname )
477 std::string normalizedName;
478 TClassEdit::GetNormalizedName(normalizedName, classname);
479 fTargetClass = normalizedName;
485 const char *TSchemaRule::GetTargetClass()
const
493 void TSchemaRule::SetTarget(
const TString& target )
504 fTargetVect =
new TObjArray();
505 fTargetVect->SetOwner();
507 ProcessList( fTargetVect, target );
513 const char *TSchemaRule::GetTargetString()
const
521 const TObjArray* TSchemaRule::GetTarget()
const
527 fTargetVect =
new TObjArray();
528 fTargetVect->SetOwner();
529 ProcessList( fTargetVect, fTarget );
539 void TSchemaRule::SetSource(
const TString& source )
550 fSourceVect =
new TObjArray();
551 fSourceVect->SetOwner();
554 ProcessDeclaration( fSourceVect, source );
561 const TObjArray* TSchemaRule::GetSource()
const
567 fSourceVect =
new TObjArray();
568 fSourceVect->SetOwner();
569 ProcessDeclaration( fSourceVect, fSource );
578 void TSchemaRule::SetInclude(
const TString& incl )
588 if( !fIncludeVect ) {
589 fIncludeVect =
new TObjArray();
590 fIncludeVect->SetOwner();
593 ProcessList( fIncludeVect, incl );
600 const TObjArray* TSchemaRule::GetInclude()
const
605 if( !fIncludeVect ) {
606 fIncludeVect =
new TObjArray();
607 fIncludeVect->SetOwner();
608 ProcessList( fIncludeVect, fInclude );
617 void TSchemaRule::SetEmbed( Bool_t embed )
625 Bool_t TSchemaRule::GetEmbed()
const
633 Bool_t TSchemaRule::IsValid()
const
635 return (fVersionVect || fChecksumVect) && (fSourceClass.Length() != 0);
641 void TSchemaRule::SetCode(
const TString& code )
649 const char *TSchemaRule::GetCode()
const
657 void TSchemaRule::SetAttributes(
const TString& attributes )
659 fAttributes = attributes;
665 const char *TSchemaRule::GetAttributes()
const
673 Bool_t TSchemaRule::HasTarget(
const TString& target )
const
679 TObjArrayIter it( fTargetVect );
680 while( (obj = it.Next()) ) {
681 TObjString* str = (TObjString*)obj;
682 if( str->GetString() == target )
691 Bool_t TSchemaRule::HasSource(
const TString& source )
const
697 TObjArrayIter it( fSourceVect );
698 while( (obj = it.Next()) ) {
699 TSources* var = (TSources*)obj;
700 if( var->GetName() == source )
709 void TSchemaRule::SetReadFunctionPointer( TSchemaRule::ReadFuncPtr_t ptr )
717 TSchemaRule::ReadFuncPtr_t TSchemaRule::GetReadFunctionPointer()
const
725 void TSchemaRule::SetReadRawFunctionPointer( TSchemaRule::ReadRawFuncPtr_t ptr )
727 fReadRawFuncPtr = ptr;
733 TSchemaRule::ReadRawFuncPtr_t TSchemaRule::GetReadRawFunctionPointer()
const
735 return fReadRawFuncPtr;
741 void TSchemaRule::SetRuleType( TSchemaRule::RuleType_t type )
749 Bool_t TSchemaRule::IsAliasRule()
const
751 return fSourceClass !=
"" && (fVersion !=
"" || fChecksum !=
"") && fTarget ==
"" && fSource ==
"" && fInclude ==
"" && fCode ==
"" && fAttributes ==
"";
757 Bool_t TSchemaRule::IsRenameRule()
const
759 return fSourceClass !=
"" && (fVersion !=
"" || fChecksum !=
"") && fTarget !=
"" && fSource !=
"" && fInclude ==
"" && fCode ==
"" && fAttributes ==
"";
765 TSchemaRule::RuleType_t TSchemaRule::GetRuleType()
const
773 Bool_t TSchemaRule::Conflicts(
const TSchemaRule* rule )
const
779 if( fSourceClass != rule->fSourceClass )
786 if( !rule->GetTarget() )
789 Bool_t haveCommonTargets = kFALSE;
790 TObjArrayIter titer( rule->GetTarget() );
794 while( (obj = titer.Next() ) ) {
795 str = (TObjString*)obj;
796 if( HasTarget( str->String() ) )
797 haveCommonTargets = kTRUE;
800 if( !haveCommonTargets )
807 if( fChecksumVect ) {
808 std::vector<UInt_t>::iterator it;
809 for( it = fChecksumVect->begin(); it != fChecksumVect->end(); ++it )
810 if( rule->TestChecksum( *it ) )
818 if( fVersionVect && rule->fVersionVect )
820 std::vector<std::pair<Int_t, Int_t> >::iterator it1;
821 std::vector<std::pair<Int_t, Int_t> >::iterator it2;
822 for( it1 = fVersionVect->begin(); it1 != fVersionVect->end(); ++it1 ) {
823 for( it2 = rule->fVersionVect->begin();
824 it2 != rule->fVersionVect->end(); ++it2 ) {
829 if( it1->first >= it2->first && it1->first <= it2->second )
832 if( it1->first < it2->first && it1->second >= it2->first )
843 Bool_t TSchemaRule::ProcessVersion(
const TString& version )
const
849 if( version[0] !=
'[' || version[version.Length()-1] !=
']' )
851 std::string ver = version.Data();
853 std::list<std::string> versions;
854 Internal::TSchemaRuleProcessor::SplitList( ver.substr( 1, ver.size()-2), versions );
856 if( versions.empty() )
864 fVersionVect =
new std::vector<std::pair<Int_t, Int_t> >;
865 fVersionVect->clear();
871 std::list<std::string>::iterator it;
872 for( it = versions.begin(); it != versions.end(); ++it ) {
873 std::pair<Int_t, Int_t> verpair;
874 if( !Internal::TSchemaRuleProcessor::ProcessVersion( *it, verpair ) )
880 fVersionVect->push_back( verpair );
888 Bool_t TSchemaRule::ProcessChecksum(
const TString& checksum )
const
896 std::string chk = (
const char*)checksum;
897 if( chk[0] !=
'[' || chk[chk.size()-1] !=
']' )
900 std::list<std::string> checksums;
901 Internal::TSchemaRuleProcessor::SplitList( chk.substr( 1, chk.size()-2), checksums );
903 if( checksums.empty() ) {
904 delete fChecksumVect;
910 fChecksumVect =
new std::vector<UInt_t>;
911 fChecksumVect->clear();
917 for(
const auto& checksumStr : checksums ) {
918 auto chksum = ParseChecksum( checksumStr.c_str() );
920 delete fChecksumVect;
921 fChecksumVect =
nullptr;
925 fChecksumVect->push_back( chksum );
934 UInt_t TSchemaRule::ParseChecksum(
const char* checksum)
const {
935 std::istringstream converter(checksum);
937 converter >> std::hex >> chksum;
938 if (converter.fail()) {
941 converter >> std::dec >> chksum;
944 if( converter.fail() ) {
954 void TSchemaRule::ProcessList( TObjArray* array,
const TString& list )
956 std::list<std::string> elems;
957 std::list<std::string>::iterator it;
958 Internal::TSchemaRuleProcessor::SplitList( (
const char*)list, elems );
965 for( it = elems.begin(); it != elems.end(); ++it ) {
966 TObjString *str =
new TObjString;
975 void TSchemaRule::ProcessDeclaration( TObjArray* array,
const TString& list )
977 std::list<std::pair<ROOT::Internal::TSchemaType,std::string> > elems;
978 std::list<std::pair<ROOT::Internal::TSchemaType,std::string> >::iterator it;
979 Internal::TSchemaRuleProcessor::SplitDeclaration( (
const char*)list, elems );
986 for( it = elems.begin(); it != elems.end(); ++it ) {
987 TSources *type =
new TSources( it->second.c_str(), it->first.fType.c_str(), it->first.fDimensions.c_str() ) ;
996 Bool_t TSchemaRule::GenerateFor( TStreamerInfo *info )
998 String funcname = fSourceClass +
"_to_" + fTargetClass;
999 if (info) funcname +=
"_v" + info->GetClassVersion();
1000 TString names = fSource +
"_" + fTarget;
1001 name.ReplaceAll(
',',
'_');
1002 name.ReplaceAll(
':',
'_');
1003 funcname +=
"_" + name;
1005 String filename = funcname +
".C";
1010 std::ofstream fileout(filename);
1013 ROOT::WriteReadRawRuleFunc( *rIt, 0, mappedname, nameTypeMap, fileout );
1014 ROOT::WriteReadRuleFunc( *rIt, 0, mappedname, nameTypeMap, fileout );
1016 gROOT->LoadMacro(filename);