29 static void RemoveEscapeSequences(std::string& rawString)
31 const std::vector<std::pair<std::string, std::string>> subPairs { {
"\\\\",
"\\"},
35 for (
auto const & subPair : subPairs){
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();
49 using namespace Internal;
51 typedef std::list<std::pair<ROOT::Internal::TSchemaType,std::string> >
SourceTypeList_t;
60 static Bool_t ValidateRule(
const std::map<std::string, std::string>& rule, std::string &error_string );
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)
71 switch( command[cursor] ) {
75 case '=':
if (level==0) {
76 std::string::size_type sub_cursor = cursor;
77 while( isspace(command[sub_cursor]) ) {
80 if ( command[sub_cursor] ==
'=' ) {
88 case '<': ++level;
break;
89 case '>':
if (level==0) {
return std::string::npos; }
105 std::string &error_string )
107 std::string::size_type
l=0;
114 if( command[command.size()-1] ==
';' )
115 command = command.substr( 0, command.size()-1 );
124 if ( endsymbol == command.length() || command[endsymbol] ==
' ' || command[endsymbol] ==
'\t' ) {
130 result[
"sourceClass"] = value;
131 result[
"targetClass"] = value;
132 if (endsymbol < command.length()) {
146 if ( endsymbol == command.length() || command[endsymbol] ==
' ' || command[endsymbol] ==
'\t' ) {
148 result[
"source"] = membervalue;
149 result[
"target"] = membervalue;
159 while( !command.empty() ) {
164 std::string::size_type pos = command.find(
'=' );
170 if( pos == std::string::npos ) {
171 error_string =
"Parsing error, no key found!";
186 if( command.size() < 1 ) {
187 error_string =
"Parsing error, wrond or no value specified for key: " + key;
191 Bool_t hasquote = command[0] ==
'"';
197 if( key ==
"code" ) {
198 if( command[1] !=
'{' ) {
199 error_string =
"Parsing error while processing key: code\n";
200 error_string +=
"Expected \"{ at the beginning of the value.";
203 l = command.find(
"}\"" );
204 if(
l == std::string::npos ) {
205 error_string =
"Parsing error while processing key: \"" + key +
"\"\n";
206 error_string +=
"Expected }\" at the end of the value.";
209 auto rawCode = command.substr( 2,
l-2 );
210 RemoveEscapeSequences(rawCode);
211 result[key] = rawCode;
220 l = command.find(
'"', 1 );
221 if (
l == std::string::npos ) {
222 error_string =
"\nParsing error while processing key: \"" + key +
"\"\n";
223 error_string +=
"Expected \" at the end of the value.";
226 result[key] = command.substr( 1,
l-1 );
228 l = command.find(
' ', 1);
229 if (
l == std::string::npos)
l = command.size();
230 result[key] = command.substr( 0,
l );
238 if(
l == command.size() )
240 command = command.substr(
l+1 );
242 std::map<std::string, std::string>::const_iterator it1;
243 it1 = result.find(
"oldtype");
244 if ( it1 != result.end() ) {
245 std::map<std::string, std::string>::const_iterator it2;
246 it2 = result.find(
"source");
247 if ( it2 != result.end() ) {
248 result[
"source"] = it1->second +
" " + it2->second;
251 if ( result.find(
"version") == result.end() && result.find(
"checksum") == result.end() ) {
252 result[
"version"] =
"[1-]";
260 auto const includeKeyName =
"include";
261 auto includeTag = result.find(includeKeyName);
262 if (includeTag != result.end()){
263 auto & includeTagValue = includeTag->second;
264 std::replace_if (includeTagValue.begin(),
265 includeTagValue.end(),
266 [](
char c){ return c ==
';';},
268 result[includeKeyName] = includeTagValue;
277 static Bool_t ValidateRule(
const std::map<std::string, std::string>& rule, std::string &error_string )
283 std::map<std::string, std::string>::const_iterator it1, it2;
284 std::list<std::string> lst;
286 it1 = rule.find(
"targetClass" );
287 if( it1 == rule.end() ) {
288 error_string =
"You always have to specify the targetClass ";
289 error_string +=
"when specyfying an IO rule";
294 std::string warning =
"IO rule for class " + className;
300 it1 = rule.find(
"sourceClass" );
301 if( it1 == rule.end())
303 error_string = warning +
" - sourceClass parameter is missing";
311 it1 = rule.find(
"version" );
312 it2 = rule.find(
"checksum" );
313 if( it1 == rule.end() && it2 == rule.end() ) {
314 error_string = warning +
" - you need to specify either version or ";
315 error_string +=
"checksum";
323 if( it2 != rule.end() ) {
324 if( it2->second.size() < 2 || it2->second[0] !=
'[' ||
325 it2->second[it2->second.size()-1] !=
']' ) {
326 error_string = warning +
" - a comma separated list of ints";
327 error_string +=
" enclosed in square brackets expected";
328 error_string +=
" as a value of checksum parameter";
335 error_string += warning +
" - the list of checksums is empty\n";
338 for(
const auto& chk : lst ) {
340 error_string = warning +
" - " + chk +
" is not a valid value";
341 error_string +=
" of checksum parameter - an integer (decimal/hex) expected";
351 std::pair<Int_t, Int_t> ver;
352 if( it1 != rule.end() ) {
353 if( it1->second.size() < 2 || it1->second[0] !=
'[' ||
354 it1->second[it1->second.size()-1] !=
']' ) {
355 error_string = warning +
" - a comma separated list of version specifiers ";
356 error_string +=
"enclosed in square brackets expected";
357 error_string +=
"as a value of version parameter";
364 error_string = warning +
" - the list of versions is empty";
367 for(
const auto& version : lst )
369 error_string = warning +
" - " + version +
" is not a valid value";
370 error_string +=
" of version parameter";
380 if( rule.size() == 3 || (rule.size() == 4 && it1 != rule.end() && it2 != rule.end()) )
386 std::string keys[] = {
"target",
"source"};
387 for(
int i = 0; i < 2; ++i ) {
388 it1 = rule.find( keys[i] );
389 if( it1 == rule.end() ) {
390 error_string = warning +
" - required parameter is missing: ";
391 error_string += keys[i];
400 it1 = rule.find(
"code");
401 if (it1 != rule.end() && it1->second !=
"") {
404 SourceTypeList_t::const_iterator it;
405 for( it = source.begin(); it != source.end(); ++it ) {
406 if ( ( it->first.fType ==
"" && it->second !=
"") ) {
407 error_string = warning +
" - type required when listing a rule's source: ";
408 error_string +=
"source=\""+ rule.find(
"source")->second +
"\"";
419 it1 = rule.find(
"embed" );
420 if( it1 != rule.end() ) {
422 if( emValue !=
"true" && emValue !=
"false" ) {
423 error_string = warning +
" - true or false expected as a value ";
424 error_string +=
"of embed parameter";
433 it1 = rule.find(
"include" );
434 if( it1 != rule.end() ) {
435 if( it1->second.empty() ) {
436 error_string = warning +
" - the include list is empty";
449 std::string& error_string)
451 std::list<std::string> mem;
452 std::list<std::string>::iterator it;
461 for( it = mem.begin(); it != mem.end(); ++it ) {
462 if( members.find( *it ) == members.end() ) {
463 error_string +=
"IO rule for class " + rule[
"targetClass"]
464 +
" data member: " + *it +
" was specified as a "
465 "target in the rule but doesn't seem to appear in "
479 std::string& className, std::string& mappedName,
482 if (!source.empty()) {
484 SourceTypeList_t::const_iterator it;
491 Bool_t generateOnFile =
false;
492 output <<
"#if 0" << std::endl;
493 for( it = source.begin(); it != source.end(); ++it ) {
495 output <<
"static Int_t id_" << it->second <<
" = oldObj->GetId(";
496 output <<
"\"" << it->second <<
"\");" << std::endl;
498 if( it->first.fType !=
"" )
499 generateOnFile =
true;
501 output <<
"#endif" << std::endl;
507 if( generateOnFile ) {
508 std::string onfileStructName = mappedName +
"_Onfile";
510 output <<
"struct " << onfileStructName <<
" {\n";
517 for( it = source.begin(); it != source.end(); ++it ) {
518 if( it->first.fType.size() ) {
519 if ( it->first.fDimensions.size() ) {
520 output <<
" typedef " << it->first.fType;
521 output <<
" onfile_" << it->second <<
"_t" << it->first.fDimensions <<
";\n";
523 output <<
"onfile_" << it->second <<
"_t &" << it->second <<
";\n";
527 output << it->first.fType <<
" &" << it->second <<
";\n";
536 output <<
" " << onfileStructName <<
"(";
537 for( start =
true, it = source.begin(); it != source.end(); ++it ) {
538 if( it->first.fType.size() == 0)
546 if (it->first.fDimensions.size() == 0) {
547 output << it->first.fType <<
" &onfile_" << it->second;
549 output <<
" onfile_" << it->second <<
"_t" <<
" &onfile_" << it->second;
558 for( start =
true, it = source.begin(); it != source.end(); ++it ) {
559 if( it->first.fType ==
"" )
567 output << it->second <<
"(onfile_" << it->second <<
")";
576 for( it = source.begin(); it != source.end(); ++it ) {
578 output <<
"static Long_t offset_Onfile_" << mappedName;
579 output <<
"_" << it->second <<
" = oldObj->GetClass()->GetDataMemberOffset(\"";
580 output << it->second <<
"\");\n";
582 output <<
" " <<
"char *onfile_add = (char*)oldObj->GetObject();\n";
583 output <<
" " << mappedName <<
"_Onfile onfile(\n";
585 for( start =
true, it = source.begin(); it != source.end(); ++it ) {
586 if( it->first.fType ==
"" )
597 if (it->first.fDimensions.size() == 0) {
598 output << it->first.fType;
600 output << mappedName <<
"_Onfile::onfile_" << it->second <<
"_t";
602 output <<
"*)(onfile_add+offset_Onfile_";
603 output << mappedName <<
"_" << it->second <<
")";
613 if( !target.empty() ) {
614 output <<
" static TClassRef cls(\"";
615 output << className <<
"\");" << std::endl;
617 std::list<std::string>::const_iterator it;
618 for( it = target.begin(); it != target.end(); ++it ) {
620 output <<
" static Long_t offset_" << *it <<
" = ";
621 output <<
"cls->GetDataMemberOffset(\"" << *it <<
"\");";
625 output <<
" " << *it <<
"_t& " << *it <<
" = ";
626 output <<
"*(" << *it <<
"_t *)(target+offset_" << *it;
627 output <<
");" << std::endl;
629 output <<
" " << memData.
fType <<
"& " << *it <<
" = ";
630 output <<
"*(" << memData.
fType <<
"*)(target+offset_" << *it;
631 output <<
");" << std::endl;
645 std::string className = rule[
"targetClass"];
651 std::ostringstream func;
652 func <<
"read_" << mappedName <<
"_" << index;
653 rule[
"funcname"] = func.str();
659 output <<
" static void " << func.str();
660 output <<
"( char* target, TVirtualObject *oldObj )" << std::endl;
661 output <<
" {" << std::endl;
662 output <<
" //--- Automatically generated variables ---" << std::endl;
668 std::list<std::pair<ROOT::Internal::TSchemaType,std::string> > source;
669 std::list<std::string> target;
674 output <<
" " << className <<
"* newObj = (" << className;
675 output <<
"*)target;" << std::endl;
676 output <<
" // Supress warning message.\n";
677 output <<
" " <<
"(void)oldObj;\n\n";
678 output <<
" " <<
"(void)newObj;\n\n";
684 output <<
" //--- User's code ---" << std::endl;
685 output <<
" " << rule[
"code"] << std::endl;
686 output <<
" }" << std::endl;
698 std::string className = rule[
"targetClass"];
704 std::ostringstream func;
705 func <<
"readraw_" << mappedName <<
"_" << index;
706 rule[
"funcname"] = func.str();
712 output <<
" static void " << func.str();
713 output <<
"( char* target, TBuffer &b )" << std::endl;
714 output <<
" {" << std::endl;
715 output <<
"#if 0" << std::endl;
716 output <<
" //--- Automatically generated variables ---" << std::endl;
722 std::list<std::pair<ROOT::Internal::TSchemaType,std::string> > source;
723 std::list<std::string> target;
727 output <<
" " << className <<
"* newObj = (" << className;
728 output <<
"*)target;" << std::endl << std::endl;
734 output <<
" //--- User's code ---" << std::endl;
735 output << rule[
"code"] << std::endl;
736 output <<
"#endif" << std::endl;
737 output <<
" }" << std::endl;
743 static void StrReplace( std::string& proc,
const std::string& pat,
744 const std::string& tr )
746 std::string::size_type it = 0;
747 std::string::size_type
s = pat.size();
748 std::string::size_type tr_len= tr.size();
753 it = proc.find( pat, it );
754 if( it == std::string::npos )
757 proc.replace( it,
s, tr );
766 const std::string& listName, std::ostream&
output )
768 std::list<SchemaRuleMap_t>::iterator it;
775 for( it = rules.begin(); it != rules.end(); ++it ) {
776 output <<
" rule = &" << listName <<
"[" << i++;
777 output <<
"];" << std::endl;
783 output <<
" rule->fSourceClass = \"" << (*it)[
"sourceClass"];
784 output <<
"\";" << std::endl;
786 if( it->find(
"target" ) != it->end() ) {
787 output <<
" rule->fTarget = \"" << (*it)[
"target"];
788 output <<
"\";" << std::endl;
791 if( it->find(
"source" ) != it->end() ) {
792 output <<
" rule->fSource = \"" << (*it)[
"source"];
793 output <<
"\";" << std::endl;
800 if( it->find(
"funcname" ) != it->end() ) {
801 std::string code = (*it)[
"code"];
805 output <<
" rule->fFunctionPtr = (void *)TFunc2void( ";
806 output << (*it)[
"funcname"] <<
");" << std::endl;
807 output <<
" rule->fCode = \"" << code;
808 output <<
"\";" << std::endl;
811 if( it->find(
"version" ) != it->end() ) {
812 output <<
" rule->fVersion = \"" << (*it)[
"version"];
813 output <<
"\";" << std::endl;
816 if( it->find(
"checksum" ) != it->end() ) {
817 output <<
" rule->fChecksum = \"" << (*it)[
"checksum"];
818 output <<
"\";" << std::endl;
821 if( it->find(
"embed" ) != it->end() ) {
822 output <<
" rule->fEmbed = " << (*it)[
"embed"];
823 output <<
";" << std::endl;
826 if( it->find(
"include" ) != it->end() ) {
827 output <<
" rule->fInclude = \"" << (*it)[
"include"];
828 output <<
"\";" << std::endl;
831 if( it->find(
"attributes" ) != it->end() ) {
832 output <<
" rule->fAttributes = \"" << (*it)[
"attributes"];
833 output <<
"\";" << std::endl;
843 std::list<std::string> tmp;
844 std::list<SchemaRuleMap_t>::iterator rule;
845 SchemaRuleMap_t::iterator attr;
846 SchemaRuleClassMap_t::iterator it;
853 for( rule = it->second.begin(); rule != it->second.end(); ++rule ) {
854 attr = rule->find(
"include" );
855 if( attr == rule->end() )
continue;
857 result.splice( result.begin(), tmp, tmp.begin(), tmp.end() );
866 for( rule = it->second.begin(); rule != it->second.end(); ++rule ) {
867 attr = rule->find(
"include" );
868 if( attr == rule->end() )
continue;
870 result.splice( result.begin(), tmp, tmp.begin(), tmp.end() );
891 std::map<std::string, std::string> rule;
892 if( !
ParseRule( args, rule, error_string ) ) {
893 error_string +=
"\nThe following rule has been omitted:\n read ";
894 error_string += args;
895 error_string +=
"\n";
903 SchemaRuleClassMap_t::iterator it;
904 std::string targetClass = rule[
"targetClass"];
905 std::string normalizedTargetName;
910 std::list<SchemaRuleMap_t> lst;
911 lst.push_back( rule );
915 it->second.push_back( rule );
927 std::map<std::string, std::string> rule;
928 if( !
ParseRule( args, rule, error_string ) ) {
929 error_string +=
"\nThe following rule has been omitted:\n readraw ";
930 error_string += args;
931 error_string +=
"\n";
939 SchemaRuleClassMap_t::iterator it;
940 std::string targetClass = rule[
"targetClass"];
941 std::string normalizedTargetName;
945 std::list<SchemaRuleMap_t> lst;
946 lst.push_back( rule );
950 it->second.push_back( rule );
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
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
static void output(int code)