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
20
21using namespace ROOT;
22using namespace ROOT::Detail;
23
24////////////////////////////////////////////////////////////////////////////////
25/// Default constructor.
26
27TSchemaRuleSet::TSchemaRuleSet(): fPersistentRules( nullptr ), fRemainingRules( nullptr ),
28 fAllRules( nullptr ), fVersion(-3), fCheckSum( 0 )
29{
32 fAllRules = new TObjArray();
34}
35
36////////////////////////////////////////////////////////////////////////////////
37/// Destructor.
38
45
46////////////////////////////////////////////////////////////////////////////////
47/// The ls function lists the contents of a class on stdout. Ls output
48/// is typically much less verbose then Dump().
49
51{
53 std::cout << "TSchemaRuleSet for " << fClassName << ":\n";
55 TObject *object = nullptr;
57 while ((object = next())) {
58 object->ls(fClassName);
59 }
61}
62
63////////////////////////////////////////////////////////////////////////////////
64
65Bool_t TSchemaRuleSet::AddRules( TSchemaRuleSet* /* rules */, EConsistencyCheck /* checkConsistency */, TString * /* errmsg */ )
66{
67 return kFALSE;
68}
69
70////////////////////////////////////////////////////////////////////////////////
71/// The consistency check always fails if the TClass object was not set!
72/// if checkConsistency is:
73/// kNoCheck: no check is done, register the rule as is
74/// kCheckConflict: check only for conflicting rules
75/// kCheckAll: check for conflict and check for rule about members that are not in the current class layout.
76/// return kTRUE if the layout is accepted, in which case we take ownership of
77/// the rule object.
78/// return kFALSE if the rule failed one of the test, the rule now needs to be deleted by the caller.
79
81{
82 //---------------------------------------------------------------------------
83 // Cannot verify the consistency if the TClass object is not present
84 /////////////////////////////////////////////////////////////////////////////
85
86 if( (checkConsistency != kNoCheck) && !fClass )
87 return kFALSE;
88
89 if( !rule->IsValid() )
90 return kFALSE;
91
92 //---------------------------------------------------------------------------
93 // If we don't check the consistency then we should just add the object
94 /////////////////////////////////////////////////////////////////////////////
95
96 if( checkConsistency == kNoCheck ) {
97 if( rule->GetEmbed() )
99 else
101 fAllRules->Add( rule );
102 return kTRUE;
103 }
104
105 //---------------------------------------------------------------------------
106 // Check if all of the target data members specified in the rule are
107 // present int the target class
108 /////////////////////////////////////////////////////////////////////////////
109
110 // Check only if we have some information about the class, otherwise we have
111 // nothing to check against
112
113 // Do not generate/build the StreamerInfo if it is not already there.
115 if (rule->GetTarget() && (fClass->GetState() > TClass::kEmulated || info)) {
116 TObjArrayIter titer( rule->GetTarget() );
117 TObject* obj;
118 while( (obj = titer.Next()) ) {
119 TObjString* str = (TObjString*)obj;
120 bool found = false;
121 // Note: an alternative would be to use the ListOfRealData which
122 // is populated in both cases but it might or might not have already
123 // been set and would make detecting if the data member is local to
124 // the current class (as opposed to a base class) more difficult.
126 found = fClass->GetDataMember(str->GetString()) || fClass->GetBaseClass(str->GetString());
127 } else if (info) {
128 found = info->GetElements()->FindObject(str->GetString());
129 }
130 if (!found) {
132 if (errmsg) {
133 errmsg->Form("the target member (%s) is unknown",str->GetString().Data());
134 }
135 return kFALSE;
136 } else {
137 // We ignore the rules that do not apply ...
138 delete rule;
139 return kTRUE;
140 }
141 }
142 }
143 }
144
145 //---------------------------------------------------------------------------
146 // Check if there is a rule conflicting with this one
147 /////////////////////////////////////////////////////////////////////////////
148
149 std::vector<const TSchemaRule*> rules = FindRules( rule->GetSourceClass() );
150 //TObjArrayIter it( rules );
151 //TSchemaRule *r;
152
153 for(auto r : rules) { // while( (obj = it.Next()) ) {
154 if( rule->Conflicts( r ) ) {
155 //delete rules;
156 if ( *r == *rule) {
157 // The rules are duplicate from each other,
158 // just ignore the new ones.
159 if (errmsg) {
160 *errmsg = "it conflicts with one of the other rules";
161 }
162 delete rule;
163 return kTRUE;
164 }
165 if (errmsg) {
166 *errmsg = "The existing rule is:\n ";
167 r->AsString(*errmsg,"s");
168 *errmsg += "\nand the ignored rule is:\n ";
169 rule->AsString(*errmsg);
170 *errmsg += ".\n";
171 }
172 return kFALSE;
173 }
174 }
175
176 //---------------------------------------------------------------------------
177 // No conflicts - insert the rules
178 /////////////////////////////////////////////////////////////////////////////
179
180 if( rule->GetEmbed() )
182 else
184 fAllRules->Add( rule );
185
186 return kTRUE;
187}
188
189////////////////////////////////////////////////////////////////////////////////
190/// Fill the string 'out' with the string representation of the rule.
191
193{
196 while( (rule = (TSchemaRule*)it.Next()) ) {
197 rule->AsString(out);
198 out += "\n";
199 }
200}
201
202////////////////////////////////////////////////////////////////////////////////
203/// Return True if we have any rule whose source class is 'source'.
204
206{
208 TObject *obj;
209 while( (obj = it.Next()) ) {
211 if( rule->GetSourceClass() == source )
212 return kTRUE;
213 }
214 // There was no explicit rule, let's see we have implicit rules.
215 if (fClass->GetCollectionProxy()) {
216 if (fClass->GetCollectionProxy()->GetValueClass() == nullptr) {
217 // We have a numeric collection, let see if the target is
218 // also a numeric collection.
220 if (src && src->GetCollectionProxy() &&
221 src->GetCollectionProxy()->HasPointers() == fClass->GetCollectionProxy()->HasPointers()) {
222 TVirtualCollectionProxy *proxy = src->GetCollectionProxy();
223 if (proxy->GetValueClass() == nullptr) {
224 return kTRUE;
225 }
226 }
227 } else {
230 if (vTargetClass->GetSchemaRules()) {
231 if (src && src->GetCollectionProxy() &&
232 src->GetCollectionProxy()->HasPointers() == fClass->GetCollectionProxy()->HasPointers()) {
233 TClass *vSourceClass = src->GetCollectionProxy()->GetValueClass();
234 if (vSourceClass) {
235 return vTargetClass->GetSchemaRules()->HasRuleWithSourceClass( vSourceClass->GetName() );
236 }
237 }
238 }
239 }
240 } else if (TClassEdit::IsStdPair(fClass->GetName())) {
242 // std::pair can be converted into each other if both its parameter can be converted into
243 // each other.
245 if (!src) {
246 Error("HasRuleWithSourceClass","Can not find the TClass for %s when matching with %s\n",source.Data(),fClass->GetName());
247 return kFALSE;
248 }
249 TVirtualStreamerInfo *sourceInfo = src->GetStreamerInfo();
251 if (!sourceInfo) {
252 Error("HasRuleWithSourceClass","Can not find the StreamerInfo for %s when matching with %s\n",source.Data(),fClass->GetName());
253 return kFALSE;
254 }
255 if (!targetInfo) {
256 Error("HasRuleWithSourceClass","Can not find the StreamerInfo for target class %s\n",fClass->GetName());
257 return kFALSE;
258 }
259 for(int i = 0 ; i<2 ; ++i) {
262 if (sourceElement->GetClass()) {
263 if (!targetElement->GetClass()) {
264 return kFALSE;
265 }
266 if (sourceElement->GetClass() == targetElement->GetClass()) {
267 continue;
268 }
269 TSchemaRuleSet *rules = sourceElement->GetClass()->GetSchemaRules();
270 if (!rules || !rules->HasRuleWithSourceClass( targetElement->GetClass()->GetName() ) ) {
271 return kFALSE;
272 }
273 } else if (targetElement->GetClass()) {
274 return kFALSE;
275 } else {
276 // both side are numeric element we can deal with it.
277 }
278 }
279 // Both side are pairs and have convertible types, let records this as a renaming rule
281 ruleobj->SetSourceClass(source);
282 ruleobj->SetTargetClass(fClass->GetName());
283 ruleobj->SetVersion("[1-]");
284 const_cast<TSchemaRuleSet*>(this)->AddRule(ruleobj);
285 return kTRUE;
286 }
287 }
288 return kFALSE;
289}
290
291////////////////////////////////////////////////////////////////////////////////
292/// Return all the rules that are about the given 'source' class.
293/// User has to delete the returned array
294
296{
297 TObject* obj;
300 // arr->SetOwner( kFALSE );
301
302 while( (obj = it.Next()) ) {
304 if( rule->GetSourceClass() == source )
305 arr.push_back( rule );
306 }
307
308#if 0
309 // Le't's see we have implicit rules.
310 if (fClass->GetCollectionProxy()) {
314 // We have a numeric collection, let see if the target is
315 // also a numeric collection (humm just a vector for now)
317 if (src && src->GetCollectionProxy()) {
318 TVirtualCollectionProxy *proxy = src->GetCollectionProxy();
319 if (proxy->GetValueClass() == 0) {
320 // ... would need to check if we already have
321 // the rule (or any rule?)
322 }
323 }
324 }
325 }
326#endif
327 return arr;
328}
329
330////////////////////////////////////////////////////////////////////////////////
331/// Return all the rules that applies to the specified version of the given 'source' class.
332/// User has to delete the returned array
333
335{
336 TObject* obj;
339 // arr->SetOwner( kFALSE );
340
341 while( (obj = it.Next()) ) {
343 if( rule->GetSourceClass() == source && rule->TestVersion( version ) )
344 arr.push_back( rule );
345 }
346
347 return arr;
348}
349
350////////////////////////////////////////////////////////////////////////////////
351/// Return all the rules that applies to the specified checksum of the given 'source' class.
352/// User has to delete the returned array
353
355{
356 TObject* obj;
359 // arr->SetOwner( kFALSE );
360
361 while( (obj = it.Next()) ) {
363 if( rule->GetSourceClass() == source && rule->TestChecksum( checksum ) )
364 arr.push_back( rule );
365 }
366
367 return arr;
368}
369
370////////////////////////////////////////////////////////////////////////////////
371/// Return all the rules that applies to the specified version OR checksum of the given 'source' class.
372/// User has to delete the returned array
373
375{
376 TObject* obj;
379 // arr->SetOwner( kFALSE );
380
381 while( (obj = it.Next()) ) {
383 if( rule->GetSourceClass() == source && ( rule->TestVersion( version ) || rule->TestChecksum( checksum ) ) )
384 arr.push_back( rule );
385 }
386
387 return arr;
388}
389
390////////////////////////////////////////////////////////////////////////////////
391
393{
394 return fClass;
395}
396
397////////////////////////////////////////////////////////////////////////////////
398
400{
401 if (fCheckSum == 0 && fClass) {
402 const_cast<TSchemaRuleSet*>(this)->fCheckSum = fClass->GetCheckSum();
403 }
404 return fCheckSum;
405}
406
407////////////////////////////////////////////////////////////////////////////////
408
410{
411 return fClassName;
412}
413
414////////////////////////////////////////////////////////////////////////////////
415
417{
418 return fVersion;
419}
420
421////////////////////////////////////////////////////////////////////////////////
422
424{
425 return fAllRules;
426}
427
428////////////////////////////////////////////////////////////////////////////////
429
434
435////////////////////////////////////////////////////////////////////////////////
436/// Remove given rule from the set - the rule is not being deleted!
437
444
445////////////////////////////////////////////////////////////////////////////////
446/// remove given array of rules from the set - the rules are not being deleted!
447
449{
450 TObject* obj;
451 TObjArrayIter it( rules );
452
453 while( (obj = it.Next()) ) {
454 fPersistentRules->Remove( obj );
455 fRemainingRules->Remove( obj );
456 fAllRules->Remove( obj );
457 }
458}
459
460////////////////////////////////////////////////////////////////////////////////
461/// Set the TClass associated with this rule set.
462
464{
465 fClass = cls;
466 fClassName = cls->GetName();
467 fVersion = cls->GetClassVersion();
468}
469
470
471////////////////////////////////////////////////////////////////////////////////
472/// Return the rule that has 'name' as a source.
473
475{
476 for( auto rule : *this ) {
477 if( rule->HasSource( name ) ) return rule;
478 }
479 return nullptr;
480}
481
482////////////////////////////////////////////////////////////////////////////////
483/// Return the rule that has 'name' as a target.
484
486{
487 for( auto rule : *this ) {
488 if( rule->HasTarget( name ) ) return rule;
489 }
490 return nullptr;
491}
492
493////////////////////////////////////////////////////////////////////////////////
494/// Return true if the set of rules has at least one rule that has the data
495/// member named 'name' as a source.
496/// If needingAlloc is true, only the rule that requires the data member to
497/// be cached will be taken in consideration.
498
500{
501 for( auto rule : *this ) {
502 if( rule->HasSource( name ) ) {
503 if (needingAlloc) {
504 const TObjArray *targets = rule->GetTarget();
505 if (targets && (targets->GetEntriesFast() > 1 || targets->IsEmpty()) ) {
506 return kTRUE;
507 }
508 if (targets && name != targets->UncheckedAt(0)->GetName() ) {
509 return kTRUE;
510 }
511 // If the rule has the same source and target and does not
512 // have any actions, then it does not need allocation.
513 if (rule->GetReadFunctionPointer() || rule->GetReadRawFunctionPointer()) {
514 return kTRUE;
515 }
516 } else {
517 return kTRUE;
518 }
519 }
520 }
521 return kFALSE;
522}
523
524////////////////////////////////////////////////////////////////////////////////
525/// Return true if the set of rules has at least one rule that has the data
526/// member named 'name' as a target.
527/// If willset is true, only the rule that will set the value of the data member.
528
530{
531 for(auto rule : *this) {
532 if( rule->HasTarget( name ) ) {
533 if (willset) {
534 const TObjArray *targets = rule->GetTarget();
535 if (targets && (targets->GetEntriesFast() > 1 || targets->IsEmpty()) ) {
536 return kTRUE;
537 }
538 const TObjArray *sources = rule->GetSource();
539 if (sources && (sources->GetEntriesFast() > 1 || sources->IsEmpty()) ) {
540 return kTRUE;
541 }
542 if (sources && name != sources->UncheckedAt(0)->GetName() ) {
543 return kTRUE;
544 }
545 // If the rule has the same source and target and does not
546 // have any actions, then it will not directly set the value.
547 if (rule->GetReadFunctionPointer() || rule->GetReadRawFunctionPointer()) {
548 return kTRUE;
549 }
550 } else {
551 return kTRUE;
552 }
553 }
554 }
555 return kFALSE;
556}
557
558////////////////////////////////////////////////////////////////////////////////
559/// Stream an object of class ROOT::TSchemaRuleSet.
560
562{
563 if (R__b.IsReading()) {
564 R__b.ReadClassBuffer(ROOT::Detail::TSchemaRuleSet::Class(),this);
565 fAllRules->Clear();
567 } else {
569 R__b.WriteClassBuffer(ROOT::Detail::TSchemaRuleSet::Class(),this);
570 }
571}
572
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
const char Option_t
Option string (const char)
Definition RtypesCore.h:80
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:6553
TDataMember * GetDataMember(const char *datamember) const
Return pointer to datamember object with name "datamember".
Definition TClass.cxx:3470
EState GetState() const
Definition TClass.h:501
TVirtualStreamerInfo * GetCurrentStreamerInfo()
Definition TClass.h:451
TClass * GetBaseClass(const char *classname)
Return pointer to the base class "classname".
Definition TClass.cxx:2660
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:4626
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition TClass.cxx:2902
@ 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:2973
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:1071
static Int_t IncreaseDirLevel()
Increase the indentation level for ls().
Definition TROOT.cxx:2890
static void IndentLevel()
Functions used by ls() to indent an object hierarchy.
Definition TROOT.cxx:2898
static Int_t DecreaseDirLevel()
Decrease the indentation level for ls().
Definition TROOT.cxx:2748
Describe one element (data member) to be Streamed.
Basic string class.
Definition TString.h:138
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:390
bool IsStdPair(std::string_view name)
Definition TClassEdit.h:231