2011-02-01 20 views
35

Sto implementando un modo per trasferire un set di dati a un dongle programmabile. Il dongle si basa su una tecnologia smart card e può eseguire all'interno un codice arbitrario. I dati di input e output vengono passati come blocchi binari ai quali è possibile accedere tramite puntatori di input e output.Array associativi in ​​C

Vorrei utilizzare un array associativo per semplificare il codice di elaborazione dati. Tutto dovrebbe funzionare in questo modo:

Prima dell'applicazione host:

// 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); 

Avanti il ​​codice all'interno del dongle:

// 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"); 

Quindi la mia domanda è circa la funzionalità parte dongle. C'è un codice C o una libreria per implementare un comportamento di array associativo simile a quanto sopra?

risposta

7

Il mio sospetto è che dovresti scrivere il tuo. Se capisco l'architettura che stai descrivendo, dovrai inviare l'intera porzione di dati in un unico pezzo. Se è così, allora la maggior parte delle librerie non funzionerà per questo perché molto probabilmente allocheranno più pezzi di memoria, il che richiederebbe più trasferimenti (e una comprensione interna della struttura). Sarebbe come cercare di utilizzare una funzione di hash della libreria e quindi inviarne il contenuto sulla rete su un socket semplicemente passando il puntatore di root alla funzione send.

Sarebbe possibile scrivere alcune utilità proprie che gestiscono un array associativo molto semplice (o hash) in un singolo blocco di memoria. Se la quantità di dati è piccola, potrebbe utilizzare una semplice ricerca lineare per le voci e sarebbe un bit di codice abbastanza compatto.

+0

Sì, hai ragione. La funzione di elaborazione dei dati in dongle riguarda un singolo pezzo di dati. Mi sento davvero come se avessi bisogno di implementare un semplice array associativo con 8 indici di lunghezza dei caratteri e un algoritmo di ricerca degli indici lineari! Ho solo pensato di non reinventare la ruota e chiedere se qualcuno l'ha già implementata. – ezpresso

+0

Sono assolutamente d'accordo con non reinventare la ruota. E certamente sembra probabile che qualcuno lo abbia già fatto ... ma trovarlo potrebbe rivelarsi difficile dal momento che è piuttosto specializzato. –

18

Glib's hash table. implementa un'interfaccia mappa o (array associativo). Ed è molto probabile che l'attuazione tabella hash più utilizzato per 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

Sì, ma non funzionerà nel modo specificato. Utilizzerà invece un struct per memorizzare i dati e le funzioni che operano su quella struttura, fornendo il risultato desiderato. Vedi A Simple Associative Array Library In C. Esempio di utilizzo:

struct map_t *test; 

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

Provare uthash, una libreria di intestazione che implementa una tabella hash in C. È piccola e abbastanza facile da usare.

2

Mark Wilkins ha dato la risposta giusta. Se vuoi inviare i dati come un singolo blocco, devi capire come le mappe C++ sono rappresentate nella tua architettura e scrivere le funzioni di accesso.

In ogni caso, se si decide di ricreare la mappa sul dongle, ho scritto una piccola libreria C in cui si potrebbe scrivere la pensa come:

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); 

e poi:

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"); 

Il hashtable è una variante dell'hash Hopscotch, che è piuttosto buona in media, e puoi avere qualsiasi tipo di combinazione per chiavi e dati (cioè puoi usare un'intera tabella come chiave).

L'obiettivo di tali funzioni era di semplificare la programmazione piuttosto che la pura velocità e il codice non è stato completamente testato, ma se ti piace l'idea e desideri espanderci, puoi dare un'occhiata al codice su googlecode.

(Ci sono altre cose come le stringhe di lunghezza variabile e una funzione di corrispondenza del modello di sttring veloce ma quelle potrebbero non essere di interesse in questo caso).

1

Il formato di serializzazione Binn è una buona soluzione per il trasferimento dati in C.

L'oggetto binn (come un oggetto JSON) è un array associativo. Ecco un esempio di utilizzo:

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); 

E a leggere:

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"); 

Si trova a soli 2 file (binn.c e binn.h) in modo che possa essere compilato all'interno del progetto, invece di essere utilizzato come una libreria condivisa.

Ma non so se può essere inserito in un dongle.

2

Questo è un thread vecchio, ma ho pensato che questo potrebbe essere ancora utile per chiunque stia cercando un'implementazione. Non ci vuole troppo codice; Ho fatto il mio in ~ 100 righe senza alcuna libreria aggiuntiva. L'ho chiamato un dizionario poiché mette in parallelo (in qualche modo) il tipo di dati Python. Ecco il mio codice:

#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))); 
} 

Purtroppo si può replicare la lista [x] sintassi, ma questa è la migliore alternativa sono venuto su con.

Problemi correlati