C++ではじめるテンプレートエンジン入門
ClearSilverとは
ClearSilverはC++で使えるテンプレートエンジンで
HDFと呼ばれるデータをテンプレートファイルに注入する仕組みになっている。HDFはテキストとしても表現できるが、プログラムのコードとしても表現できるようになっており柔軟に対応が出来る。
テンプレートには変数を埋め込むだけではなく、ifやforにあたる制御文等もあるので、複雑なデータを出力することも簡単に出来る仕様になっている。
ClearSilverはYahoo! GroupsやGoogle Groupsでも使われている。一番身近な利用例はtracかも。
また、C以外の言語でも使えるように各種バインディングが存在する
Linuxユーザーなら公式HPからソースを落としてきてビルドすればいいようだけど、WindowsでVCでビルドしたい人には敷居が高い。
VCで使う
調べた結果ここによれば、
cs_config.h を偽造
unistd.h の関数を偽造
__PRETTY_FUNCTION__ を FUNCTION に置換
とかしてみればことがわかり、ここからunistd.hを取ってきてやってみたものの、挫折。
皆さん頑張ってVCで通るようにするのはやめましょう。
http://www.void.in/wiki/ClearSilverでバイナリを配布しているのでこれを利用させてもらいましょう。
使ってみる
公式ページの解説をしているここやテンプレートで使える関数の解説をしているここがとても参考になった。
最後に、バイナリに添付されているソースをベースに外部のHDFファイルを読み込んでCSファイルをコンソールに出力するコードを書いてみた。
HDFファイル
include = #include <math.h> enum { 0 { name = Test1 value = 1 } 3 { name = Test2 value = 3 } 2 { name = Test5 value = 10 } }
CSファイル
<?cs var:include ?> enum HOGE { <?cs each:element = enum ?> <?cs var:element.name ?> = <?cs var:element.value ?>,<?cs /each ?> };
ソースファイル
#include <iostream> #include <fstream> #include <string> #include "../include/ClearSilver.h" NEOERR* csout(void* ctx, char* data) { NEO_STRING* str = (NEO_STRING*)ctx; return string_append(str, data); } int main(int argc, char* argv[]) { nerr_init(); std::ifstream ifs( "test.hdf" ); if( ifs.fail() ) return -1; std::string temp; std::string hdfText; while( !ifs.eof() ) { std::getline( ifs, temp ); hdfText += temp; hdfText += '\n'; } HDF* hdf = 0; hdf_init(&hdf); hdf_set_value( hdf, "include", "#include <math>" ); hdf_set_value( hdf, "enum.0.name", "name1" ); hdf_set_value( hdf, "enum.0.value", "100" ); hdf_set_value( hdf, "enum.1.name", "name2" ); hdf_set_value( hdf, "enum.1.value", "200" ); hdf_read_string( hdf, hdfText.c_str() ); NEO_STRING str; string_init(&str); string_clear(&str); CSPARSE* cs = NULL; cs_init(&cs, hdf); cs_parse_file(cs, "test.cs"); cs_render(cs, &str, &csout); std::cout << str.buf; string_clear(&str); cs_destroy(&cs); hdf_destroy(&hdf); return 0; }
出力
#include <math.h> enum HOGE { Test1 = 1, name2 = 200, Test2 = 3, Test5 = 10, };