17 static void RemoveEscapeSequences(std::string& rawString)
19 const std::vector<std::pair<std::string, std::string>> subPairs { {
"\\\\",
"\\"},
23 for (
auto const & subPair : subPairs){
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();
37 using namespace Internal;
39 typedef std::list<std::pair<ROOT::Internal::TSchemaType,std::string> >
SourceTypeList_t;
48 static Bool_t ValidateRule(
const std::map<std::string, std::string>& rule, std::string &error_string );
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)
59 switch( command[cursor] ) {
63 case '=':
if (level==0) {
64 std::string::size_type sub_cursor = cursor;
65 while( isspace(command[sub_cursor]) ) {
68 if ( command[sub_cursor] ==
'=' ) {
76 case '<': ++level;
break;
77 case '>':
if (level==0) {
return std::string::npos; }
93 std::string &error_string )
95 std::string::size_type
l=0;
102 if( command[command.size()-1] ==
';' )
103 command = command.substr( 0, command.size()-1 );
112 if ( endsymbol == command.length() || command[endsymbol] ==
' ' || command[endsymbol] ==
'\t' ) {
118 result[
"sourceClass"] = value;
119 result[
"targetClass"] = value;
120 if (endsymbol < command.length()) {
134 if ( endsymbol == command.length() || command[endsymbol] ==
' ' || command[endsymbol] ==
'\t' ) {
136 result[
"source"] = membervalue;
137 result[
"target"] = membervalue;
147 while( !command.empty() ) {
152 std::string::size_type pos = command.find(
'=' );
158 if( pos == std::string::npos ) {
159 error_string =
"Parsing error, no key found!";
174 if( command.size() < 1 ) {
175 error_string =
"Parsing error, wrond or no value specified for key: " + key;
179 Bool_t hasquote = command[0] ==
'"';
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.";
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.";
197 auto rawCode = command.substr( 2,
l-2 );
198 RemoveEscapeSequences(rawCode);
199 result[key] = rawCode;
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.";
214 result[key] = command.substr( 1,
l-1 );
216 l = command.find(
' ', 1);
217 if (
l == std::string::npos)
l = command.size();
218 result[key] = command.substr( 0,
l );
226 if(
l == command.size() )
228 command = command.substr(
l+1 );
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;
239 if ( result.find(
"version") == result.end() && result.find(
"checksum") == result.end() ) {
240 result[
"version"] =
"[1-]";
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 ==
';';},
256 result[includeKeyName] = includeTagValue;
265 static Bool_t ValidateRule(
const std::map<std::string, std::string>& rule, std::string &error_string )
271 std::map<std::string, std::string>::const_iterator it1, it2;
272 std::list<std::string> lst;
273 std::list<std::string>::iterator lsIt;
275 it1 = rule.find(
"targetClass" );
276 if( it1 == rule.end() ) {
277 error_string =
"You always have to specify the targetClass ";
278 error_string +=
"when specyfying an IO rule";
283 std::string warning =
"IO rule for class " + className;
289 it1 = rule.find(
"sourceClass" );
290 if( it1 == rule.end())
292 error_string = warning +
" - sourceClass parameter is missing";
300 it1 = rule.find(
"version" );
301 it2 = rule.find(
"checksum" );
302 if( it1 == rule.end() && it2 == rule.end() ) {
303 error_string = warning +
" - you need to specify either version or ";
304 error_string +=
"checksum";
312 if( it2 != rule.end() ) {
313 if( it2->second.size() < 2 || it2->second[0] !=
'[' ||
314 it2->second[it2->second.size()-1] !=
']' ) {
315 error_string = warning +
" - a comma separated list of ints";
316 error_string +=
" enclosed in square brackets expected";
317 error_string +=
" as a value of checksum parameter";
324 error_string += warning +
" - the list of checksums is empty\n";
327 for( lsIt = lst.begin(); lsIt != lst.end(); ++lsIt )
329 error_string = warning +
" - " + *lsIt +
" is not a valid value";
330 error_string +=
" of checksum parameter - an integer expected";
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";
352 error_string = warning +
" - the list of versions is empty";
355 for( lsIt = lst.begin(); lsIt != lst.end(); ++lsIt )
357 error_string = warning +
" - " + *lsIt +
" is not a valid value";
358 error_string +=
" of version parameter";
368 if( rule.size() == 3 || (rule.size() == 4 && it1 != rule.end() && it2 != rule.end()) )
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];
388 it1 = rule.find(
"code");
389 if (it1 != rule.end() && it1->second !=
"") {
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 +
"\"";
407 it1 = rule.find(
"embed" );
408 if( it1 != rule.end() ) {
410 if( emValue !=
"true" && emValue !=
"false" ) {
411 error_string = warning +
" - true or false expected as a value ";
412 error_string +=
"of embed parameter";
421 it1 = rule.find(
"include" );
422 if( it1 != rule.end() ) {
423 if( it1->second.empty() ) {
424 error_string = warning +
" - the include list is empty";
437 std::string& error_string)
439 std::list<std::string> mem;
440 std::list<std::string>::iterator it;
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 "
467 std::string& className, std::string& mappedName,
470 if (!source.empty()) {
472 SourceTypeList_t::const_iterator it;
479 Bool_t generateOnFile =
false;
480 output <<
"#if 0" << std::endl;
481 for( it = source.begin(); it != source.end(); ++it ) {
483 output <<
"static Int_t id_" << it->second <<
" = oldObj->GetId(";
484 output <<
"\"" << it->second <<
"\");" << std::endl;
486 if( it->first.fType !=
"" )
487 generateOnFile =
true;
489 output <<
"#endif" << std::endl;
495 if( generateOnFile ) {
496 std::string onfileStructName = mappedName +
"_Onfile";
498 output <<
"struct " << onfileStructName <<
" {\n";
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";
511 output <<
"onfile_" << it->second <<
"_t &" << it->second <<
";\n";
515 output << it->first.fType <<
" &" << it->second <<
";\n";
524 output <<
" " << onfileStructName <<
"(";
525 for( start =
true, it = source.begin(); it != source.end(); ++it ) {
526 if( it->first.fType.size() == 0)
534 if (it->first.fDimensions.size() == 0) {
535 output << it->first.fType <<
" &onfile_" << it->second;
537 output <<
" onfile_" << it->second <<
"_t" <<
" &onfile_" << it->second;
546 for( start =
true, it = source.begin(); it != source.end(); ++it ) {
547 if( it->first.fType ==
"" )
555 output << it->second <<
"(onfile_" << it->second <<
")";
564 for( it = source.begin(); it != source.end(); ++it ) {
566 output <<
"static Long_t offset_Onfile_" << mappedName;
567 output <<
"_" << it->second <<
" = oldObj->GetClass()->GetDataMemberOffset(\"";
568 output << it->second <<
"\");\n";
570 output <<
" " <<
"char *onfile_add = (char*)oldObj->GetObject();\n";
571 output <<
" " << mappedName <<
"_Onfile onfile(\n";
573 for( start =
true, it = source.begin(); it != source.end(); ++it ) {
574 if( it->first.fType ==
"" )
585 if (it->first.fDimensions.size() == 0) {
586 output << it->first.fType;
588 output << mappedName <<
"_Onfile::onfile_" << it->second <<
"_t";
590 output <<
"*)(onfile_add+offset_Onfile_";
591 output << mappedName <<
"_" << it->second <<
")";
601 if( !target.empty() ) {
602 output <<
" static TClassRef cls(\"";
603 output << className <<
"\");" << std::endl;
605 std::list<std::string>::const_iterator it;
606 for( it = target.begin(); it != target.end(); ++it ) {
608 output <<
" static Long_t offset_" << *it <<
" = ";
609 output <<
"cls->GetDataMemberOffset(\"" << *it <<
"\");";
613 output <<
" " << *it <<
"_t& " << *it <<
" = ";
614 output <<
"*(" << *it <<
"_t *)(target+offset_" << *it;
615 output <<
");" << std::endl;
617 output <<
" " << memData.
fType <<
"& " << *it <<
" = ";
618 output <<
"*(" << memData.
fType <<
"*)(target+offset_" << *it;
619 output <<
");" << std::endl;
633 std::string className = rule[
"targetClass"];
639 std::ostringstream func;
640 func <<
"read_" << mappedName <<
"_" << index;
641 rule[
"funcname"] = func.str();
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;
656 std::list<std::pair<ROOT::Internal::TSchemaType,std::string> > source;
657 std::list<std::string> target;
662 output <<
" " << className <<
"* newObj = (" << className;
663 output <<
"*)target;" << std::endl;
664 output <<
" // Supress warning message.\n";
665 output <<
" " <<
"if (oldObj) {}\n\n";
666 output <<
" " <<
"if (newObj) {}\n\n";
672 output <<
" //--- User's code ---" << std::endl;
673 output <<
" " << rule[
"code"] << std::endl;
674 output <<
" }" << std::endl;
686 std::string className = rule[
"targetClass"];
692 std::ostringstream func;
693 func <<
"readraw_" << mappedName <<
"_" << index;
694 rule[
"funcname"] = func.str();
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;
710 std::list<std::pair<ROOT::Internal::TSchemaType,std::string> > source;
711 std::list<std::string> target;
715 output <<
" " << className <<
"* newObj = (" << className;
716 output <<
"*)target;" << std::endl << std::endl;
722 output <<
" //--- User's code ---" << std::endl;
723 output << rule[
"code"] << std::endl;
724 output <<
"#endif" << std::endl;
725 output <<
" }" << std::endl;
731 static void StrReplace( std::string& proc,
const std::string& pat,
732 const std::string& tr )
734 std::string::size_type it = 0;
735 std::string::size_type
s = pat.size();
736 std::string::size_type tr_len= tr.size();
741 it = proc.find( pat, it );
742 if( it == std::string::npos )
745 proc.replace( it,
s, tr );
754 const std::string& listName, std::ostream&
output )
756 std::list<SchemaRuleMap_t>::iterator it;
763 for( it = rules.begin(); it != rules.end(); ++it ) {
764 output <<
" rule = &" << listName <<
"[" << i++;
765 output <<
"];" << std::endl;
771 output <<
" rule->fSourceClass = \"" << (*it)[
"sourceClass"];
772 output <<
"\";" << std::endl;
774 if( it->find(
"target" ) != it->end() ) {
775 output <<
" rule->fTarget = \"" << (*it)[
"target"];
776 output <<
"\";" << std::endl;
779 if( it->find(
"source" ) != it->end() ) {
780 output <<
" rule->fSource = \"" << (*it)[
"source"];
781 output <<
"\";" << std::endl;
788 if( it->find(
"funcname" ) != it->end() ) {
789 std::string code = (*it)[
"code"];
793 output <<
" rule->fFunctionPtr = (void *)TFunc2void( ";
794 output << (*it)[
"funcname"] <<
");" << std::endl;
795 output <<
" rule->fCode = \"" << code;
796 output <<
"\";" << std::endl;
799 if( it->find(
"version" ) != it->end() ) {
800 output <<
" rule->fVersion = \"" << (*it)[
"version"];
801 output <<
"\";" << std::endl;
804 if( it->find(
"checksum" ) != it->end() ) {
805 output <<
" rule->fChecksum = \"" << (*it)[
"checksum"];
806 output <<
"\";" << std::endl;
809 if( it->find(
"embed" ) != it->end() ) {
810 output <<
" rule->fEmbed = " << (*it)[
"embed"];
811 output <<
";" << std::endl;
814 if( it->find(
"include" ) != it->end() ) {
815 output <<
" rule->fInclude = \"" << (*it)[
"include"];
816 output <<
"\";" << std::endl;
819 if( it->find(
"attributes" ) != it->end() ) {
820 output <<
" rule->fAttributes = \"" << (*it)[
"attributes"];
821 output <<
"\";" << std::endl;
831 std::list<std::string> tmp;
832 std::list<SchemaRuleMap_t>::iterator rule;
833 SchemaRuleMap_t::iterator attr;
834 SchemaRuleClassMap_t::iterator it;
841 for( rule = it->second.begin(); rule != it->second.end(); ++rule ) {
842 attr = rule->find(
"include" );
843 if( attr == rule->end() )
continue;
845 result.splice( result.begin(), tmp, tmp.begin(), tmp.end() );
854 for( rule = it->second.begin(); rule != it->second.end(); ++rule ) {
855 attr = rule->find(
"include" );
856 if( attr == rule->end() )
continue;
858 result.splice( result.begin(), tmp, tmp.begin(), tmp.end() );
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";
891 SchemaRuleClassMap_t::iterator it;
892 std::string targetClass = rule[
"targetClass"];
893 std::string normalizedTargetName;
898 std::list<SchemaRuleMap_t> lst;
899 lst.push_back( rule );
903 it->second.push_back( rule );
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";
927 SchemaRuleClassMap_t::iterator it;
928 std::string targetClass = rule[
"targetClass"];
929 std::string normalizedTargetName;
933 std::list<SchemaRuleMap_t> lst;
934 lst.push_back( rule );
938 it->second.push_back( rule );
static bool IsANumber(const std::string &source)
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
Namespace for new ROOT classes and functions.
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.
static constexpr double s