1 /*
2  # This file is part of the Astrometry.net suite.
3  # Licensed under a 3-clause BSD style license - see LICENSE
4  */
5 #include <assert.h>
6 
7 #include "intmap.h"
8 
9 #define IMGLUE2(n,f) n ## _ ## f
10 #define IMGLUE(n,f) IMGLUE2(n,f)
11 
12 #define key_t int
13 #define nl il
14 #define KL(x) IMGLUE(nl, x)
15 
intmap_new(int datasize,int subblocksize,int blocksize,int Ndense)16 intmap_t* intmap_new(int datasize, int subblocksize, int blocksize,
17                      int Ndense) {
18     intmap_t* im = calloc(1, sizeof(intmap_t));
19     if (!blocksize)
20         blocksize = 4096;
21     im->blocksize = subblocksize;
22     im->datasize = datasize;
23     if (Ndense) {
24         im->ND = Ndense;
25         im->dense = calloc(im->ND, sizeof(bl*));
26     } else {
27         im->keys = KL(new)(blocksize);
28         im->lists = pl_new(blocksize);
29     }
30     return im;
31 }
32 
intmap_free(intmap_t * im)33 void intmap_free(intmap_t* im) {
34     int i;
35     if (im->lists) {
36         for (i=0; i<pl_size(im->lists); i++) {
37             bl* lst = pl_get(im->lists, i);
38             bl_free(lst);
39         }
40         pl_free(im->lists);
41     }
42     if (im->dense) {
43         for (i=0; i<im->ND; i++) {
44             bl* lst = im->dense[i];
45             if (!lst)
46                 continue;
47             bl_free(lst);
48         }
49         free(im->dense);
50     }
51     if (im->keys)
52         KL(free)(im->keys);
53     free(im);
54 }
55 
intmap_find(intmap_t * im,key_t key,anbool create)56 bl* intmap_find(intmap_t* im, key_t key, anbool create) {
57     key_t ind;
58     assert(key >= 0);
59     assert(im);
60     if (!im->dense) {
61         assert(im->keys);
62         assert(im->lists);
63         ind = KL(sorted_index_of)(im->keys, key);
64         if (ind == -1) {
65             bl* lst;
66             if (!create)
67                 return NULL;
68             lst = bl_new(im->blocksize, im->datasize);
69             ind = KL(insert_unique_ascending)(im->keys, key);
70             pl_insert(im->lists, ind, lst);
71             return lst;
72         }
73         return pl_get(im->lists, ind);
74     } else {
75         bl* lst;
76         assert(key < im->ND);
77         assert(im->dense);
78         lst = im->dense[key];
79         if (lst)
80             return lst;
81         if (!create)
82             return lst;
83         lst = im->dense[key] = bl_new(im->blocksize, im->datasize);
84         return lst;
85     }
86 }
87 
intmap_append(intmap_t * it,int key,void * pval)88 void intmap_append(intmap_t* it, int key, void* pval) {
89     bl* lst = intmap_find(it, key, TRUE);
90     bl_append(lst, pval);
91 }
92 
intmap_get_entry(intmap_t * im,int index,key_t * p_key,bl ** p_list)93 anbool intmap_get_entry(intmap_t* im, int index,
94                         key_t* p_key, bl** p_list) {
95     assert(im);
96     assert(index >= 0);
97     if (im->dense) {
98         if (index >= im->ND)
99             return FALSE;
100         if (p_key)
101             *p_key = index;
102         if (p_list)
103             *p_list = im->dense[index];
104         return TRUE;
105     }
106 
107     assert(im->keys);
108     assert(im->lists);
109     if (index >= KL(size)(im->keys))
110         return FALSE;
111     if (p_key)
112         *p_key = KL(get)(im->keys, index);
113     if (p_list)
114         *p_list = pl_get(im->lists, index);
115     return TRUE;
116 }
117 
118 #undef IMGLUE2
119 #undef IMGLUE
120 #undef key
121 #undef nl
122 #undef KL
123