Logo ROOT  
Reference Guide
TSchemaRuleSet.cxx
Go to the documentation of this file.
1// @(#)root/core:$Id$
2// author: Lukasz Janyst <ljanyst@cern.ch>
3
4#include "TSchemaRuleSet.h"
5#include "TSchemaRule.h"
6#include "TObjArray.h"
7#include "TObjString.h"
8#include "TClass.h"
9#include "TROOT.h"
10#include "TBuffer.h"
11#include <iostream>
12
15#include "TVirtualMutex.h"
16#include "TInterpreter.h" // For gInterpreterMutex
17#include "TStreamerElement.h"
18#include "TClassEdit.h"
19
21
22using namespace ROOT;
23using namespace ROOT::Detail;
24
25////////////////////////////////////////////////////////////////////////////////
26/// Default constructor.
27
28TSchemaRuleSet::TSchemaRuleSet(): fPersistentRules( nullptr ), fRemainingRules( nullptr ),
29 fAllRules( nullptr ), fVersion(-3), fCheckSum( 0 )
30{
33 fAllRules = new TObjArray();
35}
36
37////////////////////////////////////////////////////////////////////////////////
38/// Destructor.
39
41{
42 delete fPersistentRules;
43 delete fRemainingRules;
44 delete fAllRules;
45}
46
47////////////////////////////////////////////////////////////////////////////////
48/// The ls function lists the contents of a class on stdout. Ls output
49/// is typically much less verbose then Dump().
50
52{
54 std::cout << "TSchemaRuleSet for " << fClassName << ":\n";
56 TObject *object = nullptr;
58 while ((object = next())) {
59 object->ls(fClassName);
60 }
62}
63
64////////////////////////////////////////////////////////////////////////////////
65
66Bool_t TSchemaRuleSet::AddRules( TSchemaRuleSet* /* rules */, EConsistencyCheck /* checkConsistency */, TString * /* errmsg */ )
67{
68 return kFALSE;
69}
70
71////////////////////////////////////////////////////////////////////////////////
72/// The consistency check always fails if the TClass object was not set!
73/// if checkConsistency is:
74/// kNoCheck: no check is done, register the rule as is
75/// kCheckConflict: check only for conflicting rules
76/// kCheckAll: check for conflict and check for rule about members that are not in the current class layout.
77/// return kTRUE if the layout is accepted, in which case we take ownership of
78/// the rule object.
79/// return kFALSE if the rule failed one of the test, the rule now needs to be deleted by the caller.
80
82{
83 //---------------------------------------------------------------------------
84 // Cannot verify the consistency if the TClass object is not present
85 /////////////////////////////////////////////////////////////////////////////
86
87 if( (checkConsistency != kNoCheck) && !fClass )
88 return kFALSE;
89
90 if( !rule->IsValid() )
91 return kFALSE;
92
93 //---------------------------------------------------------------------------
94 // If we don't check the consistency then we should just add the object
95 /////////////////////////////////////////////////////////////////////////////
96
97 if( checkConsistency == kNoCheck ) {
98 if( rule->GetEmbed() )
99 fPersistentRules->Add( rule );
100 else
101 fRemainingRules->Add( rule );
102 fAllRules->Add( rule );
103 return kTRUE;
104 }
105
106 //---------------------------------------------------------------------------
107 // Check if all of the target data members specified in the rule are
108 // present int the target class
109 /////////////////////////////////////////////////////////////////////////////
110
111 // Check only if we have some information about the class, otherwise we have
112 // nothing to check against
113 bool streamerInfosTest;
114 {
116 streamerInfosTest = (fClass->GetStreamerInfos()==nullptr || fClass->GetStreamerInfos()->IsEmpty());
117 }
118 if( rule->GetTarget() && !(fClass->TestBit(TClass::kIsEmulation) && streamerInfosTest) ) {
119 TObjArrayIter titer( rule->GetTarget() );
120 TObject* obj;
121 while( (obj = titer.Next()) ) {
122 TObjString* str = (TObjString*)obj;
123 if( !fClass->GetDataMember( str->GetString() ) && !fClass->GetBaseClass( str->GetString() ) ) {
124 if (checkConsistency == kCheckAll) {
125 if (errmsg) {
126 errmsg->Form("the target member (%s) is unknown",str->GetString().Data());
127 }
128 return kFALSE;
129 } else {
130 // We ignore the rules that do not apply ...
131 delete rule;
132 return kTRUE;
133 }
134 }
135 }
136 }
137
138 //---------------------------------------------------------------------------
139 // Check if there is a rule conflicting with this one
140 /////////////////////////////////////////////////////////////////////////////
141
142 std::vector<const TSchemaRule*> rules = FindRules( rule->GetSourceClass() );
143 //TObjArrayIter it( rules );
144 //TSchemaRule *r;
145
146 for(auto r : rules) { // while( (obj = it.Next()) ) {
147 if( rule->Conflicts( r ) ) {
148 //delete rules;
149 if ( *r == *rule) {
150 // The rules are duplicate from each other,
151 // just ignore the new ones.
152 if (errmsg) {
153 *errmsg = "it conflicts with one of the other rules";
154 }
155 delete rule;
156 return kTRUE;
157 }
158 if (errmsg) {
159 *errmsg = "The existing rule is:\n ";
160 r->AsString(*errmsg,"s");
161 *errmsg += "\nand the ignored rule is:\n ";
162 rule->AsString(*errmsg);
163 *errmsg += ".\n";
164 }
165 return kFALSE;
166 }
167 }
168
169 //---------------------------------------------------------------------------
170 // No conflicts - insert the rules
171 /////////////////////////////////////////////////////////////////////////////
172
173 if( rule->GetEmbed() )
174 fPersistentRules->Add( rule );
175 else
176 fRemainingRules->Add( rule );
177 fAllRules->Add( rule );
178
179 return kTRUE;
180}
181
182////////////////////////////////////////////////////////////////////////////////
183/// Fill the string 'out' with the string representation of the rule.
184
186{
188 TSchemaRule *rule;
189 while( (rule = (TSchemaRule*)it.Next()) ) {
190 rule->AsString(out);
191 out += "\n";
192 }
193}
194
195////////////////////////////////////////////////////////////////////////////////
196/// Return True if we have any rule whose source class is 'source'.
197
199{
201 TObject *obj;
202 while( (obj = it.Next()) ) {
203 TSchemaRule* rule = (TSchemaRule*)obj;
204 if( rule->GetSourceClass() == source )
205 return kTRUE;
206 }
207 // There was no explicit rule, let's see we have implicit rules.
208 if (fClass->GetCollectionProxy()) {
209 if (fClass->GetCollectionProxy()->GetValueClass() == nullptr) {
210 // We have a numeric collection, let see if the target is
211 // also a numeric collection.
212 TClass *src = TClass::GetClass(source);
213 if (src && src->GetCollectionProxy() &&
216 if (proxy->GetValueClass() == nullptr) {
217 return kTRUE;
218 }
219 }
220 } else {
221 TClass *vTargetClass = fClass->GetCollectionProxy()->GetValueClass();
222 TClass *src = TClass::GetClass(source);
223 if (vTargetClass->GetSchemaRules()) {
224 if (src && src->GetCollectionProxy() &&
226 TClass *vSourceClass = src->GetCollectionProxy()->GetValueClass();
227 if (vSourceClass) {
228 return vTargetClass->GetSchemaRules()->HasRuleWithSourceClass( vSourceClass->GetName() );
229 }
230 }
231 }
232 }
233 } else if (TClassEdit::IsStdPair(fClass->GetName())) {
234 if (TClassEdit::IsStdPair(source)) {
235 // std::pair can be converted into each other if both its parameter can be converted into
236 // each other.
237 TClass *src = TClass::GetClass(source);
238 if (!src) {
239 Error("HasRuleWithSourceClass","Can not find the TClass for %s when matching with %s\n",source.Data(),fClass->GetName());
240 return kFALSE;
241 }
242 TVirtualStreamerInfo *sourceInfo = src->GetStreamerInfo();
244 if (!sourceInfo) {
245 Error("HasRuleWithSourceClass","Can not find the StreamerInfo for %s when matching with %s\n",source.Data(),fClass->GetName());
246 return kFALSE;
247 }
248 if (!targetInfo) {
249 Error("HasRuleWithSourceClass","Can not find the StreamerInfo for target class %s\n",fClass->GetName());
250 return kFALSE;
251 }
252 for(int i = 0 ; i<2 ; ++i) {
253 TStreamerElement *sourceElement = (TStreamerElement*)sourceInfo->GetElements()->At(i);
254 TStreamerElement *targetElement = (TStreamerElement*)targetInfo->GetElements()->At(i);
255 if (sourceElement->GetClass()) {
256 if (!targetElement->GetClass()) {
257 return kFALSE;
258 }
259 if (sourceElement->GetClass() == targetElement->GetClass()) {
260 continue;
261 }
262 TSchemaRuleSet *rules = sourceElement->GetClass()->GetSchemaRules();
263 if (!rules || !rules->HasRuleWithSourceClass( targetElement->GetClass()->GetName() ) ) {
264 return kFALSE;
265 }
266 } else if (targetElement->GetClass()) {
267 return kFALSE;
268 } else {
269 // both side are numeric element we can deal with it.
270 }
271 }
272 // Both side are pairs and have convertible types, let records this as a renaming rule
273 ROOT::TSchemaRule *ruleobj = new ROOT::TSchemaRule();
274 ruleobj->SetSourceClass(source);
275 ruleobj->SetTargetClass(fClass->GetName());
276 ruleobj->SetVersion("[1-]");
277 const_cast<TSchemaRuleSet*>(this)->AddRule(ruleobj);
278 return kTRUE;
279 }
280 }
281 return kFALSE;
282}
283
284////////////////////////////////////////////////////////////////////////////////
285/// Return all the rules that are about the given 'source' class.
286/// User has to delete the returned array
287
289{
290 TObject* obj;
292 TMatches arr;
293 // arr->SetOwner( kFALSE );
294
295 while( (obj = it.Next()) ) {
296 TSchemaRule* rule = (TSchemaRule*)obj;
297 if( rule->GetSourceClass() == source )
298 arr.push_back( rule );
299 }
300
301#if 0
302 // Le't's see we have implicit rules.
303 if (fClass->GetCollectionProxy()) {
307 // We have a numeric collection, let see if the target is
308 // also a numeric collection (humm just a vector for now)
309 TClass *src = TClass::GetClass(source);
310 if (src && src->GetCollectionProxy()) {
312 if (proxy->GetValueClass() == 0) {
313 // ... would need to check if we already have
314 // the rule (or any rule?)
315 }
316 }
317 }
318 }
319#endif
320 return arr;
321}
322
323////////////////////////////////////////////////////////////////////////////////
324/// Return all the rules that applies to the specified version of the given 'source' class.
325/// User has to delete the returned array
326
328{
329 TObject* obj;
331 TMatches arr;
332 // arr->SetOwner( kFALSE );
333
334 while( (obj = it.Next()) ) {
335 TSchemaRule* rule = (TSchemaRule*)obj;
336 if( rule->GetSourceClass() == source && rule->TestVersion( version ) )
337 arr.push_back( rule );
338 }
339
340 return arr;
341}
342
343////////////////////////////////////////////////////////////////////////////////
344/// Return all the rules that applies to the specified checksum of the given 'source' class.
345/// User has to delete the returned array
346
348{
349 TObject* obj;
351 TMatches arr;
352 // arr->SetOwner( kFALSE );
353
354 while( (obj = it.Next()) ) {
355 TSchemaRule* rule = (TSchemaRule*)obj;
356 if( rule->GetSourceClass() == source && rule->TestChecksum( checksum ) )
357 arr.push_back( rule );
358 }
359
360 return arr;
361}
362
363////////////////////////////////////////////////////////////////////////////////
364/// Return all the rules that applies to the specified version OR checksum of the given 'source' class.
365/// User has to delete the returned array
366
367const TSchemaRuleSet::TMatches TSchemaRuleSet::FindRules( const TString &source, Int_t version, UInt_t checksum ) const
368{
369 TObject* obj;
371 TMatches arr;
372 // arr->SetOwner( kFALSE );
373
374 while( (obj = it.Next()) ) {
375 TSchemaRule* rule = (TSchemaRule*)obj;
376 if( rule->GetSourceClass() == source && ( rule->TestVersion( version ) || rule->TestChecksum( checksum ) ) )
377 arr.push_back( rule );
378 }
379
380 return arr;
381}
382
383////////////////////////////////////////////////////////////////////////////////
384
386{
387 return fClass;
388}
389
390////////////////////////////////////////////////////////////////////////////////
391
393{
394 if (fCheckSum == 0 && fClass) {
395 const_cast<TSchemaRuleSet*>(this)->fCheckSum = fClass->GetCheckSum();
396 }
397 return fCheckSum;
398}
399
400////////////////////////////////////////////////////////////////////////////////
401
403{
404 return fClassName;
405}
406
407////////////////////////////////////////////////////////////////////////////////
408
410{
411 return fVersion;
412}
413
414////////////////////////////////////////////////////////////////////////////////
415
417{
418 return fAllRules;
419}
420
421////////////////////////////////////////////////////////////////////////////////
422
424{
425 return fPersistentRules;
426}
427
428////////////////////////////////////////////////////////////////////////////////
429/// Remove given rule from the set - the rule is not being deleted!
430
432{
433 fPersistentRules->Remove( rule );
434 fRemainingRules->Remove( rule );
435 fAllRules->Remove( rule );
436}
437
438////////////////////////////////////////////////////////////////////////////////
439/// remove given array of rules from the set - the rules are not being deleted!
440
442{
443 TObject* obj;
444 TObjArrayIter it( rules );
445
446 while( (obj = it.Next()) ) {
447 fPersistentRules->Remove( obj );
448 fRemainingRules->Remove( obj );
449 fAllRules->Remove( obj );
450 }
451}
452
453////////////////////////////////////////////////////////////////////////////////
454/// Set the TClass associated with this rule set.
455
457{
458 fClass = cls;
459 fClassName = cls->GetName();
460 fVersion = cls->GetClassVersion();
461}
462
463
464////////////////////////////////////////////////////////////////////////////////
465/// Return the rule that has 'name' as a source.
466
468{
469 for( auto rule : *this ) {
470 if( rule->HasSource( name ) ) return rule;
471 }
472 return nullptr;
473}
474
475////////////////////////////////////////////////////////////////////////////////
476/// Return the rule that has 'name' as a target.
477
479{
480 for( auto rule : *this ) {
481 if( rule->HasTarget( name ) ) return rule;
482 }
483 return nullptr;
484}
485
486////////////////////////////////////////////////////////////////////////////////
487/// Return true if the set of rules has at least one rule that has the data
488/// member named 'name' as a source.
489/// If needingAlloc is true, only the rule that requires the data member to
490/// be cached will be taken in consideration.
491
493{
494 for( auto rule : *this ) {
495 if( rule->HasSource( name ) ) {
496 if (needingAlloc) {
497 const TObjArray *targets = rule->GetTarget();
498 if (targets && (targets->GetEntriesFast() > 1 || targets->IsEmpty()) ) {
499 return kTRUE;
500 }
501 if (targets && name != targets->UncheckedAt(0)->GetName() ) {
502 return kTRUE;
503 }
504 // If the rule has the same source and target and does not
505 // have any actions, then it does not need allocation.
506 if (rule->GetReadFunctionPointer() || rule->GetReadRawFunctionPointer()) {
507 return kTRUE;
508 }
509 } else {
510 return kTRUE;
511 }
512 }
513 }
514 return kFALSE;
515}
516
517////////////////////////////////////////////////////////////////////////////////
518/// Return true if the set of rules has at least one rule that has the data
519/// member named 'name' as a target.
520/// If willset is true, only the rule that will set the value of the data member.
521
523{
524 for(auto rule : *this) {
525 if( rule->HasTarget( name ) ) {
526 if (willset) {
527 const TObjArray *targets = rule->GetTarget();
528 if (targets && (targets->GetEntriesFast() > 1 || targets->IsEmpty()) ) {
529 return kTRUE;
530 }
531 const TObjArray *sources = rule->GetSource();
532 if (sources && (sources->GetEntriesFast() > 1 || sources->IsEmpty()) ) {
533 return kTRUE;
534 }
535 if (sources && name != sources->UncheckedAt(0)->GetName() ) {
536 return kTRUE;
537 }
538 // If the rule has the same source and target and does not
539 // have any actions, then it will not directly set the value.
540 if (rule->GetReadFunctionPointer() || rule->GetReadRawFunctionPointer()) {
541 return kTRUE;
542 }
543 } else {
544 return kTRUE;
545 }
546 }
547 }
548 return kFALSE;
549}
550
551////////////////////////////////////////////////////////////////////////////////
552/// Stream an object of class ROOT::TSchemaRuleSet.
553
554void TSchemaRuleSet::Streamer(TBuffer &R__b)
555{
556 if (R__b.IsReading()) {
558 fAllRules->Clear();
560 } else {
563 }
564}
565
void Class()
Definition: Class.C:29
ROOT::R::TRInterface & r
Definition: Object.C:4
int Int_t
Definition: RtypesCore.h:45
unsigned int UInt_t
Definition: RtypesCore.h:46
const Bool_t kFALSE
Definition: RtypesCore.h:101
bool Bool_t
Definition: RtypesCore.h:63
const Bool_t kTRUE
Definition: RtypesCore.h:100
const char Option_t
Definition: RtypesCore.h:66
#define ClassImp(name)
Definition: Rtypes.h:364
char name[80]
Definition: TGX11.cxx:110
R__EXTERN TVirtualMutex * gInterpreterMutex
Definition: TInterpreter.h:44
#define R__LOCKGUARD(mutex)
const TSchemaRule * GetRuleWithSource(const TString &name) const
Return the rule that has 'name' as a source.
Bool_t HasRuleWithSource(const TString &name, Bool_t needingAlloc) const
Return true if the set of rules has at least one rule that has the data member named 'name' as a sour...
Bool_t HasRuleWithTarget(const TString &name, Bool_t willset) const
Return true if the set of rules has at least one rule that has the data member named 'name' as a targ...
const TSchemaRule * GetRuleWithTarget(const TString &name) const
Return the rule that has 'name' as a target.
Bool_t AddRules(TSchemaRuleSet *rules, EConsistencyCheck checkConsistency=kCheckAll, TString *errmsg=0)
TClassRef fClass
Array of all rules.
TString fClassName
Target class pointer (for consistency checking)
void RemoveRule(TSchemaRule *rule)
Remove given rule from the set - the rule is not being deleted!
const TMatches FindRules(const TString &source) const
Return all the rules that are about the given 'source' class.
const TObjArray * GetPersistentRules() const
void AsString(TString &out) const
Fill the string 'out' with the string representation of the rule.
void ls(Option_t *option="") const
The ls function lists the contents of a class on stdout.
Bool_t AddRule(TSchemaRule *rule, EConsistencyCheck checkConsistency=kCheckAll, TString *errmsg=0)
The consistency check always fails if the TClass object was not set! if checkConsistency is: kNoCheck...
TObjArray * fAllRules
Array of non-persisten rules - just for cleanup purposes - owns the elements.
void SetClass(TClass *cls)
Set the TClass associated with this rule set.
void RemoveRules(TObjArray *rules)
remove given array of rules from the set - the rules are not being deleted!
const TObjArray * GetRules() const
Bool_t HasRuleWithSourceClass(const TString &source) const
Return True if we have any rule whose source class is 'source'.
virtual ~TSchemaRuleSet()
Destructor.
void AsString(TString &out, const char *options="") const
Add to the string 'out' the string representation of the rule.
Bool_t TestVersion(Int_t version) const
Check if given version number is defined in this rule.
const TObjArray * GetTarget() const
Get the target data members of this rule (i.e. the in memory data member).
Bool_t Conflicts(const TSchemaRule *rule) const
Check if this rule conflicts with the given one.
void SetTargetClass(const TString &classname)
Set the target class of this rule (i.e. the in memory class).
const char * GetSourceClass() const
Get the source class of this rule (i.e. the onfile class).
Bool_t TestChecksum(UInt_t checksum) const
Check if given checksum is defined in this rule.
Bool_t SetVersion(const TString &version)
Set the version string - returns kFALSE if the format is incorrect.
Bool_t IsValid() const
Return kTRUE if this rule is valid.
Bool_t GetEmbed() const
Return true if this rule should be saved in the ROOT File.
void SetSourceClass(const TString &classname)
Set the source class of this rule (i.e. the onfile class).
Buffer base class used for serializing objects.
Definition: TBuffer.h:43
virtual Int_t ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onfile_class=0)=0
Bool_t IsReading() const
Definition: TBuffer.h:86
virtual Int_t WriteClassBuffer(const TClass *cl, void *pointer)=0
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:80
UInt_t GetCheckSum(ECheckSum code=kCurrentCheckSum) const
Call GetCheckSum with validity check.
Definition: TClass.cxx:6457
TDataMember * GetDataMember(const char *datamember) const
Return pointer to datamember object with name "datamember".
Definition: TClass.cxx:3392
TClass * GetBaseClass(const char *classname)
Return pointer to the base class "classname".
Definition: TClass.cxx:2642
const ROOT::Detail::TSchemaRuleSet * GetSchemaRules() const
Return the set of the schema rules if any.
Definition: TClass.cxx:1919
const TObjArray * GetStreamerInfos() const
Definition: TClass.h:489
TVirtualStreamerInfo * GetStreamerInfo(Int_t version=0, Bool_t isTransient=kFALSE) const
returns a pointer to the TVirtualStreamerInfo object for version If the object does not exist,...
Definition: TClass.cxx:4592
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2884
Version_t GetClassVersion() const
Definition: TClass.h:417
@ kIsEmulation
Definition: TClass.h:101
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2955
virtual void AddAll(const TCollection *col)
Add all objects from collection col to this collection.
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
Iterator of object array.
Definition: TObjArray.h:126
TObject * Next()
Return next object in array. Returns 0 when no more objects in array.
Definition: TObjArray.cxx:931
An array of TObjects.
Definition: TObjArray.h:37
Int_t GetEntriesFast() const
Definition: TObjArray.h:64
void Add(TObject *obj)
Definition: TObjArray.h:74
virtual void Clear(Option_t *option="")
Remove all objects from the array.
Definition: TObjArray.cxx:321
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:90
Bool_t IsEmpty() const
Definition: TObjArray.h:71
virtual TObject * Remove(TObject *obj)
Remove object from array.
Definition: TObjArray.cxx:719
TObject * At(Int_t idx) const
Definition: TObjArray.h:166
Collectable string class.
Definition: TObjString.h:28
const TString & GetString() const
Definition: TObjString.h:46
Mother of all ROOT objects.
Definition: TObject.h:37
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:359
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:187
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:893
static Int_t IncreaseDirLevel()
Increase the indentation level for ls().
Definition: TROOT.cxx:2795
static void IndentLevel()
Functions used by ls() to indent an object hierarchy.
Definition: TROOT.cxx:2803
static Int_t DecreaseDirLevel()
Decrease the indentation level for ls().
Definition: TROOT.cxx:2699
TClass * GetClass() const
Basic string class.
Definition: TString.h:136
const char * Data() const
Definition: TString.h:369
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2314
virtual Int_t GetProperties() const
virtual TClass * GetValueClass() const =0
virtual Int_t GetCollectionType() const =0
virtual Bool_t HasPointers() const =0
Abstract Interface class describing Streamer information for one class.
virtual TObjArray * GetElements() const =0
Special implementation of ROOT::RRangeCast for TCollection, including a check that the cast target ty...
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
bool IsStdPair(std::string_view name)
Definition: TClassEdit.h:191