《openssl 编程》之文本数据库

来源:互联网 发布:央视网络春晚 编辑:程序博客网 时间:2024/06/14 12:57

第十章   文本数据库

10.1  概述

       Openss实现了一个简单的文本数据库,它可以从文件读取数据和将数据写到文件中,并且可以根据关键字段来查询数据。Openssl的文本数据库供apps/目录下的文件调用,比如apps.c、ca.c和ocsp.c。openssl文本数据库典型的例子为apps/demoCA/index.txt。文本数据库一行代表数据库的一行,各个列之间必须用一个\t隔开,用#进行注释(#必须在开始位置),以空行结束。比如下面的例子:

赵春平    28    湖北

       zcp  28    荆门

       文本数据库的查找用到了哈希表。openssl读取的所有行数据存放在堆栈中,并为每一列数据建立一个单独的哈希表。每个哈希表中存放了所有行数据的地址。查询时,用户指定某一列,openssl根据对应的哈希表进行查找。

10.2  数据结构

       数据结构在crypto/txt_db/txt_db.h中定义,如下:

       typedef struct txt_db_st

       {

              int num_fields;

              STACK *data;

              LHASH **index;

              int (**qual)(char **);

              long error;

              long arg1;

              long arg2;

              char **arg_row;

       } TXT_DB;

       意义如下:

       num_fields:表明文本数据库的列数。

data:用来存放数据,每一行数据组织成为一个字符串数组(每个数组值对应该行的一列),  并将此数组地址push到堆栈中。

index:哈希表数组,每一列对应一个哈希表。每一列都可以建哈希表,如果不建哈希表将不能查找该列数据。

qual:一个函数地址数组,数组的每个元素对应一列,进行插入该列哈希表前的过滤。这些函数用于判断一行数据的一列或者多列是否满足某种条件,如果满足将不能插入到哈希表中去(但是能存入堆栈)。每一列都可以设置一个这样的函数。这些函数由用户实现。比如,一个文本数据库中,有名字列和年龄列,并且要求名字长度不能小于2,年龄不能小于0和大于200。用户为名字列实现了一个qual函数,只用来检查名字长度,对于年龄列实现一个qual函数,只用来检查年龄。当用户要插入一条记录,名字长度为1,但是年龄合法,那么该记录能插入到年龄列对应的哈希表中,而不能插入名字列对应的哈希表。

error、arg1、arg2和arg_row用于存放错误信息。

10.3  函数说明

1)  TXT_DB *TXT_DB_read(BIO *in, int num)

用于从BIO中读入数据,转换为TXT_DB,num用于明确指明列数,本函数不建立哈希表。

2)  long TXT_DB_write(BIO *out, TXT_DB *db)

              将TXT_DB内容写入BIO;

3)  int TXT_DB_create_index(TXT_DB *db,int field,int (*qual)(char **),

              LHASH_HASH_FN_TYPE hash, LHASH_COMP_FN_TYPE cmp)

给field指定的列建立哈希表。db为需要建索引的TXT_DB,hash为一行数据的hash运算回调函数,cmp为一行数据的比较函数。

4)  char **TXT_DB_get_by_index(TXT_DB *db, int idx, char **value)

根据关键字段来查询数据,查询结果返回一行数据db为文本数据库,idx表明采用哪一列的哈希表来查找;value为查询条件。

5)  int TXT_DB_insert(TXT_DB *db,char **value)

              往TXT_DB中插入一行数据。value数组以NULL表示结束。

6)    void TXT_DB_free(TXT_DB *db)

              清除TXT_DB。

10.4  编程示例

       /* txtdb.dat的内容

       赵春平    28    湖北       无

       zcp  28    荆门       无

       */

       #include <openssl/bio.h>

       #include <openssl/txt_db.h>

       #include <openssl/lhash.h>

      

       /* 名字过滤 */

       static       int    name_filter(char **in)

       {

              if(strlen(in[0])<2)

                     return 0;

              return 1;

       }

 

       static unsigned long index_name_hash(const char **a)

       {

              const char *n;

      

            n=a[0];

            while (*n == '0') n++;

            return(lh_strhash(n));

       }

      

       static int index_name_cmp(const char **a, const char **b)

       {

              const char *aa,*bb;

      

              for (aa=a[0]; *aa == '0'; aa++);

              for (bb=b[0]; *bb == '0'; bb++);

              return(strcmp(aa,bb));

       }

      

       int    main()

       {

              TXT_DB        *db=NULL,*out=NULL;

              BIO               *in;

              int                  num,ret;

              char        **added=NULL,**rrow=0,**row=NULL;

      

              in=BIO_new_file("txtdb.dat","r");

              num=1024;

              db=TXT_DB_read(in,4);

      

              added=(char **)OPENSSL_malloc(sizeof(char *)*(3+1));

                  added[0]=(char *)OPENSSL_malloc(10);

              #if 1

              strcpy(added[0],"skp");

              #else

              strcpy(added[0],"a");     /* 不能插入名字对应的哈希表 */

              #endif

             

              added[1]=(char *)OPENSSL_malloc(10);

              strcpy(added[1],"22");

      

              added[2]=(char *)OPENSSL_malloc(10);

              strcpy(added[2],"chairman");

          

              added[3]=NULL;

      

              ret=TXT_DB_insert(db,added);

              if(ret!=1)

              {

                     printf("err!\n");

                     return -1;

              }

              ret=TXT_DB_create_index(db,0, name_filter,index_name_hash,index_name_cmp);

              if(ret!=1)

              {

                     printf("err\n");

                     return 0;

              }

              row=(char **)malloc(2*sizeof(char *));

                  row[0]=(char *)malloc(10);

              strcpy(row[0],"skp");

              row[1]=NULL;

              rrow=TXT_DB_get_by_index(db,0,row);

              if(rrow!=NULL)

                     printf("%s      %s   %s\n",rrow[0],rrow[1],rrow[2]);

              out=BIO_new_file("txtdb2.dat","w");

              ret=TXT_DB_write(out,db);

              TXT_DB_free(db);

              BIO_free(in);

              BIO_free(out);

              return 0;

       }

       本示例只对第一列做了哈希。需要注意的是,added数组及其元素申请空间时尽量采用OPENSSL_malloc而不是malloc,且其申请的空间由TXT_DB_free(调用OPENSSL_free)释放。

0 0
原创粉丝点击