ObjFW  Diff

Differences From Artifact [36d525a782]:

To Artifact [af7c460737]:


23
24
25
26
27
28
29

30
31
32
33
34
35
36
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37







+







#import "OFString.h"
#import "OFArray.h"
#import "OFDictionary.h"

#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFInvalidEncodingException.h"
#import "OFInvalidFormatException.h"
#import "OFOpenItemFailedException.h"

#ifdef OF_AMIGAOS
# include <proto/dos.h>
# include <proto/exec.h>
# include <proto/locale.h>
#endif
79
80
81
82
83
84
85























































86
87
88
89
90
91
92
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







			*language = [OFString stringWithCString: locale
						       encoding: enc];
	} @finally {
		free(locale);
	}
}
#endif

static OFString *
evaluateDictionary(OFDictionary *dictionary, OFDictionary *variables)
{
	OFEnumerator *keyEnumerator = [dictionary keyEnumerator];
	OFEnumerator *objectEnumerator = [dictionary objectEnumerator];
	OFString *key;
	id object;

	while ((key = [keyEnumerator nextObject]) != nil &&
	    (object = [objectEnumerator nextObject]) != nil) {
		OFString *var, *expected;
		size_t pos;

		if (![key isKindOfClass: [OFString class]] ||
		    ![object isKindOfClass: [OFString class]])
			@throw [OFInvalidFormatException exception];

		if (key.length == 0)
			continue;

		pos = [key rangeOfString: @"="].location;
		if (pos == OF_NOT_FOUND)
			@throw [OFInvalidFormatException exception];

		var = [key substringWithRange: of_range(0, pos)];
		expected = [key substringWithRange:
		    of_range(pos + 1, key.length - pos - 1)];

		if ([[variables objectForKey: var] isEqual: expected])
			return object;
	}

	return [dictionary objectForKey: @""];
}

static OFString *
evaluateArray(OFArray *array, OFDictionary *variables)
{
	OFMutableString *string = [OFMutableString string];

	for (id object in array) {
		if ([object isKindOfClass: [OFString class]])
			[string appendString: object];
		else if ([object isKindOfClass: [OFDictionary class]])
			[string appendString:
			    evaluateDictionary(object, variables)];
		else
			@throw [OFInvalidFormatException exception];
	}

	[string makeImmutable];

	return string;
}

@implementation OFLocale
@synthesize language = _language, territory = _territory, encoding = _encoding;
@synthesize decimalPoint = _decimalPoint;

+ (OFLocale *)currentLocale
{
311
312
313
314
315
316
317


318
319
320





321
322
323
324
325
326
327
328
329

330
331
332
333
334
335
336
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391

392
393
394
395
396
397
398
399







+
+



+
+
+
+
+








-
+








- (OFString *)localizedStringForID: (OFConstantString *)ID
			  fallback: (OFConstantString *)fallback
			 arguments: (va_list)arguments
{
	OFMutableString *ret = [OFMutableString string];
	void *pool = objc_autoreleasePoolPush();
	OFMutableDictionary *variables;
	OFConstantString *name;
	const char *UTF8String = NULL;
	size_t last, UTF8StringLength;
	int state = 0;

	variables = [OFMutableDictionary dictionary];
	while ((name = va_arg(arguments, OFConstantString *)) != nil)
		[variables setObject: [va_arg(arguments, id) description]
			      forKey: name];

	for (OFDictionary *strings in _localizedStrings) {
		id string = [strings objectForKey: ID];

		if (string == nil)
			continue;

		if ([string isKindOfClass: [OFArray class]])
			string = [string componentsJoinedByString: @""];
			string = evaluateArray(string, variables);

		UTF8String = [string UTF8String];
		UTF8StringLength = [string UTF8StringLength];
		break;
	}

	if (UTF8String == NULL) {
358
359
360
361
362
363
364
365
366
367
368
369
370
371

372
373
374
375
376
377
378
379
380
381
382

383
384
385
386
387
388

389
390
391
392
393
394
395
396
397
398
399
421
422
423
424
425
426
427



428
429
430

431









432

433






434




435
436
437
438
439
440
441







-
-
-



-
+
-
-
-
-
-
-
-
-
-

-
+
-
-
-
-
-
-
+
-
-
-
-







			} else {
				[ret appendString: @"%"];
				state = 0;
			}
			break;
		case 2:
			if (UTF8String[i] == ']') {
				va_list argsCopy;
				OFConstantString *name;

				OFString *var = [OFString
				    stringWithUTF8String: UTF8String + last
						  length: i - last];

				OFString *value = [variables objectForKey: var];
				/*
				 * We loop, as most of the time, we only have
				 * one or maybe two variables, meaning looping
				 * is faster than constructing a dictionary.
				 */
				va_copy(argsCopy, arguments);
				while ((name = va_arg(argsCopy,
				    OFConstantString *)) != nil) {
					id value = va_arg(argsCopy, id);

					if (value == nil)
				if (value != nil)
						@throw
						    [OFInvalidArgumentException
						    exception];

					if ([name isEqual: var]) {
						[ret appendString:
					[ret appendString: value];
						    [value description]];
						break;
					}
				}

				last = i + 1;
				state = 0;
			}
			break;
		}
	}