Logo ROOT   6.08/07
Reference Guide
RConversionRuleParser.cxx
Go to the documentation of this file.
1 // @(#)root/core:$Id$
2 // author: Lukasz Janyst <ljanyst@cern.ch>
3 
5 #include "TSchemaRuleProcessor.h"
6 #include "TMetaUtils.h"
7 
8 #include <iostream>
9 #include <algorithm>
10 #include <string>
11 #include <utility>
12 #include <map>
13 #include <sstream>
14 
15 namespace {
16  static void RemoveEscapeSequences(std::string& rawString)
17  {
18  const std::vector<std::pair<std::string, std::string>> subPairs { {"\\\\","\\"},
19  {"\\\"","\""},
20  {"\\\'","\'"}};
21  size_t start_pos = 0;
22  for (auto const & subPair : subPairs){
23  start_pos = 0;
24  auto from = subPair.first;
25  auto to = subPair.second;
26  while((start_pos = rawString.find(from, start_pos)) != std::string::npos) {
27  rawString.replace(start_pos, from.length(), to);
28  start_pos += to.length();
29  }
30  }
31  }
32 }
33 
34 namespace ROOT
35 {
36  using namespace Internal;
37 
38  typedef std::list<std::pair<ROOT::Internal::TSchemaType,std::string> > SourceTypeList_t;
39 
40  //--------------------------------------------------------------------------
41  // Allocate global variables
42  /////////////////////////////////////////////////////////////////////////////
43 
46 
47  static Bool_t ValidateRule( const std::map<std::string, std::string>& rule, std::string &error_string );
48 
49  static std::string::size_type FindEndSymbol(std::string &command)
50  {
51  // Find the end of a symbol.
52 
53  if (command.length() == 0) return std::string::npos;
54  std::string::size_type cursor;
55  unsigned int level = 0;
56  for (cursor = 0 ; cursor < command.length(); ++cursor)
57  {
58  switch( command[cursor] ) {
59  case ' ':
60  case '\t':
61  case '\r':
62  case '=': if (level==0) {
63  std::string::size_type sub_cursor = cursor;
64  while( isspace(command[sub_cursor]) ) {
65  ++sub_cursor;
66  }
67  if ( command[sub_cursor] == '=' ) {
68  return sub_cursor;
69  } else {
70  return cursor;
71  }
72  } else {
73  break;
74  }
75  case '<': ++level; break;
76  case '>': if (level==0) { return std::string::npos; }
77  --level; break;
78  default: {
79  // nothing to do
80  }
81  };
82  }
83  return cursor;
84  }
85 
86 
87  /////////////////////////////////////////////////////////////////////////////
88  /// Parse the schema rule as specified in the LinkDef file
89 
90  Bool_t ParseRule( std::string command,
91  std::map<std::string, std::string> &result,
92  std::string &error_string )
93  {
94  std::string::size_type l=0;
95  command = TSchemaRuleProcessor::Trim( command );
96 
97  //-----------------------------------------------------------------------
98  // Remove the semicolon from the end if declared
99  //////////////////////////////////////////////////////////////////////////
100 
101  if( command[command.size()-1] == ';' )
102  command = command.substr( 0, command.size()-1 );
103 
104  //-----------------------------------------------------------------------
105  // If the first symbol does not end is not followed by equal then it
106  // defaults to being the sourceClass.
107  //////////////////////////////////////////////////////////////////////////
108 
109  {
110  std::string::size_type endsymbol = FindEndSymbol( command );
111  if ( endsymbol == command.length() || command[endsymbol] == ' ' || command[endsymbol] == '\t' ) {
112 
113 // std::string::size_type space_pos = command.find( ' ' );
114 // std::string::size_type equal_pos = command.find( '=' );
115 // if ( space_pos < equal_pos) {
116  std::string value = TSchemaRuleProcessor::Trim( command.substr( 0, endsymbol ) );
117  result["sourceClass"] = value;
118  result["targetClass"] = value;
119  if (endsymbol < command.length()) {
120  command = TSchemaRuleProcessor::Trim( command.substr( endsymbol+1 ) );
121  } else {
122  command.clear();
123  }
124 
125  //-----------------------------------------------------------------------
126  // If the first symbol is the targetClass then the 2nd symbol can be
127  // the source data member name.
128  //-----------------------------------------------------------------------
129 // space_pos = command.find( ' ' );
130 // equal_pos = command.find( '=' );
131 // if ( space_pos < equal_pos ) {
132  endsymbol = FindEndSymbol( command );
133  if ( endsymbol == command.length() || command[endsymbol] == ' ' || command[endsymbol] == '\t' ) {
134  std::string membervalue = TSchemaRuleProcessor::Trim( command.substr( 0, endsymbol ) );
135  result["source"] = membervalue;
136  result["target"] = membervalue;
137  command = TSchemaRuleProcessor::Trim( command.substr( endsymbol+1 ) );
138  }
139  }
140  }
141 
142  //-----------------------------------------------------------------------
143  // Process the input until there are no characters left
144  //////////////////////////////////////////////////////////////////////////
145 
146  while( !command.empty() ) {
147  //--------------------------------------------------------------------
148  // Find key token
149  ///////////////////////////////////////////////////////////////////////
150 
151  std::string::size_type pos = command.find( '=' );
152 
153  //--------------------------------------------------------------------
154  // No equality sign found - no keys left
155  ///////////////////////////////////////////////////////////////////////
156 
157  if( pos == std::string::npos ) {
158  error_string = "Parsing error, no key found!";
159  return false;
160  }
161 
162  //--------------------------------------------------------------------
163  // The key was found - process the arguments
164  ///////////////////////////////////////////////////////////////////////
165 
166  std::string key = TSchemaRuleProcessor::Trim( command.substr( 0, pos ) );
167  command = TSchemaRuleProcessor::Trim( command.substr( pos+1 ) );
168 
169  //--------------------------------------------------------------------
170  // Nothing left to be processed
171  ///////////////////////////////////////////////////////////////////////
172 
173  if( command.size() < 1 ) {
174  error_string = "Parsing error, wrond or no value specified for key: " + key;
175  return false;
176  }
177 
178  Bool_t hasquote = command[0] == '"';
179 
180  //--------------------------------------------------------------------
181  // Processing code tag: "{ code }"
182  ///////////////////////////////////////////////////////////////////////
183 
184  if( key == "code" ) {
185  if( command[1] != '{' ) {
186  error_string = "Parsing error while processing key: code\n";
187  error_string += "Expected \"{ at the beginning of the value.";
188  return false;
189  }
190  l = command.find( "}\"" );
191  if( l == std::string::npos ) {
192  error_string = "Parsing error while processing key: \"" + key + "\"\n";
193  error_string += "Expected }\" at the end of the value.";
194  return false;
195  }
196  auto rawCode = command.substr( 2, l-2 );
197  RemoveEscapeSequences(rawCode);
198  result[key] = rawCode;
199  ++l;
200  }
201  //--------------------------------------------------------------------
202  // Processing normal tag: "value"
203  ///////////////////////////////////////////////////////////////////////
204 
205  else {
206  if( hasquote) {
207  l = command.find( '"', 1 );
208  if (l == std::string::npos ) {
209  error_string = "\nParsing error while processing key: \"" + key + "\"\n";
210  error_string += "Expected \" at the end of the value.";
211  return false;
212  }
213  result[key] = command.substr( 1, l-1 );
214  } else {
215  l = command.find(' ', 1);
216  if (l == std::string::npos) l = command.size();
217  result[key] = command.substr( 0, l );
218  }
219  }
220 
221  //--------------------------------------------------------------------
222  // Everything went ok
223  ///////////////////////////////////////////////////////////////////////
224 
225  if( l == command.size() )
226  break;
227  command = command.substr( l+1 );
228  }
229  std::map<std::string, std::string>::const_iterator it1;
230  it1 = result.find("oldtype");
231  if ( it1 != result.end() ) {
232  std::map<std::string, std::string>::const_iterator it2;
233  it2 = result.find("source");
234  if ( it2 != result.end() ) {
235  result["source"] = it1->second + " " + it2->second;
236  }
237  }
238  if ( result.find("version") == result.end() && result.find("checksum") == result.end() ) {
239  result["version"] = "[1-]";
240  }
241 
242  //------------------------------------------------------------------------
243  // "include" tag. Replace ";" with "," for backwards compatibility with
244  // ROOT5
245  //////////////////////////////////////////////////////////////////////////
246 
247  auto const includeKeyName = "include";
248  auto includeTag = result.find(includeKeyName);
249  if (includeTag != result.end()){
250  auto & includeTagValue = includeTag->second;
251  std::replace_if (includeTagValue.begin(),
252  includeTagValue.end(),
253  [](char c){ return c == ';';},
254  ',');
255  result[includeKeyName] = includeTagValue;
256  }
257 
258  return ValidateRule( result, error_string);
259  }
260 
261  /////////////////////////////////////////////////////////////////////////////
262  /// Validate if the user specified rules are correct
263 
264  static Bool_t ValidateRule( const std::map<std::string, std::string>& rule, std::string &error_string )
265  {
266  //-----------------------------------------------------------------------
267  // Check if we have target class name
268  //////////////////////////////////////////////////////////////////////////
269 
270  std::map<std::string, std::string>::const_iterator it1, it2;
271  std::list<std::string> lst;
272  std::list<std::string>::iterator lsIt;
273 
274  it1 = rule.find( "targetClass" );
275  if( it1 == rule.end() ) {
276  error_string = "You always have to specify the targetClass ";
277  error_string += "when specyfying an IO rule";
278  return false;
279  }
280 
281  std::string className = TSchemaRuleProcessor::Trim( it1->second );
282  std::string warning = "IO rule for class " + className;
283 
284  //-----------------------------------------------------------------------
285  // Check if we have the source tag
286  //////////////////////////////////////////////////////////////////////////
287 
288  it1 = rule.find( "sourceClass" );
289  if( it1 == rule.end())
290  {
291  error_string = warning + " - sourceClass parameter is missing";
292  return false;
293  }
294 
295  //-----------------------------------------------------------------------
296  // Check if we have either version or checksum specified
297  //////////////////////////////////////////////////////////////////////////
298 
299  it1 = rule.find( "version" );
300  it2 = rule.find( "checksum" );
301  if( it1 == rule.end() && it2 == rule.end() ) {
302  error_string = warning + " - you need to specify either version or ";
303  error_string += "checksum";
304  return false;
305  }
306 
307  //-----------------------------------------------------------------------
308  // Check if the checksum has been set to right value
309  //////////////////////////////////////////////////////////////////////////
310 
311  if( it2 != rule.end() ) {
312  if( it2->second.size() < 2 || it2->second[0] != '[' ||
313  it2->second[it2->second.size()-1] != ']' ) {
314  error_string = warning + " - a comma separated list of ints";
315  error_string += " enclosed in square brackets expected";
316  error_string += " as a value of checksum parameter";
317  return false;
318  }
319 
320  TSchemaRuleProcessor::SplitList( it2->second.substr( 1, it2->second.size()-2 ),
321  lst );
322  if( lst.empty() ) {
323  std::string warn = warning + " - the list of checksums is empty\n";
324  ROOT::TMetaUtils::Warning(0, warn.c_str());
325  }
326 
327  for( lsIt = lst.begin(); lsIt != lst.end(); ++lsIt )
328  if( !TSchemaRuleProcessor::IsANumber( *lsIt ) ) {
329  error_string = warning + " - " + *lsIt + " is not a valid value";
330  error_string += " of checksum parameter - an integer expected";
331  return false;
332  }
333  }
334 
335  //-----------------------------------------------------------------------
336  // Check if the version is correct
337  //////////////////////////////////////////////////////////////////////////
338 
339  std::pair<Int_t, Int_t> ver;
340  if( it1 != rule.end() ) {
341  if( it1->second.size() < 2 || it1->second[0] != '[' ||
342  it1->second[it1->second.size()-1] != ']' ) {
343  error_string = warning + " - a comma separated list of version specifiers ";
344  error_string += "enclosed in square brackets expected";
345  error_string += "as a value of version parameter";
346  return false;
347  }
348 
349  TSchemaRuleProcessor::SplitList( it1->second.substr( 1, it1->second.size()-2 ),
350  lst );
351  if( lst.empty() ) {
352  error_string = warning + " - the list of versions is empty";
353  }
354 
355  for( lsIt = lst.begin(); lsIt != lst.end(); ++lsIt )
356  if( !TSchemaRuleProcessor::ProcessVersion( *lsIt, ver ) ) {
357  error_string = warning + " - " + *lsIt + " is not a valid value";
358  error_string += " of version parameter";
359  return false;
360  }
361  }
362 
363  //-----------------------------------------------------------------------
364  // Check if we're dealing with renameing declaration - sourceClass,
365  // targetClass and either version or checksum required
366  //////////////////////////////////////////////////////////////////////////
367 
368  if( rule.size() == 3 || (rule.size() == 4 && it1 != rule.end() && it2 != rule.end()) )
369  return true;
370 
371  //-----------------------------------------------------------------------
372  // Check if we have all the keys we need
373  //-----------------------------------------------------------------------
374  std::string keys[] = {"target", "source"};
375  for( int i = 0; i < 2; ++i ) {
376  it1 = rule.find( keys[i] );
377  if( it1 == rule.end() ) {
378  error_string = warning + " - required parameter is missing: ";
379  error_string += keys[i];
380  return false;
381  }
382  }
383 
384  //-----------------------------------------------------------------------
385  // Check the source contains proper declarations.
386  //////////////////////////////////////////////////////////////////////////
387 
388  it1 = rule.find("code");
389  if (it1 != rule.end() && it1->second != "") {
390  SourceTypeList_t source;
391  TSchemaRuleProcessor::SplitDeclaration( rule.find("source")->second, source );
392  SourceTypeList_t::const_iterator it;
393  for( it = source.begin(); it != source.end(); ++it ) {
394  if ( ( it->first.fType == "" && it->second != "") ) {
395  error_string = warning + " - type required when listing a rule's source: ";
396  error_string += "source=\""+ rule.find("source")->second +"\"";
397  return false;
398  }
399  }
400  }
401 
402  //-----------------------------------------------------------------------
403  // Check if we have an embed parameter and if so if it has been set to
404  // the right value
405  //////////////////////////////////////////////////////////////////////////
406 
407  it1 = rule.find( "embed" );
408  if( it1 != rule.end() ) {
409  std::string emValue = TSchemaRuleProcessor::Trim( it1->second );
410  if( emValue != "true" && emValue != "false" ) {
411  error_string = warning + " - true or false expected as a value ";
412  error_string += "of embed parameter";
413  return false;
414  }
415  }
416 
417  //-----------------------------------------------------------------------
418  // Check if the include list is not empty
419  //////////////////////////////////////////////////////////////////////////
420 
421  it1 = rule.find( "include" );
422  if( it1 != rule.end() ) {
423  if( it1->second.empty() ) {
424  error_string = warning + " - the include list is empty";
425  return false;
426  }
427  }
428 
429  return true;
430  }
431 
432  /////////////////////////////////////////////////////////////////////////////
433  /// Check if given rule contains references to valid data members
434 
436  MembersTypeMap_t& members )
437  {
438  std::list<std::string> mem;
439  std::list<std::string>::iterator it;
440  // MembersMap_t::iterator rIt;
441 
442  TSchemaRuleProcessor::SplitList( rule["target"], mem );
443 
444  //-----------------------------------------------------------------------
445  // Loop over the data members
446  //////////////////////////////////////////////////////////////////////////
447 
448  for( it = mem.begin(); it != mem.end(); ++it ) {
449  if( members.find( *it ) == members.end() ) {
450  std::string warn = "IO rule for class " + rule["targetClass"];
451  warn += " data member: " + *it + " was specified as a ";
452  warn += "target in the rule but doesn't seem to appear in ";
453  warn += "target class\n";
454  ROOT::TMetaUtils::Warning(0, warn.c_str());
455  return false;
456  }
457  }
458  return true;
459  }
460 
461  /////////////////////////////////////////////////////////////////////////////
462  ///-----------------------------------------------------------------------
463  /// Write down the sources
464  ///-----------------------------------------------------------------------
465 
466  static void WriteAutoVariables( const std::list<std::string>& target,
467  const SourceTypeList_t& source,
468  MembersTypeMap_t& members,
469  std::string& className, std::string& mappedName,
470  std::ostream& output )
471  {
472  if (!source.empty()) {
473  Bool_t start = true;
474  SourceTypeList_t::const_iterator it;
475 
476  //--------------------------------------------------------------------
477  // Write IDs and check if we should generate the onfile structure
478  // this is done if the type was declared
479  ///////////////////////////////////////////////////////////////////////
480 
481  Bool_t generateOnFile = false;
482  output << "#if 0" << std::endl; // this is to be removed later
483  for( it = source.begin(); it != source.end(); ++it ) {
484  output << " ";
485  output << "static Int_t id_" << it->second << " = oldObj->GetId(";
486  output << "\"" << it->second << "\");" << std::endl;
487 
488  if( it->first.fType != "" )
489  generateOnFile = true;
490  }
491  output << "#endif" << std::endl; // this is to be removed later
492 
493  //--------------------------------------------------------------------
494  // Declare the on-file structure - if needed
495  ///////////////////////////////////////////////////////////////////////
496 
497  if( generateOnFile ) {
498  std::string onfileStructName = mappedName + "_Onfile";
499  output << " ";
500  output << "struct " << onfileStructName << " {\n";
501 
502  //-----------------------------------------------------------------
503  // List the data members with non-empty type declarations
504  ////////////////////////////////////////////////////////////////////
505  /// fprintf(stderr, "Seeing %s %s %s\n", it->first.fType.c_str(), it->second.c_str(), it->first.fDimensions.c_str());
506 
507  for( it = source.begin(); it != source.end(); ++it ) {
508  if( it->first.fType.size() ) {
509  if ( it->first.fDimensions.size() ) {
510  output << " typedef " << it->first.fType;
511  output << " onfile_" << it->second << "_t" << it->first.fDimensions << ";\n";
512  output << " ";
513  output << "onfile_" << it->second << "_t &" << it->second << ";\n";
514 
515  } else {
516  output << " ";
517  output << it->first.fType << " &" << it->second << ";\n";
518  }
519  }
520  }
521 
522  //-----------------------------------------------------------------
523  // Generate the constructor
524  ////////////////////////////////////////////////////////////////////
525 
526  output << " " << onfileStructName << "(";
527  for( start = true, it = source.begin(); it != source.end(); ++it ) {
528  if( it->first.fType.size() == 0)
529  continue;
530 
531  if( !start )
532  output << ", ";
533  else
534  start = false;
535 
536  if (it->first.fDimensions.size() == 0) {
537  output << it->first.fType << " &onfile_" << it->second;
538  } else {
539  output << " onfile_" << it->second << "_t" << " &onfile_" << it->second;
540  }
541  }
542  output << " ): ";
543 
544  //-----------------------------------------------------------------
545  // Generate the constructor's initializer list
546  ////////////////////////////////////////////////////////////////////
547 
548  for( start = true, it = source.begin(); it != source.end(); ++it ) {
549  if( it->first.fType == "" )
550  continue;
551 
552  if( !start )
553  output << ", ";
554  else
555  start = false;
556 
557  output << it->second << "(onfile_" << it->second << ")";
558  }
559  output << " {}\n";
560  output << " " << "};\n";
561 
562  //-----------------------------------------------------------------
563  // Initialize the structure - to be changed later
564  ////////////////////////////////////////////////////////////////////
565 
566  for( it = source.begin(); it != source.end(); ++it ) {
567  output << " ";
568  output << "static Long_t offset_Onfile_" << mappedName;
569  output << "_" << it->second << " = oldObj->GetClass()->GetDataMemberOffset(\"";
570  output << it->second << "\");\n";
571  }
572  output << " " << "char *onfile_add = (char*)oldObj->GetObject();\n";
573  output << " " << mappedName << "_Onfile onfile(\n";
574 
575  for( start = true, it = source.begin(); it != source.end(); ++it ) {
576  if( it->first.fType == "" )
577  continue;
578 
579  if( !start )
580  output << ",\n";
581 
582  else
583  start = false;
584 
585  output << " ";
586  output << "*(";
587  if (it->first.fDimensions.size() == 0) {
588  output << it->first.fType;
589  } else {
590  output << mappedName << "_Onfile::onfile_" << it->second << "_t";
591  }
592  output << "*)(onfile_add+offset_Onfile_";
593  output << mappedName << "_" << it->second << ")";
594  }
595  output << " );\n\n";
596  }
597  }
598 
599  //-----------------------------------------------------------------------
600  // Write down the targets
601  //////////////////////////////////////////////////////////////////////////
602 
603  if( !target.empty() ) {
604  output << " static TClassRef cls(\"";
605  output << className << "\");" << std::endl;
606 
607  std::list<std::string>::const_iterator it;
608  for( it = target.begin(); it != target.end(); ++it ) {
609  Internal::TSchemaType memData = members[*it];
610  output << " static Long_t offset_" << *it << " = ";
611  output << "cls->GetDataMemberOffset(\"" << *it << "\");";
612  output << std::endl;
613  if (memData.fDimensions.size()) {
614  output << " typedef " << memData.fType << " " << *it << "_t" << memData.fDimensions << ";" << std::endl;
615  output << " " << *it << "_t& " << *it << " = ";
616  output << "*(" << *it << "_t *)(target+offset_" << *it;
617  output << ");" << std::endl;
618  } else {
619  output << " " << memData.fType << "& " << *it << " = ";
620  output << "*(" << memData.fType << "*)(target+offset_" << *it;
621  output << ");" << std::endl;
622  }
623  }
624  }
625  }
626 
627  /////////////////////////////////////////////////////////////////////////////
628  /// Write the conversion function for Read rule, the function name
629  /// is being written to rule["funcname"]
630 
631  void WriteReadRuleFunc( SchemaRuleMap_t& rule, int index,
632  std::string& mappedName, MembersTypeMap_t& members,
633  std::ostream& output )
634  {
635  std::string className = rule["targetClass"];
636 
637  //-----------------------------------------------------------------------
638  // Create the function name
639  //////////////////////////////////////////////////////////////////////////
640 
641  std::ostringstream func;
642  func << "read_" << mappedName << "_" << index;
643  rule["funcname"] = func.str();
644 
645  //-----------------------------------------------------------------------
646  // Write the header
647  //////////////////////////////////////////////////////////////////////////
648 
649  output << " static void " << func.str();
650  output << "( char* target, TVirtualObject *oldObj )" << std::endl;
651  output << " {" << std::endl;
652  output << " //--- Automatically generated variables ---" << std::endl;
653 
654  //-----------------------------------------------------------------------
655  // Write the automatically generated variables
656  //////////////////////////////////////////////////////////////////////////
657 
658  std::list<std::pair<ROOT::Internal::TSchemaType,std::string> > source;
659  std::list<std::string> target;
660  TSchemaRuleProcessor::SplitDeclaration( rule["source"], source );
661  TSchemaRuleProcessor::SplitList( rule["target"], target );
662 
663  WriteAutoVariables( target, source, members, className, mappedName, output );
664  output << " " << className << "* newObj = (" << className;
665  output << "*)target;" << std::endl;
666  output << " // Supress warning message.\n";
667  output << " " << "if (oldObj) {}\n\n";
668  output << " " << "if (newObj) {}\n\n";
669 
670  //-----------------------------------------------------------------------
671  // Write the user's code
672  //////////////////////////////////////////////////////////////////////////
673 
674  output << " //--- User's code ---" << std::endl;
675  output << " " << rule["code"] << std::endl;
676  output << " }" << std::endl;
677  }
678 
679 
680  /////////////////////////////////////////////////////////////////////////////
681  /// Write the conversion function for ReadRaw rule, the function name
682  /// is being written to rule["funcname"]
683 
684  void WriteReadRawRuleFunc( SchemaRuleMap_t& rule, int index,
685  std::string& mappedName, MembersTypeMap_t& members,
686  std::ostream& output )
687  {
688  std::string className = rule["targetClass"];
689 
690  //-----------------------------------------------------------------------
691  // Create the function name
692  //////////////////////////////////////////////////////////////////////////
693 
694  std::ostringstream func;
695  func << "readraw_" << mappedName << "_" << index;
696  rule["funcname"] = func.str();
697 
698  //-----------------------------------------------------------------------
699  // Write the header
700  //////////////////////////////////////////////////////////////////////////
701 
702  output << " static void " << func.str();
703  output << "( char* target, TBuffer &b )" << std::endl;
704  output << " {" << std::endl;
705  output << "#if 0" << std::endl;
706  output << " //--- Automatically generated variables ---" << std::endl;
707 
708  //-----------------------------------------------------------------------
709  // Write the automatically generated variables
710  //////////////////////////////////////////////////////////////////////////
711 
712  std::list<std::pair<ROOT::Internal::TSchemaType,std::string> > source;
713  std::list<std::string> target;
714  TSchemaRuleProcessor::SplitList( rule["target"], target );
715 
716  WriteAutoVariables( target, source, members, className, mappedName, output );
717  output << " " << className << "* newObj = (" << className;
718  output << "*)target;" << std::endl << std::endl;
719 
720  //-----------------------------------------------------------------------
721  // Write the user's code
722  //////////////////////////////////////////////////////////////////////////
723 
724  output << " //--- User's code ---" << std::endl;
725  output << rule["code"] << std::endl;
726  output << "#endif" << std::endl;
727  output << " }" << std::endl;
728  }
729 
730  /////////////////////////////////////////////////////////////////////////////
731  /// Replace all accurances of given string with other string
732 
733  static void StrReplace( std::string& proc, const std::string& pat,
734  const std::string& tr )
735  {
736  std::string::size_type it = 0;
737  std::string::size_type s = pat.size();
738  std::string::size_type tr_len= tr.size();
739 
740  if( s == 0 ) return;
741 
742  while( 1 ) {
743  it = proc.find( pat, it );
744  if( it == std::string::npos )
745  break;
746 
747  proc.replace( it, s, tr );
748  it += tr_len;
749  }
750  }
751 
752  /////////////////////////////////////////////////////////////////////////////
753  /// Write schema rules
754 
755  void WriteSchemaList( std::list<SchemaRuleMap_t>& rules,
756  const std::string& listName, std::ostream& output )
757  {
758  std::list<SchemaRuleMap_t>::iterator it;
759  int i = 0;
760 
761  //-----------------------------------------------------------------------
762  // Loop over the rules
763  //////////////////////////////////////////////////////////////////////////
764 
765  for( it = rules.begin(); it != rules.end(); ++it ) {
766  output << " rule = &" << listName << "[" << i++;
767  output << "];" << std::endl;
768 
769  //--------------------------------------------------------------------
770  // Write down the mandatory fields
771  ///////////////////////////////////////////////////////////////////////
772 
773  output << " rule->fSourceClass = \"" << (*it)["sourceClass"];
774  output << "\";" << std::endl;
775 
776  if( it->find( "target" ) != it->end() ) {
777  output << " rule->fTarget = \"" << (*it)["target"];
778  output << "\";" << std::endl;
779  }
780 
781  if( it->find( "source" ) != it->end() ) {
782  output << " rule->fSource = \"" << (*it)["source"];
783  output << "\";" << std::endl;
784  }
785 
786  //--------------------------------------------------------------------
787  // Deal with non mandatory keys
788  ///////////////////////////////////////////////////////////////////////
789 
790  if( it->find( "funcname" ) != it->end() ) {
791  std::string code = (*it)["code"];
792  StrReplace( code, "\n", "\\n" );
793  StrReplace( code, "\"", "\\\"");
794 
795  output << " rule->fFunctionPtr = (void *)TFunc2void( ";
796  output << (*it)["funcname"] << ");" << std::endl;
797  output << " rule->fCode = \"" << code;
798  output << "\";" << std::endl;
799  }
800 
801  if( it->find( "version" ) != it->end() ) {
802  output << " rule->fVersion = \"" << (*it)["version"];
803  output << "\";" << std::endl;
804  }
805 
806  if( it->find( "checksum" ) != it->end() ) {
807  output << " rule->fChecksum = \"" << (*it)["checksum"];
808  output << "\";" << std::endl;
809  }
810 
811  if( it->find( "embed" ) != it->end() ) {
812  output << " rule->fEmbed = " << (*it)["embed"];
813  output << ";" << std::endl;
814  }
815 
816  if( it->find( "include" ) != it->end() ) {
817  output << " rule->fInclude = \"" << (*it)["include"];
818  output << "\";" << std::endl;
819  }
820 
821  if( it->find( "attributes" ) != it->end() ) {
822  output << " rule->fAttributes = \"" << (*it)["attributes"];
823  output << "\";" << std::endl;
824  }
825  }
826  }
827 
828  /////////////////////////////////////////////////////////////////////////////
829  /// Get the list of includes specified in the shema rules
830 
831  void GetRuleIncludes( std::list<std::string> &result )
832  {
833  std::list<std::string> tmp;
834  std::list<SchemaRuleMap_t>::iterator rule;
835  SchemaRuleMap_t::iterator attr;
836  SchemaRuleClassMap_t::iterator it;
837 
838  //-----------------------------------------------------------------------
839  // Processing read rules
840  //////////////////////////////////////////////////////////////////////////
841 
842  for( it = gReadRules.begin(); it != gReadRules.end(); ++it ) {
843  for( rule = it->second.begin(); rule != it->second.end(); ++rule ) {
844  attr = rule->find( "include" );
845  if( attr == rule->end() ) continue;
846  TSchemaRuleProcessor::SplitList( attr->second, tmp );
847  result.splice( result.begin(), tmp, tmp.begin(), tmp.end() );
848  }
849  }
850 
851  //-----------------------------------------------------------------------
852  // Processing read raw rules
853  //////////////////////////////////////////////////////////////////////////
854 
855  for( it = gReadRawRules.begin(); it != gReadRawRules.end(); ++it ) {
856  for( rule = it->second.begin(); rule != it->second.end(); ++rule ) {
857  attr = rule->find( "include" );
858  if( attr == rule->end() ) continue;
859  TSchemaRuleProcessor::SplitList( attr->second, tmp );
860  result.splice( result.begin(), tmp, tmp.begin(), tmp.end() );
861  }
862  }
863 
864  //-----------------------------------------------------------------------
865  // Removing duplicates
866  //////////////////////////////////////////////////////////////////////////
867 
868  result.sort();
869  result.unique();
870  }
871 
872  /////////////////////////////////////////////////////////////////////////////
873  /// I am being called when a read pragma is encountered
874 
875  void ProcessReadPragma( const char* args )
876  {
877  //-----------------------------------------------------------------------
878  // Parse the rule and check it's validity
879  //////////////////////////////////////////////////////////////////////////
880 
881  std::map<std::string, std::string> rule;
882  std::string error_string;
883  if( !ParseRule( args, rule, error_string ) ) {
884  error_string += "\nThe following rule has been omitted:\n read ";
885  error_string += args;
886  error_string += "\n";
887  ROOT::TMetaUtils::Error(0, error_string.c_str());
888  return;
889  }
890 
891  //-----------------------------------------------------------------------
892  // Append the rule to the list
893  //////////////////////////////////////////////////////////////////////////
894 
895  SchemaRuleClassMap_t::iterator it;
896  std::string targetClass = rule["targetClass"];
897  it = gReadRules.find( targetClass );
898  if( it == gReadRules.end() ) {
899  std::list<SchemaRuleMap_t> lst;
900  lst.push_back( rule );
901  gReadRules[targetClass] = lst;
902  }
903  else
904  it->second.push_back( rule );
905  }
906 
907  /////////////////////////////////////////////////////////////////////////////
908  /// I am being called then a readraw pragma is encountered
909 
910  void ProcessReadRawPragma( const char* args )
911  {
912  //-----------------------------------------------------------------------
913  // Parse the rule and check it's validity
914  //////////////////////////////////////////////////////////////////////////
915 
916  std::map<std::string, std::string> rule;
917  std::string error_string;
918  if( !ParseRule( args, rule, error_string ) ) {
919  error_string += "\nThe following rule has been omitted:\n readraw ";
920  error_string += args;
921  error_string += "\n";
922  ROOT::TMetaUtils::Error(0, error_string.c_str());
923  return;
924  }
925 
926  //-----------------------------------------------------------------------
927  // Append the rule to the list
928  //////////////////////////////////////////////////////////////////////////
929 
930  SchemaRuleClassMap_t::iterator it;
931  std::string targetClass = rule["targetClass"];
932  it = gReadRawRules.find( targetClass );
933  if( it == gReadRawRules.end() ) {
934  std::list<SchemaRuleMap_t> lst;
935  lst.push_back( rule );
936  gReadRawRules[targetClass] = lst;
937  }
938  else
939  it->second.push_back( rule );
940  }
941 
942 
943 }
void WriteReadRawRuleFunc(SchemaRuleMap_t &rule, int index, std::string &mappedName, MembersTypeMap_t &members, std::ostream &output)
Write the conversion function for ReadRaw rule, the function name is being written to rule["funcname"...
std::map< std::string, ROOT::Internal::TSchemaType > MembersTypeMap_t
This namespace contains pre-defined functions to be used in conjuction with TExecutor::Map and TExecu...
Definition: StringConv.hxx:21
return c
void Error(const char *location, const char *va_(fmt),...)
Definition: TMetaUtils.h:767
void WriteSchemaList(std::list< SchemaRuleMap_t > &rules, const std::string &listName, std::ostream &output)
Write schema rules.
std::list< std::pair< ROOT::Internal::TSchemaType, std::string > > SourceTypeList_t
static bool IsANumber(const std::string &source)
bool Bool_t
Definition: RtypesCore.h:59
bool HasValidDataMembers(SchemaRuleMap_t &rule, MembersTypeMap_t &members)
Check if given rule contains references to valid data members.
static void SplitDeclaration(const std::string &source, std::list< std::pair< ROOT::Internal::TSchemaType, std::string > > &result)
bool ParseRule(std::string rule, MembersMap_t &result, std::string &error_string)
static std::string::size_type FindEndSymbol(std::string &command)
void GetRuleIncludes(std::list< std::string > &result)
Get the list of includes specified in the shema rules.
SchemaRuleClassMap_t gReadRules
static void SplitList(const std::string &source, std::list< std::string > &result, char delimiter=',')
static void WriteAutoVariables(const std::list< std::string > &target, const SourceTypeList_t &source, MembersTypeMap_t &members, std::string &className, std::string &mappedName, std::ostream &output)
Write down the sources
TLine * l
Definition: textangle.C:4
std::map< std::string, std::list< SchemaRuleMap_t > > SchemaRuleClassMap_t
void WriteReadRuleFunc(SchemaRuleMap_t &rule, int index, std::string &mappedName, MembersTypeMap_t &members, std::ostream &output)
Write the conversion function for Read rule, the function name is being written to rule["funcname"]...
void ProcessReadRawPragma(const char *args)
I am being called then a readraw pragma is encountered.
SchemaRuleClassMap_t gReadRawRules
void ProcessReadPragma(const char *args)
I am being called when a read pragma is encountered.
double func(double *x, double *p)
Definition: stressTF1.cxx:213
void Warning(const char *location, const char *va_(fmt),...)
Definition: TMetaUtils.h:797
static void StrReplace(std::string &proc, const std::string &pat, const std::string &tr)
Replace all accurances of given string with other string.
static Bool_t ValidateRule(const std::map< std::string, std::string > &rule, std::string &error_string)
Validate if the user specified rules are correct.
double result[121]
std::map< std::string, std::string > SchemaRuleMap_t
static std::string Trim(const std::string &source)
static bool ProcessVersion(const std::string &source, std::pair< Int_t, Int_t > &result)