Oolite
Loading...
Searching...
No Matches
OOConvertSystemDescriptions.m
Go to the documentation of this file.
1/*
2
3OOConvertSystemDescriptions.m
4Oolite
5
6
7Copyright (C) 2008 Jens Ayton
8
9Permission is hereby granted, free of charge, to any person obtaining a copy
10of this software and associated documentation files (the "Software"), to deal
11in the Software without restriction, including without limitation the rights
12to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13copies of the Software, and to permit persons to whom the Software is
14furnished to do so, subject to the following conditions:
15
16The above copyright notice and this permission notice shall be included in all
17copies or substantial portions of the Software.
18
19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25SOFTWARE.
26
27*/
28
29#import "Universe.h"
30
31
32#if OO_LOCALIZATION_TOOLS
33
37#import "ResourceManager.h"
38
39static NSMutableDictionary *InitKeyToIndexDict(NSDictionary *dict, NSMutableSet **outUsedIndices);
40static NSString *IndexToKey(NSUInteger index, NSDictionary *indicesToKeys, BOOL useFallback);
41static NSArray *ConvertIndicesToKeys(NSArray *entry, NSDictionary *indicesToKeys);
42static NSNumber *KeyToIndex(NSString *key, NSMutableDictionary *ioKeysToIndices, NSMutableSet *ioUsedIndicies, NSUInteger *ioSlotCache);
43static NSArray *ConvertKeysToIndices(NSArray *entry, NSMutableDictionary *ioKeysToIndices, NSMutableSet *ioUsedIndicies, NSUInteger *ioSlotCache);
44static NSUInteger HighestIndex(NSMutableDictionary *sparseArray); // Actually returns highest index + 1, which is fine.
45
46
48{
49 NSDictionary *sysDescDict = nil;
50 NSArray *sysDescArray = nil;
51 NSDictionary *keyMap = nil;
52 NSData *data = nil;
53 NSString *error = nil;
54
55 sysDescDict = [ResourceManager dictionaryFromFilesNamed:@"sysdesc.plist"
56 inFolder:@"Config"
57 andMerge:NO];
58 if (sysDescDict == nil)
59 {
60 OOLog(@"sysdesc.compile.failed.fileNotFound", @"%@", @"Could not load a dictionary from sysdesc.plist, ignoring --compile-sysdesc option.");
61 return;
62 }
63
64 keyMap = [ResourceManager dictionaryFromFilesNamed:@"sysdesc_key_table.plist"
65 inFolder:@"Config"
66 andMerge:NO];
67 // keyMap is optional, so no nil check
68
69 sysDescArray = OOConvertSystemDescriptionsToArrayFormat(sysDescDict, keyMap);
70 if (sysDescArray == nil)
71 {
72 OOLog(@"sysdesc.compile.failed.conversion", @"%@", @"Could not convert sysdesc.plist to descriptions.plist format for some reason.");
73 return;
74 }
75
76 sysDescDict = [NSDictionary dictionaryWithObject:sysDescArray forKey:@"system_description"];
77
78 if (asXML)
79 {
80 data = [NSPropertyListSerialization dataFromPropertyList:sysDescDict
81 format:NSPropertyListXMLFormat_v1_0
82 errorDescription:&error];
83 }
84 else
85 {
86 data = [sysDescDict oldSchoolPListFormatWithErrorDescription:&error];
87 }
88
89 if (data == nil)
90 {
91 OOLog(@"sysdesc.compile.failed.XML", @"Could not convert translated sysdesc.plist to property list: %@.", error);
92 return;
93 }
94
95 if ([ResourceManager writeDiagnosticData:data toFileNamed:@"sysdesc-compiled.plist"])
96 {
97 OOLog(@"sysdesc.compile.success", @"%@", @"Wrote translated sysdesc.plist to sysdesc-compiled.plist.");
98 }
99 else
100 {
101 OOLog(@"sysdesc.compile.failed.writeFailure", @"%@", @"Could not write translated sysdesc.plist to sysdesc-compiled.plist.");
102 }
103}
104
105
107{
108 NSArray *sysDescArray = nil;
109 NSDictionary *sysDescDict = nil;
110 NSDictionary *keyMap = nil;
111 NSData *data = nil;
112 NSString *error = nil;
113
114 sysDescArray = [[UNIVERSE descriptions] oo_arrayForKey:@"system_description"];
115
116 keyMap = [ResourceManager dictionaryFromFilesNamed:@"sysdesc_key_table.plist"
117 inFolder:@"Config"
118 andMerge:NO];
119 // keyMap is optional, so no nil check
120
121 sysDescDict = OOConvertSystemDescriptionsToDictionaryFormat(sysDescArray, keyMap);
122 if (sysDescArray == nil)
123 {
124 OOLog(@"sysdesc.export.failed.conversion", @"%@", @"Could not convert system_description do sysdesc.plist format for some reason.");
125 return;
126 }
127
128 if (asXML)
129 {
130 data = [NSPropertyListSerialization dataFromPropertyList:sysDescDict
131 format:NSPropertyListXMLFormat_v1_0
132 errorDescription:&error];
133 }
134 else
135 {
136 data = [sysDescDict oldSchoolPListFormatWithErrorDescription:&error];
137 }
138
139 if (data == nil)
140 {
141 OOLog(@"sysdesc.export.failed.XML", @"Could not convert translated system_description to XML property list: %@.", error);
142 return;
143 }
144
145 if ([ResourceManager writeDiagnosticData:data toFileNamed:@"sysdesc.plist"])
146 {
147 OOLog(@"sysdesc.export.success", @"%@", @"Wrote translated system_description to sysdesc.plist.");
148 }
149 else
150 {
151 OOLog(@"sysdesc.export.failed.writeFailure", @"%@", @"Could not write translated system_description to sysdesc.plist.");
152 }
153}
154
155
156NSArray *OOConvertSystemDescriptionsToArrayFormat(NSDictionary *descriptionsInDictionaryFormat, NSDictionary *indicesToKeys)
157{
158 NSMutableDictionary *result = nil;
159 NSAutoreleasePool *pool = nil;
160 NSString *key = nil;
161 NSArray *entry = nil;
162 NSMutableDictionary *keysToIndices = nil;
163 NSMutableSet *usedIndices = nil;
164 NSUInteger slotCache = 0;
165 NSNumber *index = nil;
166 NSUInteger i, count;
167 NSMutableArray *realResult = nil;
168
169 pool = [[NSAutoreleasePool alloc] init];
170
171 // Use a dictionary as a sparse array.
172 result = [NSMutableDictionary dictionaryWithCapacity:[descriptionsInDictionaryFormat count]];
173
174 keysToIndices = InitKeyToIndexDict(indicesToKeys, &usedIndices);
175
176 foreachkey (key, descriptionsInDictionaryFormat)
177 {
178 entry = ConvertKeysToIndices([descriptionsInDictionaryFormat objectForKey:key], keysToIndices, usedIndices, &slotCache);
179 index = KeyToIndex(key, keysToIndices, usedIndices, &slotCache);
180
181 [result setObject:entry forKey:index];
182 }
183
184 count = HighestIndex(result);
185 realResult = [NSMutableArray arrayWithCapacity:count];
186 for (i = 0; i < count; i++)
187 {
188 entry = [result objectForKey:[NSNumber numberWithUnsignedInteger:i]];
189 if (entry == nil) entry = [NSArray array];
190 [realResult addObject:entry];
191 }
192
193 [realResult retain];
194 [pool release];
195 return [realResult autorelease];
196}
197
198
199NSDictionary *OOConvertSystemDescriptionsToDictionaryFormat(NSArray *descriptionsInArrayFormat, NSDictionary *indicesToKeys)
200{
201 NSMutableDictionary *result = nil;
202 NSAutoreleasePool *pool = nil;
203 NSArray *entry = nil;
204 NSString *key = nil;
205 NSUInteger i = 0;
206
207 result = [NSMutableDictionary dictionaryWithCapacity:[descriptionsInArrayFormat count]];
208 pool = [[NSAutoreleasePool alloc] init];
209
210 foreach (entry, descriptionsInArrayFormat)
211 {
212 entry = ConvertIndicesToKeys(entry, indicesToKeys);
213 key = IndexToKey(i, indicesToKeys, YES);
214 ++i;
215
216 [result setObject:entry forKey:key];
217 }
218
219 [pool release];
220 return result;
221}
222
223
224NSString *OOStringifySystemDescriptionLine(NSString *line, NSDictionary *indicesToKeys, BOOL useFallback)
225{
226 NSUInteger p1, p2;
227 NSRange searchRange;
228 NSString *before = nil, *after = nil, *middle = nil;
229 NSString *key = nil;
230
231 searchRange.location = 0;
232 searchRange.length = [line length];
233
234 while ([line rangeOfString:@"[" options:NSLiteralSearch range:searchRange].location != NSNotFound)
235 {
236 p1 = [line rangeOfString:@"[" options:NSLiteralSearch range:searchRange].location;
237 p2 = [line rangeOfString:@"]" options:NSLiteralSearch range:searchRange].location + 1;
238
239 before = [line substringWithRange:NSMakeRange(0, p1)];
240 after = [line substringWithRange:NSMakeRange(p2,[line length] - p2)];
241 middle = [line substringWithRange:NSMakeRange(p1 + 1 , p2 - p1 - 2)];
242
243 if ([[middle stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"0123456789"]] isEqual:@""] && ![middle isEqual:@""])
244 {
245 // Found [] around integers only
246 key = IndexToKey([middle intValue], indicesToKeys, useFallback);
247 if (key != nil)
248 {
249 line = [NSString stringWithFormat:@"%@[#%@]%@", before, key, after];
250 }
251 }
252
253 searchRange.length -= p2 - searchRange.location;
254 searchRange.location = [line length] - searchRange.length;
255 }
256 return line;
257}
258
259
260static NSMutableDictionary *InitKeyToIndexDict(NSDictionary *dict, NSMutableSet **outUsedIndices)
261{
262 NSString *key = nil;
263 NSNumber *number = nil;
264 NSMutableDictionary *result = nil;
265 NSMutableSet *used = nil;
266
267 assert(outUsedIndices != NULL);
268
269 result = [NSMutableDictionary dictionaryWithCapacity:[dict count]];
270 used = [NSMutableSet setWithCapacity:[dict count]];
271
272 foreachkey (key, dict)
273 {
274 // Convert keys of dict to array indices
275 number = [NSNumber numberWithInt:[key intValue]];
276 [result setObject:number forKey:[dict objectForKey:key]];
277 [used addObject:number];
278 }
279
280 *outUsedIndices = used;
281 return result;
282}
283
284
285static NSString *IndexToKey(NSUInteger index, NSDictionary *indicesToKeys, BOOL useFallback)
286{
287 NSString *result = [indicesToKeys objectForKey:[NSString stringWithFormat:@"%llu", index]];
288 if (result == nil && useFallback) result = [NSString stringWithFormat:@"block_%llu", index];
289
290 return result;
291}
292
293
294static NSArray *ConvertIndicesToKeys(NSArray *entry, NSDictionary *indicesToKeys)
295{
296 NSString *line = nil;
297 NSMutableArray *result = nil;
298
299 result = [NSMutableArray arrayWithCapacity:[entry count]];
300
301 foreach (line, entry)
302 {
303 [result addObject:OOStringifySystemDescriptionLine(line, indicesToKeys, YES)];
304 }
305
306 return result;
307}
308
309
310static NSNumber *KeyToIndex(NSString *key, NSMutableDictionary *ioKeysToIndices, NSMutableSet *ioUsedIndicies, NSUInteger *ioSlotCache)
311{
312 NSNumber *result = nil;
313
314 assert(ioSlotCache != NULL);
315
316 result = [ioKeysToIndices objectForKey:key];
317 if (result == nil)
318 {
319 // Search for free index
320 do
321 {
322 result = [NSNumber numberWithUnsignedInteger:(*ioSlotCache)++];
323 }
324 while ([ioUsedIndicies containsObject:result]);
325
326 [ioKeysToIndices setObject:result forKey:key];
327 [ioUsedIndicies addObject:result];
328 OOLog(@"sysdesc.compile.unknownKey", @"Assigning key \"%@\" to index %@.", key, result);
329 }
330
331 return result;
332}
333
334
335static NSArray *ConvertKeysToIndices(NSArray *entry, NSMutableDictionary *ioKeysToIndices, NSMutableSet *ioUsedIndicies, NSUInteger *ioSlotCache)
336{
337 NSString *line = nil;
338 NSUInteger p1, p2;
339 NSRange searchRange;
340 NSMutableArray *result = nil;
341 NSString *before = nil, *after = nil, *middle = nil;
342
343 result = [NSMutableArray arrayWithCapacity:[entry count]];
344
345 foreach (line, entry)
346 {
347 searchRange.location = 0;
348 searchRange.length = [line length];
349
350 while ([line rangeOfString:@"[" options:NSLiteralSearch range:searchRange].location != NSNotFound)
351 {
352 p1 = [line rangeOfString:@"[" options:NSLiteralSearch range:searchRange].location;
353 p2 = [line rangeOfString:@"]" options:NSLiteralSearch range:searchRange].location + 1;
354
355 before = [line substringWithRange:NSMakeRange(0, p1)];
356 after = [line substringWithRange:NSMakeRange(p2,[line length] - p2)];
357 middle = [line substringWithRange:NSMakeRange(p1 + 1 , p2 - p1 - 2)];
358
359 if ([middle length] > 1 && [middle hasPrefix:@"#"])
360 {
361 // Found [] around key
362 line = [NSString stringWithFormat:@"%@[%@]%@", before, KeyToIndex([middle substringFromIndex:1], ioKeysToIndices, ioUsedIndicies, ioSlotCache), after];
363 }
364
365 searchRange.length -= p2 - searchRange.location;
366 searchRange.location = [line length] - searchRange.length;
367 }
368
369 [result addObject:line];
370 }
371
372 return result;
373}
374
375
376static NSUInteger HighestIndex(NSMutableDictionary *sparseArray)
377{
378 NSNumber *key = nil;
379 NSUInteger curr, highest = 0;
380
381 foreachkey (key, sparseArray)
382 {
383 curr = [key intValue];
384 if (highest < curr) highest = curr;
385 }
386
387 return highest;
388}
389
390#endif
#define foreachkey(VAR, DICT)
Definition OOCocoa.h:353
static NSMutableDictionary * InitKeyToIndexDict(NSDictionary *dict, NSMutableSet **outUsedIndices)
static NSArray * ConvertKeysToIndices(NSArray *entry, NSMutableDictionary *ioKeysToIndices, NSMutableSet *ioUsedIndicies, NSUInteger *ioSlotCache)
static NSUInteger HighestIndex(NSMutableDictionary *sparseArray)
void CompileSystemDescriptions(BOOL asXML)
void ExportSystemDescriptions(BOOL asXML)
static NSNumber * KeyToIndex(NSString *key, NSMutableDictionary *ioKeysToIndices, NSMutableSet *ioUsedIndicies, NSUInteger *ioSlotCache)
static NSArray * ConvertIndicesToKeys(NSArray *entry, NSDictionary *indicesToKeys)
NSDictionary * OOConvertSystemDescriptionsToDictionaryFormat(NSArray *descriptionsInArrayFormat, NSDictionary *indicesToKeys)
NSString * OOStringifySystemDescriptionLine(NSString *line, NSDictionary *indicesToKeys, BOOL useFallback)
NSArray * OOConvertSystemDescriptionsToArrayFormat(NSDictionary *descriptionsInDictionaryFormat, NSDictionary *indicesToKeys)
static NSString * IndexToKey(NSUInteger index, NSDictionary *indicesToKeys, BOOL useFallback)
#define OOLog(class, format,...)
Definition OOLogging.h:88
unsigned count
return nil
NSDictionary * dictionaryFromFilesNamed:inFolder:andMerge:(NSString *fileName,[inFolder] NSString *folderName,[andMerge] BOOL mergeFiles)