xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/d/dmd/root/aav.c (revision 627f7eb200a4419d89b531d55fccd2ee3ffdcde0)
1*627f7eb2Smrg 
2*627f7eb2Smrg /* Copyright (C) 2010-2019 by The D Language Foundation, All Rights Reserved
3*627f7eb2Smrg  * http://www.digitalmars.com
4*627f7eb2Smrg  * Distributed under the Boost Software License, Version 1.0.
5*627f7eb2Smrg  * (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
6*627f7eb2Smrg  * https://github.com/D-Programming-Language/dmd/blob/master/src/root/aav.c
7*627f7eb2Smrg  */
8*627f7eb2Smrg 
9*627f7eb2Smrg /**
10*627f7eb2Smrg  * Implementation of associative arrays.
11*627f7eb2Smrg  *
12*627f7eb2Smrg  */
13*627f7eb2Smrg 
14*627f7eb2Smrg #include "dsystem.h"
15*627f7eb2Smrg #include "aav.h"
16*627f7eb2Smrg #include "rmem.h"
17*627f7eb2Smrg 
18*627f7eb2Smrg 
hash(size_t a)19*627f7eb2Smrg inline size_t hash(size_t a)
20*627f7eb2Smrg {
21*627f7eb2Smrg     a ^= (a >> 20) ^ (a >> 12);
22*627f7eb2Smrg     return a ^ (a >> 7) ^ (a >> 4);
23*627f7eb2Smrg }
24*627f7eb2Smrg 
25*627f7eb2Smrg struct aaA
26*627f7eb2Smrg {
27*627f7eb2Smrg     aaA *next;
28*627f7eb2Smrg     Key key;
29*627f7eb2Smrg     Value value;
30*627f7eb2Smrg };
31*627f7eb2Smrg 
32*627f7eb2Smrg struct AA
33*627f7eb2Smrg {
34*627f7eb2Smrg     aaA* *b;
35*627f7eb2Smrg     size_t b_length;
36*627f7eb2Smrg     size_t nodes;       // total number of aaA nodes
37*627f7eb2Smrg     aaA* binit[4];      // initial value of b[]
38*627f7eb2Smrg 
39*627f7eb2Smrg     aaA aafirst;        // a lot of these AA's have only one entry
40*627f7eb2Smrg };
41*627f7eb2Smrg 
42*627f7eb2Smrg /****************************************************
43*627f7eb2Smrg  * Determine number of entries in associative array.
44*627f7eb2Smrg  */
45*627f7eb2Smrg 
dmd_aaLen(AA * aa)46*627f7eb2Smrg size_t dmd_aaLen(AA* aa)
47*627f7eb2Smrg {
48*627f7eb2Smrg     return aa ? aa->nodes : 0;
49*627f7eb2Smrg }
50*627f7eb2Smrg 
51*627f7eb2Smrg 
52*627f7eb2Smrg /*************************************************
53*627f7eb2Smrg  * Get pointer to value in associative array indexed by key.
54*627f7eb2Smrg  * Add entry for key if it is not already there, returning a pointer to a null Value.
55*627f7eb2Smrg  * Create the associative array if it does not already exist.
56*627f7eb2Smrg  */
57*627f7eb2Smrg 
dmd_aaGet(AA ** paa,Key key)58*627f7eb2Smrg Value* dmd_aaGet(AA** paa, Key key)
59*627f7eb2Smrg {
60*627f7eb2Smrg     //printf("paa = %p\n", paa);
61*627f7eb2Smrg 
62*627f7eb2Smrg     if (!*paa)
63*627f7eb2Smrg     {   AA *a = (AA *)mem.xmalloc(sizeof(AA));
64*627f7eb2Smrg         a->b = (aaA**)a->binit;
65*627f7eb2Smrg         a->b_length = 4;
66*627f7eb2Smrg         a->nodes = 0;
67*627f7eb2Smrg         a->binit[0] = NULL;
68*627f7eb2Smrg         a->binit[1] = NULL;
69*627f7eb2Smrg         a->binit[2] = NULL;
70*627f7eb2Smrg         a->binit[3] = NULL;
71*627f7eb2Smrg         *paa = a;
72*627f7eb2Smrg         assert((*paa)->b_length == 4);
73*627f7eb2Smrg     }
74*627f7eb2Smrg     //printf("paa = %p, *paa = %p\n", paa, *paa);
75*627f7eb2Smrg 
76*627f7eb2Smrg     assert((*paa)->b_length);
77*627f7eb2Smrg     size_t i = hash((size_t)key) & ((*paa)->b_length - 1);
78*627f7eb2Smrg     aaA** pe = &(*paa)->b[i];
79*627f7eb2Smrg     aaA *e;
80*627f7eb2Smrg     while ((e = *pe) != NULL)
81*627f7eb2Smrg     {
82*627f7eb2Smrg         if (key == e->key)
83*627f7eb2Smrg             return &e->value;
84*627f7eb2Smrg         pe = &e->next;
85*627f7eb2Smrg     }
86*627f7eb2Smrg 
87*627f7eb2Smrg     // Not found, create new elem
88*627f7eb2Smrg     //printf("create new one\n");
89*627f7eb2Smrg 
90*627f7eb2Smrg     size_t nodes = ++(*paa)->nodes;
91*627f7eb2Smrg     e = (nodes != 1) ? (aaA *)mem.xmalloc(sizeof(aaA)) : &(*paa)->aafirst;
92*627f7eb2Smrg     //e = new aaA();
93*627f7eb2Smrg     e->next = NULL;
94*627f7eb2Smrg     e->key = key;
95*627f7eb2Smrg     e->value = NULL;
96*627f7eb2Smrg     *pe = e;
97*627f7eb2Smrg 
98*627f7eb2Smrg     //printf("length = %d, nodes = %d\n", (*paa)->b_length, nodes);
99*627f7eb2Smrg     if (nodes > (*paa)->b_length * 2)
100*627f7eb2Smrg     {
101*627f7eb2Smrg         //printf("rehash\n");
102*627f7eb2Smrg         dmd_aaRehash(paa);
103*627f7eb2Smrg     }
104*627f7eb2Smrg 
105*627f7eb2Smrg     return &e->value;
106*627f7eb2Smrg }
107*627f7eb2Smrg 
108*627f7eb2Smrg 
109*627f7eb2Smrg /*************************************************
110*627f7eb2Smrg  * Get value in associative array indexed by key.
111*627f7eb2Smrg  * Returns NULL if it is not already there.
112*627f7eb2Smrg  */
113*627f7eb2Smrg 
dmd_aaGetRvalue(AA * aa,Key key)114*627f7eb2Smrg Value dmd_aaGetRvalue(AA* aa, Key key)
115*627f7eb2Smrg {
116*627f7eb2Smrg     //printf("_aaGetRvalue(key = %p)\n", key);
117*627f7eb2Smrg     if (aa)
118*627f7eb2Smrg     {
119*627f7eb2Smrg         size_t i;
120*627f7eb2Smrg         size_t len = aa->b_length;
121*627f7eb2Smrg         i = hash((size_t)key) & (len-1);
122*627f7eb2Smrg         aaA* e = aa->b[i];
123*627f7eb2Smrg         while (e)
124*627f7eb2Smrg         {
125*627f7eb2Smrg             if (key == e->key)
126*627f7eb2Smrg                 return e->value;
127*627f7eb2Smrg             e = e->next;
128*627f7eb2Smrg         }
129*627f7eb2Smrg     }
130*627f7eb2Smrg     return NULL;    // not found
131*627f7eb2Smrg }
132*627f7eb2Smrg 
133*627f7eb2Smrg 
134*627f7eb2Smrg /********************************************
135*627f7eb2Smrg  * Rehash an array.
136*627f7eb2Smrg  */
137*627f7eb2Smrg 
dmd_aaRehash(AA ** paa)138*627f7eb2Smrg void dmd_aaRehash(AA** paa)
139*627f7eb2Smrg {
140*627f7eb2Smrg     //printf("Rehash\n");
141*627f7eb2Smrg     if (*paa)
142*627f7eb2Smrg     {
143*627f7eb2Smrg         AA *aa = *paa;
144*627f7eb2Smrg         if (aa)
145*627f7eb2Smrg         {
146*627f7eb2Smrg             size_t len = aa->b_length;
147*627f7eb2Smrg             if (len == 4)
148*627f7eb2Smrg                 len = 32;
149*627f7eb2Smrg             else
150*627f7eb2Smrg                 len *= 4;
151*627f7eb2Smrg             aaA** newb = (aaA**)mem.xmalloc(sizeof(aaA)*len);
152*627f7eb2Smrg             memset(newb, 0, len * sizeof(aaA*));
153*627f7eb2Smrg 
154*627f7eb2Smrg             for (size_t k = 0; k < aa->b_length; k++)
155*627f7eb2Smrg             {   aaA *e = aa->b[k];
156*627f7eb2Smrg                 while (e)
157*627f7eb2Smrg                 {   aaA* enext = e->next;
158*627f7eb2Smrg                     size_t j = hash((size_t)e->key) & (len-1);
159*627f7eb2Smrg                     e->next = newb[j];
160*627f7eb2Smrg                     newb[j] = e;
161*627f7eb2Smrg                     e = enext;
162*627f7eb2Smrg                 }
163*627f7eb2Smrg             }
164*627f7eb2Smrg             if (aa->b != (aaA**)aa->binit)
165*627f7eb2Smrg                 mem.xfree(aa->b);
166*627f7eb2Smrg 
167*627f7eb2Smrg             aa->b = newb;
168*627f7eb2Smrg             aa->b_length = len;
169*627f7eb2Smrg         }
170*627f7eb2Smrg     }
171*627f7eb2Smrg }
172