ObjFW  Diff

Differences From Artifact [15b00187cf]:

To Artifact [0671e3687a]:


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
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







-
+














-
+














-
+
















-
+













-
+







	@try {
		_HTTPClient = [[OFHTTPClient alloc] init];
		_HTTPClient.delegate = self;

		_uppercaseTableSize           = SIZE_MAX;
		_lowercaseTableSize           = SIZE_MAX;
		_titlecaseTableSize           = SIZE_MAX;
		_casefoldingTableSize         = SIZE_MAX;
		_caseFoldingTableSize         = SIZE_MAX;
		_decompositionTableSize       = SIZE_MAX;
		_decompositionCompatTableSize = SIZE_MAX;
	} @catch (id e) {
		@throw e;
		[self release];
	}

	return self;
}

- (void)applicationDidFinishLaunching
{
	OFHTTPRequest *request;

	[of_stdout writeString: @"Downloading UnicodeData.txt…"];
	[OFStdOut writeString: @"Downloading UnicodeData.txt…"];
	_state = STATE_UNICODE_DATA;
	request = [OFHTTPRequest requestWithURL:
	    [OFURL URLWithString: UNICODE_DATA_URL]];
	[_HTTPClient asyncPerformRequest: request];
}

-      (void)client: (OFHTTPClient *)client
  didPerformRequest: (OFHTTPRequest *)request
	   response: (OFHTTPResponse *)response
	  exception: (id)exception
{
	if (exception != nil)
		@throw exception;

	[of_stdout writeLine: @" done"];
	[OFStdOut writeLine: @" done"];

	switch (_state) {
	case STATE_UNICODE_DATA:
		[self parseUnicodeData: response];
		break;
	case STATE_CASE_FOLDING:
		[self parseCaseFolding: response];
		break;
	}
}

- (void)parseUnicodeData: (OFHTTPResponse *)response
{
	OFString *line;
	OFHTTPRequest *request;

	[of_stdout writeString: @"Parsing UnicodeData.txt…"];
	[OFStdOut writeString: @"Parsing UnicodeData.txt…"];

	while ((line = [response readLine]) != nil) {
		void *pool2;
		OFArray OF_GENERIC(OFString *) *components;
		OFUnichar codePoint;

		if (line.length == 0)
			continue;

		pool2 = objc_autoreleasePoolPush();

		components = [line componentsSeparatedByString: @";"];
		if (components.count != 15) {
			of_log(@"Invalid line: %@\n", line);
			OFLog(@"Invalid line: %@\n", line);
			[OFApplication terminateWithStatus: 1];
		}

		codePoint = (OFUnichar)[[components objectAtIndex: 0]
		    unsignedLongLongValueWithBase: 16];

		if (codePoint > 0x10FFFF)
160
161
162
163
164
165
166
167

168
169

170
171
172
173
174
175
176
177
178
179
180

181
182
183
184
185
186
187
188
189
190
191
192
193
194

195
196
197
198
199
200
201
202
203
204
205
206
207
208

209
210
211
212
213
214

215
216
217
218
219
220
221
160
161
162
163
164
165
166

167
168

169
170
171
172
173
174
175
176
177
178
179

180
181
182
183
184
185
186
187
188
189
190
191
192
193

194
195
196
197
198
199
200
201
202
203
204
205
206
207

208
209
210
211
212
213

214
215
216
217
218
219
220
221







-
+

-
+










-
+













-
+













-
+





-
+








		objc_autoreleasePoolPop(pool2);
	}

	[self applyDecompositionRecursivelyForTable: _decompositionTable];
	[self applyDecompositionRecursivelyForTable: _decompositionCompatTable];

	[of_stdout writeLine: @" done"];
	[OFStdOut writeLine: @" done"];

	[of_stdout writeString: @"Downloading CaseFolding.txt…"];
	[OFStdOut writeString: @"Downloading CaseFolding.txt…"];
	_state = STATE_CASE_FOLDING;
	request = [OFHTTPRequest requestWithURL:
	    [OFURL URLWithString: CASE_FOLDING_URL]];
	[_HTTPClient asyncPerformRequest: request];
}

