Общего Назначения С Словарь


Я пытаюсь создать общего назначения с словарь (как непрозрачный тип данных) способны динамически выделять основные типы (целые числа, поплавки, канаты и тоскует), а также признавать недействительными указатели на уже выделенных пользовательских типов. Он работает как далеко, как мой испытание показывает, но я сомневаюсь в архитектуре и не могу помочь, но чувствую, что чего-то не хватает или что я может быть с видом что-то очень очевидно, не так. Есть ли лучший способ пойти об этом?

Примечание: mem_free() и mem_alloc() простые функции malloc/бесплатные фантики и serialize_type делает то, что он говорит.

словарь.с

#include "dictionary.h"

#define DICT_VOID_PTR_TYPE      0
#define DICT_FUNC_PTR_TYPE      1
#define DICT_INT_TYPE           5
#define DICT_LONG_TYPE          6
#define DICT_FLOAT_TYPE         7
#define DICT_STR_TYPE           8

#define DICT_MAX_KEY_LEN        32

#define SERIALIZE_IN            100
#define SERIALIZE_OUT           101


typedef struct dict_node_s{
    int_t              type;
    int_t              alloc_size;
    char_t             *key;
    void               *value;
    struct dict_node_s *next;
}dict_node_t;


struct dictionary{
    dict_node_t  **entries;
    int_t        size;
    int_t        cnt;
};


uint_t dict_hash(dict_t *dict, char_t *s)
{
    uint_t hash_val;
    for (hash_val = 0; *s != '\0'; s++)
        hash_val = *s + 31 * hash_val;
    return hash_val % (dict->size);
}


void dict_clr(dict_t *dict)
{
    int_t cntr = 0;
    for (int_t i = 0; i < dict->size; i++){
        dict_node_t *n = dict->entries[i];
        while (n != NULL) {
            dict_node_t *next = n->next;
            if (n->alloc_size > 0)
                mem_free(n->value);

            mem_free(n->key);
            mem_free(n);

            cntr++;
            n = next;
        }
        dict->entries[i] = NULL;
    }
    dict->cnt -= cntr;
}


bool_t dict_remove(dict_t *dict, char_t *key)
{
    dict_node_t *prev = NULL;
    uint_t       hash = dict_hash(dict, key);

    for (dict_node_t *np = dict->entries[hash]; np != NULL; np = np->next){
        if (strcmp(key, np->key) == 0){
            dict_node_t *next = np->next;

            if (np->alloc_size > 0){
                mem_free(np->value);
            }
            mem_free(np->key);
            mem_free(np);

            if (prev != NULL)
                prev->next = next;
            else if (next != NULL)
                dict->entries[hash] = next;
            else
                dict->entries[hash] = NULL;
            dict->cnt--;
            return TRUE;
        }
        prev = np;
    }
    return FALSE;
}


int_t dict_size(dict_t *dict)
{
    if (dict != NULL){
        return dict->cnt;
    }
    return 0;
}

dict_t *dict_init(int_t size)
{
    dict_t *dict = mem_alloc(sizeof(dict_t));

    ASSERT(dict != NULL);
    dict->size = size;
    dict->cnt  = 0;
    dict->entries = mem_alloc(size * sizeof(dict_node_t*));
    for (int_t i = 0; i < size; i++){
        dict->entries[i] = NULL;
    }
    return dict;
}



