<commit_before>/*
 * String hash map.
 *
 * author: <NAME> <<EMAIL>>
 */

#include "strmap.h"
#include "compiler.h"

#include <assert.h>
#include <string.h>

struct slot {
    struct slot *next;
    struct pair pair;
};

struct strmap {
    pool_t pool;
    unsigned capacity;
    struct slot *current_slot;
    unsigned next_slot;
    struct slot slots[1];
};

static inline unsigned
calc_hash(const char *p) {
    unsigned hash = 5381;

    assert(p != NULL);

    while (*p != 0)
        hash = (hash << 5) + hash + *p++;

    return hash;
}

strmap_t
strmap_new(pool_t pool, unsigned capacity)
{
    strmap_t map = p_calloc(pool, sizeof(*map) + sizeof(map->slots) * (capacity - 1));
    assert(capacity > 1);
    map->pool = pool;
    map->capacity = capacity;
    return map;
}

void
strmap_addn(strmap_t map, const char *key, const char *value)
{
    unsigned hash = calc_hash(key);
    struct slot *slot, *prev;

    assert(value != NULL);

    slot = &map->slots[hash % map->capacity];
    if (slot->pair.key != NULL) {
        while (slot->next != NULL) {
            slot = slot->next;
            assert(slot->pair.key != NULL);
            assert(slot->pair.value != NULL);
        }

        prev = slot;
        slot = p_malloc(map->pool, sizeof(*slot));
        slot->next = NULL;
        prev->next = slot;
    }

    slot->pair.key = key;
    slot->pair.value = value;
}

static inline const char *
strmap_maybe_overwrite(struct slot *slot, const char *value, int overwrite)
{
    const char *old = slot->pair.value;
    assert(old != NULL);
    if (overwrite)
        slot->pair.value = value;
    return old;
}

const char *
strmap_put(strmap_t map, const char *key, const char *value, int overwrite)
{
    unsigned hash = calc_hash(key);
    struct slot *slot, *prev;

    assert(key != NULL);
    assert(value != NULL);

    prev = &map->slots[hash % map->capacity];
    if (prev->pair.key != NULL && strcmp(prev->pair.key, key) == 0)
        return strmap_maybe_overwrite(prev, value, overwrite);

    for (slot = prev->next; slot != NULL; slot = prev->next) {
        assert(slot->pair.key != NULL);
        assert(slot->pair.value != NULL);

        if (strcmp(slot->pair.key, key) == 0)
            return strmap_maybe_overwrite(slot, value, overwrite);
    }

    slot = p_malloc(map->pool, sizeof(*slot));
    slot->next = NULL;
    slot->pair.key = key;<commit_msg>fixed strmap_put() for empty slot<commit_after>/*
 * String hash map.
 *
 * author: <NAME> <<EMAIL>>
 */

#include "strmap.h"
#include "compiler.h"

#include <assert.h>
#include <string.h>

struct slot {
    struct slot *next;
    struct pair pair;
};

struct strmap {
    pool_t pool;
    unsigned capacity;
    struct slot *current_slot;
    unsigned next_slot;
    struct slot slots[1];
};

static inline unsigned
calc_hash(const char *p) {
    unsigned hash = 5381;

    assert(p != NULL);

    while (*p != 0)
        hash = (hash << 5) + hash + *p++;

    return hash;
}

strmap_t
strmap_new(pool_t pool, unsigned capacity)
{
    strmap_t map = p_calloc(pool, sizeof(*map) + sizeof(map->slots) * (capacity - 1));
    assert(capacity > 1);
    map->pool = pool;
    map->capacity = capacity;
    return map;
}

void
strmap_addn(strmap_t map, const char *key, const char *value)
{
    unsigned hash = calc_hash(key);
    struct slot *slot, *prev;

    assert(value != NULL);

    slot = &map->slots[hash % map->capacity];
    if (slot->pair.key != NULL) {
        while (slot->next != NULL) {
            slot = slot->next;
            assert(slot->pair.key != NULL);
            assert(slot->pair.value != NULL);
        }

        prev = slot;
        slot = p_malloc(map->pool, sizeof(*slot));
        slot->next = NULL;
        prev->next = slot;
    }

    slot->pair.key = key;
    slot->pair.value = value;
}

static inline const char *
strmap_maybe_overwrite(struct slot *slot, const char *value, int overwrite)
{
    const char *old = slot->pair.value;
    assert(old != NULL);
    if (overwrite)
        slot->pair.value = value;
    return old;
}

const char *
strmap_put(strmap_t map, const char *key, const char *value, int overwrite)
{
    unsigned hash = calc_hash(key);
    struct slot *slot, *prev;

    assert(key != NULL);
    assert(value != NULL);

    prev = &map->slots[hash % map->capacity];
    if (prev->pair.key == NULL) {
        prev->pair.key = key;
        prev->pair.value = value;
        return NULL;
    } else if (strcmp(prev->pair.key, key) == 0)
        return strmap_maybe_overwrite(prev, value, overwrite);

    for (slot = prev->next; slot != NULL; slot = prev->next) {
        assert(slot->pair.key != NULL);
        assert(slot->pair.value != NULL);

        if (strcmp(slot->pair.key, key) == 0)
            return strmap_maybe_overwrite(slot, value, overwrite);
    }

    slot = p_malloc(map->pool, sizeof(*slot));
    slot->next = NULL;
    slot->pair.key = key;
{'fraction_non_alphanumeric': 0.15144720750101917, 'fraction_numerical': 0.004484304932735426, 'mean_word_length': 2.5975073313782993, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 75, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1591220', 'n_tokens_mistral': 1674, 'n_tokens_neox': 1650, 'n_words': 431}