File: idex.c

package info (click to toggle)
freeciv 2.6.2-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, sid
  • size: 212,508 kB
  • sloc: ansic: 443,831; cpp: 29,541; sh: 7,982; makefile: 7,886; python: 1,933; xml: 945
file content (171 lines) | stat: -rw-r--r-- 6,218 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/***********************************************************************
 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
***********************************************************************/

/***********************************************************************
   idex = ident index: a lookup table for quick mapping of unit and city
   id values to unit and city pointers.

   Method: use separate hash tables for each type.
   Means code duplication for city/unit cases, but simplicity advantages.
   Don't have to manage memory at all: store pointers to unit and city
   structs allocated elsewhere, and keys are pointers to id values inside
   the structs.

   Note id values should probably be unsigned int: here leave as plain int
   so can use pointers to pcity->id etc.
***********************************************************************/

#ifdef HAVE_CONFIG_H
#include <fc_config.h>
#endif

/* utility */
#include "log.h"

/* common */
#include "city.h"
#include "unit.h"

#include "idex.h"


/* struct city_hash. */
#define SPECHASH_TAG city
#define SPECHASH_INT_KEY_TYPE
#define SPECHASH_IDATA_TYPE struct city *
#include "spechash.h"

/* struct unit_hash. */
#define SPECHASH_TAG unit
#define SPECHASH_INT_KEY_TYPE
#define SPECHASH_IDATA_TYPE struct unit *
#include "spechash.h"


/* "Global" data: */
static struct city_hash *idex_city_hash = NULL;
static struct unit_hash *idex_unit_hash = NULL;

/**************************************************************************
   Initialize.  Should call this at the start before use.
***************************************************************************/
void idex_init(void)
{
  fc_assert_ret(idex_city_hash == NULL);
  fc_assert_ret(idex_unit_hash == NULL);

  idex_city_hash = city_hash_new();
  idex_unit_hash = unit_hash_new();
}

/**************************************************************************
   Free the hashs.
***************************************************************************/
void idex_free(void)
{
  city_hash_destroy(idex_city_hash);
  idex_city_hash = NULL;

  unit_hash_destroy(idex_unit_hash);
  idex_unit_hash = NULL;
}

/**************************************************************************
   Register a city into idex, with current pcity->id.
   Call this when pcity created.
***************************************************************************/
void idex_register_city(struct city *pcity)
{
  struct city *old;

  city_hash_replace_full(idex_city_hash, pcity->id, pcity, NULL, &old);
  fc_assert_ret_msg(NULL == old,
                    "IDEX: city collision: new %d %p %s, old %d %p %s",
                    pcity->id, (void *) pcity, city_name_get(pcity),
                    old->id, (void *) old, city_name_get(old));
}

/**************************************************************************
   Register a unit into idex, with current punit->id.
   Call this when punit created.
***************************************************************************/
void idex_register_unit(struct unit *punit)
{
  struct unit *old;

  unit_hash_replace_full(idex_unit_hash, punit->id, punit, NULL, &old);
  fc_assert_ret_msg(NULL == old,
                    "IDEX: unit collision: new %d %p %s, old %d %p %s",
                    punit->id, (void *) punit, unit_rule_name(punit),
                    old->id, (void *) old, unit_rule_name(old));
}

/**************************************************************************
   Remove a city from idex, with current pcity->id.
   Call this when pcity deleted.
***************************************************************************/
void idex_unregister_city(struct city *pcity)
{
  struct city *old;

  city_hash_remove_full(idex_city_hash, pcity->id, NULL, &old);
  fc_assert_ret_msg(NULL != old,
                    "IDEX: city unreg missing: %d %p %s",
                    pcity->id, (void *) pcity, city_name_get(pcity));
  fc_assert_ret_msg(old == pcity, "IDEX: city unreg mismatch: "
                    "unreg %d %p %s, old %d %p %s",
                    pcity->id, (void *) pcity, city_name_get(pcity),
                    old->id, (void *) old, city_name_get(old));
}

/**************************************************************************
   Remove a unit from idex, with current punit->id.
   Call this when punit deleted.
***************************************************************************/
void idex_unregister_unit(struct unit *punit)
{
  struct unit *old;

  unit_hash_remove_full(idex_unit_hash, punit->id, NULL, &old);
  fc_assert_ret_msg(NULL != old,
                    "IDEX: unit unreg missing: %d %p %s",
                    punit->id, (void *) punit, unit_rule_name(punit));
  fc_assert_ret_msg(old == punit, "IDEX: unit unreg mismatch: "
                    "unreg %d %p %s, old %d %p %s",
                    punit->id, (void *) punit, unit_rule_name(punit),
                    old->id, (void*) old, unit_rule_name(old));
}

/**************************************************************************
   Lookup city with given id.
   Returns NULL if the city is not registered (which is not an error).
***************************************************************************/
struct city *idex_lookup_city(int id)
{
  struct city *pcity;

  city_hash_lookup(idex_city_hash, id, &pcity);
  return pcity;
}

/**************************************************************************
   Lookup unit with given id.
   Returns NULL if the unit is not registered (which is not an error).
***************************************************************************/
struct unit *idex_lookup_unit(int id)
{
  struct unit *punit;

  unit_hash_lookup(idex_unit_hash, id, &punit);
  return punit;
}