1 /*
2 map.c - a map (associative array) implementation
3 
4 Copyright (c) 2002 - 2005, 2017 dbjh
5 
6 
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11 
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21 #ifdef  _MSC_VER
22 #pragma warning(push)
23 #pragma warning(disable: 4668) // 'symbol' is not defined as a preprocessor macro, replacing with '0' for 'directives'
24 #endif
25 #include <stdio.h>
26 #ifdef  _MSC_VER
27 #pragma warning(pop)
28 #endif
29 #include <stdlib.h>
30 #include <string.h>
31 #include "map.h"
32 #if     defined DJGPP && defined DLL
33 #include "dxedll_priv.h"
34 #endif
35 
36 
37 st_map_t *
map_create(int n_elements)38 map_create (int n_elements)
39 {
40   st_map_t *map;
41   int size = sizeof (st_map_t) + n_elements * sizeof (st_map_element_t);
42 
43   if ((map = (st_map_t *) malloc (size)) == NULL)
44     {
45       fprintf (stderr, "ERROR: Not enough memory for buffer (%d bytes)\n", size);
46       exit (1);
47     }
48   map->data = (st_map_element_t *) (((unsigned char *) map) + sizeof (st_map_t));
49   memset (map->data, MAP_FREE_KEY, n_elements * sizeof (st_map_element_t));
50   map->size = n_elements;
51   map->cmp_key = map_cmp_key_def;
52   return map;
53 }
54 
55 
56 st_map_t *
map_resize(st_map_t * map,int n_elements)57 map_resize (st_map_t *map, int n_elements)
58 {
59   int size = sizeof (st_map_t) + n_elements * sizeof (st_map_element_t);
60   st_map_t *old_map = map;
61 
62   if ((map = (st_map_t *) realloc (old_map, size)) == NULL)
63     {
64       fprintf (stderr, "ERROR: Not enough memory for buffer (%d bytes)\n", size);
65       free (old_map);
66       exit (1);
67     }
68   map->data = (st_map_element_t *) (((unsigned char *) map) + sizeof (st_map_t));
69   if (n_elements > map->size)
70     memset (((unsigned char *) map->data) + map->size * sizeof (st_map_element_t),
71             MAP_FREE_KEY, (n_elements - map->size) * sizeof (st_map_element_t));
72   map->size = n_elements;
73   return map;
74 }
75 
76 
77 void
map_copy(st_map_t * dest,st_map_t * src)78 map_copy (st_map_t *dest, st_map_t *src)
79 {
80   memcpy (dest->data, src->data, src->size * sizeof (st_map_element_t));
81   dest->cmp_key = src->cmp_key;
82 }
83 
84 
85 int
map_cmp_key_def(void * key1,void * key2)86 map_cmp_key_def (void *key1, void *key2)
87 {
88   return key1 != key2;
89 }
90 
91 
92 st_map_t *
map_put(st_map_t * map,void * key,void * object)93 map_put (st_map_t *map, void *key, void *object)
94 {
95   int n = 0;
96 
97   while (n < map->size && map->data[n].key != MAP_FREE_KEY &&
98          map->cmp_key (map->data[n].key, key))
99     n++;
100 
101   if (n == map->size)                           // current map is full
102     map = map_resize (map, map->size + 20);
103 
104   map->data[n].key = key;
105   map->data[n].object = object;
106 
107   return map;
108 }
109 
110 
111 void *
map_get(st_map_t * map,void * key)112 map_get (st_map_t *map, void *key)
113 {
114   int n = 0;
115 
116   while (n < map->size && (map->data[n].key == MAP_FREE_KEY ||
117          map->cmp_key (map->data[n].key, key)))
118     n++;
119 
120   if (n == map->size)
121     return NULL;
122 
123   return map->data[n].object;
124 }
125 
126 
127 void
map_del(st_map_t * map,void * key)128 map_del (st_map_t *map, void *key)
129 {
130   int n = 0;
131 
132   while (n < map->size && (map->data[n].key == MAP_FREE_KEY ||
133          map->cmp_key (map->data[n].key, key)))
134     n++;
135 
136   if (n < map->size)
137     map->data[n].key = MAP_FREE_KEY;
138 }
139 
140 
141 void
map_dump(st_map_t * map)142 map_dump (st_map_t *map)
143 {
144   int n = 0;
145 
146   while (n < map->size)
147     {
148       printf ("%p -> %p\n", map->data[n].key, map->data[n].object);
149       n++;
150     }
151 }
152