Skip to content

Commit d065848

Browse files
committed
Modified ITemplateVariableLookup interface to support "string template variables" and "stream template variables".
Stream template variables do not support template variables recursive lookup. This means that a stream that contains entries such as `${foo}` will not be processed and will be output as a literal string `${foo}`.
1 parent 06af3fb commit d065848

File tree

7 files changed

+116
-65
lines changed

7 files changed

+116
-65
lines changed

src/bin2cpp/BaseGenerator.cpp

Lines changed: 48 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -56,56 +56,68 @@ namespace bin2cpp
5656
return mContext;
5757
}
5858

59-
std::string BaseGenerator::lookupTemplateVariable(const std::string& name)
59+
bool BaseGenerator::lookupStringTemplateVariable(const std::string& name, std::string& output)
6060
{
61-
if ( name == "bin2cpp_output_file_macro_guard" ) return getCppIncludeGuardMacroName(mContext.headerFilename);
62-
if ( name == "bin2cpp_output_file_header" ) return getHeaderTemplate();
63-
if ( name == "bin2cpp_file_object_macro_guard_prefix" ) return getClassMacroGuardPrefix();
64-
if ( name == "bin2cpp_file_manager_file_header" ) return getHeaderTemplate(false);
65-
if ( name == "bin2cpp_file_manager_header_file_name" ) return mContext.managerHeaderFilename;
66-
if ( name == "bin2cpp_file_manager_macro_guard_prefix" ) return getFileManagerMacroGuardPrefix();
67-
if ( name == "bin2cpp_baseclass" ) return mContext.baseClass;
68-
if ( name == "bin2cpp_classname" ) return getClassName();
69-
if ( name == "bin2cpp_namespace" ) return mContext.codeNamespace;
70-
//if ( name == "bin2cpp_baseclass_uppercase" ) return ra::strings::Uppercase(mContext.baseClass);
71-
//if ( name == "bin2cpp_classname_uppercase" ) return ra::strings::Uppercase(getClassName());
72-
//if ( name == "bin2cpp_namespace_uppercase" ) return ra::strings::Lowercase(mContext.codeNamespace);
73-
//if ( name == "bin2cpp_baseclass_lowercase" ) return ra::strings::Lowercase(mContext.baseClass);
74-
//if ( name == "bin2cpp_classname_lowercase" ) return ra::strings::Lowercase(getClassName());
75-
//if ( name == "bin2cpp_namespace_lowercase" ) return ra::strings::Lowercase(mContext.codeNamespace);
76-
if ( name == "bin2cpp_function_identifier" ) return mContext.functionIdentifier;
77-
if ( name == "bin2cpp_function_identifier_lowercase" ) return ra::strings::Lowercase(mContext.functionIdentifier);
78-
if ( name == "bin2cpp_getter_function_name" ) return getGetterFunctionName();
79-
if ( name == "bin2cpp_insert_input_file_as_code" ) return getInputFileDataAsCode();
80-
if ( name == "bin2cpp_header_source_file_include_path" ) return getCppHeaderIncludePath();
81-
if ( name == "bin2cpp_file_object_file_name_impl" ) return getFileClassGetFileNameImplementation();
82-
if ( name == "bin2cpp_file_object_file_path_impl" ) return getFileClassGetFilePathImplementation();
83-
if ( name == "bin2cpp_file_object_file_name" ) return getFileClassFileName();
84-
if ( name == "bin2cpp_file_object_file_path" ) return getFileClassFilePath();
85-
if ( name == "bin2cpp_cpp_get_save_method_impl" ) return getCppSaveMethodTemplate();
86-
if ( name == "bin2cpp_cpp_get_file_manager_registration_impl" && mContext.registerFiles ) return getCppFileManagerRegistrationImplementationTemplate();
87-
if ( name == "bin2cpp_c_file_manager_registration_predeclaration" && mContext.registerFiles ) return getCFileManagerRegistrationPredeclarationImplementation();
88-
if ( name == "bin2cpp_c_file_manager_registration_implementation" && mContext.registerFiles ) return getCFileManagerStaticFileRegistrationImplementation();
61+
if ( name == "bin2cpp_output_file_macro_guard" ) { output = getCppIncludeGuardMacroName(mContext.headerFilename); return true; }
62+
if ( name == "bin2cpp_output_file_header" ) { output = getHeaderTemplate(); return true; }
63+
if ( name == "bin2cpp_file_object_macro_guard_prefix" ) { output = getClassMacroGuardPrefix(); return true; }
64+
if ( name == "bin2cpp_file_manager_file_header" ) { output = getHeaderTemplate(false); return true; }
65+
if ( name == "bin2cpp_file_manager_header_file_name" ) { output = mContext.managerHeaderFilename; return true; }
66+
if ( name == "bin2cpp_file_manager_macro_guard_prefix" ) { output = getFileManagerMacroGuardPrefix(); return true; }
67+
if ( name == "bin2cpp_baseclass" ) { output = mContext.baseClass; return true; }
68+
if ( name == "bin2cpp_classname" ) { output = getClassName(); return true; }
69+
if ( name == "bin2cpp_namespace" ) { output = mContext.codeNamespace; return true; }
70+
//if ( name == "bin2cpp_baseclass_uppercase" ) { output = ra::strings::Uppercase(mContext.baseClass); return true; }
71+
//if ( name == "bin2cpp_classname_uppercase" ) { output = ra::strings::Uppercase(getClassName()); return true; }
72+
//if ( name == "bin2cpp_namespace_uppercase" ) { output = ra::strings::Lowercase(mContext.codeNamespace); return true; }
73+
//if ( name == "bin2cpp_baseclass_lowercase" ) { output = ra::strings::Lowercase(mContext.baseClass); return true; }
74+
//if ( name == "bin2cpp_classname_lowercase" ) { output = ra::strings::Lowercase(getClassName()); return true; }
75+
//if ( name == "bin2cpp_namespace_lowercase" ) { output = ra::strings::Lowercase(mContext.codeNamespace); return true; }
76+
if ( name == "bin2cpp_function_identifier" ) { output = mContext.functionIdentifier; return true; }
77+
if ( name == "bin2cpp_function_identifier_lowercase" ) { output = ra::strings::Lowercase(mContext.functionIdentifier); return true; }
78+
if ( name == "bin2cpp_getter_function_name" ) { output = getGetterFunctionName(); return true; }
79+
if ( name == "bin2cpp_header_source_file_include_path" ) { output = getCppHeaderIncludePath(); return true; }
80+
if ( name == "bin2cpp_file_object_file_name_impl" ) { output = getFileClassGetFileNameImplementation(); return true; }
81+
if ( name == "bin2cpp_file_object_file_path_impl" ) { output = getFileClassGetFilePathImplementation(); return true; }
82+
if ( name == "bin2cpp_file_object_file_name" ) { output = getFileClassFileName(); return true; }
83+
if ( name == "bin2cpp_file_object_file_path" ) { output = getFileClassFilePath(); return true; }
84+
if ( name == "bin2cpp_cpp_get_save_method_impl" ) { output = getCppSaveMethodTemplate(); return true; }
85+
if ( name == "bin2cpp_cpp_get_file_manager_registration_impl" && mContext.registerFiles ) { output = getCppFileManagerRegistrationImplementationTemplate(); return true; }
86+
if ( name == "bin2cpp_c_file_manager_registration_predeclaration" && mContext.registerFiles ) { output = getCFileManagerRegistrationPredeclarationImplementation(); return true; }
87+
if ( name == "bin2cpp_c_file_manager_registration_implementation" && mContext.registerFiles ) { output = getCFileManagerStaticFileRegistrationImplementation(); return true; }
8988

9089
if ( name == "bin2cpp_c_file_manager_registration_post_init_impl" && mContext.registerFiles )
9190
{
92-
std::string output;
93-
output += " \n";
94-
output += " // register when loaded if static initialisation does not work\n";
95-
output += " ${bin2cpp_namespace}_filemanager_register_file(file);\n";
96-
return output;
91+
std::string tmp;
92+
tmp += " \n";
93+
tmp += " // register when loaded if static initialisation does not work\n";
94+
tmp += " ${bin2cpp_namespace}_filemanager_register_file(file);\n";
95+
output = tmp;
96+
return true;
9797
}
9898

9999
if ( name == "bin2cpp_input_file_size" )
100100
{
101101
//determine file properties
102102
uint32_t file_size = ra::filesystem::GetFileSize(mContext.inputFilePath.c_str());
103103
std::string file_size_str = ra::strings::ToString(file_size);
104-
return file_size_str;
104+
output = file_size_str;
105+
return true;
105106
}
106107

107108
// Unknown name
108-
return "";
109+
return false;
110+
}
111+
112+
bool BaseGenerator::lookupStreamTemplateVariable(const std::string& name, std::ostream& output)
113+
{
114+
if ( name == "bin2cpp_insert_input_file_as_code" )
115+
{
116+
output << getInputFileDataAsCode();
117+
return true;
118+
}
119+
120+
return false;
109121
}
110122

