Documentation
Library |
genesis |
Version |
2.0.0 |
This section contains the Seadex genesis documentation including the API reference.
Building genesis
This section provides you with instructions on how to build genesis in your environment.
Getting the source
Building
These building options are available:
-
Microsoft Visual Studio - Description of how to build the genesis library with Microsoft Visual Studio and the Microsoft Visual Studio Compiler (using the provided solution and projects).
-
CMake - Description page for building the genesis library using CMake for Linux and Windows (Visual Studio/MSBuild).
Other compilers and platforms
Building for Linux with GCC is supported out of the box. For other compilers and/or platforms you can just adopt the CMake files.
Alternatively, you can quite easily set up your build. All you need to build genesis with a different compiler suite and/or on a different platform is C++17 support. Just take the genesis source code and set up a library project according to the procedures necessary for your platform.
You can also contact us to get a quote for commercial support for porting genesis to your platform!
If you run into compiler/build problems in your environment (especially compiler errors or warnings), please contact us. We then will try to resolve these issues.
Microsoft Visual Studio
2019
For Visual Studio 2019 a ready-to-use solution is provided. It contains:
-
genesis - source code of the genesis library
-
examples - project using and demonstrating some of the features of genesis
-
build - a folder containing the property sheets for the projects
-
genesis.sln - the solution file that contains the projects mentioned above
-
license file
-
docs - a folder containing the documentation
Use of Conan
The genesis library can use Conan to get its dependencies (see the Dependencies)
After the build, the genesis library can be integrated into your projects.
CMake
The build with CMake is currently tested for Linux (Debian, GCC, Clang) and Windows (Microsoft Visual Studio).
The CMakeFileLists.txt files are located in the solution directory, the genesis project directory and the examples directory.
Generating with CMake and Conan
|
Note
|
The following commands require Conan version 2.0. |
Linux
In a terminal go to the directory into which you extracted genesis and run the following commands:
conan install . -g CMakeToolchain --profile=release --build=missing -of cmake
cd cmake
cmake .. -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_POLICY_DEFAULT_CMP0091=NEW -DCMAKE_BUILD_TYPE=Release -DGEN_BUILD_EXAMPLES=ON
cmake --build --preset conan-release
|
Note
|
Options (e.g. architecture) are used from the Conan profile. |
Windows
In a terminal go to the directory into which you extracted genesis and run the following commands:
conan install . -g CMakeToolchain --profile=release --build=missing
cmake . -G "Visual Studio 16 2019" -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_POLICY_DEFAULT_CMP0091=NEW -DGEN_BUILD_EXAMPLES=ON
cmake --build --preset conan-release
|
Note
|
Options like architecture, Visual Studio version (generator), etc… are used from Conan profiles. |
Release/Debug
Choosing between release and debug builds is done via Conan profiles and presets.
Preprocessor definitions
Using genesis' preprocessor definitions with CMake is also possible by passing them as parameters in the console/terminal.
| Definition | Description |
|---|---|
CPP_VERSION=[VALUE] |
Sets the standard for the C++ compiler. When it is not used, C++11 will be used. |
Build options
The genesis build can be customized using the following options:
| Definition | Description |
|---|---|
GEN_BUILD_EXAMPLES=[OFF] |
When GEN_BUILD_EXAMPLES is defined, the example is built as well. By default, it is not defined and therefore, not built. |
FMT_LIB_INCLUDE=[VALUE] FMT_LIB=[VALUE] SPDLOG_LIB_INCLUDE=[VALUE] SPDLOG_LIB=[VALUE] ESSENTIALS_LIB_INCLUDE=[VALUE] ESSENTIALS_LIB=[VALUE] |
To use the essentials, fmt and spdlog libraries from the user location, all the variables must be used at the same time with the correct paths. For the libs, the library is specified as well (e.g. "…/fmt/lib/fmt.lib"). |
Dependencies
The genesis library starting with version 2.0 has the following dependencies:
-
seadex-essentials/2.1.3
-
spdlog/1.11.0
-
fmt/9.1.0
These dependencies can be provided using Conan (see Use of Conan).
Features
List of supported functionality.
Steps and blocks
The genesis library generates code by using internally defined elements.
Basic elements are called steps. There are:
-
Text step - containing a text sequence from the template file
-
Variable step - a variable that will be replaced by its value
The 'blocks' are complex elements that can contain other elements (steps and other blocks):
-
Condition block - represents an 'if'
-
Loop block - represents a loop (more precisely: a 'for')
-
Switch block - represents a 'switch' statement.
-
Template block - represents a recipe block created from a template file
Text step
A text step contains a sequence of text from the template file. It will be written to the output string stream when the output is generated.
Variable step
A variable step contains the name of a variable. When the output is generated, the value of the variable will be written.
Command
$var(variable_name)
Condition block
A condition block represents an 'if'. If the condition is true, then all nested elements will be created, otherwise not.
Command
A condition block has the following structure:
$if(condition_name[, condition_modifier])
// child steps
$fi
A condition block must end with a '$fi' command. If the condition is not correctly ended (with '$fi'), then the template is considered ill-formed.
Condition modifier
A condition block can have an optional condition modifier. The following pre-defined values can be used:
Value |
in template file |
Effect |
NONE |
Does not affect the condition. |
|
NOT |
not |
Negate the result of the condition. |
The default value of the condition modifier is 'NONE'.
|
Note
|
New line after the close command '$fi' is discarded. |
Loop block
A loop block represents a 'for' loop. For each iteration of the loop, all nested elements will be created.
Command
$loop(loop_name)
// child steps
$pool
A loop block must end with a '$pool' command. If the loop is not correctly ended (with '$pool'), then the template is considered to be ill-formed.
|
Note
|
New line after the close command '$pool' is discarded. |
Switch block
A switch block represents a 'switch' statement. Only elements of the selected case will be created.
Command
$switch(switch_name)
$case(0)
// child steps
$esac
$case(1)
// child steps
$esac
// ...
$default()
// child steps
$tluafed
$hctiws
A switch block must end with a '$hctiws' command (it is 'switch' backward).
Case and default
Each case command ( '$case') must have a matching closing command ('$esac'). Cases take an index as a parameter (an int).
The default command '$default' has to have empty parentheses and an end command '$tluafed' ('default' backward).
An index value will be passed to the switch block during generation. The value is determined by the return value of the method 'get_switch_case' of the callback interface. Then the code within the matching case command will be generated. If the value returned by the callback method does not match any of the cases then the code within the default command will be generated. The default command is optional though. If it is omitted and no case matches, no code will be generated for the switch block at all.
Only indexes equal to or greater than 0 are legal.
|
Note
|
New lines after the close commands '$esac', '$tluafed' and '$hctiws' are discarded. |
Template block
A template block reads the specified template file which is treated as a recipe itself. All nested elements will be created.
Command
$template(template_file_name)
|
Note
|
template_file_name must contain the extension of the template file as well! |
Recipe callback
The recipe callback is the interface that has to be implemented by the generator using genesis.
The recipe callback has the following default methods:
| Method | Parameters | Return type | Scope |
|---|---|---|---|
get_variable_content |
variable name (string) |
string |
Returns the content of the variable with the given name. |
condition_begin |
condition name (string) |
void |
Executes actions before the check of the condition with the given name. |
check_condition |
condition name (string) condition modifier |
bool |
Checks the condition with the given name and returns its result. |
condition_end |
condition name (string) |
void |
Executes actions after the condition with the given name. |
before_loop |
loop name (string) |
void |
Executes actions before the loop with the given name is executed. |
before_loop_iteration |
loop name (string) |
void |
Executes actions before an iteration of the loop with the given name is executed. |
check_loop_condition |
loop name (string) |
bool |
Checks if the loop with the given name needs to execute another iteration. |
after_loop_iteration |
loop name (string) |
void |
Executes actions after an iteration of the loop with the given name was executed. |
after_loop |
loop name (string) |
void |
Executes actions after the loop with the given name was executed. |
get_switch_case |
switch name (string) |
int |
Returns the index of the case of the switch with the given name which shall be executed. |
Escape sequences
In genesis the '$' symbol represents the start of a command. For example:
$var(variable_name)
$loop(condition_name)
$pool
genesis defines certain escape sequences. An escape sequence starts with a '$' (dollar sign) just like a command.
Line break
genesis has a special command for inserting a new line: '$@'. When this sequence is found in the template, it will be replaced by a new line character.
Print $
If a '$' is needed in the output, then a double '$' has to be used.
Example
I got $$s!
The template above will print 'I got $s!'
Examples
In this section examples of generators that use the genesis library are provided. For now a simple HTML page generator is available, other examples will be added in the future.
-
[Html page generator] - A project demonstrating how genesis can be used to generate a simple HTML page. It is using a base template and a table template that is called multiple times.
HTML page generator example
In this example, the genesis library is used to create a generator for an HTML page that contains tables with cities for different countries.
Template files
Base template
The base template is the entry point for generating the page.
It looks like this:
<!DOCTYPE html>
<html>
<head>
<style>
table {
font-family: arial, sans-serif;
border-collapse: collapse;
width: 300px;
}
td, th {
border: 1px solid #E7C324;;
text-align: left;
padding: 3px;
height: 20px;
}
tr:nth-child(even) {
background-color: #252525;
}
body{
background-color:#262626;
color: #E7C324;
}
hr{
color: #E7C324;
}
</style>
<title>Population of big cities</title>
</head>
<body>
<h1>Population of big cities.</h1>
<p>List of countries:</p>
<p style="font-size:12px">*The capital is marked <b>bold</b> and <a style="color:#1E90FF">blue</a></p>
$loop(countries)
<h3> <b>$var(country_name)</b></h3>
$template(country_table.gtpl)
<hr>
$pool
</body>
</html>
This template for an HTML page contains a loop (starting at line 40, and ending at line 44) for iterating over a list of countries. For each country, the name will be generated using the '$var' command (line 41). Then a template that generates the table will be called using the '$template' command (line 42). The loop ends with the command '$pool'.
Table template file
The template file for a table looks like this:
<table>
<tr>
<th>City</th>
<th>Population</th>
</tr>
$loop(cities)
<tr>
<td>$if(is_capital)<b><p style="color:#1E90FF">$fi$var(city_name)$if(is_capital)</p></b>$fi</td>
<td>$if(is_capital)<b><p style="color:#1E90FF">$fi$var(city_population)$if(is_capital)</p></b>$fi</td>
</tr>
$pool
</table>
Each city will be represented in one line. In the columns are placed the name and the population of the city. For each city, we check if the city is the capital city of the country by calling '$if' command (lines 8 and 9). If the city has the index of the capital city, then the line containing the capital city is made bold and blue. The end of condition command '$fi' is called at the end.
Result
The output HTML file containing a table with the cities of a specific country looks like this.
Data
Countries and cities are stored in the structs country and city respectively:
struct country
{
std::string name_;
std::vector<city> cities_;
std::size_t capital_index_;
};
struct city
{
std::string name_;
int population_;
};
The structs are used in a configuration struct., The data is added manually in this case, but it could be read from file a file, a database, …
struct config
{
config();
std::string template_path_;
std::string source_template_file_;
std::string output_file_;
std::vector<country> countries_;
};
genesis’s callback interface implementation
genesis offers a recipe callback interface which has to be implemented containing the generator logic.
For example, the function for getting the variable contents looks like this:
std::string recipe_callback_impl::get_variable_content( const std::string& _variable_name )
{
std::string result( "" );
if( _variable_name == CITY_NAME )
{
result = config_.countries_[country_index_].cities_[city_index_].name_;
}
else if( _variable_name == CITY_POPULATION )
{
result = sxe::to_string( config_.countries_[country_index_].cities_[city_index_].population_ );
}
else if( _variable_name == COUNTRY_NAME )
{
result = config_.countries_[country_index_].name_;
}
return( result );
}
For each (city, population and country) the value is taken from a specific list with a specific index.
In the 'before_loop' method the indexes are set to 0 and in the 'after_loop_iteration' method they get incremented:
void recipe_callback_impl::after_loop_iteration( const std::string& _loop_name )
{
if( _loop_name == LOOP_COUNTRIES )
{
++country_index_;
}
else if( _loop_name == LOOP_CITIES )
{
++city_index_;
}
}
Checking the condition of the loop is done by checking if the index value is less than the size of the vector containing the data:
if( _loop_name == LOOP_COUNTRIES )
{
result = country_index_ < config_.countries_.size();
}
Checking the '$if' condition is pretty much the same: indexes are compared.
if( _condition_name == CONDITION_IS_CAPITAL )
{
result = config_.countries_[country_index_].capital_index_ == city_index_;
}
Generating the HTML page
Generating the HTML page is simple now. The configuration and callback objects are created. The callback is then passed to the recipe. Next, the 'generate' method is called on the recipe object. Finally, the content of the stream with the generated code is written into the output file by calling the 'write_to_file' method.
examples::config configuration;
examples::recipe_callback_impl recipe_callback( configuration );
sx::genesis::recipe source_recipe( configuration.source_template_file_, cb, configuration.template_path_ );
source_recipe.generate();
source_recipe.write_to_file( configuration.output_file_ );
Source code
The source code can be found on GitHub.
MIT License
Copyright (c) 2017-, Seadex GmbH
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Downloads
Changelog
Versions
All notable changes to this project are documented on this page.
[2.0.0]
Changed
-
use essentials 2.0
-
dropped the hermes library dependency
[0.3.2]
Changed
-
use essentials and hermes as libraries
-
CMake: use external CMakeHelpers files
-
CMake: refactoring of build files
Fixed
-
rename private method recipe::create to recipe::create_impl because of bug (warning in clang)
-
added SX_UNUSED_VARIABLE to is_delimiter_char, else a warning is generated in clang as it is not used (SX_ASSERT)
[0.2.0]
Added
-
Support for Visual Studio 2017 builds
Changed
-
rename: condition_block’s private method check_modifier to apply_modifier
-
method create_child of the class recipe_block is now protected
[0.1.0]
-
The very first released version of genesis
Contact & support
Your feedback is very important to and for us!
In case you have questions, suggestions, if you want to file a bug report, or if we can assist you in any other way please send us an email to genesis@seadex.de.
Also, we are very glad if you Show your appreciation!
Commercial support
Seadex GmbH from Trossingen, Germany can provide you with commercial support.
Support is available in the form of (but not limited to) the development of specific tools for your environment, custom development within essentials, consulting, or training.
Also, Seadex can support you with additional developers.
Please contact us if you have a question or require a quote.
Show your appreciation
If you like genesis and find it useful, we would be very happy if you’d show your appreciation in one way or the other. It helps us to attract more attention to genesis. The more attention it gets the more feedback and input we get. And that is the knowledge we need to improve genesis further.
There are multiple ways to show your appreciation:
-
Star genesis on GitHub
-
Contact us (via Contact & support) and allow us to feature you (or your company) as a reference user.