Jinjac is a library which adapt the jinja templating language for C. its aim is to be very minimalistic and with few dependancies in order to be able to use it in a embedded software. Nevertheless it tries to implement a large set feature.
It comes from with several unit tests (see test folders)
Here we are an example with the buffer API. It rules similar with file API.
char* template =
"Hello from jinjac {{ user }} !\n"
"{% for x in data -%}\n"
" -> data {{ x }}\n"
"{% endfor %}\n"
"end template\n"
;
jinjac_init();
jinjac_parameter john;
john.type = TYPE_STRING;
john.value.type_string = "John";
jinjac_parameter_insert("user", &john);
jinjac_parameter_array_insert("data", TYPE_INT, 10, 5, 8, 987, 16, 1, 5, 9, 8, 58, 6);
char* pResult = NULL;
int sizeResult = 0;
jinjac_render_with_buffer(template, strlen(template), &pResult, &sizeResult);
fprintf(stdout, "%s\n", pResult);
free(pResult);
jinjac_destroy();
It will return
Hello from jinjac John !
-> data 5
-> data 8
-> data 987
-> data 16
-> data 1
-> data 5
-> data 9
-> data 8
-> data 58
-> data 6
end template
It can be possible to use an other variable management, by implementing the parameter search and get callbacks as indicated in this example
// map search and get callback
jinjac_parameter_callback jinjac_specific_search_cb =
{
.search = p_search,
.get = p_get,
.array_getProperties = p_array_getProperties,
.array_getValue = p_array_getValue
};
//after initialisation register it
jinjac_parameter_register(&jinjac_specific_search_cb);
//callback implementation
int p_search(char* key, int32_t* privKey, int* isArray)
{
//simulate another array of data to test
int founded = 0;
int bIsArray;
bIsArray = 0;
if (strcmp(key, "@name") == 0)
{
*privKey = 0;
founded = 1;
if (isArray != NULL)
*isArray = 0;
}
return founded;
}
J_STATUS p_get(int32_t privKey, jinjac_parameter* param)
{
J_STATUS s;
s = J_OK;
switch (privKey)
{
case 0: //@name
param->type = TYPE_STRING;
param->value.type_string = "Tyrion";
break;
default:
s = J_ERROR; //not found
break;
}
return s;
}
See example in file jinjac_test_app.c Then after, the library will use the indicated functions to search and retrieve parameters.
- basic template replacing (with all types of data e.g. string, integer, double)
- filtering (see list of build-in function)
- comment management
- function execution
- for statement
- if statement
- strip whitespace (with minus characters in statement)
- possibly to manage variables without store them into jinjac library
Here we are the list of limitation. (or the aim of this library some of thems are not really necessary)
- missing build-in function (see table at the end)
- in if statement 'is' is not managed
- negative value (-X) not managed in expression
- whitespace control (with '+' characters)
- in fact it has the default behavior and you can control whitespace strip with '-'
- raw statement
- set statement
- template inheritance
- child template
- super block
- extends
- html espacing
- in for the loop variables doesn't exist
- in for the else is not managed
- macros / call
- filters as statement
- assignment in function argument
- include
- autoescape
- parameter management
Search of parameter could be improved by using a hash table on variable name
- object management
Separate parameter and ast object and add a object form for parameter (design improvement)
The library uses standard glibc library and need flex and bison to build.
cmake is used to construct make system.
To perform coverage analysis, you need to install lcov package.
It uses dynamic memory allocation (malloc()
and free()
).
It exists 3 scripts which can be used to configure the build of the library:
-
build_debug.sh
This one configures to build library in debug mode (with trace and assertion) -
build_release.sh
This one configure in release mode. Example:
$ ./build_release.sh
$ cd build_release
$ make all
$ ctest
build_coverage.sh
this one configures and builds the library, performs unit tests and retrieves the coverage.
ruby and valgrind are used to perform tests.
Here we are the list of build-in functions to implement and current status
function | description | status |
---|---|---|
abs() | not implemented | |
attr() | not implemented | |
batch() | not implemented | |
capitalize() | first char in upper case another in lower | [OK] |
center() | center the value center(s, width=80) | [OK] |
default() | default value if undefined | low prio |
dictsort() | not implemented | |
escape() | low prio | |
filesizeformat() | not implemented | |
first() | not implemented | |
float() | not implemented | |
forceescape() | not implemented | |
format() | format string according to parameter (equivalent to printf) | [OK] |
groupby() | not implemented | |
indent() | low prio | |
int() | not implemented | |
join() | concatenate the sequence into a string | [OK] |
last() | low prio | |
length() | low prio | |
list() | not implemented | |
lower() | put string in lower case | [OK] |
map() | not implemented | |
max() | not implemented | |
min() | not implemented | |
pprint() | not implemented | |
random() | not implemented | |
reject() | not implemented | |
rejectattr() | not implemented | |
replace() | low prio | |
reverse() | low prio | |
round() | not implemented | |
safe() | not implemented | |
select() | not implemented | |
selectattr() | not implemented | |
slice() | low prio | |
sort() | not implemented | |
string() | not implemented | |
striptags() | not implemented | |
sum() | not implemented | |
title() | set first char of word in upper case, othersiwe in lower case | [OK] |
tojson() | not implemented | |
trim() | remove space at begin and end of the string | [OK] |
truncate() | truncate a string at a specified offset plus extras options | [OK] |
unique() | not implemented | |
upper() | set string to upper case | [OK] |
urlencode() | not implemented | |
urlize() | not implemented | |
wordcount() | not implemented | |
wordwrap() | low prio | |
xmlattr() | not implemented |