《openssl 编程》之文本数据库
第十章???文本數據庫
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)釋放。
總結
以上是生活随笔為你收集整理的《openssl 编程》之文本数据库的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《openssl编程》之配置文件
- 下一篇: 《openssl 编程》之大数