|
蓝森林 http://www.lslnet.com 2006年6月6日 10:18
cgi程序醒目,用c写了一个template,测试.
昨天写了一天,基本算法算是完成了,仍未优化(过早的优化本身就是给自己找麻烦是吧:)),但看到国内cgi程序中, template方面的资料很少,很多公司用了却不公开(深恶痛绝,虽然他们有自己的原因, 但这种基础原理都没有说的, 无语了)!决心好好写一个.
以后会将所有cgi程序需要用到功能全都加进去~,由于匆促, 只实现了模板基本功能~有兴趣共同开发和切磋的朋友在这里讨论吧:).
我将陆续添加功能,和完善,这个只是给朋友看看的,呵呵.
帮忙排错,呵呵谢谢了.
[color=red]附件有整包下载, 下载附件后,改变成.rar文件,解压即可[/color]
基本原理:将多个文件 或是 变量 压缩到一个 二叉树中, 然后通过指定关键树来进行模板建立.
风格,与 PHP的pear中的temlate类类似
set_file('文件变量名', '文件地址');
set_var('变量名', '变量值');
parse('文件变量名');
注意,现在没有进行递归判断,就是,如果同时倒入了A和B文件,
A文件中引用了B,B文件中也引用了A,我想会进入死循环,没来得及写。
还有,增加缓存我想也是必要的,因为同一个页面可能导入多个同样的变量.
测试程序
[code]
/*
* test :
* g++ -o ubbs ubbs.c utemplate.c ufunction.c
*/
#include <stdio.h>;
#include "ubbs.h"
int main(int argc, char** argv)
{
//ErrorMsg("hehehlo");
printf("Content-Type: text/html\n\n");
uTemplate a("template");
a.set_file("index", "index.html");
a.set_file("body", "body.html");
a.set_var("name", "Hello");
a.set_var("title", "这是一个测试页面");
a.set_var("name", "My name is ukalpa");
a.set_var("footer", "This is footer");
a.parse("index");
return 0;
}
[/code]
模板主程序:
[code]
/* Implementation of Template functions from ubbs.h
*
* Written by uKalpa@sohu.com
* www.ruuy.com
*/
#include "ubbs.h"
#include <stdio.h>;
#include <fcntl.h>;
#include <sys/types.h>;
#include <sys/uio.h>;
#include <unistd.h>;
#include <sys/stat.h>; // get file status
/*
* just use in this lib
*/
int compare_tpl(struct uTree *a, struct uTree *b);
struct uTree *search_tpl(struct uTree *head, const char *name);
void temp_show(struct Node *x)
{
if (NULL == x)
{
return;
}
Node *xxx;
xxx = x;
while (xxx)
{
printf("|%s|\n", xxx->;value);
xxx = xxx->;next;
}
}
// class function ---------------------------------------------------
/*
* construct template
*/
uTemplate::uTemplate(const char *tag_folder = "")
{
this->;tpl_folder = tag_folder; //文件夹
this->;tpl_tree = NULL; // init tree
}
/*
* xigou template
*/
uTemplate::~uTemplate()
{
// free
this->;free_tpl(this->;tpl_tree);
}
/*
* free_tpl
* free all sapce
*/
void uTemplate::free_tpl(struct uTree *p)
{
if (p)
{
if (TPL_FILE == p->;type) // file
{
if (NULL != p->;head)
{
Node *q = p->;head, *q1;
while (q)
{
q1 = q;
delete q1->;value;
delete q1;
q = q->;next;
}
}
}
else // var
{
delete p->;value;
}
if (NULL != p->;left)
{
free_tpl(p->;left);
}
if (NULL != p->;right)
{
free_tpl(p->;right);
}
delete p;
}
}
/*
* set_file
* @tree_name : 压入的变量名
* @filename : 文件名
*/
void uTemplate::set_file(const char *tree_name, const char *filename)
{
if (NULL == tree_name || NULL == filename)
{
ErrorMsg("Error 5: 没有名称");
}
char tmp_str[512]; // store error msg
struct uTree *x;
x = new uTree;
if (NULL == x)
{
ErrorMsg("Error 1: 给树分配空间失败");
}
//将值存储入树
{
// step 1: 将名称写入树
memset(x->;name, 0, 255);
strcpy(x->;name, tree_name); //树名称
// setp 2: init left , right son
x->;left = NULL;
x->;right = NULL;
x->;value = NULL;
x->;type = TPL_FILE; //表明是文件
// step 3: read file into link
char file[255];
memset(file, 0, 255);
if (0 == strcmp(this->;tpl_folder, ""))
{
sprintf(file, "./%s", filename);
}
else
{
sprintf(file, "%s/%s", this->;tpl_folder, filename);
}
// get file info
struct stat fbuf;
if (-1 == stat(file, &fbuf))
{
sprintf(tmp_str, "Error 2: can`t get file size : %s", file);
ErrorMsg(tmp_str);
}
int filesize = fbuf.st_size; // filesize
// read file now ,
int fd = 0;
fd = open(file, O_RDONLY);
if (-1 == fd)
{
sprintf(tmp_str, "Error 3: can`t load file : %s", file);
ErrorMsg(tmp_str);
}
// when filesize = 0
if (0 == filesize)
{
x->;head = NULL;
x->;tail = NULL;
return;
}
char *sbuf = NULL;
sbuf = new char[filesize + 1];
memset(sbuf, 0, filesize + 1);
read(fd, sbuf, filesize);
close(fd);
// in link table
int i = 0, j = 0, k = 0, m = 0, tmp_i = 0;
bool flg1 = false, flg2 = false;
while(sbuf[i] != 0)
{
if (sbuf[i] == '{')
{
j = i + 1; // write now position
flg1 = true;
}
else if (flg1 == true && (sbuf[i] == ' ' || sbuf[i] == '\t' || sbuf[i] == '\n'))
{
flg1 = false;
}
else if (flg1 == true && sbuf[i] == '}')
{
k = i - 1;
flg2 = true;
}
if (flg2 == true)
{
if (j - 2 >; m) // 静态
{
struct Node *tree_n1;
tree_n1 = new Node;
if (NULL == x->;head)
{
x->;tail = x->;head = tree_n1;
}
tree_n1->;value = new char[j - 1 - m];
memset(tree_n1->;value, 0, j - 1 - m);
tmp_i = 0;
for(m; m < j - 1; m++)
{
tree_n1->;value[tmp_i++] = sbuf[m];
}
tree_n1->;next = NULL;
tree_n1->;type = TPL_FILE;
x->;tail->;next = tree_n1;
x->;tail = tree_n1;
}
if (k >; j) //元素
{
struct Node *tree_n2;
tree_n2 = new Node;
if (NULL == x->;head)
{
x->;tail = x->;head = tree_n2;
}
tree_n2->;value = new char[k - j + 1];
memset(tree_n2->;value, 0, k - j + 1);
tmp_i = 0;
for(m = j; m < k + 1; m++)
{
tree_n2->;value[tmp_i++] = sbuf[m];
}
tree_n2->;next = NULL;
tree_n2->;type = TPL_VAR;
x->;tail->;next = tree_n2;
x->;tail = tree_n2;
}
flg1 = flg2 = false;
m = i + 1;
}
i++;
} // end while
// let`s go on static store into the Node ,
if (m < i) //静态
{
struct Node *tree_n3;
tree_n3 = new Node;
tree_n3->;value = new char[i - m + 1];
memset(tree_n3->;value, 0, i - m + 1);
tmp_i = 0;
for(m; m <= i - 1; m++)
{
tree_n3->;value[tmp_i++] = sbuf[m];
}
tree_n3->;next = NULL;
tree_n3->;type = TPL_FILE;
if (NULL == x->;head)
{
x->;tail = x->;head = tree_n3;
}
else
{
x->;tail->;next = tree_n3;
x->;tail = tree_n3;
}
}
// put into the tree
if (NULL == x)
{
return ;
}
if (NULL == this->;tpl_tree)
{
this->;tpl_tree = x;
return;
}
struct uTree *tmp;
tmp = this->;tpl_tree;
i = 0;
while (tmp)
{
i = compare_tpl(tmp, x);
if (i >; 0)
{
if (NULL == tmp->;left)
{
tmp->;left = x;
return ;
}
else
{
tmp = tmp->;left;
}
}
else if (i < 0)
{
if (NULL == tmp->;right)
{
tmp->;right = x;
return;
}
else
{
tmp = tmp->;right;
}
}
else // when equal
{
// 当两个相等时,只要把新的值赋予给老的结点就OK
//delete old Node
// delete old Link
Node *head1 = NULL;
while (tmp->;head)
{
if (NULL != tmp->;head->;value)
{
delete tmp->;head->;value;
tmp->;head->;value = NULL;
}
head1 = tmp->;head;
tmp->;head = tmp->;head->;next;
delete head1;
}
tmp->;head = x->;head;
delete x;
return;
}
}
return;
}
}
/*
* set_var
* @tree_name : 树中名称
* @value : 变量存放值
* @size : value的长度
*/
void uTemplate::set_var(const char *name, char *value, int size = -1)
{
if (NULL == name || NULL == value)
{
return;
}
if (NULL == this->;tpl_tree)
{
ErrorMsg("Error 6: 模板仍未建立,非法使用变量");
}
struct uTree *var;
var = new uTree;
var->;left = NULL;
var->;right = NULL;
strcpy(var->;name, name);
var->;type = TPL_VAR;
int ssize = size;
if (ssize < 0)
{
ssize = strlen(value);
}
//var->;count = ssize; // no use now
var->;value = new char[ssize + 1];
memset(var->;value, 0, ssize + 1);
strcpy(var->;value, value);
struct uTree *p;
p = this->;tpl_tree;
int i = 0;
while (p)
{
i = strcmp(p->;name, name);
if (i >; 0)
{
if (NULL == p->;left)
{
p->;left = var;
return;
}
else
{
p = p->;left;
}
}
else if (i < 0)
{
if(NULL == p->;right)
{
p->;right = var;
return;
}
else
{
p = p->;right;
}
}
else
{
// fisrt estimate if it is FILE, if it`s a file , not go on.
if (TPL_VAR == p->;type)
{
// delete old string
delete p->;value;
p->;value = var->;value;
delete var;
return;
}
}
}
}
/*
* parse
* tree_name : 文件名称
*/
void uTemplate::parse(const char *tree_name)
{
// step find file
if (NULL == tree_name)
{
ErrorMsg("Error 7: no inde... parse name");
return ;
}
struct uTree *p;
p = this->;tpl_tree;
int i = 0;
struct Node *pp = NULL;
while (p && NULL == pp)
{
i = strcmp(p->;name, tree_name);
if (i >; 0)
{
p = p->;left;
}
else if (i < 0)
{
p = p->;right;
}
else
{
pp = p->;head;
}
}
if (pp)
{
// print file
struct uTree *tmp;
while(pp)
{
if (TPL_FILE == pp->;type) //静态文本
{
printf(pp->;value);
}
else
{
// search in the tree
tmp = search_tpl(this->;tpl_tree, pp->;value);
if (NULL != tmp)
{
if (TPL_FILE == tmp->;type)
{
parse(tmp->;name);
}
else
{
printf(tmp->;value);
}
}
}
pp = pp->;next;
}
}
//else // for support recursion
//{
// ErrorMsg("Error 4 : can`t find this node for parse");
//}
}
// ========================= self define =================================
/*
* search_tpl
*/
struct uTree *search_tpl(struct uTree *head, const char *name)
{
struct uTree *p = head;
if (NULL == name || NULL == head)
{
return NULL;
}
int i = 0;
while (p)
{
i = strcmp(p->;name, name);
if(i >; 0)
{
p = p->;left;
}
else if (i < 0)
{
p = p->;right;
}
else
{
return p;
}
}
return NULL;
}
/*
* compare two elements in tpl
*/
int compare_tpl(struct uTree *a, struct uTree *b)
{
if (NULL == a || NULL == b || NULL == a->;name || NULL == b->;name)
{
return -1;
}
return strcmp(a->;name, b->;name);
}
[/code] |
cgi程序醒目,用c写了一个template,测试.
晕,把图下下来~然后更改文件名就OK了. |
| |