Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

How can I do this?

Name: Joints, Simon Peyote 2008-03-25 17:22

I want to create a linked list data-structure in C, but I do not want to have to malloc any memory. Is it possible to do this in a way that makes it simple to traverse and add to the list?

Regards,

Simon Peyote Joints

Name: Anonymous 2008-03-25 17:52

#include "HashMap.h"

#include <stdlib.h>
#include <string.h>

enum EntryState {
    ES_EMPTY = 0,
    ES_SINGLE,
    ES_BUCKET
};

static size_t hash_sdbm( const char *s ) {
    size_t hash = 0, c;
    unsigned char *us = (unsigned char*) s;

    while ( c = *us++ )
        hash = c + ( hash << 6 ) + ( hash << 16 ) - hash;

    return hash;
}

HashMap hashmap_alloc() {
    return hashmap_alloc_size( 1024 );
}

HashMap hashmap_alloc_size( size_t s ) {
    HashMap ret;
    ret.size = s;
    ret.data = calloc( s, sizeof( HashMapEntry ) );
    return ret;
}

HashMap hashmap_copy( HashMap* h ) {
    HashMap ret;
    size_t i, j;

    ret.size = h->size;
    ret.data = malloc( h->size * sizeof( HashMapEntry ) );

    for ( i = 0; i < h->size; ++i ) {
        HashMapEntry *he = &h->data[i], *re = &ret.data[i];
        re->state = he->state;

        if ( he->state == ES_SINGLE ) {
            re->entry.value = he->entry.value;
            re->entry.key = malloc( strlen( he->entry.key ) + 1 );
            strcpy( re->entry.key, he->entry.key );
        }
        else if ( he->state == ES_BUCKET ) {
            re->bucket = vector_alloc();
            for ( j = 0; j < vector_size( &he->bucket ); ++j ) {
                KeyValuePair *kvp = vector_index( &he->bucket, j );
                KeyValuePair *nkvp = malloc( sizeof( KeyValuePair ) );
                nkvp->key = malloc( strlen( kvp->key ) + 1 );
                strcpy( nkvp->key, kvp->key );
                nkvp->value = kvp->value;
                vector_push_back( &re->bucket, nkvp );
            }
        }
    }

    return ret;
}

void hashmap_free( HashMap* h ) {
    size_t i, j;

    for ( i = 0; i < h->size; ++i ) {
        HashMapEntry *he = &h->data[i];

        if ( he->state == ES_SINGLE ) {
            free( he->entry.key );
        }
        else if ( he->state == ES_BUCKET ) {
            for ( j = 0; i < vector_size( &he->bucket ); ++j ) {
                KeyValuePair *kvp = vector_index( &he->bucket, j );
                free( kvp->key );
                free( kvp );
            }
            vector_free( &he->bucket );
        }
    }

    /* free the data */
    free( h->data );
}

bool hashmap_haskey( HashMap* h, const char* k ) {
    return hashmap_get( h, k ) != 0;
}

static HashMapEntry* hashmap_getentry( HashMap* h, const char* k ) {
    size_t index = hash_sdbm( k ) % h->size;
    return &h->data[ index ];
}

void* hashmap_get( HashMap* h, const char* k ) {
    HashMapEntry *e = hashmap_getentry( h, k );   
    size_t i;

    if ( e->state == ES_SINGLE ) {
        if ( !strcmp( e->entry.key, k ) )
            return e->entry.value;
        return 0;
    }
    else if ( e->state == ES_BUCKET ) {
        Vector *v = &e->bucket;
        for ( i = 0; i < v->size; ++i ) {
            KeyValuePair *kvp = vector_index( v, i );
            if ( !strcmp( kvp->key, k ) )
                return kvp->value;
        }
        return 0;
    }

    return 0;
}

void hashmap_insert( HashMap* h, const char* k, void* v ) {
    HashMapEntry *e = hashmap_getentry( h, k );

    if ( e->state == ES_EMPTY ) {
        e->state = ES_SINGLE;
        e->entry.key = malloc( strlen( k ) + 1 );
        strcpy( e->entry.key, k );
        e->entry.value = v;
    }
    else if ( e->state == ES_SINGLE ) {
        KeyValuePair kvp = e->entry;
        KeyValuePair *pkvp;

        e->state = ES_BUCKET;
        e->bucket = vector_alloc();

        pkvp = malloc( sizeof( KeyValuePair ) );
        pkvp->key = kvp.key;
        pkvp->value = kvp.value;
        vector_push_back( &e->bucket, pkvp );
    }

    if ( e->state == ES_BUCKET ) {
        KeyValuePair *pkvp;
        pkvp = malloc( sizeof( KeyValuePair ) );
        pkvp->key = malloc( strlen( k ) + 1 );
        strcpy( pkvp->key, k );
        pkvp->value = v;
        vector_push_back( &e->bucket, pkvp );
    }
}

void hashmap_remove( HashMap* h, const char* k ) {
    HashMapEntry *e = hashmap_getentry( h, k );
    size_t i;

    if ( e->state == ES_SINGLE ) {
        free( e->entry.key );
        e->state = ES_EMPTY;
    }
    else if ( e->state == ES_BUCKET ) {
        Vector cv = vector_copy( &e->bucket );
        vector_clear( &e->bucket );

        for ( i = 0; i < vector_size( &cv ); ++i ) {
            KeyValuePair *kvp = vector_index( &cv, i );
           
            if ( !strcmp( kvp->key, k ) ) {
                free( kvp->key );
                free( kvp );
            }
            else {
                vector_push_back( &e->bucket, kvp );
            }
        }

        vector_free( &cv );

        if ( vector_empty( &e->bucket ) ) {
            vector_free( &e->bucket );
            e->state = ES_EMPTY;
        }
    }
}

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List