void serialize_dict(dict_t *dict, FILE *fp, int_t kind)
{
    ASSERT(dict != NULL);

    if (kind == SERIALIZE_OUT){
        serialize_int(&dict->size, fp, kind);
        serialize_int(&dict->cnt, fp, kind);

        for (int_t i = 0; i < dict->size; i++){
            for (dict_node_t *node = dict->entries[i]; node != NULL; node = node->next){
                serialize_int(&node->type, fp, kind);
                serialize_int(&node->alloc_size, fp, kind);
                for (int_t i = 0; i < DICT_MAX_KEY_LEN; i++){
                    serialize_char(&node->key[i], fp, kind);
                }
                switch (node->type) {
                    case DICT_INT_TYPE:
                        serialize_int((int_t*)node->value, fp, kind);
                        break;
                    case DICT_FLOAT_TYPE:
                        serialize_float((float_t*)node->value, fp, kind);
                        break;
                    case DICT_LONG_TYPE:
                        serialize_long((long_t*)node->value, fp, kind);
                        break;
                    case DICT_STR_TYPE:
                        for (int_t i = 0; i < node->alloc_size; i++){
                            serialize_char((char_t*)&node->value[i], fp, kind);
                        }
                        break;
                    default:
                        break;
                }
            }
        }
    }
    else if (kind == SERIALIZE_IN) {
        char_t  key[DICT_MAX_KEY_LEN];
        int_t   size, cnt;
        int_t   alloc_size = 0, type = 0, key_len = -1;
        int_t   ival;
        float_t fval;
        long_t  lval;
        char_t  *s;

        dict_clr(dict);

        serialize_int(&size, fp, kind);
        serialize_int(&cnt, fp, kind);

        dict->size = size;

        for (int_t i = 0; i < cnt; i++){
            serialize_int(&type, fp, kind);
            serialize_int(&alloc_size, fp, kind);
            for (int_t j = 0; j < DICT_MAX_KEY_LEN; j++){
                serialize_char(&key[j], fp, kind);
            }

            switch (type) {
                case DICT_INT_TYPE:
                    serialize_int(&ival, fp, kind);
                    dict_add_int(dict, key, ival);
                    break;
                case DICT_FLOAT_TYPE:
                    serialize_float(&fval, fp, kind);
                    dict_add_float(dict, key, fval);
                    break;
                case DICT_LONG_TYPE:
                    serialize_long(&lval, fp, kind);
                    dict_add_long(dict, key, lval);
                    break;
                case DICT_STR_TYPE:
                    s = mem_alloc(alloc_size);
                    for (int_t j = 0; j < alloc_size; j++){
                        serialize_char(&s[j], fp, kind);
                    }
                    dict_add_str(dict, key, s, alloc_size);
                    mem_free(s);
                    break;
                default:
                    break;
            }
        }
    }
}


int_t dict_atmoic_size(dict_t *dict, char_t *key)
{
    for (dict_node_t *np = dict->entries[dict_hash(dict, key)]; np != NULL; np = np->next){
        if (strcmp(key, np->key) == 0){
            return np->alloc_size;
        }
    }
    return -1;
}

void *dict_atmoic_ptr(dict_t *dict,
                      char_t *key,
                      int_t  type,
                      void   *func_param)
{
    for (dict_node_t *np = dict->entries[dict_hash(dict, key)]; np != NULL; np = np->next){
        if (strcmp(key, np->key) == 0 && np->type == type){

            if (type == DICT_VOID_PTR_TYPE){
                if (np->alloc_size > 0)
                    return &np->value;
                else
                    return np->value;
            }
            else if (type == DICT_FUNC_PTR_TYPE){
                dict_func_ptr func_ptr = np->value;
                func_ptr(func_param);
            }
            else{
                return np->value;
            }
        }
    }
    return NULL;
}

void *dict_atomic_add(dict_t *dict,
                      char_t *name,
                      void   *ptr,
                      int_t  type,
                      int_t  alloc_size)
{
    dict_node_t  *node;
    uint_t       hashval;

    for (node = dict->entries[dict_hash(dict, name)]; node != NULL; node = node->next){
        if (strcmp(name, node->key) == 0){
            return NULL;
        }
    }

    ASSERT((ptr != NULL || alloc_size > 0) && strlen(name) < DICT_MAX_KEY_LEN);

    node = (dict_node_t*) mem_alloc(sizeof(dict_node_t));

    if (node != NULL){
        node->alloc_size    = alloc_size;
        node->key = mem_alloc(DICT_MAX_KEY_LEN);
        strcpy(node->key, name);

        if (node->alloc_size > 0)
            node->value = mem_alloc(node->alloc_size);
        else if (ptr != NULL)
            node->value = ptr;

        node->type             = type;
        hashval                = dict_hash(dict, name);
        node->next             = dict->entries[hashval];
        dict->entries[hashval] = node;
        dict->cnt++;

        if (type == DICT_FUNC_PTR_TYPE)
            return NULL;
        else
            return node->value;
    }
    return NULL;
}