111123
//-------------------------------

src/bin2cpp/BaseGenerator.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ namespace bin2cpp
4545
virtual const Context & getContext() const;
4646

4747
//ITemplateVariableLookup methods
48-
virtual std::string lookupTemplateVariable(const std::string& name);
48+
virtual bool lookupStringTemplateVariable(const std::string& name, std::string& output);
49+
virtual bool lookupStreamTemplateVariable(const std::string& name, std::ostream& output);
4950

5051
//same header file for all generators
5152
virtual bool createCppHeaderFile(const char * header_file_path);

src/bin2cpp/ITemplateVariableLookup.h

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626
#define ITEMPLATE_VARIABLE_LOOKUP_H
2727

2828
#include <string>
29-
29+
#include <ostream>
30+
3031
namespace bin2cpp
3132
{
3233

@@ -37,11 +38,23 @@ namespace bin2cpp
3738
{}
3839

3940
///<summary>
40-
///Look up the value for a given template variable name.
41+
///Lookup the string value for a given template variable name.
42+
///String template variables supports recursive lookup.
43+
///</summary>
44+
///<param name="name">The name of the template variable.</param>
45+
///<param name="output">The output string for getting the value or the template variable.</param>
46+
///<return>Returns true when the template variable is handled by the instance. Returns false otherwise.<return>
47+
virtual bool lookupStringTemplateVariable(const std::string& name, std::string& output) = 0;
48+
49+
///<summary>
50+
///Lookup the string value for a given template variable name.
51+
///Stream template variables do not support template variables recursive lookup.
52+
///If a streams loopup outputs text such as `${foo}`, it will not be processed and will be output as literal string `${foo}`.
4153
///</summary>
4254
///<param name="name">The name of the template variable.</param>
43-
///<return>Returns the value of the template variable. Returns an empty string if unknown.<return>
44-
virtual std::string lookupTemplateVariable(const std::string& name) = 0;
55+
///<param name="output">The output string for getting the value or the template variable.</param>
56+
///<return>Returns true when the template variable is handled by the instance. Returns false otherwise.<return>
57+
virtual bool lookupStreamTemplateVariable(const std::string& name, std::ostream& output) = 0;
4558

4659
};
4760

