1 /***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
13
14 /***********************************************************************
15 idex = ident index: a lookup table for quick mapping of unit and city
16 id values to unit and city pointers.
17
18 Method: use separate hash tables for each type.
19 Means code duplication for city/unit cases, but simplicity advantages.
20 Don't have to manage memory at all: store pointers to unit and city
21 structs allocated elsewhere, and keys are pointers to id values inside
22 the structs.
23
24 Note id values should probably be unsigned int: here leave as plain int
25 so can use pointers to pcity->id etc.
26 ***********************************************************************/
27
28 #ifdef HAVE_CONFIG_H
29 #include <fc_config.h>
30 #endif
31
32 /* utility */
33 #include "log.h"
34
35 /* common */
36 #include "city.h"
37 #include "unit.h"
38
39 #include "idex.h"
40
41
42 /* struct city_hash. */
43 #define SPECHASH_TAG city
44 #define SPECHASH_INT_KEY_TYPE
45 #define SPECHASH_IDATA_TYPE struct city *
46 #include "spechash.h"
47
48 /* struct unit_hash. */
49 #define SPECHASH_TAG unit
50 #define SPECHASH_INT_KEY_TYPE
51 #define SPECHASH_IDATA_TYPE struct unit *
52 #include "spechash.h"
53
54
55 /* "Global" data: */
56 static struct city_hash *idex_city_hash = NULL;
57 static struct unit_hash *idex_unit_hash = NULL;
58
59 /**************************************************************************
60 Initialize. Should call this at the start before use.
61 ***************************************************************************/
idex_init(void)62 void idex_init(void)
63 {
64 fc_assert_ret(idex_city_hash == NULL);
65 fc_assert_ret(idex_unit_hash == NULL);
66
67 idex_city_hash = city_hash_new();
68 idex_unit_hash = unit_hash_new();
69 }
70
71 /**************************************************************************
72 Free the hashs.
73 ***************************************************************************/
idex_free(void)74 void idex_free(void)
75 {
76 city_hash_destroy(idex_city_hash);
77 idex_city_hash = NULL;
78
79 unit_hash_destroy(idex_unit_hash);
80 idex_unit_hash = NULL;
81 }
82
83 /**************************************************************************
84 Register a city into idex, with current pcity->id.
85 Call this when pcity created.
86 ***************************************************************************/
idex_register_city(struct city * pcity)87 void idex_register_city(struct city *pcity)
88 {
89 struct city *old;
90
91 city_hash_replace_full(idex_city_hash, pcity->id, pcity, NULL, &old);
92 fc_assert_ret_msg(NULL == old,
93 "IDEX: city collision: new %d %p %s, old %d %p %s",
94 pcity->id, (void *) pcity, city_name_get(pcity),
95 old->id, (void *) old, city_name_get(old));
96 }
97
98 /**************************************************************************
99 Register a unit into idex, with current punit->id.
100 Call this when punit created.
101 ***************************************************************************/
idex_register_unit(struct unit * punit)102 void idex_register_unit(struct unit *punit)
103 {
104 struct unit *old;
105
106 unit_hash_replace_full(idex_unit_hash, punit->id, punit, NULL, &old);
107 fc_assert_ret_msg(NULL == old,
108 "IDEX: unit collision: new %d %p %s, old %d %p %s",
109 punit->id, (void *) punit, unit_rule_name(punit),
110 old->id, (void *) old, unit_rule_name(old));
111 }
112
113 /**************************************************************************
114 Remove a city from idex, with current pcity->id.
115 Call this when pcity deleted.
116 ***************************************************************************/
idex_unregister_city(struct city * pcity)117 void idex_unregister_city(struct city *pcity)
118 {
119 struct city *old;
120
121 city_hash_remove_full(idex_city_hash, pcity->id, NULL, &old);
122 fc_assert_ret_msg(NULL != old,
123 "IDEX: city unreg missing: %d %p %s",
124 pcity->id, (void *) pcity, city_name_get(pcity));
125 fc_assert_ret_msg(old == pcity, "IDEX: city unreg mismatch: "
126 "unreg %d %p %s, old %d %p %s",
127 pcity->id, (void *) pcity, city_name_get(pcity),
128 old->id, (void *) old, city_name_get(old));
129 }
130
131 /**************************************************************************
132 Remove a unit from idex, with current punit->id.
133 Call this when punit deleted.
134 ***************************************************************************/
idex_unregister_unit(struct unit * punit)135 void idex_unregister_unit(struct unit *punit)
136 {
137 struct unit *old;
138
139 unit_hash_remove_full(idex_unit_hash, punit->id, NULL, &old);
140 fc_assert_ret_msg(NULL != old,
141 "IDEX: unit unreg missing: %d %p %s",
142 punit->id, (void *) punit, unit_rule_name(punit));
143 fc_assert_ret_msg(old == punit, "IDEX: unit unreg mismatch: "
144 "unreg %d %p %s, old %d %p %s",
145 punit->id, (void *) punit, unit_rule_name(punit),
146 old->id, (void*) old, unit_rule_name(old));
147 }
148
149 /**************************************************************************
150 Lookup city with given id.
151 Returns NULL if the city is not registered (which is not an error).
152 ***************************************************************************/
idex_lookup_city(int id)153 struct city *idex_lookup_city(int id)
154 {
155 struct city *pcity;
156
157 city_hash_lookup(idex_city_hash, id, &pcity);
158 return pcity;
159 }
160
161 /**************************************************************************
162 Lookup unit with given id.
163 Returns NULL if the unit is not registered (which is not an error).
164 ***************************************************************************/
idex_lookup_unit(int id)165 struct unit *idex_lookup_unit(int id)
166 {
167 struct unit *punit;
168
169 unit_hash_lookup(idex_unit_hash, id, &punit);
170 return punit;
171 }
172