Line data Source code
1 0 : /*
2 :
3 : OOConvertSystemDescriptions.m
4 : Oolite
5 :
6 :
7 : Copyright (C) 2008 Jens Ayton
8 :
9 : Permission is hereby granted, free of charge, to any person obtaining a copy
10 : of this software and associated documentation files (the "Software"), to deal
11 : in the Software without restriction, including without limitation the rights
12 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 : copies of the Software, and to permit persons to whom the Software is
14 : furnished to do so, subject to the following conditions:
15 :
16 : The above copyright notice and this permission notice shall be included in all
17 : copies or substantial portions of the Software.
18 :
19 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 : SOFTWARE.
26 :
27 : */
28 :
29 : #import "Universe.h"
30 :
31 :
32 : #if OO_LOCALIZATION_TOOLS
33 :
34 : #import "OOConvertSystemDescriptions.h"
35 : #import "OldSchoolPropertyListWriting.h"
36 : #import "OOCollectionExtractors.h"
37 : #import "ResourceManager.h"
38 :
39 : static NSMutableDictionary *InitKeyToIndexDict(NSDictionary *dict, NSMutableSet **outUsedIndices);
40 : static NSString *IndexToKey(NSUInteger index, NSDictionary *indicesToKeys, BOOL useFallback);
41 : static NSArray *ConvertIndicesToKeys(NSArray *entry, NSDictionary *indicesToKeys);
42 : static NSNumber *KeyToIndex(NSString *key, NSMutableDictionary *ioKeysToIndices, NSMutableSet *ioUsedIndicies, NSUInteger *ioSlotCache);
43 : static NSArray *ConvertKeysToIndices(NSArray *entry, NSMutableDictionary *ioKeysToIndices, NSMutableSet *ioUsedIndicies, NSUInteger *ioSlotCache);
44 : static NSUInteger HighestIndex(NSMutableDictionary *sparseArray); // Actually returns highest index + 1, which is fine.
45 :
46 :
47 0 : void CompileSystemDescriptions(BOOL asXML)
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 :
106 0 : void ExportSystemDescriptions(BOOL asXML)
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 :
156 0 : NSArray *OOConvertSystemDescriptionsToArrayFormat(NSDictionary *descriptionsInDictionaryFormat, NSDictionary *indicesToKeys)
157 : {
158 : NSMutableDictionary *result = nil;
159 : NSAutoreleasePool *pool = nil;
160 : NSString *key = nil;
161 : NSArray *entry = nil;
162 : NSEnumerator *keyEnum = nil;
163 : NSMutableDictionary *keysToIndices = nil;
164 : NSMutableSet *usedIndices = nil;
165 : NSUInteger slotCache = 0;
166 : NSNumber *index = nil;
167 : NSUInteger i, count;
168 : NSMutableArray *realResult = nil;
169 :
170 : pool = [[NSAutoreleasePool alloc] init];
171 :
172 : // Use a dictionary as a sparse array.
173 : result = [NSMutableDictionary dictionaryWithCapacity:[descriptionsInDictionaryFormat count]];
174 :
175 : keysToIndices = InitKeyToIndexDict(indicesToKeys, &usedIndices);
176 :
177 : for (keyEnum = [descriptionsInDictionaryFormat keyEnumerator]; (key = [keyEnum nextObject]); )
178 : {
179 : entry = ConvertKeysToIndices([descriptionsInDictionaryFormat objectForKey:key], keysToIndices, usedIndices, &slotCache);
180 : index = KeyToIndex(key, keysToIndices, usedIndices, &slotCache);
181 :
182 : [result setObject:entry forKey:index];
183 : }
184 :
185 : count = HighestIndex(result);
186 : realResult = [NSMutableArray arrayWithCapacity:count];
187 : for (i = 0; i < count; i++)
188 : {
189 : entry = [result objectForKey:[NSNumber numberWithUnsignedInteger:i]];
190 : if (entry == nil) entry = [NSArray array];
191 : [realResult addObject:entry];
192 : }
193 :
194 : [realResult retain];
195 : [pool release];
196 : return [realResult autorelease];
197 : }
198 :
199 :
200 0 : NSDictionary *OOConvertSystemDescriptionsToDictionaryFormat(NSArray *descriptionsInArrayFormat, NSDictionary *indicesToKeys)
201 : {
202 : NSMutableDictionary *result = nil;
203 : NSAutoreleasePool *pool = nil;
204 : NSArray *entry = nil;
205 : NSEnumerator *entryEnum = nil;
206 : NSString *key = nil;
207 : NSUInteger i = 0;
208 :
209 : result = [NSMutableDictionary dictionaryWithCapacity:[descriptionsInArrayFormat count]];
210 : pool = [[NSAutoreleasePool alloc] init];
211 :
212 : for (entryEnum = [descriptionsInArrayFormat objectEnumerator]; (entry = [entryEnum nextObject]); )
213 : {
214 : entry = ConvertIndicesToKeys(entry, indicesToKeys);
215 : key = IndexToKey(i, indicesToKeys, YES);
216 : ++i;
217 :
218 : [result setObject:entry forKey:key];
219 : }
220 :
221 : [pool release];
222 : return result;
223 : }
224 :
225 :
226 0 : NSString *OOStringifySystemDescriptionLine(NSString *line, NSDictionary *indicesToKeys, BOOL useFallback)
227 : {
228 : NSUInteger p1, p2;
229 : NSRange searchRange;
230 : NSString *before = nil, *after = nil, *middle = nil;
231 : NSString *key = nil;
232 :
233 : searchRange.location = 0;
234 : searchRange.length = [line length];
235 :
236 : while ([line rangeOfString:@"[" options:NSLiteralSearch range:searchRange].location != NSNotFound)
237 : {
238 : p1 = [line rangeOfString:@"[" options:NSLiteralSearch range:searchRange].location;
239 : p2 = [line rangeOfString:@"]" options:NSLiteralSearch range:searchRange].location + 1;
240 :
241 : before = [line substringWithRange:NSMakeRange(0, p1)];
242 : after = [line substringWithRange:NSMakeRange(p2,[line length] - p2)];
243 : middle = [line substringWithRange:NSMakeRange(p1 + 1 , p2 - p1 - 2)];
244 :
245 : if ([[middle stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"0123456789"]] isEqual:@""] && ![middle isEqual:@""])
246 : {
247 : // Found [] around integers only
248 : key = IndexToKey([middle intValue], indicesToKeys, useFallback);
249 : if (key != nil)
250 : {
251 : line = [NSString stringWithFormat:@"%@[#%@]%@", before, key, after];
252 : }
253 : }
254 :
255 : searchRange.length -= p2 - searchRange.location;
256 : searchRange.location = [line length] - searchRange.length;
257 : }
258 : return line;
259 : }
260 :
261 :
262 0 : static NSMutableDictionary *InitKeyToIndexDict(NSDictionary *dict, NSMutableSet **outUsedIndices)
263 : {
264 : NSEnumerator *keyEnum = nil;
265 : NSString *key = nil;
266 : NSNumber *number = nil;
267 : NSMutableDictionary *result = nil;
268 : NSMutableSet *used = nil;
269 :
270 : assert(outUsedIndices != NULL);
271 :
272 : result = [NSMutableDictionary dictionaryWithCapacity:[dict count]];
273 : used = [NSMutableSet setWithCapacity:[dict count]];
274 :
275 : for (keyEnum = [dict keyEnumerator]; (key = [keyEnum nextObject]); )
276 : {
277 : // Convert keys of dict to array indices
278 : number = [NSNumber numberWithInt:[key intValue]];
279 : [result setObject:number forKey:[dict objectForKey:key]];
280 : [used addObject:number];
281 : }
282 :
283 : *outUsedIndices = used;
284 : return result;
285 : }
286 :
287 :
288 0 : static NSString *IndexToKey(NSUInteger index, NSDictionary *indicesToKeys, BOOL useFallback)
289 : {
290 : NSString *result = [indicesToKeys objectForKey:[NSString stringWithFormat:@"%lu", index]];
291 : if (result == nil && useFallback) result = [NSString stringWithFormat:@"block_%lu", index];
292 :
293 : return result;
294 : }
295 :
296 :
297 0 : static NSArray *ConvertIndicesToKeys(NSArray *entry, NSDictionary *indicesToKeys)
298 : {
299 : NSEnumerator *lineEnum = nil;
300 : NSString *line = nil;
301 : NSMutableArray *result = nil;
302 :
303 : result = [NSMutableArray arrayWithCapacity:[entry count]];
304 :
305 : for (lineEnum = [entry objectEnumerator]; (line = [lineEnum nextObject]); )
306 : {
307 : [result addObject:OOStringifySystemDescriptionLine(line, indicesToKeys, YES)];
308 : }
309 :
310 : return result;
311 : }
312 :
313 :
314 0 : static NSNumber *KeyToIndex(NSString *key, NSMutableDictionary *ioKeysToIndices, NSMutableSet *ioUsedIndicies, NSUInteger *ioSlotCache)
315 : {
316 : NSNumber *result = nil;
317 :
318 : assert(ioSlotCache != NULL);
319 :
320 : result = [ioKeysToIndices objectForKey:key];
321 : if (result == nil)
322 : {
323 : // Search for free index
324 : do
325 : {
326 : result = [NSNumber numberWithUnsignedInteger:(*ioSlotCache)++];
327 : }
328 : while ([ioUsedIndicies containsObject:result]);
329 :
330 : [ioKeysToIndices setObject:result forKey:key];
331 : [ioUsedIndicies addObject:result];
332 : OOLog(@"sysdesc.compile.unknownKey", @"Assigning key \"%@\" to index %@.", key, result);
333 : }
334 :
335 : return result;
336 : }
337 :
338 :
339 0 : static NSArray *ConvertKeysToIndices(NSArray *entry, NSMutableDictionary *ioKeysToIndices, NSMutableSet *ioUsedIndicies, NSUInteger *ioSlotCache)
340 : {
341 : NSEnumerator *lineEnum = nil;
342 : NSString *line = nil;
343 : NSUInteger p1, p2;
344 : NSRange searchRange;
345 : NSMutableArray *result = nil;
346 : NSString *before = nil, *after = nil, *middle = nil;
347 :
348 : result = [NSMutableArray arrayWithCapacity:[entry count]];
349 :
350 : for (lineEnum = [entry objectEnumerator]; (line = [lineEnum nextObject]); )
351 : {
352 : searchRange.location = 0;
353 : searchRange.length = [line length];
354 :
355 : while ([line rangeOfString:@"[" options:NSLiteralSearch range:searchRange].location != NSNotFound)
356 : {
357 : p1 = [line rangeOfString:@"[" options:NSLiteralSearch range:searchRange].location;
358 : p2 = [line rangeOfString:@"]" options:NSLiteralSearch range:searchRange].location + 1;
359 :
360 : before = [line substringWithRange:NSMakeRange(0, p1)];
361 : after = [line substringWithRange:NSMakeRange(p2,[line length] - p2)];
362 : middle = [line substringWithRange:NSMakeRange(p1 + 1 , p2 - p1 - 2)];
363 :
364 : if ([middle length] > 1 && [middle hasPrefix:@"#"])
365 : {
366 : // Found [] around key
367 : line = [NSString stringWithFormat:@"%@[%@]%@", before, KeyToIndex([middle substringFromIndex:1], ioKeysToIndices, ioUsedIndicies, ioSlotCache), after];
368 : }
369 :
370 : searchRange.length -= p2 - searchRange.location;
371 : searchRange.location = [line length] - searchRange.length;
372 : }
373 :
374 : [result addObject:line];
375 : }
376 :
377 : return result;
378 : }
379 :
380 :
381 0 : static NSUInteger HighestIndex(NSMutableDictionary *sparseArray)
382 : {
383 : NSEnumerator *keyEnum = nil;
384 : NSNumber *key = nil;
385 : NSUInteger curr, highest = 0;
386 :
387 : for (keyEnum = [sparseArray keyEnumerator]; (key = [keyEnum nextObject]); )
388 : {
389 : curr = [key intValue];
390 : if (highest < curr) highest = curr;
391 : }
392 :
393 : return highest;
394 : }
395 :
396 : #endif
|