/*
* module_builtin.c
*
* Created on: 2017-7-16
* Author: zengl
*/
#include "main.h"
#include "module_builtin.h"
/**
* zenglServer通过crustache第三方库来解析mustache模板
* crustache的github地址:https://github.com/vmg/crustache
* mustache模板:https://mustache.github.io/
* mustache模板的基本语法:https://mustache.github.io/mustache.5.html
* 作者对crustache库代码做了一些修改(包括修复其中的bug)
*/
#include "crustache/crustache.h"
#include "crustache/buffer.h"
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <sys/stat.h>
................................................
/**
* bltMustacheFileRender模块函数,渲染mustache模板
* filename参数表示模板文件名(可以是相对于当前执行脚本的相对路径),可选的array参数表示需要在模板中渲染的数据(一个哈希数组)
* 例如:
* use builtin;
* data["val"] = "my world!";
* data["zl"] = "welcome to zengl!";
* schools[] = '哈佛大学';
* schools[] = '牛津大学';
* schools[] = '家里蹲大学';
* data['schools'] = schools;
* print bltMustacheFileRender("test.tpl",data);
* 假设模板文件test.tpl的内容如下:
* <b>hello {{val}}!</b>
* <h3>{{ zl }}</h3>
* {{# schools}} {{! 循环将schools里的成员显示出来}}
* <p>{{ . }}</p>
* {{/ schools}}
* 那么执行的结果类似如下所示:
* <b>hello my world!!</b>
* <h3>welcome to zengl!</h3>
* <p>哈佛大学</p>
* <p>牛津大学</p>
* <p>家里蹲大学</p>
*/
ZL_EXP_VOID module_builtin_mustache_file_render(ZL_EXP_VOID * VM_ARG,ZL_EXP_INT argcount)
{
ZENGL_EXPORT_MOD_FUN_ARG arg = {ZL_EXP_FAT_NONE,{0}};
if(argcount < 1)
zenglApi_Exit(VM_ARG,"usage: bltMustacheFileRender(filename[, array])");
zenglApi_GetFunArg(VM_ARG,1,&arg); //得到第一个参数
if(arg.type != ZL_EXP_FAT_STR)
zenglApi_Exit(VM_ARG,"first argument filename of bltMustacheFileRender must be string");
char * filename = arg.val.str;
char full_path[FULL_PATH_SIZE];
MAIN_DATA * my_data = zenglApi_GetExtraData(VM_ARG, "my_data");
builtin_make_fullpath(full_path, filename, my_data);
int file_size;
char * api_name = "bltMustacheFileRender";
char * file_contents = builtin_get_file_content(VM_ARG, full_path, api_name, &file_size);
crustache_template *template = builtin_crustache_new_template(VM_ARG, file_contents, api_name, file_size, full_path);
zenglApi_FreeMem(VM_ARG, file_contents);
builtin_mustache_context context = {0};
if(argcount >= 2) {
zenglApi_GetFunArg(VM_ARG,2,&arg);
if(arg.type == ZL_EXP_FAT_MEMBLOCK) {
context.ctx = arg;
}
}
if(context.ctx.val.memblock.ptr == NULL) {
if(zenglApi_CreateMemBlock(VM_ARG,&context.ctx.val.memblock,0) == -1) {
zenglApi_Exit(VM_ARG,zenglApi_GetErrorString(VM_ARG));
}
}
crustache_var ctx;
ctx.type = CRUSTACHE_VAR_CONTEXT;
ctx.data = (void *)(&context);
struct buf *output_buf = bufnew(128);
int error = crustache_render(output_buf, template, &ctx);
if (error < 0)
{
char error_node[256];
crustache_error_rendernode(error_node, sizeof(error_node), template);
crustache_free(template);
bufrelease(output_buf);
zenglApi_Exit(VM_ARG, "%s error: %s (%s)\n", api_name, (char *)crustache_strerror(error), error_node);
}
char * output_str = zenglApi_AllocMem(VM_ARG, output_buf->size + 1);
memcpy(output_str, output_buf->data, output_buf->size);
output_str[output_buf->size] = '\0';
zenglApi_SetRetVal(VM_ARG,ZL_EXP_FAT_STR, output_str, 0, 0);
crustache_free(template);
bufrelease(output_buf);
zenglApi_FreeMem(VM_ARG, output_str);
}
|