forked from electronicarts/CnC_Generals_Zero_Hour
-
Notifications
You must be signed in to change notification settings - Fork 185
Expand file tree
/
Copy pathNameKeyGenerator.h
More file actions
155 lines (125 loc) · 5.94 KB
/
NameKeyGenerator.h
File metadata and controls
155 lines (125 loc) · 5.94 KB
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
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** 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 3 of the License, 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.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: NameKeyGenerator.h ///////////////////////////////////////////////////////////////////////
// Created: Michael Booth, May 2001
// Colin Day, May 2001
// Desc: Name key system to translate between names and unique key ids
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "Lib/BaseType.h"
#include "Common/SubsystemInterface.h"
#include "Common/GameMemory.h"
#include "Common/AsciiString.h"
//-------------------------------------------------------------------------------------------------
// Note that NameKeyType isn't a "real" enum, but an enum type used to enforce the
// fact that NameKeys are really magic cookies, and aren't really interchangeable
// with integers. NAMEKEY_INVALID is always a legal value, but all other values are dynamically
// determined at runtime. (The generated code is basically identical, of course.)
//-------------------------------------------------------------------------------------------------
enum NameKeyType CPP_11(: Int)
{
NAMEKEY_INVALID = 0,
NAMEKEY_MAX = 1<<23, // max ordinal value of a NameKey (some code relies on these fitting into 24 bits safely)
FORCE_NAMEKEYTYPE_LONG = 0x7fffffff, // a trick to ensure the NameKeyType is a 32-bit int
};
//-------------------------------------------------------------------------------------------------
// A bucket entry for the name key generator
//-------------------------------------------------------------------------------------------------
class Bucket : public MemoryPoolObject
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( Bucket, "NameKeyBucketPool" );
public:
Bucket();
//~Bucket();
Bucket *m_nextInSocket;
NameKeyType m_key;
AsciiString m_nameString;
};
inline Bucket::Bucket() : m_nextInSocket(nullptr), m_key(NAMEKEY_INVALID) { }
inline Bucket::~Bucket() { }
//-------------------------------------------------------------------------------------------------
// This class implements the conversion of an arbitrary string into a unique
// integer "key". Calling the nameToKey() method with the same string is
// guaranteed to return the same key. Also, all keys generated by an
// instance of this class are guaranteed to be unique with respect to that
// instance's catalog of names. Multiple instances of this class can be
// created to service multiple namespaces.
//-------------------------------------------------------------------------------------------------
class NameKeyGenerator : public SubsystemInterface
{
public:
NameKeyGenerator();
virtual ~NameKeyGenerator();
virtual void init();
virtual void reset();
virtual void update() { }
/// Given a string, convert into a unique integer key.
NameKeyType nameToKey(const AsciiString& name);
NameKeyType nameToLowercaseKey(const AsciiString& name);
/// Given a string, convert into a unique integer key.
NameKeyType nameToKey(const char* name);
NameKeyType nameToLowercaseKey(const char *name);
// given a key, return the name. this is almost never needed,
// except for a few rare cases like object serialization. also
// note that it's not particularly fast; it does a dumb linear
// search for the key.
AsciiString keyToName(NameKeyType key);
// Get a string out of the INI. Store it into a NameKeyType
static void parseStringAsNameKeyType( INI *ini, void *instance, void *store, const void* userData );
#if RETAIL_COMPATIBLE_CRC
#if RTS_ZEROHOUR
void syncNameKeyID();
#endif
void verifyNameKeyID(UnsignedInt expectedNextID) const;
#endif
private:
enum
{
// socketcount should be prime, and not "close" to a power of 2, for best results.
SOCKET_COUNT = 45007
};
NameKeyType createNameKey(UnsignedInt hash, const AsciiString& name);
void freeSockets();
Bucket* m_sockets[SOCKET_COUNT]; ///< Catalog of all Buckets already generated
UnsignedInt m_nextID; ///< Next available ID
};
//-------------------------------------------------------------------------------------------------
// Externals
//-------------------------------------------------------------------------------------------------
extern NameKeyGenerator *TheNameKeyGenerator; ///< just one namespace for now
// typing "TheNameKeyGenerator->nameToKey()" is awfully wordy. Here are shorter synonyms:
inline NameKeyType NAMEKEY(const AsciiString& name) { return TheNameKeyGenerator->nameToKey(name); }
inline NameKeyType NAMEKEY(const char* name) { return TheNameKeyGenerator->nameToKey(name); }
inline AsciiString KEYNAME(NameKeyType nk) { return TheNameKeyGenerator->keyToName(nk); }
//-------------------------------------------------------------------------------------------------
class StaticNameKey
{
private:
mutable NameKeyType m_key;
const char* m_name;
public:
StaticNameKey(const char* p) : m_key(NAMEKEY_INVALID), m_name(p) {}
NameKeyType key() const;
// ugh, this is a little hokey, but lets us pretend that a StaticNameKey == NameKeyType
operator NameKeyType() const { return key(); }
};