2011-02-01 134 views
35

我正在實現一種將一組數據傳輸到可編程加密狗的方法。加密狗基於智能卡技術,可以在其中執行任意代碼。輸入和輸出數據作爲二進制塊傳遞,可以通過輸入和輸出指針訪問。關聯數組C

我想使用關聯數組來簡化數據處理代碼。一切都應該以這種方式工作:

首先主機應用程序:

// Host application in C++ 
in_data["method"] = "calc_r"; 
in_data["id"] = 12; 
in_data["loc_a"] = 56.19; 
in_data["loc_l"] = 44.02; 
processor->send(in_data); 

下一頁加密狗裏的代碼:

// Some dongle function in C 
char* method_name = assoc_get_string(in_data, "method"); 
int id = assoc_get_int(in_data, "id"); 
float loc_a = assoc_get_float(in_data, "loc_a"); 
float loc_l = assoc_get_float(in_data, "loc_l"); 

所以我的問題是關於狗的部分功能。是否有C代碼或庫來實現像上面這樣的關聯數組行爲?

回答

7

我懷疑是你必須自己寫。如果我瞭解您所描述的架構,那麼您將需要將整個數據塊發送到一個整體。如果是這樣,那麼大多數庫不會爲此工作,因爲它們很可能會分配多塊內存,這需要多次傳輸(並且對內部結構有所瞭解)。這與嘗試使用庫哈希函數並通過網絡在套接字上發送其內容相似,只需將根指針傳遞給send函數即可。

可以編寫自己的一些實用程序來管理一個非常簡單的關聯數組(或散列)在單個內存塊中。如果數據量很小,它可以使用簡單的線性搜索條目,並且是相當緊湊的代碼。

+0

是的,你是對的。加密狗中的數據處理功能處理單個數據。我真的覺得我需要實現一個簡單的關聯數組,其中包含8個字符長度索引和一個線性索引搜索算法!我只是認爲不要重新發明輪子,並詢問是否有人已經實施它。 – ezpresso 2011-02-01 18:25:54

18

Glib's hash table.實現了地圖接口或(關聯數組)。 它是最有可能爲C.

GHashTable *table=g_hash_table_new(g_str_hash, g_str_equal); 

/* put */ 
g_hash_table_insert(table,"SOME_KEY","SOME_VALUE"); 

/* get */ 
gchar *value = (gchar *) g_hash_table_lookup(table,"SOME_KEY"); 
3

是的,但它不會按照您指定的方式工作。它將使用struct來存儲對該結構進行操作的數據和函數,從而爲您提供所需的結果。請參閱A Simple Associative Array Library In C。使用示例:

struct map_t *test; 

test=map_create(); 
map_set(test,"One","Won"); 
map_set(test,"Two","Too"); 
map_set(test,"Four","Fore"); 
9

嘗試uthash,一個頭文件庫實現在C中的散列表。它很小,相當容易使用。

2

馬克威爾金斯給了你正確的答案。如果您想將數據作爲單個塊發送,則需要了解C++映射在體系結構中的表示方式,並編寫訪問功能。

無論如何,如果你決定重新加密狗上的地圖,我寫了一個小的C庫,你可以寫這樣想:

tbl_t in_data=NULL; 

tblSetSS(in_data,"method","calc_r"); 
tblSetSN(in_data,"id",12); 
tblSetSF(in_data,"loc_a",56.19); 
tblSetSF(in_data,"loc_l",44.02); 

然後:

char *method_name = tblGetP(in_data, "method"); 
int id   = tblGetN(in_data, "id"); 
float loc_a  = tblGetF(in_data, "loc_a"); 
float loc_l  = tblGetF(in_data, "loc_l"); 

的散列表是Hopscotch散列的一種變體,平均而言相當不錯,並且您可以將任何類型的鍵和數據組合在一起(例如,您可以使用整個表作爲鍵)。

該功能的重點在於簡化編程而不是純粹的速度,代碼沒有經過全面測試,但如果您喜歡這個想法並想擴展它,可以查看googlecode上的代碼。

(還有其他一些東西,如可變長度的字符串和快速sttring模式匹配功能,但在這種情況下可能不感興趣)。

1

Binn序列化格式是用於C.

的BINN對象(如JSON對象)的數據傳送的良好的解決方案是一個關聯數組。下面是一個使用示例:

binn *obj; 

    // create a new object 
    obj = binn_object(); 

    // add values to it 
    binn_object_set_str(obj, "method", "calc_r"); 
    binn_object_set_int32(obj, "id", 12); 
    binn_object_set_float(obj, "loc_a", 56.19); 
    binn_object_set_float(obj, "loc_l", 44.02); 

    // send over the network 
    send(sock, binn_ptr(obj), binn_size(obj)); 

    // release the buffer 
    binn_free(obj); 

,並閱讀:

char* method_name = binn_object_str(obj, "method"); 
    int id = binn_object_int32(obj, "id"); 
    float loc_a = binn_object_float(obj, "loc_a"); 
    float loc_l = binn_object_float(obj, "loc_l"); 

僅有2文件(binn.c和binn.h),所以它可以在項目中被編譯用於代替作爲共享庫。

但我不知道它是否適合加密狗。

2

