Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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
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() )
100 else
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
114 // Do not generate/build the StreamerInfo if it is not already there.
116 if (rule->GetTarget() && (fClass->GetState() > TClass::kEmulated || info)) {
117 TObjArrayIter titer( rule->GetTarget() );
118 TObject* obj;
119 while( (obj = titer.Next()) ) {
120 TObjString* str = (TObjString*)obj;
121 bool found = false;
122 // Note: an alternative would be to use the ListOfRealData which
123 // is populated in both cases but it might or might not have already
124 // been set and would make detecting if the data member is local to
125 // the current class (as opposed to a base class) more difficult.
127 found = fClass->GetDataMember(str->GetString()) || fClass->GetBaseClass(str->GetString());
128 } else if (info) {
129 found = info->GetElements()->FindObject(str->GetString());
130 }
131 if (!found) {
133 if (errmsg) {
134 errmsg->Form("the target member (%s) is unknown",str->GetString().Data());
135 }
136 return kFALSE;
137 } else {
138 // We ignore the rules that do not apply ...
139 delete rule;
140 return kTRUE;
141 }
142 }
143 }
144 }
145
146 //---------------------------------------------------------------------------
147 // Check if there is a rule conflicting with this one
148 /////////////////////////////////////////////////////////////////////////////
149
150 std::vector<const TSchemaRule*> rules = FindRules( rule->GetSourceClass() );
151 //TObjArrayIter it( rules );
152 //TSchemaRule *r;
153
154 for(auto r : rules) { // while( (obj = it.Next()) ) {
155 if( rule->Conflicts( r ) ) {
156 //delete rules;
157 if ( *r == *rule) {
158 // The rules are duplicate from each other,
159 // just ignore the new ones.
160 if (errmsg) {
161 *errmsg = "it conflicts with one of the other rules";
162 }
163 delete rule;
164 return kTRUE;
165 }
166 if (errmsg) {
167 *errmsg = "The existing rule is:\n ";
168 r->AsString(*errmsg,"s");
169 *errmsg += "\nand the ignored rule is:\n ";
170 rule->AsString(*errmsg);
171 *errmsg += ".\n";
172 }
173 return kFALSE;
174 }
175 }
176
177 //---------------------------------------------------------------------------
178 // No conflicts - insert the rules
179 /////////////////////////////////////////////////////////////////////////////
180
181 if( rule->GetEmbed() )
183 else
185 fAllRules->Add( rule );
186
187 return kTRUE;
188}
189
190////////////////////////////////////////////////////////////////////////////////
191/// Fill the string 'out' with the string representation of the rule.
192
194{
197 while( (rule = (TSchemaRule*)it.Next()) ) {
198 rule->AsString(out);
199 out += "\n";
200 }
201}
202
203////////////////////////////////////////////////////////////////////////////////
204/// Return True if we have any rule whose source class is 'source'.
205
207{
209 TObject *obj;
210 while( (obj = it.Next()) ) {
212 if( rule->GetSourceClass() == source )
213 return kTRUE;
214 }
215 // There was no explicit rule, let's see we have implicit rules.
216 if (fClass->GetCollectionProxy()) {
217 if (fClass->GetCollectionProxy()->GetValueClass() == nullptr) {
218 // We have a numeric collection, let see if the target is
219 // also a numeric collection.
221 if (src && src->GetCollectionProxy() &&
222 src->GetCollectionProxy()->HasPointers() == fClass->GetCollectionProxy()->HasPointers()) {
223 TVirtualCollectionProxy *proxy = src->GetCollectionProxy();
224 if (proxy->GetValueClass() == nullptr) {
225 return kTRUE;
226 }
227 }
228 } else {
231 if (vTargetClass->GetSchemaRules()) {
232 if (src && src->GetCollectionProxy() &&
233 src->GetCollectionProxy()->HasPointers() == fClass->GetCollectionProxy()->HasPointers()) {
234 TClass *vSourceClass = src->GetCollectionProxy()->GetValueClass();
235 if (vSourceClass) {
236 return vTargetClass->GetSchemaRules()->HasRuleWithSourceClass( vSourceClass->GetName() );
237 }
238 }
239 }
240 }
241 } else if (TClassEdit::IsStdPair(fClass->GetName())) {
243 // std::pair can be converted into each other if both its parameter can be converted into
244 // each other.
246 if (!src) {
247 Error("HasRuleWithSourceClass","Can not find the TClass for %s when matching with %s\n",source.Data(),fClass->GetName());
248 return kFALSE;
249 }
250 TVirtualStreamerInfo *sourceInfo = src->GetStreamerInfo();
252 if (!sourceInfo) {
253 Error("HasRuleWithSourceClass","Can not find the StreamerInfo for %s when matching with %s\n",source.Data(),fClass->GetName());
254 return kFALSE;
255 }
256 if (!targetInfo) {
257 Error("HasRuleWithSourceClass","Can not find the StreamerInfo for target class %s\n",fClass->GetName());
258 return kFALSE;
259 }
260 for(int i = 0 ; i<2 ; ++i) {
263 if (sourceElement->GetClass()) {
264 if (!targetElement->GetClass()) {
265 return kFALSE;
266 }
267 if (sourceElement->GetClass() == targetElement->GetClass()) {
268 continue;
269 }
270 TSchemaRuleSet *rules = sourceElement->GetClass()->GetSchemaRules();
271 if (!rules || !rules->HasRuleWithSourceClass( targetElement->GetClass()->GetName() ) ) {
272 return kFALSE;
273 }
274 } else if (targetElement->GetClass()) {
275 return kFALSE;
276 } else {
277 // both side are numeric element we can deal with it.
278 }
279 }
280 // Both side are pairs and have convertible types, let records this as a renaming rule
282 ruleobj->SetSourceClass(source);
283 ruleobj->SetTargetClass(fClass->GetName());
284 ruleobj->SetVersion("[1-]");
285 const_cast<TSchemaRuleSet*>(this)->AddRule(ruleobj);
286 return kTRUE;
287 }
288 }
289 return kFALSE;
290}
291
292////////////////////////////////////////////////////////////////////////////////
293/// Return all the rules that are about the given 'source' class.
294/// User has to delete the returned array
295
297{
298 TObject* obj;
301 // arr->SetOwner( kFALSE );
302
303 while( (obj = it.Next()) ) {
305 if( rule->GetSourceClass() == source )
306 arr.push_back( rule );
307 }
308
309#if 0
310 // Le't's see we have implicit rules.
311 if (fClass->GetCollectionProxy()) {
315 // We have a numeric collection, let see if the target is
316 // also a numeric collection (humm just a vector for now)
318 if (src && src->GetCollectionProxy()) {
319 TVirtualCollectionProxy *proxy = src->GetCollectionProxy();
320 if (proxy->GetValueClass() == 0) {
321 // ... would need to check if we already have
322 // the rule (or any rule?)
323 }
324 }
325 }
326 }
327#endif
328 return arr;
329}
330
331////////////////////////////////////////////////////////////////////////////////
332/// Return all the rules that applies to the specified version of the given 'source' class.
333/// User has to delete the returned array
334
336{
337 TObject* obj;
340 // arr->SetOwner( kFALSE );
341
342 while( (obj = it.Next()) ) {
344 if( rule->GetSourceClass() == source && rule->TestVersion( version ) )
345 arr.push_back( rule );
346 }
347
348 return arr;
349}
350
351////////////////////////////////////////////////////////////////////////////////
352/// Return all the rules that applies to the specified checksum of the given 'source' class.
353/// User has to delete the returned array
354
356{
357 TObject* obj;
360 // arr->SetOwner( kFALSE );
361
362 while( (obj = it.Next()) ) {
364 if( rule->GetSourceClass() == source && rule->TestChecksum( checksum ) )
365 arr.push_back( rule );
366 }
367
368 return arr;
369}
370
371////////////////////////////////////////////////////////////////////////////////
372/// Return all the rules that applies to the specified version OR checksum of the given 'source' class.
373/// User has to delete the returned array
374
376{
377 TObject* obj;
380 // arr->SetOwner( kFALSE );
381
382 while( (obj = it.Next()) ) {
384 if( rule->GetSourceClass() == source && ( rule->TestVersion( version ) || rule->TestChecksum( checksum ) ) )
385 arr.push_back( rule );
386 }
387
388 return arr;
389}
390
391////////////////////////////////////////////////////////////////////////////////
392
394{
395 return fClass;
396}
397
398////////////////////////////////////////////////////////////////////////////////
399
401{
402 if (fCheckSum == 0 && fClass) {
403 const_cast<TSchemaRuleSet*>(this)->fCheckSum = fClass->GetCheckSum();
404 }
405 return fCheckSum;
406}
407
408////////////////////////////////////////////////////////////////////////////////
409
411{
412 return fClassName;
413}
414
415////////////////////////////////////////////////////////////////////////////////
416
418{
419 return fVersion;
420}
421
422////////////////////////////////////////////////////////////////////////////////
423
425{
426 return fAllRules;
427}
428
429////////////////////////////////////////////////////////////////////////////////
430
435
436////////////////////////////////////////////////////////////////////////////////
437/// Remove given rule from the set - the rule is not being deleted!
438
445
446////////////////////////////////////////////////////////////////////////////////
447/// remove given array of rules from the set - the rules are not being deleted!
448
450{
451 TObject* obj;
452 TObjArrayIter it( rules );
453
454 while( (obj = it.Next()) ) {
455 fPersistentRules->Remove( obj );
456 fRemainingRules->Remove( obj );
457 fAllRules->Remove( obj );
458 }
459}
460
461////////////////////////////////////////////////////////////////////////////////
462/// Set the TClass associated with this rule set.
463
465{
466 fClass = cls;
467 fClassName = cls->GetName();
468 fVersion = cls->GetClassVersion();
469}
470
471
472////////////////////////////////////////////////////////////////////////////////
473/// Return the rule that has 'name' as a source.
474
476{
477 for( auto rule : *this ) {
478 if( rule->HasSource( name ) ) return rule;
479 }
480 return nullptr;
481}
482
483////////////////////////////////////////////////////////////////////////////////
484/// Return the rule that has 'name' as a target.
485
487{
488 for( auto rule : *this ) {
489 if( rule->HasTarget( name ) ) return rule;
490 }
491 return nullptr;
492}
493
494////////////////////////////////////////////////////////////////////////////////
495/// Return true if the set of rules has at least one rule that has the data
496/// member named 'name' as a source.
497/// If needingAlloc is true, only the rule that requires the data member to
498/// be cached will be taken in consideration.
499
501{
502 for( auto rule : *this ) {
503 if( rule->HasSource( name ) ) {
504 if (needingAlloc) {
505 const TObjArray *targets = rule->GetTarget();
506 if (targets && (targets->GetEntriesFast() > 1 || targets->IsEmpty()) ) {
507 return kTRUE;
508 }
509 if (targets && name != targets->UncheckedAt(0)->GetName() ) {
510 return kTRUE;
511 }
512 // If the rule has the same source and target and does not
513 // have any actions, then it does not need allocation.
514 if (rule->GetReadFunctionPointer() || rule->GetReadRawFunctionPointer()) {
515 return kTRUE;
516 }
517 } else {
518 return kTRUE;
519 }
520 }
521 }
522 return kFALSE;
523}
524
525////////////////////////////////////////////////////////////////////////////////
526/// Return true if the set of rules has at least one rule that has the data
527/// member named 'name' as a target.
528/// If willset is true, only the rule that will set the value of the data member.
529
531{
532 for(auto rule : *this) {
533 if( rule->HasTarget( name ) ) {
534 if (willset) {
535 const TObjArray *targets = rule->GetTarget();
536 if (targets && (targets->GetEntriesFast() > 1 || targets->IsEmpty()) ) {
537 return kTRUE;
538 }
539 const TObjArray *sources = rule->GetSource();
540 if (sources && (sources->GetEntriesFast() > 1 || sources->IsEmpty()) ) {
541 return kTRUE;
542 }
543 if (sources && name != sources->UncheckedAt(0)->GetName() ) {
544 return kTRUE;
545 }
546 // If the rule has the same source and target and does not
547 // have any actions, then it will not directly set the value.
548 if (rule->GetReadFunctionPointer() || rule->GetReadRawFunctionPointer()) {
549 return kTRUE;
550 }
551 } else {
552 return kTRUE;
553 }
554 }
555 }
556 return kFALSE;
557}
558
559////////////////////////////////////////////////////////////////////////////////
560/// Stream an object of class ROOT::TSchemaRuleSet.
561
563{
564 if (R__b.IsReading()) {
565 R__b.ReadClassBuffer(ROOT::Detail::TSchemaRuleSet::Class(),this);
566 fAllRules->Clear();
568 } else {
570 R__b.WriteClassBuffer(ROOT::Detail::TSchemaRuleSet::Class(),this);
571 }
572}
573
constexpr Bool_t kFALSE
Definition RtypesCore.h:94
constexpr Bool_t kTRUE
Definition RtypesCore.h:93
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:374
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t src
char name[80]
Definition TGX11.cxx:110
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.
void Streamer(TBuffer &) override
Stream an object of class ROOT::TSchemaRuleSet.
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
Bool_t AddRule(TSchemaRule *rule, EConsistencyCheck checkConsistency=kCheckAll, TString *errmsg=nullptr)
The consistency check always fails if the TClass object was not set! if checkConsistency is: kNoCheck...
void AsString(TString &out) const
Fill the string 'out' with the string representation of the rule.
Bool_t AddRules(TSchemaRuleSet *rules, EConsistencyCheck checkConsistency=kCheckAll, TString *errmsg=nullptr)
void ls(Option_t *option="") const override
The ls function lists the contents of a class on stdout.
TObjArray * fAllRules
Array of non-persistent 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.
TSchemaRuleSet()
Default constructor.
Buffer base class used for serializing objects.
Definition TBuffer.h:43
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:84
UInt_t GetCheckSum(ECheckSum code=kCurrentCheckSum) const
Call GetCheckSum with validity check.
Definition TClass.cxx:6619
TDataMember * GetDataMember(const char *datamember) const
Return pointer to datamember object with name "datamember".
Definition TClass.cxx:3540
EState GetState() const
Definition TClass.h:495
TVirtualStreamerInfo * GetCurrentStreamerInfo()
Definition TClass.h:446
TClass * GetBaseClass(const char *classname)
Return pointer to the base class "classname".
Definition TClass.cxx:2756
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:4696
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition TClass.cxx:2998
@ kEmulated
Definition TClass.h:128
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:3069
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.
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
Iterator of object array.
Definition TObjArray.h:117
TObject * Next() override
Return next object in array. Returns 0 when no more objects in array.
An array of TObjects.
Definition TObjArray.h:31
void Clear(Option_t *option="") override
Remove all objects from the array.
TObject * Remove(TObject *obj) override
Remove object from array.
void Add(TObject *obj) override
Definition TObjArray.h:68
Collectable string class.
Definition TObjString.h:28
Mother of all ROOT objects.
Definition TObject.h:41
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1020
static Int_t IncreaseDirLevel()
Increase the indentation level for ls().
Definition TROOT.cxx:2887
static void IndentLevel()
Functions used by ls() to indent an object hierarchy.
Definition TROOT.cxx:2895
static Int_t DecreaseDirLevel()
Decrease the indentation level for ls().
Definition TROOT.cxx:2746
Basic string class.
Definition TString.h:139
Defines a common interface to inspect/change the contents of an object that represents a collection.
virtual Int_t GetProperties() const
Return miscallenous properties of the proxy (see TVirtualCollectionProxy::EProperty)
virtual TClass * GetValueClass() const =0
If the value type is a user-defined class, return a pointer to the TClass representing the value type...
virtual Int_t GetCollectionType() const =0
Return the type of the proxied collection (see enumeration TClassEdit::ESTLType)
virtual Bool_t HasPointers() const =0
Return true if the content is of type 'pointer to'.
Abstract Interface class describing Streamer information for one class.
Special implementation of ROOT::RRangeCast for TCollection, including a check that the cast target ty...
Definition TObject.h:389
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:184