src/bin2cpp/TemplateProcessor.cpp

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -116,17 +116,36 @@ namespace bin2cpp
116116
continue;
117117
}
118118

119-
// Do the variable expansion
120-
std::string expanded_value = mVariableLookup ? mVariableLookup->lookupTemplateVariable(variable_name) : "";
119+
// Do not crash if no lookup is provided.
120+
// All template variables will be empty.
121+
if ( !mVariableLookup )
122+
{
123+
pos = end_pos + 1;
124+
continue;
125+
}
121126

122-
// Add variable to recursion history before expanding
123-
recursion_history.insert(variable_name);
127+
// Check if template variable is a string and do the variable expansion
128+
std::string expanded_value;
129+
bool found_as_string = mVariableLookup->lookupStringTemplateVariable(variable_name, expanded_value);
124130

125-
// Recursively process expanded value with updated recursion tracking
126-
processTemplate(output_stream, expanded_value, recursion_history);
131+
// Proceed with the recursive handling
132+
if ( found_as_string )
133+
{
134+
// Add variable to recursion history before expanding
135+
recursion_history.insert(variable_name);
127136

128-
// Remove variable from recursion history after recursion returns
129-
recursion_history.erase(variable_name);
137+
// Recursively process expanded value with updated recursion tracking
138+
processTemplate(output_stream, expanded_value, recursion_history);
139+
140+
// Remove variable from recursion history after recursion returns
141+
recursion_history.erase(variable_name);
142+
}
143+
else
144+
{
145+
// Check if template variable is a stream
146+
// Stream based template variables do not support recursive lookup and tracking
147+
bool found_as_stream = mVariableLookup->lookupStreamTemplateVariable(variable_name, output_stream);
148+
}
130149

