Mercurial > hg > CbC > CbC_gcc
diff gcc/d/dmd/root/aav.c @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gcc/d/dmd/root/aav.c Thu Feb 13 11:34:05 2020 +0900 @@ -0,0 +1,171 @@ + +/* Copyright (C) 2010-2019 by The D Language Foundation, All Rights Reserved + * http://www.digitalmars.com + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt) + * https://github.com/D-Programming-Language/dmd/blob/master/src/root/aav.c + */ + +/** + * Implementation of associative arrays. + * + */ + +#include "dsystem.h" +#include "aav.h" +#include "rmem.h" + + +inline size_t hash(size_t a) +{ + a ^= (a >> 20) ^ (a >> 12); + return a ^ (a >> 7) ^ (a >> 4); +} + +struct aaA +{ + aaA *next; + Key key; + Value value; +}; + +struct AA +{ + aaA* *b; + size_t b_length; + size_t nodes; // total number of aaA nodes + aaA* binit[4]; // initial value of b[] + + aaA aafirst; // a lot of these AA's have only one entry +}; + +/**************************************************** + * Determine number of entries in associative array. + */ + +size_t dmd_aaLen(AA* aa) +{ + return aa ? aa->nodes : 0; +} + + +/************************************************* + * Get pointer to value in associative array indexed by key. + * Add entry for key if it is not already there, returning a pointer to a null Value. + * Create the associative array if it does not already exist. + */ + +Value* dmd_aaGet(AA** paa, Key key) +{ + //printf("paa = %p\n", paa); + + if (!*paa) + { AA *a = (AA *)mem.xmalloc(sizeof(AA)); + a->b = (aaA**)a->binit; + a->b_length = 4; + a->nodes = 0; + a->binit[0] = NULL; + a->binit[1] = NULL; + a->binit[2] = NULL; + a->binit[3] = NULL; + *paa = a; + assert((*paa)->b_length == 4); + } + //printf("paa = %p, *paa = %p\n", paa, *paa); + + assert((*paa)->b_length); + size_t i = hash((size_t)key) & ((*paa)->b_length - 1); + aaA** pe = &(*paa)->b[i]; + aaA *e; + while ((e = *pe) != NULL) + { + if (key == e->key) + return &e->value; + pe = &e->next; + } + + // Not found, create new elem + //printf("create new one\n"); + + size_t nodes = ++(*paa)->nodes; + e = (nodes != 1) ? (aaA *)mem.xmalloc(sizeof(aaA)) : &(*paa)->aafirst; + //e = new aaA(); + e->next = NULL; + e->key = key; + e->value = NULL; + *pe = e; + + //printf("length = %d, nodes = %d\n", (*paa)->b_length, nodes); + if (nodes > (*paa)->b_length * 2) + { + //printf("rehash\n"); + dmd_aaRehash(paa); + } + + return &e->value; +} + + +/************************************************* + * Get value in associative array indexed by key. + * Returns NULL if it is not already there. + */ + +Value dmd_aaGetRvalue(AA* aa, Key key) +{ + //printf("_aaGetRvalue(key = %p)\n", key); + if (aa) + { + size_t i; + size_t len = aa->b_length; + i = hash((size_t)key) & (len-1); + aaA* e = aa->b[i]; + while (e) + { + if (key == e->key) + return e->value; + e = e->next; + } + } + return NULL; // not found +} + + +/******************************************** + * Rehash an array. + */ + +void dmd_aaRehash(AA** paa) +{ + //printf("Rehash\n"); + if (*paa) + { + AA *aa = *paa; + if (aa) + { + size_t len = aa->b_length; + if (len == 4) + len = 32; + else + len *= 4; + aaA** newb = (aaA**)mem.xmalloc(sizeof(aaA)*len); + memset(newb, 0, len * sizeof(aaA*)); + + for (size_t k = 0; k < aa->b_length; k++) + { aaA *e = aa->b[k]; + while (e) + { aaA* enext = e->next; + size_t j = hash((size_t)e->key) & (len-1); + e->next = newb[j]; + newb[j] = e; + e = enext; + } + } + if (aa->b != (aaA**)aa->binit) + mem.xfree(aa->b); + + aa->b = newb; + aa->b_length = len; + } + } +}