- (void)parseCaseFolding: (OFHTTPResponse *)response
{
	OFString *line;

	[of_stdout writeString: @"Parsing CaseFolding.txt…"];
	[OFStdOut writeString: @"Parsing CaseFolding.txt…"];

	while ((line = [response readLine]) != nil) {
		void *pool2;
		OFArray OF_GENERIC(OFString *) *components;
		OFUnichar codePoint;

		if (line.length == 0 || [line hasPrefix: @"#"])
			continue;

		pool2 = objc_autoreleasePoolPush();

		components = [line componentsSeparatedByString: @"; "];
		if (components.count != 4) {
			of_log(@"Invalid line: %s\n", line);
			OFLog(@"Invalid line: %s\n", line);
			[OFApplication terminateWithStatus: 1];
		}

		if (![[components objectAtIndex: 1] isEqual: @"S"] &&
		    ![[components objectAtIndex: 1] isEqual: @"C"])
			continue;

		codePoint = (OFUnichar)[[components objectAtIndex: 0]
		    unsignedLongLongValueWithBase: 16];

		if (codePoint > 0x10FFFF)
			@throw [OFOutOfRangeException exception];

		_casefoldingTable[codePoint] = (OFUnichar)[[components
		_caseFoldingTable[codePoint] = (OFUnichar)[[components
		    objectAtIndex: 2] unsignedLongLongValueWithBase: 16];

		objc_autoreleasePoolPop(pool2);
	}

	[of_stdout writeLine: @" done"];
	[OFStdOut writeLine: @" done"];

	[self writeFiles];
}

- (void)applyDecompositionRecursivelyForTable: (OFString *[0x110000])table
{
	bool done;
268
269
270
271
272
273
274
275

276
277
278
279
280
281
282
283

284
285
286
287
288
289
290
268
269
270
271
272
273
274

275
276
277
278
279
280
281
282

283
284
285
286
287
288
289
290







-
+







-
+







	} while (!done);
}

- (void)writeFiles
{
	OFURL *URL;

	[of_stdout writeString: @"Writing files…"];
	[OFStdOut writeString: @"Writing files…"];

	URL = [OFURL fileURLWithPath: @"../../src/unicode.m"];
	[self writeTablesToFile: URL.fileSystemRepresentation];

	URL = [OFURL fileURLWithPath: @"../../src/unicode.h"];
	[self writeHeaderToFile: URL.fileSystemRepresentation];

	[of_stdout writeLine: @" done"];
	[OFStdOut writeLine: @" done"];

	[OFApplication terminate];
}

- (void)writeTablesToFile: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
412
413
414
415
416
417
418
419

420
421
422
423
424

425
426

427
428
429


430
431
432
433
434
435
436
437
438
439

440
441
442
443
444
445
446
447
448
449
450
451
452








453
454
455
456
457
458
459
412
413
414
415
416
417
418

419
420
421
422
423

424
425

426
427


428
429
430
431
432
433
434
435
436
437
438

439
440
441
442
443
444








445
446
447
448
449
450
451
452
453
454
455
456
457
458
459







-
+




-
+

-
+

-
-
+
+









-
+





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








			[file writeString: @"};\n\n"];

			objc_autoreleasePoolPop(pool2);
		}
	}

	/* Write casefoldingPage%u if it does NOT match lowercasePage%u */
	/* Write caseFoldingPage%u if it does NOT match lowercasePage%u */
	for (OFUnichar i = 0; i < 0x110000; i += 0x100) {
		bool isEmpty = true;

		for (OFUnichar j = i; j < i + 0x100; j++) {
			if (_casefoldingTable[j] != 0) {
			if (_caseFoldingTable[j] != 0) {
				isEmpty = !memcmp(_lowercaseTable + i,
				    _casefoldingTable + i,
				    _caseFoldingTable + i,
				    256 * sizeof(OFUnichar));
				_casefoldingTableSize = i >> 8;
				_casefoldingTableUsed[_casefoldingTableSize] =
				_caseFoldingTableSize = i >> 8;
				_caseFoldingTableUsed[_caseFoldingTableSize] =
				    (isEmpty ? 2 : 1);
				break;
			}
		}

		if (!isEmpty) {
			void *pool2 = objc_autoreleasePoolPush();

			[file writeFormat: @"static const OFUnichar "
					   @"casefoldingPage%u[0x100] = {\n",
					   @"caseFoldingPage%u[0x100] = {\n",
					   i >> 8];

			for (OFUnichar j = i; j < i + 0x100; j += 8)
				[file writeFormat:
				    @"\t%u, %u, %u, %u, %u, %u, %u, %u,\n",
				    _casefoldingTable[j],
				    _casefoldingTable[j + 1],
				    _casefoldingTable[j + 2],
				    _casefoldingTable[j + 3],
				    _casefoldingTable[j + 4],
				    _casefoldingTable[j + 5],
				    _casefoldingTable[j + 6],
				    _casefoldingTable[j + 7]];
				    _caseFoldingTable[j],
				    _caseFoldingTable[j + 1],
				    _caseFoldingTable[j + 2],
				    _caseFoldingTable[j + 3],
				    _caseFoldingTable[j + 4],
				    _caseFoldingTable[j + 5],
				    _caseFoldingTable[j + 6],
				    _caseFoldingTable[j + 7]];

			[file writeString: @"};\n\n"];

			objc_autoreleasePoolPop(pool2);
		}
	}

