Oolite 1.91.0.7644-241112-7f5034b
Loading...
Searching...
No Matches
OOConstToJSString.m
Go to the documentation of this file.
1/*
2
3OOConstToJSString.m
4
5
6Oolite
7Copyright (C) 2004-2013 Giles C Williams and contributors
8
9This program is free software; you can redistribute it and/or
10modify it under the terms of the GNU General Public License
11as published by the Free Software Foundation; either version 2
12of the License, or (at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with this program; if not, write to the Free Software
21Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22MA 02110-1301, USA.
23
24*/
25
26#include "OOConstToJSString.h"
27
28
29/*
30 Each type of constant has its own lookup table, which is a linear list of
31 TableEntry structs plus a count.
32
33 The list is statically initialized with the constant values and C strings.
34 OOConstToJSStringInit() (through InitTable()) replaces the C strings with
35 interned JSStrings (hence the void * type). These are subsequently
36 constant and no other strings with the same value should occur, i.e. they
37 should be comparable with pointer equality. Because I'm paranoid, we fall
38 back to full string comparison if this fails.
39
40 ConstTables are globals, which are accessed as local externs in the inlines
41 in the header. All the advantages of globals with most of the advantages
42 of encapsulation, sorta.
43
44 -- Ahruman 2011-01-15
45*/
46
47typedef struct
48{
49 NSInteger value;
50 const char *cString;
51 JSString *jsString;
53
54typedef struct ConstTable
55{
56 NSUInteger count;
59
60#define TABLE(entries) { sizeof entries / sizeof *entries, entries }
61
62
63static BOOL sInited = NO;
64
65/*
66 The interned string "UNDEFINED", returned by OOJSStringFromConstantPRIVATE()
67 if passed a bogus constant value.
68*/
69static JSString *sUndefinedString;
70
71
72/*
73 Initialize table contents (with C strings, see above) from table files.
74*/
75#define ENTRY(label, val) { .value = label, .cString = #label },
76#define GALACTIC_HYPERSPACE_ENTRY(label, val) { .value = GALACTIC_HYPERSPACE_##label, .cString = #label },
77#define DIFF_STRING_ENTRY(label, string) { .value = label, .cString = string },
78
80{
81 #include "OOCompassMode.tbl"
82};
83
85{
86 #include "OOEntityStatus.tbl"
87};
88
90{
91 #include "OOGalacticHyperspaceBehaviour.tbl"
92};
93
95{
96 #include "OOGUIScreenID.tbl"
97};
98
100{
101 #include "OOScanClass.tbl"
102};
103
105{
106 #include "OOViewID.tbl"
107};
108
110{
111 #include "OOShipDamageType.tbl"
112};
113
115{
116 #include "OOLegalStatusReason.tbl"
117};
118
120{
121 #include "OOLongRangeChartMode.tbl"
122};
123
124#undef ENTRY
125#undef GALACTIC_HYPERSPACE_ENTRY
126#undef DIFF_STRING_ENTRY
127
128
138
139static void InitTable(JSContext *context, ConstTable *table);
140
141
142// MARK: Initialization
143
144void OOConstToJSStringInit(JSContext *context)
145{
146 NSCAssert(!sInited, @"OOConstToJSStringInit() called while already inited.");
147 NSCParameterAssert(context != NULL && JS_IsInRequest(context));
148
149 sUndefinedString = JS_InternString(context, "UNDEFINED");
150
160
161 sInited = YES;
162}
163
164
166{
167 NSCAssert(sInited, @"OOConstToJSStringDestroy() called while not inited.");
168 sInited = NO;
169 // jsString pointers are now officially junk.
170}
171
172
173static int CompareEntries(const void *a, const void *b)
174{
175 const TableEntry *entA = a;
176 const TableEntry *entB = b;
177
178 if (entA->value < entB->value) return -1;
179 if (entA->value > entB->value) return 1;
180 return 0;
181}
182
183
184static void InitTable(JSContext *context, ConstTable *table)
185{
186 NSCParameterAssert(context != NULL && JS_IsInRequest(context) && table != NULL);
187
188 NSUInteger i;
189 for(i = 0; i < table->count; i++)
190 {
191 table->entries[i].jsString = JS_InternString(context, table->entries[i].cString);
192 }
193
194 qsort(table->entries, table->count, sizeof *table->entries, CompareEntries);
195}
196
197
198// MARK: Lookup
199
200JSString *OOJSStringFromConstantPRIVATE(JSContext *context, NSInteger value, struct ConstTable *table)
201{
202 NSCAssert1(sInited, @"%s called before OOConstToJSStringInit().", __PRETTY_FUNCTION__);
203 NSCParameterAssert(context != NULL && JS_IsInRequest(context));
204 NSCParameterAssert(table != NULL && table->count > 0);
205
206 // Binary search.
207 NSUInteger min = 0, max = table->count - 1;
208 NSInteger current;
209 do
210 {
211 NSUInteger mid = (min + max) / 2;
212 current = table->entries[mid].value;
213 if (current < value)
214 {
215 min = mid + 1;
216 }
217 else if (current > value)
218 {
219 max = mid - 1;
220 }
221 else
222 {
223 return table->entries[mid].jsString;
224 }
225 }
226 while (min <= max);
227
228 return sUndefinedString;
229}
230
231
232NSUInteger OOConstantFromJSStringPRIVATE(JSContext *context, JSString *string, struct ConstTable *table, NSInteger defaultValue)
233{
234 NSCAssert1(sInited, @"%s called before OOConstToJSStringInit().", __PRETTY_FUNCTION__);
235 NSCParameterAssert(context != NULL && JS_IsInRequest(context) && table != NULL);
236
237 // Quick pass: look for pointer-equal string.
238 NSUInteger i, count = table->count;
239 for(i = 0; i < count; i++)
240 {
241 if (table->entries[i].jsString == string)
242 {
243 return table->entries[i].value;
244 }
245 }
246
247
248 // Slow pass: use string comparison. This is expected to fail.
249 if (string != NULL)
250 {
251 for(i = 0; i < count; i++)
252 {
253 int32 result;
254 if (JS_CompareStrings(context, string, table->entries[i].jsString, &result) && result == 0)
255 {
256 return table->entries[i].value;
257 }
258 }
259 }
260
261 // Fail.
262 return defaultValue;
263}
264
265
266NSUInteger OOConstantFromJSValuePRIVATE(JSContext *context, jsval value, struct ConstTable *table, NSInteger defaultValue)
267{
268 if (EXPECT(JSVAL_IS_STRING(value)))
269 {
270 return OOConstantFromJSStringPRIVATE(context, JSVAL_TO_STRING(value), table, defaultValue);
271 }
272 else
273 {
274 return defaultValue;
275 }
276
277}
NSUInteger OOConstantFromJSStringPRIVATE(JSContext *context, JSString *string, struct ConstTable *table, NSInteger defaultValue)
ConstTable gOOViewIDConstTable
ConstTable gOOEntityStatusConstTable
static TableEntry sOOEntityStatusTableEntries[]
static TableEntry sOOGalacticHyperspaceBehaviourTableEntries[]
void OOConstToJSStringDestroy(void)
static int CompareEntries(const void *a, const void *b)
static JSString * sUndefinedString
JSString * OOJSStringFromConstantPRIVATE(JSContext *context, NSInteger value, struct ConstTable *table)
ConstTable gOOLongRangeChartModeConstTable
ConstTable gOOCompassModeConstTable
static TableEntry sOOViewIDTableEntries[]
ConstTable gOOLegalStatusReasonConstTable
void OOConstToJSStringInit(JSContext *context)
static TableEntry sOOScanClassTableEntries[]
struct ConstTable ConstTable
static void InitTable(JSContext *context, ConstTable *table)
ConstTable gOOShipDamageTypeConstTable
ConstTable gOOScanClassConstTable
#define TABLE(entries)
ConstTable gOOGUIScreenIDConstTable
static TableEntry sOOCompassModeTableEntries[]
static BOOL sInited
ConstTable gOOGalacticHyperspaceBehaviourConstTable
static TableEntry sOOLongRangeChartModeTableEntries[]
static TableEntry sOOShipDamageTypeTableEntries[]
static TableEntry sOOGUIScreenIDTableEntries[]
static TableEntry sOOLegalStatusReasonTableEntries[]
NSUInteger OOConstantFromJSValuePRIVATE(JSContext *context, jsval value, struct ConstTable *table, NSInteger defaultValue)
#define EXPECT(x)
#define JS_IsInRequest(context)
unsigned count
TableEntry * entries
NSUInteger count
NSInteger value
const char * cString
JSString * jsString