zoukankan      html  css  js  c++  java
  • libctemplate——源码分析

    前言

    在阅读此文章前,建议先阅读我之前写的《libctemplate——C语言模块引擎简介及使用》,以便对这个库有一个初步的认识。通过对库的代码阅读,对库有了一定的认识,提练一些重要的知识点,以作记录。

    原理

    1、通过一系列接口函数建立字典树,属于MVC中的C,即controllor部分;接口在头文件中,主要包括

    // 添加简单的变量,键值对
    TMPL_varlist *TMPL_add_var(TMPL_varlist *varlist, ...);
    
    // 添加一个循环列表中值列表中
    TMPL_varlist *TMPL_add_loop(TMPL_varlist *varlist, const char *name, TMPL_loop *loop);
    
    // 在循环列表中添加值列表
    TMPL_loop *TMPL_add_varlist(TMPL_loop *loop, TMPL_varlist *varlist);

    2、调用TMPL_write接口,把字典中的值替换模板中的变量,并输出

    // 一般使用,只需要提供filename,varlist,out
    int TMPL_write(const char *filename, const char *tmplstr,
        const TMPL_fmtlist *fmtlist, const TMPL_varlist *varlist,
        FILE *out, FILE *errout);

    这个函数内部,又分几步完成

    (1)把文件一次性读入缓存中

    (2)解析缓存,转换为各种类型的标签(tagnode),组成一棵标签树

    (3)从标签树根开始,输出各个标签的内容;需要输出标签中的变量值时就查找字典树。

    显示view(标签)

    libctemplate允许在模板文件(html)中使用的一些特定标签,这些特定的标签如tag_kind枚举类型定义。具体意义见注释。

     1 typedef enum {
     2     tag_text    = 0x001,   /* text sequence */
     3     tag_var     = 0x002,   /* TMPL_VAR      */
     4     tag_if      = 0x004,   /* TMPL_IF       */
     5     tag_elsif   = 0x008,   /* TMPL_ELSIF    */
     6     tag_else    = 0x010,   /* <TMPL_ELSE>   */
     7     tag_endif   = 0x020,   /* </TMPL_IF>    */
     8     tag_include = 0x040,   /* TMPL_INCLUDE  */
     9     tag_loop    = 0x080,   /* TMPL_LOOP     */
    10     tag_break   = 0x100,   /* TMPL_BREAK    */
    11     tag_cont    = 0x200,   /* TMPL_CONTINUE */
    12     tag_endloop = 0x400    /* </TMPL_LOOP>  */
    13 } tag_kind;

    模型model(字典)

    1 struct TMPL_var {
    2     TMPL_var *next;     /* next simple variable on list */
    3     const char *name;
    4     char value[1];      /* value and name stored here */
    5 };
    1 struct TMPL_varlist {
    2     TMPL_varlist *next;  /* next variable list on a list */
    3     TMPL_var   *var;     /* list of my simple variables */
    4     TMPL_loop  *loop;    /* list of my loop variables */
    5     TMPL_loop  *parent;  /* my parent loop variable (if any) */
    6 };
    1 struct TMPL_loop {
    2     TMPL_loop *next;       /* next loop variable on a list */
    3     const char *name;      /* my name */
    4     TMPL_varlist *varlist; /* list of my variable lists */
    5     TMPL_varlist *tail;    /* tail of "varlist" */
    6     TMPL_varlist *parent;  /* my parent variable list */
    7 };

    简单键值对插入

    以一个简单的例子作为说明。

    1 // 插入姓名和年龄,所有键与值用字符串表示,以0表示结束
    2 TMPL_varlist *mainList = 0;
    3 personList = TMPL_add_var(0, "Name", "lucy", "Age", "16", 0);
    函数TMPL_add_var原型如下所示,从原型可以看出,是可变参数的
    TMPL_varlist* TMPL_add_var(TMPL_varlist *varlist, ...)

    执行此函数操作后,会建成一个链表,所结成的结构如下所示

  • 相关阅读:
    Should I expose synchronous wrappers for asynchronous methods?
    .NET Memory Allocation Profiling with Visual Studio 2012
    Should I expose asynchronous wrappers for synchronous methods?
    Patterns for Asynchronous MVVM Applications: Commands
    WPF/SL: lazy loading TreeView
    Reusable async validation for WPF with Prism 5
    Entity Framework Code First
    ConsoleHelper 类
    [Forward]Sweeping the IDisposable minefield
    Enums and Lookup Tables with EF Code First
  • 原文地址:https://www.cnblogs.com/qinwanlin/p/5124779.html
Copyright © 2011-2022 走看看