579
580
581
582
583
584
585
586

587
588
589
590

591
592

593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611

612
613

614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632

633
634

635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655

656
657
658


659
660
661
662
663




664
665
666
667
668

669
670
671
672
673
674
675
676
677
678

679
680

681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699

700
701

702
703
704
705
706
707
708
579
580
581
582
583
584
585

586
587
588
589

590
591

592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610

611
612

613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631

632
633

634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654

655
656


657
658
659




660
661
662
663
664
665
666
667

668
669
670
671
672
673
674
675
676
677

678
679

680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698

699
700

701
702
703
704
705
706
707
708







-
+



-
+

-
+


















-
+

-
+


















-
+

-
+




















-
+

-
-
+
+

-
-
-
-
+
+
+
+




-
+









-
+

-
+


















-
+

-
+







	/*
	 * Those are currently set to the last index.
	 * But from now on, we need the size.
	 */
	_uppercaseTableSize++;
	_lowercaseTableSize++;
	_titlecaseTableSize++;
	_casefoldingTableSize++;
	_caseFoldingTableSize++;
	_decompositionTableSize++;
	_decompositionCompatTableSize++;

	/* Write of_unicode_uppercase_table */
	/* Write OFUnicodeUppercaseTable */
	[file writeFormat: @"const OFUnichar *const "
			   @"of_unicode_uppercase_table[0x%X] = {\n\t",
			   @"OFUnicodeUppercaseTable[0x%X] = {\n\t",
			   _uppercaseTableSize];

	for (OFUnichar i = 0; i < _uppercaseTableSize; i++) {
		if (_uppercaseTableUsed[i])
			[file writeFormat: @"uppercasePage%u", i];
		else
			[file writeString: @"emptyPage"];

		if (i + 1 < _uppercaseTableSize) {
			if ((i + 1) % 4 == 0)
				[file writeString: @",\n\t"];
			else
				[file writeString: @", "];
		}
	}

	[file writeString: @"\n};\n\n"];

	/* Write of_unicode_lowercase_table */
	/* Write OFUnicodeLowercaseTable */
	[file writeFormat: @"const OFUnichar *const "
			   @"of_unicode_lowercase_table[0x%X] = {\n\t",
			   @"OFUnicodeLowercaseTable[0x%X] = {\n\t",
			   _lowercaseTableSize];

	for (OFUnichar i = 0; i < _lowercaseTableSize; i++) {
		if (_lowercaseTableUsed[i])
			[file writeFormat: @"lowercasePage%u", i];
		else
			[file writeString: @"emptyPage"];

		if (i + 1 < _lowercaseTableSize) {
			if ((i + 1) % 4 == 0)
				[file writeString: @",\n\t"];
			else
				[file writeString: @", "];
		}
	}

	[file writeString: @"\n};\n\n"];

	/* Write of_unicode_titlecase_table */
	/* Write OFUnicodeTitlecaseTable */
	[file writeFormat: @"const OFUnichar *const "
			   @"of_unicode_titlecase_table[0x%X] = {\n\t",
			   @"OFUnicodeTitlecaseTable[0x%X] = {\n\t",
			   _titlecaseTableSize];

	for (OFUnichar i = 0; i < _titlecaseTableSize; i++) {
		if (_titlecaseTableUsed[i] == 1)
			[file writeFormat: @"titlecasePage%u", i];
		else if (_titlecaseTableUsed[i] == 2)
			[file writeFormat: @"uppercasePage%u", i];
		else
			[file writeString: @"emptyPage"];

		if (i + 1 < _titlecaseTableSize) {
			if ((i + 1) % 4 == 0)
				[file writeString: @",\n\t"];
			else
				[file writeString: @", "];
		}
	}

	[file writeString: @"\n};\n\n"];

	/* Write of_unicode_casefolding_table */
	/* Write OFUnicodeCaseFoldingTable */
	[file writeFormat: @"const OFUnichar *const "
			   @"of_unicode_casefolding_table[0x%X] = {\n\t",
			   _casefoldingTableSize];
			   @"OFUnicodeCaseFoldingTable[0x%X] = {\n\t",
			   _caseFoldingTableSize];

	for (OFUnichar i = 0; i < _casefoldingTableSize; i++) {
		if (_casefoldingTableUsed[i] == 1)
			[file writeFormat: @"casefoldingPage%u", i];
		else if (_casefoldingTableUsed[i] == 2)
	for (OFUnichar i = 0; i < _caseFoldingTableSize; i++) {
		if (_caseFoldingTableUsed[i] == 1)
			[file writeFormat: @"caseFoldingPage%u", i];
		else if (_caseFoldingTableUsed[i] == 2)
			[file writeFormat: @"lowercasePage%u", i];
		else
			[file writeString: @"emptyPage"];

		if (i + 1 < _casefoldingTableSize) {
		if (i + 1 < _caseFoldingTableSize) {
			if ((i + 1) % 3 == 0)
				[file writeString: @",\n\t"];
			else
				[file writeString: @", "];
		}
	}

	[file writeString: @"\n};\n\n"];

	/* Write of_unicode_decomposition_table */
	/* Write OFUnicodeDecompositionTable */
	[file writeFormat: @"const char *const "
			   @"*of_unicode_decomposition_table[0x%X] = {\n\t",
			   @"*OFUnicodeDecompositionTable[0x%X] = {\n\t",
			   _decompositionTableSize];

	for (OFUnichar i = 0; i < _decompositionTableSize; i++) {
		if (_decompositionTableUsed[i])
			[file writeFormat: @"decompositionPage%u", i];
		else
			[file writeString: @"emptyDecompositionPage"];

		if (i + 1 < _decompositionTableSize) {
			if ((i + 1) % 3 == 0)
				[file writeString: @",\n\t"];
			else
				[file writeString: @", "];
		}
	}

	[file writeString: @"\n};\n\n"];

	/* Write of_unicode_decomposition_compat_table */
	/* Write OFUnicodeDecompositionCompatTable */
	[file writeFormat: @"const char *const "
			   @"*of_unicode_decomposition_compat_table[0x%X] = {"
			   @"*OFUnicodeDecompositionCompatTable[0x%X] = {"
			   @"\n\t",
			   _decompositionCompatTableSize];

	for (OFUnichar i = 0; i < _decompositionCompatTableSize; i++) {
		if (_decompositionCompatTableUsed[i] == 1)
			[file writeFormat: @"decompCompatPage%u", i];
		else if (_decompositionCompatTableUsed[i] == 2)
729
730
731
732
733
734
735
736
737
738
739
740
741






742
743

744
745
746
747
748
749
750
751

752
753
754

755
756
757

758
759
760

761
762
763
764


765
766

767

768
769
770
771
772
773
774
729
730
731
732
733
734
735






736
737
738
739
740
741
742

743
744
745
746
747
748
749
750

751

752

753

754

755

756

757

758


759
760
761

762

763
764
765
766
767
768
769
770







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

-
+







-
+
-

-
+
-

-
+
-

-
+
-

-
-
+
+

-
+
-
+







	OFFile *file = [OFFile fileWithPath: path
				       mode: @"w"];

	[file writeString: COPYRIGHT
	    @"#import \"OFString.h\"\n\n"];

	[file writeFormat:
	    @"#define OF_UNICODE_UPPERCASE_TABLE_SIZE 0x%X\n"
	    @"#define OF_UNICODE_LOWERCASE_TABLE_SIZE 0x%X\n"
	    @"#define OF_UNICODE_TITLECASE_TABLE_SIZE 0x%X\n"
	    @"#define OF_UNICODE_CASEFOLDING_TABLE_SIZE 0x%X\n"
	    @"#define OF_UNICODE_DECOMPOSITION_TABLE_SIZE 0x%X\n"
	    @"#define OF_UNICODE_DECOMPOSITION_COMPAT_TABLE_SIZE 0x%X\n\n",
	    @"#define OFUnicodeUppercaseTableSize 0x%X\n"
	    @"#define OFUnicodeLowercaseTableSize 0x%X\n"
	    @"#define OFUnicodeTitlecaseTableSize 0x%X\n"
	    @"#define OFUnicodeCaseFoldingTableSize 0x%X\n"
	    @"#define OFUnicodeDecompositionTableSize 0x%X\n"
	    @"#define OFUnicodeDecompositionCompatTableSize 0x%X\n\n",
	    _uppercaseTableSize, _lowercaseTableSize, _titlecaseTableSize,
	    _casefoldingTableSize, _decompositionTableSize,
	    _caseFoldingTableSize, _decompositionTableSize,
	    _decompositionCompatTableSize];

	[file writeString:
	    @"#ifdef __cplusplus\n"
	    @"extern \"C\" {\n"
	    @"#endif\n"
	    @"extern const OFUnichar *const _Nonnull\n"
	    @"    of_unicode_uppercase_table["
	    @"    OFUnicodeUppercaseTable[OFUnicodeUppercaseTableSize];\n"
	    @"OF_UNICODE_UPPERCASE_TABLE_SIZE];\n"
	    @"extern const OFUnichar *const _Nonnull\n"
	    @"    of_unicode_lowercase_table["
	    @"    OFUnicodeLowercaseTable[OFUnicodeLowercaseTableSize];\n"
	    @"OF_UNICODE_LOWERCASE_TABLE_SIZE];\n"
	    @"extern const OFUnichar *const _Nonnull\n"
	    @"    of_unicode_titlecase_table["
	    @"    OFUnicodeTitlecaseTable[OFUnicodeTitlecaseTableSize];\n"
	    @"OF_UNICODE_TITLECASE_TABLE_SIZE];\n"
	    @"extern const OFUnichar *const _Nonnull\n"
	    @"    of_unicode_casefolding_table["
	    @"    OFUnicodeCaseFoldingTable[OFUnicodeCaseFoldingTableSize];\n"
	    @"OF_UNICODE_CASEFOLDING_TABLE_SIZE];\n"
	    @"extern const char *const _Nullable *const _Nonnull\n"
	    @"    of_unicode_decomposition_table["
	    @"OF_UNICODE_DECOMPOSITION_TABLE_SIZE];\n"
	    @"    OFUnicodeDecompositionTable["
	    @"OFUnicodeDecompositionTableSize];\n"
	    @"extern const char *const _Nullable *const _Nonnull\n"
	    @"    of_unicode_decomposition_compat_table["
	    @"    OFUnicodeDecompositionCompatTable["
	    @"OF_UNICODE_DECOMPOSITION_COMPAT_TABLE_SIZE];\n"
	    @"OFUnicodeDecompositionCompatTableSize];\n"
	    @"#ifdef __cplusplus\n"
	    @"}\n"
	    @"#endif\n"];

	objc_autoreleasePoolPop(pool);
}
@end