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