131150
pos = end_pos + 1;
132151
}

src/bin2cpp/Win32ResourceGenerator.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -376,13 +376,13 @@ namespace bin2cpp
376376
return false; // not supported
377377
}
378378

379-
std::string Win32ResourceGenerator::lookupTemplateVariable(const std::string& name)
379+
bool Win32ResourceGenerator::lookupStringTemplateVariable(const std::string& name, std::string& output)
380380
{
381-
if ( name == "bin2cpp_win32_resource_random_identifier" ) return getRandomIdentifier(mContext.inputFilePath.c_str());
382-
if ( name == "bin2cpp_win32_local_info_struct_name" ) return getLocalInfoStructName();
381+
if ( name == "bin2cpp_win32_resource_random_identifier" ) { output = getRandomIdentifier(mContext.inputFilePath.c_str()); return true; }
382+
if ( name == "bin2cpp_win32_local_info_struct_name" ) { output = getLocalInfoStructName(); return true; }
383383

384384
// Unknown name
385-
return this->BaseGenerator::lookupTemplateVariable(name);
385+
return this->BaseGenerator::lookupStringTemplateVariable(name, output);
386386
}
387387

388388
std::string Win32ResourceGenerator::getLocalInfoStructName()

src/bin2cpp/Win32ResourceGenerator.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ namespace bin2cpp
4444
virtual bool printFileContent();
4545

4646
//ITemplateVariableLookup methods
47-
virtual std::string lookupTemplateVariable(const std::string& name);
47+
virtual bool lookupStringTemplateVariable(const std::string& name, std::string& output);
4848

4949
protected:
5050
virtual std::string getResourceFilePath(const char * file_path);

test/bin2cpp_unittest/TestTemplateProcessor.cpp

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,25 @@
3535
class SampleVariableLookup : public bin2cpp::ITemplateVariableLookup
3636
{
3737
public:
38-
std::string lookupTemplateVariable(const std::string& name) override
38+
bool lookupStringTemplateVariable(const std::string& name, std::string& output) override
3939
{
40-
if ( name == "first-name" ) return "Luke";
41-
if ( name == "last-name" ) return "Skywalker";
42-
if ( name == "full-name" ) return "${first-name} ${last-name}";
43-
if ( name == "age" ) return "53";
44-
if ( name == "job" ) return "Jedi Knight";
45-
if ( name == "children" ) return "2";
46-
if ( name == "foo" ) return "foo is ${bar}";
47-
if ( name == "bar" ) return "bar is ${baz}";
48-
if ( name == "baz" ) return "baz is ${foo}";
49-
return "";
40+
if ( name == "first-name" ) { output = "Luke"; return true; }
41+
if ( name == "last-name" ) { output = "Skywalker"; return true; }
42+
if ( name == "full-name" ) { output = "${first-name} ${last-name}"; return true; }
43+
if ( name == "age" ) { output = "53"; return true; }
44+
if ( name == "job" ) { output = "Jedi Knight"; return true; }
45+
if ( name == "children" ) { output = "2"; return true; }
46+
if ( name == "foo" ) { output = "foo is ${bar}"; return true; }
47+
if ( name == "bar" ) { output = "bar is ${baz}"; return true; }
48+
if ( name == "baz" ) { output = "baz is ${foo}"; return true; }
49+
return false;
5050
}
51+
52+
bool lookupStreamTemplateVariable(const std::string& name, std::ostream& output) override
53+
{
54+
return false;
55+
}
56+
5157
};
5258

5359
void TestTemplateProcessor::SetUp()

0 commit comments

Comments
 (0)