28 static void RemoveEscapeSequences(std::string& rawString)
30 const std::vector<std::pair<std::string, std::string>> subPairs { {
"\\\\",
"\\"},
34 for (
auto const & subPair : subPairs){
36 auto from = subPair.first;
37 auto to = subPair.second;
38 while((start_pos = rawString.find(from, start_pos)) != std::string::npos) {
39 rawString.replace(start_pos, from.length(), to);
40 start_pos += to.length();
50 typedef std::list<std::pair<ROOT::Internal::TSchemaType,std::string> >
SourceTypeList_t;
59 static Bool_t ValidateRule(
const std::map<std::string, std::string>& rule, std::string &error_string );
65 if (command.length() == 0)
return std::string::npos;
66 std::string::size_type cursor;
67 unsigned int level = 0;
68 for (cursor = 0 ; cursor < command.length(); ++cursor)
70 switch( command[cursor] ) {
74 case '=':
if (level==0) {
75 std::string::size_type sub_cursor = cursor;
76 while( isspace(command[sub_cursor]) ) {
79 if ( command[sub_cursor] ==
'=' ) {
87 case '<': ++level;
break;
88 case '>':
if (level==0) {
return std::string::npos; }
104 std::string &error_string )
106 std::string::size_type
l=0;
113 if( command[command.size()-1] ==
';' )
114 command = command.substr( 0, command.size()-1 );
123 if ( endsymbol == command.length() || command[endsymbol] ==
' ' || command[endsymbol] ==
'\t' ) {
129 result[
"sourceClass"] = value;
130 result[
"targetClass"] = value;
131 if (endsymbol < command.length()) {
145 if ( endsymbol == command.length() || command[endsymbol] ==
' ' || command[endsymbol] ==
'\t' ) {
147 result[
"source"] = membervalue;
148 result[
"target"] = membervalue;
158 while( !command.empty() ) {
163 std::string::size_type
pos = command.find(
'=' );
169 if(
pos == std::string::npos ) {
170 error_string =
"Parsing error, no key found!";
185 if( command.size() < 1 ) {
186 error_string =
"Parsing error, wrond or no value specified for key: " + key;
190 Bool_t hasquote = command[0] ==
'"';
196 if( key ==
"code" ) {
202 auto clean_command = [](
const std::string &
c) {
205 first_trim.substr(first_trim.find_first_of(
'"') + 1, first_trim.find_last_of(
'"') - 1);
207 return '"' + second_trim +
'"';
209 command = clean_command(command);
211 if( command[1] !=
'{' ) {
212 error_string =
"Parsing error while processing key: code\n";
213 error_string +=
"Expected \"{ at the beginning of the value.";
216 l = command.find(
"}\"" );
217 if(
l == std::string::npos ) {
218 error_string =
"Parsing error while processing key: \"" + key +
"\"\n";
219 error_string +=
"Expected }\" at the end of the value.";
222 auto rawCode = command.substr( 2,
l-2 );
223 RemoveEscapeSequences(rawCode);
224 result[key] = rawCode;
233 l = command.find(
'"', 1 );
234 if (
l == std::string::npos ) {
235 error_string =
"\nParsing error while processing key: \"" + key +
"\"\n";
236 error_string +=
"Expected \" at the end of the value.";
239 result[key] = command.substr( 1,
l-1 );
241 l = command.find(
' ', 1);
242 if (
l == std::string::npos)
l = command.size();
243 result[key] = command.substr( 0,
l );
251 if(
l == command.size() )
253 command = command.substr(
l+1 );
255 std::map<std::string, std::string>::const_iterator it1;
256 it1 = result.find(
"oldtype");
257 if ( it1 != result.end() ) {
258 std::map<std::string, std::string>::const_iterator it2;
259 it2 = result.find(
"source");
260 if ( it2 != result.end() ) {
261 result[
"source"] = it1->second +
" " + it2->second;
264 if ( result.find(
"version") == result.end() && result.find(
"checksum") == result.end() ) {
265 result[
"version"] =
"[1-]";
273 auto const includeKeyName =
"include";
274 auto includeTag = result.find(includeKeyName);
275 if (includeTag != result.end()){
276 auto & includeTagValue = includeTag->second;
277 std::replace_if (includeTagValue.begin(),
278 includeTagValue.end(),
279 [](
char c){ return c ==
';';},
281 result[includeKeyName] = includeTagValue;
290 static Bool_t ValidateRule(
const std::map<std::string, std::string>& rule, std::string &error_string )
296 std::map<std::string, std::string>::const_iterator it1, it2;
297 std::list<std::string> lst;
299 it1 = rule.find(
"targetClass" );
300 if( it1 == rule.end() ) {
301 error_string =
"You always have to specify the targetClass ";
302 error_string +=
"when specyfying an IO rule";
307 std::string warning =
"IO rule for class " + className;
313 it1 = rule.find(
"sourceClass" );
314 if( it1 == rule.end())
316 error_string = warning +
" - sourceClass parameter is missing";
324 it1 = rule.find(
"version" );
325 it2 = rule.find(
"checksum" );
326 if( it1 == rule.end() && it2 == rule.end() ) {
327 error_string = warning +
" - you need to specify either version or ";
328 error_string +=
"checksum";
336 if( it2 != rule.end() ) {
337 if( it2->second.size() < 2 || it2->second[0] !=
'[' ||
338 it2->second[it2->second.size()-1] !=
']' ) {
339 error_string = warning +
" - a comma separated list of ints";
340 error_string +=
" enclosed in square brackets expected";
341 error_string +=
" as a value of checksum parameter";
348 error_string += warning +
" - the list of checksums is empty\n";
351 for(
const auto& chk : lst ) {
353 error_string = warning +
" - " + chk +
" is not a valid value";
354 error_string +=
" of checksum parameter - an integer (decimal/hex) expected";
364 std::pair<Int_t, Int_t> ver;
365 if( it1 != rule.end() ) {
366 if( it1->second.size() < 2 || it1->second[0] !=
'[' ||
367 it1->second[it1->second.size()-1] !=
']' ) {
368 error_string = warning +
" - a comma separated list of version specifiers ";
369 error_string +=
"enclosed in square brackets expected";
370 error_string +=
"as a value of version parameter";
377 error_string = warning +
" - the list of versions is empty";
380 for(
const auto& version : lst )
382 error_string = warning +
" - " + version +
" is not a valid value";
383 error_string +=
" of version parameter";
393 if( rule.size() == 3 || (rule.size() == 4 && it1 != rule.end() && it2 != rule.end()) )
399 std::string keys[] = {
"target",
"source"};
400 for(
int i = 0; i < 2; ++i ) {
401 it1 = rule.find( keys[i] );
402 if( it1 == rule.end() ) {
403 error_string = warning +
" - required parameter is missing: ";
404 error_string += keys[i];
413 it1 = rule.find(
"code");
414 if (it1 != rule.end() && it1->second !=
"") {
417 SourceTypeList_t::const_iterator it;
418 for( it = source.begin(); it != source.end(); ++it ) {
419 if ( ( it->first.fType ==
"" && it->second !=
"") ) {
420 error_string = warning +
" - type required when listing a rule's source: ";
421 error_string +=
"source=\""+ rule.find(
"source")->second +
"\"";
432 it1 = rule.find(
"embed" );
433 if( it1 != rule.end() ) {
435 if( emValue !=
"true" && emValue !=
"false" ) {
436 error_string = warning +
" - true or false expected as a value ";
437 error_string +=
"of embed parameter";
446 it1 = rule.find(
"include" );
447 if( it1 != rule.end() ) {
448 if( it1->second.empty() ) {
449 error_string = warning +
" - the include list is empty";
462 std::string& error_string)
464 std::list<std::string> mem;
465 std::list<std::string>::iterator it;
474 for( it = mem.begin(); it != mem.end(); ++it ) {
475 if( members.find( *it ) == members.end() ) {
476 error_string +=
"IO rule for class " + rule[
"targetClass"]
477 +
" data member: " + *it +
" was specified as a "
478 "target in the rule but doesn't seem to appear in "
492 std::string& className, std::string& mappedName,
493 std::ostream& output )
495 if (!source.empty()) {
497 SourceTypeList_t::const_iterator it;
504 Bool_t generateOnFile =
false;
505 output <<
"#if 0" << std::endl;
506 for( it = source.begin(); it != source.end(); ++it ) {
508 output <<
"static Int_t id_" << it->second <<
" = oldObj->GetId(";
509 output <<
"\"" << it->second <<
"\");" << std::endl;
511 if( it->first.fType !=
"" )
512 generateOnFile =
true;
514 output <<
"#endif" << std::endl;
520 if( generateOnFile ) {
521 std::string onfileStructName = mappedName +
"_Onfile";
523 output <<
"struct " << onfileStructName <<
" {\n";
530 for( it = source.begin(); it != source.end(); ++it ) {
531 if( it->first.fType.size() ) {
532 if ( it->first.fDimensions.size() ) {
533 output <<
" typedef " << it->first.fType;
534 output <<
" onfile_" << it->second <<
"_t" << it->first.fDimensions <<
";\n";
536 output <<
"onfile_" << it->second <<
"_t &" << it->second <<
";\n";
540 output << it->first.fType <<
" &" << it->second <<
";\n";
549 output <<
" " << onfileStructName <<
"(";
550 for(
start =
true, it = source.begin(); it != source.end(); ++it ) {
551 if( it->first.fType.size() == 0)
559 if (it->first.fDimensions.size() == 0) {
560 output << it->first.fType <<
" &onfile_" << it->second;
562 output <<
" onfile_" << it->second <<
"_t" <<
" &onfile_" << it->second;
571 for(
start =
true, it = source.begin(); it != source.end(); ++it ) {
572 if( it->first.fType ==
"" )
580 output << it->second <<
"(onfile_" << it->second <<
")";
583 output <<
" " <<
"};\n";
589 for( it = source.begin(); it != source.end(); ++it ) {
591 output <<
"static Long_t offset_Onfile_" << mappedName;
592 output <<
"_" << it->second <<
" = oldObj->GetClass()->GetDataMemberOffset(\"";
593 output << it->second <<
"\");\n";
595 output <<
" " <<
"char *onfile_add = (char*)oldObj->GetObject();\n";
596 output <<
" " << mappedName <<
"_Onfile onfile(\n";
598 for(
start =
true, it = source.begin(); it != source.end(); ++it ) {
599 if( it->first.fType ==
"" )
610 if (it->first.fDimensions.size() == 0) {
611 output << it->first.fType;
613 output << mappedName <<
"_Onfile::onfile_" << it->second <<
"_t";
615 output <<
"*)(onfile_add+offset_Onfile_";
616 output << mappedName <<
"_" << it->second <<
")";
626 if( !target.empty() ) {
627 output <<
" static TClassRef cls(\"";
628 output << className <<
"\");" << std::endl;
630 std::list<std::string>::const_iterator it;
631 for( it = target.begin(); it != target.end(); ++it ) {
633 output <<
" static Long_t offset_" << *it <<
" = ";
634 output <<
"cls->GetDataMemberOffset(\"" << *it <<
"\");";
637 output <<
" typedef " << memData.
fType <<
" " << *it <<
"_t" << memData.
fDimensions <<
";" << std::endl;
638 output <<
" " << *it <<
"_t& " << *it <<
" = ";
639 output <<
"*(" << *it <<
"_t *)(target+offset_" << *it;
640 output <<
");" << std::endl;
642 output <<
" " << memData.
fType <<
"& " << *it <<
" = ";
643 output <<
"*(" << memData.
fType <<
"*)(target+offset_" << *it;
644 output <<
");" << std::endl;
656 std::ostream& output )
658 std::string className = rule[
"targetClass"];
664 std::ostringstream func;
665 func <<
"read_" << mappedName <<
"_" << index;
666 rule[
"funcname"] = func.str();
672 output <<
" static void " << func.str();
673 output <<
"( char* target, TVirtualObject *oldObj )" << std::endl;
674 output <<
" {" << std::endl;
675 output <<
" //--- Automatically generated variables ---" << std::endl;
681 std::list<std::pair<ROOT::Internal::TSchemaType,std::string> > source;
682 std::list<std::string> target;
687 output <<
" " << className <<
"* newObj = (" << className;
688 output <<
"*)target;" << std::endl;
689 output <<
" // Supress warning message.\n";
690 output <<
" " <<
"(void)oldObj;\n\n";
691 output <<
" " <<
"(void)newObj;\n\n";
697 output <<
" //--- User's code ---" << std::endl;
698 output <<
" " << rule[
"code"] << std::endl;
699 output <<
" }" << std::endl;
709 std::ostream& output )
711 std::string className = rule[
"targetClass"];
717 std::ostringstream func;
718 func <<
"readraw_" << mappedName <<
"_" << index;
719 rule[
"funcname"] = func.str();
725 output <<
" static void " << func.str();
726 output <<
"( char* target, TBuffer &b )" << std::endl;
727 output <<
" {" << std::endl;
728 output <<
"#if 0" << std::endl;
729 output <<
" //--- Automatically generated variables ---" << std::endl;
735 std::list<std::pair<ROOT::Internal::TSchemaType,std::string> > source;
736 std::list<std::string> target;
740 output <<
" " << className <<
"* newObj = (" << className;
741 output <<
"*)target;" << std::endl << std::endl;
747 output <<
" //--- User's code ---" << std::endl;
748 output << rule[
"code"] << std::endl;
749 output <<
"#endif" << std::endl;
750 output <<
" }" << std::endl;
756 static void StrReplace( std::string& proc,
const std::string& pat,
757 const std::string& tr )
759 std::string::size_type it = 0;
760 std::string::size_type s = pat.size();
761 std::string::size_type tr_len= tr.size();
766 it = proc.find( pat, it );
767 if( it == std::string::npos )
770 proc.replace( it, s, tr );
779 const std::string& listName, std::ostream& output )
781 std::list<SchemaRuleMap_t>::iterator it;
788 for( it = rules.begin(); it != rules.end(); ++it ) {
789 output <<
" rule = &" << listName <<
"[" << i++;
790 output <<
"];" << std::endl;
796 output <<
" rule->fSourceClass = \"" << (*it)[
"sourceClass"];
797 output <<
"\";" << std::endl;
799 if( it->find(
"target" ) != it->end() ) {
800 output <<
" rule->fTarget = \"" << (*it)[
"target"];
801 output <<
"\";" << std::endl;
804 if( it->find(
"source" ) != it->end() ) {
809 std::string norm_sources;
810 std::string norm_type;
811 for(
auto it2 = source.begin(); it2 != source.end(); ++it2 ) {
813 norm_sources += norm_type +
" " + it2->second + it2->first.fDimensions +
"; ";
815 output <<
" rule->fSource = \"" << norm_sources;
816 output <<
"\";" << std::endl;
823 if( it->find(
"funcname" ) != it->end() ) {
824 std::string code = (*it)[
"code"];
828 output <<
" rule->fFunctionPtr = (void *)TFunc2void( ";
829 output << (*it)[
"funcname"] <<
");" << std::endl;
830 output <<
" rule->fCode = \"" << code;
831 output <<
"\";" << std::endl;
834 if( it->find(
"version" ) != it->end() ) {
835 output <<
" rule->fVersion = \"" << (*it)[
"version"];
836 output <<
"\";" << std::endl;
839 if( it->find(
"checksum" ) != it->end() ) {
840 output <<
" rule->fChecksum = \"" << (*it)[
"checksum"];
841 output <<
"\";" << std::endl;
844 if( it->find(
"embed" ) != it->end() ) {
845 output <<
" rule->fEmbed = " << (*it)[
"embed"];
846 output <<
";" << std::endl;
849 if( it->find(
"include" ) != it->end() ) {
850 output <<
" rule->fInclude = \"" << (*it)[
"include"];
851 output <<
"\";" << std::endl;
854 if( it->find(
"attributes" ) != it->end() ) {
855 output <<
" rule->fAttributes = \"" << (*it)[
"attributes"];
856 output <<
"\";" << std::endl;
866 std::list<std::string> tmp;
867 std::list<SchemaRuleMap_t>::iterator rule;
868 SchemaRuleMap_t::iterator attr;
869 SchemaRuleClassMap_t::iterator it;
876 for (rule = it->second.fRules.begin(); rule != it->second.fRules.end(); ++rule) {
877 attr = rule->find(
"include" );
878 if( attr == rule->end() )
continue;
880 result.splice( result.begin(), tmp, tmp.begin(), tmp.end() );
889 for (rule = it->second.fRules.begin(); rule != it->second.fRules.end(); ++rule) {
890 attr = rule->find(
"include" );
891 if( attr == rule->end() )
continue;
893 result.splice( result.begin(), tmp, tmp.begin(), tmp.end() );
914 std::map<std::string, std::string> rule;
915 if( !
ParseRule( args, rule, error_string ) ) {
916 error_string +=
"\nThe following rule has been omitted:\n read ";
917 error_string += args;
918 error_string +=
"\n";
926 SchemaRuleClassMap_t::iterator it;
927 std::string targetClass = rule[
"targetClass"];
928 std::string normalizedTargetName;
933 std::list<SchemaRuleMap_t> lst;
934 lst.push_back( rule );
935 gReadRules[normalizedTargetName].fRules = lst;
938 it->second.fRules.push_back(rule);
950 std::map<std::string, std::string> rule;
951 if( !
ParseRule( args, rule, error_string ) ) {
952 error_string +=
"\nThe following rule has been omitted:\n readraw ";
953 error_string += args;
954 error_string +=
"\n";
962 SchemaRuleClassMap_t::iterator it;
963 std::string targetClass = rule[
"targetClass"];
964 std::string normalizedTargetName;
968 std::list<SchemaRuleMap_t> lst;
969 lst.push_back( rule );
973 it->second.fRules.push_back(rule);
bool Bool_t
Boolean (0=false, 1=true) (bool).
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
std::list< std::pair< ROOT::Internal::TSchemaType, std::string > > SourceTypeList_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"...
std::map< std::string, RRulesList > SchemaRuleClassMap_t
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.