Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TSchemaRule.cxx
Go to the documentation of this file.
1 // @(#)root/core:$Id$
2 // author: Lukasz Janyst <ljanyst@cern.ch>
3 
4 #include "TSchemaRule.h"
5 
7 #include "TClassEdit.h"
8 #include "TSchemaRuleProcessor.h"
9 #include "TSchemaType.h"
10 #include "TObjArray.h"
11 #include "TObjString.h"
12 #include "TNamed.h"
13 #include <utility>
14 #include <iostream>
15 #include <vector>
16 #include <list>
17 #include <string>
18 #include <cstdlib>
19 #include <sstream>
20 #include "TROOT.h"
21 #include "Riostream.h"
22 
23 ClassImp(TSchemaRule);
24 
25 using namespace ROOT;
26 
27 namespace {
28  static Bool_t IsIrrelevantCharacter(char c)
29  {
30  return (c == ' ' || c == '\n' || c == '\t');
31  }
32 
33  static void AdvanceOverIrrelevantCharacter(const char*& str)
34  {
35  while (IsIrrelevantCharacter(*str)) {
36  ++str;
37  }
38  }
39 
40  // check if lhs matches rhs if we ignore irelevant white space differences
41 
42  static Bool_t IsCodeEquivalent(const TString& lhs, const TString& rhs)
43  {
44  Bool_t result = kTRUE;
45 
46  if (lhs != rhs) {
47  const char null = '\0';
48  const char* left = lhs.Data();
49  const char* right = rhs.Data();
50  Bool_t literal = false;
51  // skip initial white space
52  AdvanceOverIrrelevantCharacter(left);
53  AdvanceOverIrrelevantCharacter(right);
54 
55  while (*left != null || *right != null) {
56  // If both chars are white space, skip consecutive white space
57  if (!literal && IsIrrelevantCharacter(*left) && IsIrrelevantCharacter(*right)) {
58  AdvanceOverIrrelevantCharacter(left);
59  AdvanceOverIrrelevantCharacter(right);
60  continue;
61  }
62  // Check if one string has trailing white space, and the other doesn't.
63  if (*left == null || *right == null) {
64  AdvanceOverIrrelevantCharacter(left);
65  AdvanceOverIrrelevantCharacter(right);
66  result = (*left == null && *right == null);
67  break;
68  }
69 
70  if (*left != *right) {
71  result = kFALSE;
72  break;
73  }
74 
75  if (*left == '"') {
76  literal = !literal;
77  }
78  ++left;
79  ++right;
80  }
81  }
82  return result;
83  }
84 
85 }
86 
87 ////////////////////////////////////////////////////////////////////////////////
88 /// Default Constructor.
89 
90 TSchemaRule::TSchemaRule(): fVersionVect( 0 ), fChecksumVect( 0 ),
91  fTargetVect( 0 ), fSourceVect( 0 ),
92  fIncludeVect( 0 ), fEmbed( kTRUE ),
93  fReadFuncPtr( 0 ), fReadRawFuncPtr( 0 ),
94  fRuleType( kNone )
95 {
96 }
97 
98 ////////////////////////////////////////////////////////////////////////////////
99 /// Destructor.
100 
101 TSchemaRule::~TSchemaRule()
102 {
103  delete fVersionVect;
104  delete fChecksumVect;
105  delete fTargetVect;
106  delete fSourceVect;
107  delete fIncludeVect;
108 }
109 
110 ////////////////////////////////////////////////////////////////////////////////
111 /// Copy Constructor.
112 
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 ),
118  fRuleType( kNone )
119 {
120  *this = rhs;
121 }
122 
123 ////////////////////////////////////////////////////////////////////////////////
124 /// Copy operator.
125 
126 TSchemaRule& TSchemaRule::operator = ( const TSchemaRule& rhs )
127 {
128  if( this != &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;
135  fCode = rhs.fCode;
136  fEmbed = rhs.fEmbed;
137  fReadFuncPtr = rhs.fReadFuncPtr;
138  fReadRawFuncPtr = rhs.fReadRawFuncPtr;
139  fRuleType = rhs.fRuleType;
140  fAttributes = rhs.fAttributes;
141  }
142  return *this;
143 }
144 
145 ////////////////////////////////////////////////////////////////////////////////
146 /// Return true if the rule have the same effects.
147 
148 Bool_t TSchemaRule::operator == ( const TSchemaRule& rhs ) const
149 {
150  if( this != &rhs ) {
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 );
162  if (result &&
163  ( (fReadRawFuncPtr != rhs.fReadRawFuncPtr && fReadRawFuncPtr != 0 && rhs.fReadRawFuncPtr != 0)
164  || (fReadFuncPtr != rhs.fReadFuncPtr && fReadFuncPtr != 0 && rhs.fReadFuncPtr != 0) ) )
165  {
166  result = kFALSE;
167  }
168 
169  return result;
170  }
171  return kTRUE;
172 }
173 
174 ////////////////////////////////////////////////////////////////////////////////
175 /// The ls function lists the contents of a class on stdout. Ls output
176 /// is typically much less verbose then Dump().
177 
178 void TSchemaRule::ls(Option_t *targetname) const
179 {
180  TROOT::IndentLevel();
181  std::cout << "Schema Evolution Rule: ";
182  if (fRuleType==kReadRule) std::cout << "read ";
183  else if (fRuleType==kReadRawRule) std::cout << "readraw ";
184  std::cout << "\n";
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 << "\" ";
192  std::cout << "\n";
193  TROOT::IndentLevel();
194  std::cout << "source=\"" << fSource << "\" ";
195  std::cout << "target=\"" << fTarget << "\" ";
196  std::cout << "\n";
197  if (fInclude.Length()) {
198  TROOT::IndentLevel();
199  std::cout << "include=\"" << fInclude << "\" " << "\n";
200  }
201  if (fAttributes.Length()) {
202  TROOT::IndentLevel();
203  std::cout << "attributes=\"" << fAttributes << "\"" << "\n";
204  }
205  if (fCode.Length()) {
206  TROOT::IndentLevel();
207  std::cout << "code=\"{" << fCode << "}\" "
208  << "\n";
209  }
210  TROOT::DecreaseDirLevel();
211 }
212 
213 ////////////////////////////////////////////////////////////////////////////////
214 /// Add to the string 'out' the string representation of the rule.
215 /// if options contains:
216 /// 's' : add the short form of the rule is possible
217 /// 'x' : add the xml form of the rule
218 
219 void TSchemaRule::AsString(TString &out, const char *options) const
220 {
221  TString opt(options);
222  opt.ToLower();
223  Bool_t shortform = opt.Contains('s');
224  Bool_t xmlform = opt.Contains('x');
225 
226  TString end;
227  if (xmlform) {
228  /*
229  <read sourceClass="ClassA" version="[2]" targetClass="ClassA" source="int m_unit;" target="m_unit" >
230  <![CDATA[ { m_unit = 10*onfile.m_unit; } ]]>
231  </read>
232  */
233  shortform = kFALSE;
234  out += "<";
235  if (fRuleType==kReadRule) { out += "read "; end = "</read>"; }
236  else if (fRuleType==kReadRawRule) { out += "readraw "; end = "</readraw>"; }
237  else { out += "-- "; end = "-->"; }
238 
239  } else {
240  if (!shortform || fRuleType!=kReadRule) {
241  out += "type=";
242  if (fRuleType==kReadRule) out += "read ";
243  else if (fRuleType==kReadRawRule) out += "readraw ";
244  else out += " ";
245  }
246  }
247  if (!shortform || (fSourceClass != fTargetClass) ) {
248  out += "sourceClass=\"" + fSourceClass + "\" ";
249  out += "targetClass=\"" + fTargetClass + "\" ";
250  } else {
251  out += fSourceClass + " ";
252  }
253  if (shortform && fTarget == fSource) {
254  out += fSource + " ";
255  }
256  if (!shortform || (fVersion != "[1-]")) {
257  if (fVersion.Length()) out += "version=\"" + fVersion + "\" ";
258  }
259  if (fChecksum.Length()) out += "checksum=\"" + fChecksum + "\" ";
260  if (!shortform || fTarget != fSource) {
261  out += "source=\"" + fSource + "\" ";
262  out += "target=\"" + fTarget + "\" ";
263  }
264  if (fInclude.Length()) out += "include=\"" + fInclude + "\" ";
265  if (fAttributes.Length()) out += "attributes=\"" + fAttributes + "\" ";
266  if (xmlform) {
267  out += "> ";
268  }
269  if (xmlform) {
270  if (fCode.Length()) {
271  out += "\n<![CDATA[ { " + fCode + " ]]>\n ";
272  } else if (fReadFuncPtr) {
273  // Can we guess?
274  // out += "code=\" + nameof(fReadFuncPtr) + "\" ";
275  } else if (fReadRawFuncPtr) {
276  // Can we guess?
277  // out += "code=\" + nameof(fReadRawFuncPtr) + "\" ";
278  }
279  } else {
280  if (fCode.Length()) {
281  out += "code=\"{" + fCode + "}\" ";
282  } else if (fReadFuncPtr) {
283  // Can we guess?
284  // out += "code=\" + nameof(fReadFuncPtr) + "\" ";
285  } else if (fReadRawFuncPtr) {
286  // Can we guess?
287  // out += "code=\" + nameof(fReadRawFuncPtr) + "\" ";
288  }
289  }
290  if (xmlform) {
291  out += end;
292  }
293 }
294 
295 ////////////////////////////////////////////////////////////////////////////////
296 /// Zero out this rule object.
297 
298 void TSchemaRule::Clear( const char * /* option */)
299 {
300  fVersion.Clear();
301  fChecksum.Clear();
302  fSourceClass.Clear();
303  fTarget.Clear();
304  fSource.Clear();
305  fInclude.Clear();
306  fCode.Clear();
307  fAttributes.Clear();
308  fReadRawFuncPtr = 0;
309  fReadFuncPtr = 0;
310  fRuleType = kNone;
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;
316 }
317 
318 ////////////////////////////////////////////////////////////////////////////////
319 /// Set the content fot this object from the rule
320 /// See TClass::AddRule for details on the syntax.
321 
322 Bool_t TSchemaRule::SetFromRule( const char *rule )
323 {
324  //-----------------------------------------------------------------------
325  // Parse the rule and check it's validity
326  /////////////////////////////////////////////////////////////////////////////
327 
328  ROOT::Internal::MembersMap_t rule_values;
329 
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());
333  return kFALSE;
334  }
335  ROOT::Internal::MembersMap_t::const_iterator it1;
336 
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 );
343  } else {
344  SetRuleType( TSchemaRule::kNone );
345  }
346  } else {
347  // Default to read.
348  SetRuleType( TSchemaRule::kReadRule );
349  }
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 );
370  // if (code is functioname) {
371  // switch (ruleobj->GetRuleType() ) {
372  // case kRead: SetReadFunctionPointer( )
373  // case kReadRewa: SetReadRawFunctionPointer( )
374  // }
375 
376  return kTRUE;
377 }
378 
379 ////////////////////////////////////////////////////////////////////////////////
380 /// Set the version string - returns kFALSE if the format is incorrect
381 
382 Bool_t TSchemaRule::SetVersion( const TString& version )
383 {
384  fVersion = "";
385  Bool_t ret = ProcessVersion( version );
386  if( ret )
387  fVersion = version;
388  return ret;
389 }
390 
391 ////////////////////////////////////////////////////////////////////////////////
392 /// Get the version string.
393 
394 const char *TSchemaRule::GetVersion() const
395 {
396  return fVersion;
397 }
398 
399 
400 ////////////////////////////////////////////////////////////////////////////////
401 /// Check if given version number is defined in this rule
402 
403 Bool_t TSchemaRule::TestVersion( Int_t version ) const
404 {
405  if( fVersion == "" )
406  return kFALSE;
407 
408  if( !fVersionVect )
409  ProcessVersion( fVersion ); // At this point the version string should always be correct
410 
411  if (version == -1) {
412  version = 1;
413  }
414 
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 )
418  return kTRUE;
419  }
420  return kFALSE;
421 }
422 
423 ////////////////////////////////////////////////////////////////////////////////
424 /// Set the checksum string - returns kFALSE if the format is incorrect
425 
426 Bool_t TSchemaRule::SetChecksum( const TString& checksum )
427 {
428  fChecksum = "";
429  Bool_t ret = ProcessChecksum( checksum );
430  if( ret )
431  fChecksum = checksum;
432  return ret;
433 }
434 
435 ////////////////////////////////////////////////////////////////////////////////
436 /// Check if given checksum is defined in this rule
437 
438 Bool_t TSchemaRule::TestChecksum( UInt_t checksum ) const
439 {
440  if( fChecksum == "" )
441  return kFALSE;
442 
443  if( !fChecksumVect )
444  ProcessChecksum( fChecksum ); // At this point the checksum string should always be correct
445 
446  std::vector<UInt_t>::iterator it;
447  for( it = fChecksumVect->begin(); it != fChecksumVect->end(); ++it ) {
448  if( checksum == *it )
449  return kTRUE;
450  }
451  return kFALSE;
452 }
453 
454 ////////////////////////////////////////////////////////////////////////////////
455 /// Set the source class of this rule (i.e. the onfile class).
456 
457 void TSchemaRule::SetSourceClass( const TString& classname )
458 {
459  std::string normalizedName;
460  TClassEdit::GetNormalizedName(normalizedName, classname);
461  fSourceClass = normalizedName;
462 }
463 
464 ////////////////////////////////////////////////////////////////////////////////
465 /// Get the source class of this rule (i.e. the onfile class).
466 
467 const char *TSchemaRule::GetSourceClass() const
468 {
469  return fSourceClass;
470 }
471 
472 ////////////////////////////////////////////////////////////////////////////////
473 /// Set the target class of this rule (i.e. the in memory class).
474 
475 void TSchemaRule::SetTargetClass( const TString& classname )
476 {
477  std::string normalizedName;
478  TClassEdit::GetNormalizedName(normalizedName, classname);
479  fTargetClass = normalizedName;
480 }
481 
482 ////////////////////////////////////////////////////////////////////////////////
483 /// Get the targte class of this rule (i.e. the in memory class).
484 
485 const char *TSchemaRule::GetTargetClass() const
486 {
487  return fTargetClass;
488 }
489 
490 ////////////////////////////////////////////////////////////////////////////////
491 /// Set the target member of this rule (i.e. the in memory data member).
492 
493 void TSchemaRule::SetTarget( const TString& target )
494 {
495  fTarget = target;
496 
497  if( target == "" ) {
498  delete fTargetVect;
499  fTargetVect = 0;
500  return;
501  }
502 
503  if( !fTargetVect ) {
504  fTargetVect = new TObjArray();
505  fTargetVect->SetOwner();
506  }
507  ProcessList( fTargetVect, target );
508 }
509 
510 ////////////////////////////////////////////////////////////////////////////////
511 /// Get the target data members of this rule as a simple string (i.e. the in memory data member).
512 
513 const char *TSchemaRule::GetTargetString() const
514 {
515  return fTarget;
516 }
517 
518 ////////////////////////////////////////////////////////////////////////////////
519 /// Get the target data members of this rule (i.e. the in memory data member).
520 
521 const TObjArray* TSchemaRule::GetTarget() const
522 {
523  if( fTarget == "" )
524  return 0;
525 
526  if( !fTargetVect ) {
527  fTargetVect = new TObjArray();
528  fTargetVect->SetOwner();
529  ProcessList( fTargetVect, fTarget );
530  }
531 
532  return fTargetVect;
533 }
534 
535 ////////////////////////////////////////////////////////////////////////////////
536 /// Set the list of source members. This should be in the form of a declaration:
537 /// Int_t fOldMember; TNamed fName;
538 
539 void TSchemaRule::SetSource( const TString& source )
540 {
541  fSource = source;
542 
543  if( source == "" ) {
544  delete fSourceVect;
545  fSourceVect = 0;
546  return;
547  }
548 
549  if( !fSourceVect ) {
550  fSourceVect = new TObjArray();
551  fSourceVect->SetOwner();
552  }
553 
554  ProcessDeclaration( fSourceVect, source );
555 }
556 
557 ////////////////////////////////////////////////////////////////////////////////
558 /// Get the list of source members as a TObjArray of TNamed object,
559 /// with the name being the member name and the title being its type.
560 
561 const TObjArray* TSchemaRule::GetSource() const
562 {
563  if( fSource == "" )
564  return 0;
565 
566  if( !fSourceVect ) {
567  fSourceVect = new TObjArray();
568  fSourceVect->SetOwner();
569  ProcessDeclaration( fSourceVect, fSource );
570  }
571  return fSourceVect;
572 }
573 
574 ////////////////////////////////////////////////////////////////////////////////
575 /// Set the comma separated list of header files to include to be able
576 /// to compile this rule.
577 
578 void TSchemaRule::SetInclude( const TString& incl )
579 {
580  fInclude = incl;
581 
582  if( incl == "" ) {
583  delete fIncludeVect;
584  fIncludeVect = 0;
585  return;
586  }
587 
588  if( !fIncludeVect ) {
589  fIncludeVect = new TObjArray();
590  fIncludeVect->SetOwner();
591  }
592 
593  ProcessList( fIncludeVect, incl );
594 }
595 
596 ////////////////////////////////////////////////////////////////////////////////
597 /// Return the list of header files to include to be able to
598 /// compile this rule as a TObjArray of TObjString
599 
600 const TObjArray* TSchemaRule::GetInclude() const
601 {
602  if( fInclude == "" )
603  return 0;
604 
605  if( !fIncludeVect ) {
606  fIncludeVect = new TObjArray();
607  fIncludeVect->SetOwner();
608  ProcessList( fIncludeVect, fInclude );
609  }
610 
611  return fIncludeVect;
612 }
613 
614 ////////////////////////////////////////////////////////////////////////////////
615 /// Set whether this rule should be save in the ROOT file (if true)
616 
617 void TSchemaRule::SetEmbed( Bool_t embed )
618 {
619  fEmbed = embed;
620 }
621 
622 ////////////////////////////////////////////////////////////////////////////////
623 /// Return true if this rule should be saved in the ROOT File.
624 
625 Bool_t TSchemaRule::GetEmbed() const
626 {
627  return fEmbed;
628 }
629 
630 ////////////////////////////////////////////////////////////////////////////////
631 /// Return kTRUE if this rule is valid.
632 
633 Bool_t TSchemaRule::IsValid() const
634 {
635  return (fVersionVect || fChecksumVect) && (fSourceClass.Length() != 0);
636 }
637 
638 ////////////////////////////////////////////////////////////////////////////////
639 /// Set the source code of this rule.
640 
641 void TSchemaRule::SetCode( const TString& code )
642 {
643  fCode = code;
644 }
645 
646 ////////////////////////////////////////////////////////////////////////////////
647 /// Get the source code of this rule.
648 
649 const char *TSchemaRule::GetCode() const
650 {
651  return fCode;
652 }
653 
654 ////////////////////////////////////////////////////////////////////////////////
655 /// Set the attributes code of this rule.
656 
657 void TSchemaRule::SetAttributes( const TString& attributes )
658 {
659  fAttributes = attributes;
660 }
661 
662 ////////////////////////////////////////////////////////////////////////////////
663 /// Get the attributes code of this rule.
664 
665 const char *TSchemaRule::GetAttributes() const
666 {
667  return fAttributes;
668 }
669 
670 ////////////////////////////////////////////////////////////////////////////////
671 /// Return true if one of the rule's data member target is 'target'.
672 
673 Bool_t TSchemaRule::HasTarget( const TString& target ) const
674 {
675  if( !fTargetVect )
676  return kFALSE;
677 
678  TObject* obj;
679  TObjArrayIter it( fTargetVect );
680  while( (obj = it.Next()) ) {
681  TObjString* str = (TObjString*)obj;
682  if( str->GetString() == target )
683  return kTRUE;
684  }
685  return kFALSE;
686 }
687 
688 ////////////////////////////////////////////////////////////////////////////////
689 /// Return true if one of the rule's data member source is 'source'
690 
691 Bool_t TSchemaRule::HasSource( const TString& source ) const
692 {
693  if( !fSourceVect )
694  return kFALSE;
695 
696  TObject* obj;
697  TObjArrayIter it( fSourceVect );
698  while( (obj = it.Next()) ) {
699  TSources* var = (TSources*)obj;
700  if( var->GetName() == source )
701  return kTRUE;
702  }
703  return kFALSE;
704 }
705 
706 ////////////////////////////////////////////////////////////////////////////////
707 /// Set the pointer to the function to be run for the rule (if it is a read rule).
708 
709 void TSchemaRule::SetReadFunctionPointer( TSchemaRule::ReadFuncPtr_t ptr )
710 {
711  fReadFuncPtr = ptr;
712 }
713 
714 ////////////////////////////////////////////////////////////////////////////////
715 /// Get the pointer to the function to be run for the rule (if it is a read rule).
716 
717 TSchemaRule::ReadFuncPtr_t TSchemaRule::GetReadFunctionPointer() const
718 {
719  return fReadFuncPtr;
720 }
721 
722 ////////////////////////////////////////////////////////////////////////////////
723 /// Set the pointer to the function to be run for the rule (if it is a raw read rule).
724 
725 void TSchemaRule::SetReadRawFunctionPointer( TSchemaRule::ReadRawFuncPtr_t ptr )
726 {
727  fReadRawFuncPtr = ptr;
728 }
729 
730 ////////////////////////////////////////////////////////////////////////////////
731 /// Get the pointer to the function to be run for the rule (if it is a raw read rule).
732 
733 TSchemaRule::ReadRawFuncPtr_t TSchemaRule::GetReadRawFunctionPointer() const
734 {
735  return fReadRawFuncPtr;
736 }
737 
738 ////////////////////////////////////////////////////////////////////////////////
739 /// Set the type of the rule.
740 
741 void TSchemaRule::SetRuleType( TSchemaRule::RuleType_t type )
742 {
743  fRuleType = type;
744 }
745 
746 ////////////////////////////////////////////////////////////////////////////////
747 /// Return kTRUE if the rule is a strict renaming of one of the data member of the class.
748 
749 Bool_t TSchemaRule::IsAliasRule() const
750 {
751  return fSourceClass != "" && (fVersion != "" || fChecksum != "") && fTarget == "" && fSource == "" && fInclude == "" && fCode == "" && fAttributes == "";
752 }
753 
754 ////////////////////////////////////////////////////////////////////////////////
755 /// Return kTRUE if the rule is a strict renaming of the class to a new name.
756 
757 Bool_t TSchemaRule::IsRenameRule() const
758 {
759  return fSourceClass != "" && (fVersion != "" || fChecksum != "") && fTarget != "" && fSource != "" && fInclude == "" && fCode == "" && fAttributes == "";
760 }
761 
762 ////////////////////////////////////////////////////////////////////////////////
763 /// Return the type of the rule.
764 
765 TSchemaRule::RuleType_t TSchemaRule::GetRuleType() const
766 {
767  return fRuleType;
768 }
769 
770 ////////////////////////////////////////////////////////////////////////////////
771 /// Check if this rule conflicts with the given one.
772 
773 Bool_t TSchemaRule::Conflicts( const TSchemaRule* rule ) const
774 {
775  //---------------------------------------------------------------------------
776  // If the rules have different sources then the don't conflict
777  /////////////////////////////////////////////////////////////////////////////
778 
779  if( fSourceClass != rule->fSourceClass )
780  return kFALSE;
781 
782  //---------------------------------------------------------------------------
783  // Check if the rules have common target
784  /////////////////////////////////////////////////////////////////////////////
785 
786  if( !rule->GetTarget() )
787  return kFALSE;
788 
789  Bool_t haveCommonTargets = kFALSE;
790  TObjArrayIter titer( rule->GetTarget() );
791  TObjString *str;
792  TObject *obj;
793 
794  while( (obj = titer.Next() ) ) {
795  str = (TObjString*)obj;
796  if( HasTarget( str->String() ) )
797  haveCommonTargets = kTRUE;
798  }
799 
800  if( !haveCommonTargets )
801  return kFALSE;
802 
803  //---------------------------------------------------------------------------
804  // Check if there are conflicting checksums
805  /////////////////////////////////////////////////////////////////////////////
806 
807  if( fChecksumVect ) {
808  std::vector<UInt_t>::iterator it;
809  for( it = fChecksumVect->begin(); it != fChecksumVect->end(); ++it )
810  if( rule->TestChecksum( *it ) )
811  return kTRUE;
812  }
813 
814  //---------------------------------------------------------------------------
815  // Check if there are conflicting versions
816  /////////////////////////////////////////////////////////////////////////////
817 
818  if( fVersionVect && rule->fVersionVect )
819  {
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 ) {
825  //------------------------------------------------------------------
826  // the rules conflict it their version ranges intersect
827  ////////////////////////////////////////////////////////////////////
828 
829  if( it1->first >= it2->first && it1->first <= it2->second )
830  return kTRUE;
831 
832  if( it1->first < it2->first && it1->second >= it2->first )
833  return kTRUE;
834  }
835  }
836  }
837  return kFALSE;
838 }
839 
840 ////////////////////////////////////////////////////////////////////////////////
841 /// Check if specified version string is correct and build version vector.
842 
843 Bool_t TSchemaRule::ProcessVersion( const TString& version ) const
844 {
845  //---------------------------------------------------------------------------
846  // Check if we have valid list
847  /////////////////////////////////////////////////////////////////////////////
848 
849  if( version[0] != '[' || version[version.Length()-1] != ']' )
850  return kFALSE;
851  std::string ver = version.Data();
852 
853  std::list<std::string> versions;
854  Internal::TSchemaRuleProcessor::SplitList( ver.substr( 1, ver.size()-2), versions );
855 
856  if( versions.empty() )
857  {
858  delete fVersionVect;
859  fVersionVect = 0;
860  return kFALSE;
861  }
862 
863  if( !fVersionVect )
864  fVersionVect = new std::vector<std::pair<Int_t, Int_t> >;
865  fVersionVect->clear();
866 
867  //---------------------------------------------------------------------------
868  // Check the validity of each list element
869  /////////////////////////////////////////////////////////////////////////////
870 
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 ) )
875  {
876  delete fVersionVect;
877  fVersionVect = 0;
878  return kFALSE;
879  }
880  fVersionVect->push_back( verpair );
881  }
882  return kTRUE;
883 }
884 
885 ////////////////////////////////////////////////////////////////////////////////
886 /// Check if specified checksum string is correct and build checksum vector.
887 
888 Bool_t TSchemaRule::ProcessChecksum( const TString& checksum ) const
889 {
890  //---------------------------------------------------------------------------
891  // Check if we have valid list
892  /////////////////////////////////////////////////////////////////////////////
893 
894  if (!checksum[0])
895  return kFALSE;
896  std::string chk = (const char*)checksum;
897  if( chk[0] != '[' || chk[chk.size()-1] != ']' )
898  return kFALSE;
899 
900  std::list<std::string> checksums;
901  Internal::TSchemaRuleProcessor::SplitList( chk.substr( 1, chk.size()-2), checksums );
902 
903  if( checksums.empty() ) {
904  delete fChecksumVect;
905  fChecksumVect = 0;
906  return kFALSE;
907  }
908 
909  if( !fChecksumVect )
910  fChecksumVect = new std::vector<UInt_t>;
911  fChecksumVect->clear();
912 
913  //---------------------------------------------------------------------------
914  // Check the validity of each list element
915  /////////////////////////////////////////////////////////////////////////////
916 
917  for( const auto& checksumStr : checksums ) {
918  auto chksum = ParseChecksum( checksumStr.c_str() );
919  if (chksum == 0u) {
920  delete fChecksumVect;
921  fChecksumVect = nullptr;
922  return kFALSE;
923  }
924 
925  fChecksumVect->push_back( chksum );
926  }
927  return kTRUE;
928 }
929 
930 ////////////////////////////////////////////////////////////////////////////////
931 /// Parse the checksum in the given string. Returns either the checksum or zero
932 /// if the string is not a hex or decimal number.
933 
934 UInt_t TSchemaRule::ParseChecksum(const char* checksum) const {
935  std::istringstream converter(checksum);
936  UInt_t chksum;
937  converter >> std::hex >> chksum;
938  if (converter.fail()) {
939  converter.clear();
940  converter.seekg(0);
941  converter >> std::dec >> chksum;
942  }
943 
944  if( converter.fail() ) {
945  return 0u;
946  }
947 
948  return chksum;
949 }
950 
951 ////////////////////////////////////////////////////////////////////////////////
952 /// Split the list as a comma separated list into a TObjArray of TObjString.
953 
954 void TSchemaRule::ProcessList( TObjArray* array, const TString& list )
955 {
956  std::list<std::string> elems;
957  std::list<std::string>::iterator it;
958  Internal::TSchemaRuleProcessor::SplitList( (const char*)list, elems );
959 
960  array->Clear();
961 
962  if( elems.empty() )
963  return;
964 
965  for( it = elems.begin(); it != elems.end(); ++it ) {
966  TObjString *str = new TObjString;
967  *str = it->c_str();
968  array->Add( str );
969  }
970 }
971 
972 ////////////////////////////////////////////////////////////////////////////////
973 /// Split the list as a declaration into as a TObjArray of TNamed(name,type).
974 
975 void TSchemaRule::ProcessDeclaration( TObjArray* array, const TString& list )
976 {
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 );
980 
981  array->Clear();
982 
983  if( elems.empty() )
984  return;
985 
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() ) ;
988  array->Add( type );
989  }
990 }
991 
992 #if 0
993 ////////////////////////////////////////////////////////////////////////////////
994 /// Generate the actual function for the rule.
995 
996 Bool_t TSchemaRule::GenerateFor( TStreamerInfo *info )
997 {
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;
1004 
1005  String filename = funcname + ".C";
1006  if (!false) {
1007  filename += '+';
1008  }
1009 
1010  std::ofstream fileout(filename);
1011 
1012 
1013  ROOT::WriteReadRawRuleFunc( *rIt, 0, mappedname, nameTypeMap, fileout );
1014  ROOT::WriteReadRuleFunc( *rIt, 0, mappedname, nameTypeMap, fileout );
1015 
1016  gROOT->LoadMacro(filename);
1017 }
1018 
1019 #endif