蓝森林首页 | 返回主页 | 本站地图 | 站内搜索 | 联系信箱 |
 您目前的位置:首页 > 自由软件 > 技术交流 > 应用编程


    

蓝森林 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了.



Copyright © 1999-2000 LSLNET.COM. All rights reserved. 蓝森林网站 版权所有。 E-mail : webmaster@lslnet.com