這是一個古老的線程,但我認爲這可能對任何尋找實現的人都有用。它不需要太多的代碼;我在沒有任何額外的圖書館的情況下做了100行。我將它稱爲字典,因爲它與python數據類型相似(有點類似)。這裏是我的代碼:

#include <stdlib.h> 
#include <stdio.h> 
#include <stdbool.h> 

typedef struct hollow_list hollow_list; 

struct hollow_list{ 
    unsigned int size; 
    void *value; 
    bool *written; 
    hollow_list *children; 
}; 

//Creates a hollow list and allocates all of the needed memory 
hollow_list hollow_list_create(unsigned int size){ 
    hollow_list output; 
    output = (hollow_list) {.size = size, .value = (void *) 0, .written = calloc(size, sizeof(bool)), .children = calloc(size, sizeof(hollow_list))}; 
    return output; 
} 

//Frees all memory of associated with a hollow list and its children 
void hollow_list_free(hollow_list *l, bool free_values){ 
    int i; 
    for(i = 0; i < l->size; i++){ 
     hollow_list_free(l->children + i, free_values); 
    } 
    if(free_values){ 
     free(l->value); 
    } 
    free(l); 
} 

//Reads from the hollow list and returns a pointer to the item's data 
void *hollow_list_read(hollow_list *l, unsigned int index){ 
    if(index == 0){ 
     return l->value; 
    } 
    unsigned int bit_checker; 
    bit_checker = 1<<(l->size - 1); 
    int i; 
    for(i = 0; i < l->size; i++){ 
     if(bit_checker & index){ 
      if(l->written[i] == true){ 
       return hollow_list_read(l->children + i, bit_checker^index); 
      } else { 
       return (void *) 0; 
      } 
     } 
     bit_checker >>= 1; 
    } 
} 

//Writes to the hollow list, allocating memory only as it needs 
void hollow_list_write(hollow_list *l, unsigned int index, void *value){ 
    if(index == 0){ 
     l->value = value; 
    } else { 
     unsigned int bit_checker; 
     bit_checker = 1<<(l->size - 1); 
     int i; 
     for(i = 0; i < l->size; i++){ 
      if(bit_checker & index){ 
       if(!l->written[i]){ 
        l->children[i] = hollow_list_create(l->size - i - 1); 
        l->written[i] = true; 
       } 
       hollow_list_write(l->children + i, bit_checker^index, value); 
       break; 
      } 
      bit_checker >>= 1; 
     } 
    } 
} 

typedef struct dictionary dictionary; 

struct dictionary{ 
    void *value; 
    hollow_list *child; 
}; 

dictionary dictionary_create(){ 
    dictionary output; 
    output.child = malloc(sizeof(hollow_list)); 
    *output.child = hollow_list_create(8); 
    output.value = (void *) 0; 
    return output; 
} 

void dictionary_write(dictionary *dict, char *index, unsigned int strlen, void *value){ 
    void *hollow_list_value; 
    dictionary *new_dict; 
    int i; 
    for(i = 0; i < strlen; i++){ 
     hollow_list_value = hollow_list_read(dict->child, (int) index[i]); 
     if(hollow_list_value == (void *) 0){ 
      new_dict = malloc(sizeof(dictionary)); 
      *new_dict = dictionary_create(); 
      hollow_list_write(dict->child, (int) index[i], new_dict); 
      dict = new_dict; 
     } else { 
      dict = (dictionary *) hollow_list_value; 
     } 
    } 
    dict->value = value; 
} 

void *dictionary_read(dictionary *dict, char *index, unsigned int strlen){ 
    void *hollow_list_value; 
    dictionary *new_dict; 
    int i; 
    for(i = 0; i < strlen; i++){ 
     hollow_list_value = hollow_list_read(dict->child, (int) index[i]); 
     if(hollow_list_value == (void *) 0){ 
      return hollow_list_value; 
     } else { 
      dict = (dictionary *) hollow_list_value; 
     } 
    } 
    return dict->value; 
} 

int main(){ 
    char index0[] = "hello, this is a test"; 
    char index1[] = "hello, this is also a test"; 
    char index2[] = "hello world"; 
    char index3[] = "hi there!"; 
    char index4[] = "this is something"; 
    char index5[] = "hi there"; 

    int item0 = 0; 
    int item1 = 1; 
    int item2 = 2; 
    int item3 = 3; 
    int item4 = 4; 

    dictionary d; 
    d = dictionary_create(); 
    dictionary_write(&d, index0, 21, &item0); 
    dictionary_write(&d, index1, 26, &item1); 
    dictionary_write(&d, index2, 11, &item2); 
    dictionary_write(&d, index3, 13, &item3); 
    dictionary_write(&d, index4, 17, &item4); 

    printf("%d\n", *((int *) dictionary_read(&d, index0, 21))); 
    printf("%d\n", *((int *) dictionary_read(&d, index1, 26))); 
    printf("%d\n", *((int *) dictionary_read(&d, index2, 11))); 
    printf("%d\n", *((int *) dictionary_read(&d, index3, 13))); 
    printf("%d\n", *((int *) dictionary_read(&d, index4, 17))); 
    printf("%d\n", ((int) dictionary_read(&d, index5, 8))); 
} 

可惜你不能複製列表[X]語法,但是這是我想出了最好的選擇。