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