int_t dict_int(dict_t *dict, char_t *key)
{
    return *(int_t*)dict_atmoic_ptr(dict, key, DICT_INT_TYPE, NULL);
}


void dict_set_int(dict_t *dict, char_t *key, int_t value)
{
    *(int_t*)dict_atmoic_ptr(dict, key, DICT_INT_TYPE, NULL) = value;
}


bool_t dict_add_int(dict_t *dict, char_t *name, int_t initial_val)
{
    bool_t success = dict_atomic_add(dict, name, NULL, DICT_INT_TYPE, sizeof(int_t));
    if (success)
        dict_set_int(dict, name, initial_val);
    return success;
}


float_t dict_float(dict_t *dict, char_t *key)
{
    return *(float_t*)dict_atmoic_ptr(dict, key, DICT_FLOAT_TYPE, NULL);
}


void dict_set_float(dict_t *dict, char_t *key, float_t value)
{
    *(float_t*)dict_atmoic_ptr(dict, key, DICT_FLOAT_TYPE, NULL) = value;
}


bool_t dict_add_float(dict_t *dict, char_t *name, float_t initial_val)
{
    bool_t success = dict_atomic_add(dict, name, NULL, DICT_FLOAT_TYPE, sizeof(float_t));
    if (success)
        dict_set_float(dict, name, initial_val);
    return success;
}


long_t dict_long(dict_t *dict, char_t *key)
{
    return *(long_t*)dict_atmoic_ptr(dict, key, DICT_LONG_TYPE, NULL);
}


void dict_set_long(dict_t *dict, char_t *key, long_t value)
{
    *(long_t*)dict_atmoic_ptr(dict, key, DICT_LONG_TYPE, NULL) = value;
}


bool_t dict_add_long(dict_t *dict, char_t *name, long_t initial_val)
{
    bool_t success = dict_atomic_add(dict, name, NULL, DICT_LONG_TYPE, sizeof(long_t));
    if (success)
        dict_set_long(dict, name, initial_val);
    return success;
}


char_t *dict_str(dict_t *dict, char_t *key)
{
    return (char_t*)dict_atmoic_ptr(dict, key, DICT_STR_TYPE, NULL);
}

void dict_set_str(dict_t *dict, char_t *key, char_t *value)
{
    if (strlen(value) < dict_atmoic_size(dict, key)-1){
        strcpy((char_t*)dict_atmoic_ptr(dict, key, DICT_STR_TYPE, NULL), value);
    }
}


bool_t dict_add_str(dict_t *dict, char_t *key, char_t *initial_str, int_t max_len)
{
    int_t str_size = max_len;

    if (str_size <= 0 && initial_str != NULL)
        str_size = strlen(initial_str)+1;

    bool_t success = dict_atomic_add(dict, key, NULL, DICT_STR_TYPE, str_size);
    if (success && initial_str != NULL)
        dict_set_str(dict, key, initial_str);
    return success;
}


void dict_func(dict_t *dict, char_t *key, void *param)
{
    dict_atmoic_ptr(dict, key, DICT_FUNC_PTR_TYPE, param);
}


bool_t dict_add_func(dict_t *dict, char_t *name, dict_func_ptr func)
{
    return dict_atomic_add(dict, name, func, DICT_FUNC_PTR_TYPE, 0);
}



void *dict_ptr(dict_t *dict, char_t *name)
{
    return dict_atmoic_ptr(dict, name, DICT_VOID_PTR_TYPE, NULL);
}


bool_t dict_add_ptr(dict_t *dict, char_t* name, void *data)
{
    return (dict_atomic_add(dict, name, data, DICT_VOID_PTR_TYPE, 0) != NULL);
}


120
4
задан 24 марта 2018 в 06:03 Источник Поделиться
Комментарии