ObjFW  Diff

Differences From Artifact [961145e2e1]:

To Artifact [fc310b0712]:


183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)OF_initWithUTF8String: (const char*)UTF8String
			       length: (size_t)UTF8StringLength
			      storage: (char*)storage
{
	self = [super init];

	@try {
		if (UTF8StringLength >= 3 &&
		    memcmp(UTF8String, "\xEF\xBB\xBF", 3) == 0) {
			UTF8String += 3;







|

|







183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
		[self release];
		@throw e;
	}

	return self;
}

- (instancetype)OF_initWithUTF8String: (const char *)UTF8String
			       length: (size_t)UTF8StringLength
			      storage: (char *)storage
{
	self = [super init];

	@try {
		if (UTF8StringLength >= 3 &&
		    memcmp(UTF8String, "\xEF\xBB\xBF", 3) == 0) {
			UTF8String += 3;
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
		[self release];
		@throw e;
	}

	return self;
}

- initWithCString: (const char*)cString
	 encoding: (of_string_encoding_t)encoding
	   length: (size_t)cStringLength
{
	self = [super init];

	@try {
		const of_char16_t *table;







|







220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
		[self release];
		@throw e;
	}

	return self;
}

- initWithCString: (const char *)cString
	 encoding: (of_string_encoding_t)encoding
	   length: (size_t)cStringLength
{
	self = [super init];

	@try {
		const of_char16_t *table;
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
		[self release];
		@throw e;
	}

	return self;
}

- initWithUTF8StringNoCopy: (char*)UTF8String
	      freeWhenDone: (bool)freeWhenDone
{
	self = [super init];

	@try {
		size_t UTF8StringLength = strlen(UTF8String);

		if (UTF8StringLength >= 3 &&
		    memcmp(UTF8String, "\xEF\xBB\xBF", 3) == 0) {
			UTF8String += 3;
			UTF8StringLength -= 3;
		}

		_s = &_storage;

		_s->cString = (char*)UTF8String;
		_s->cStringLength = UTF8StringLength;

		if (freeWhenDone)
			_s->freeWhenDone = UTF8String;

		switch (of_string_utf8_check(UTF8String, UTF8StringLength,
		    &_s->length)) {







|















|







384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
		[self release];
		@throw e;
	}

	return self;
}

- initWithUTF8StringNoCopy: (char *)UTF8String
	      freeWhenDone: (bool)freeWhenDone
{
	self = [super init];

	@try {
		size_t UTF8StringLength = strlen(UTF8String);

		if (UTF8StringLength >= 3 &&
		    memcmp(UTF8String, "\xEF\xBB\xBF", 3) == 0) {
			UTF8String += 3;
			UTF8StringLength -= 3;
		}

		_s = &_storage;

		_s->cString = (char *)UTF8String;
		_s->cStringLength = UTF8StringLength;

		if (freeWhenDone)
			_s->freeWhenDone = UTF8String;

		switch (of_string_utf8_check(UTF8String, UTF8StringLength,
		    &_s->length)) {
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
460
461
462
463
		[self release];
		@throw e;
	}

	return self;
}

- initWithString: (OFString*)string
{
	self = [super init];

	@try {
		_s = &_storage;

		_s->cStringLength = [string UTF8StringLength];

		if ([string isKindOfClass: [OFString_UTF8 class]] ||
		    [string isKindOfClass: [OFMutableString_UTF8 class]])
			_s->isUTF8 = ((OFString_UTF8*)string)->_s->isUTF8;
		else
			_s->isUTF8 = true;

		_s->length = [string length];

		_s->cString = [self allocMemoryWithSize: _s->cStringLength + 1];
		memcpy(_s->cString, [string UTF8String], _s->cStringLength + 1);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- initWithCharacters: (const of_unichar_t*)characters
	      length: (size_t)length
{
	self = [super init];

	@try {
		size_t j;








|










|















|







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
460
461
462
463
		[self release];
		@throw e;
	}

	return self;
}

- initWithString: (OFString *)string
{
	self = [super init];

	@try {
		_s = &_storage;

		_s->cStringLength = [string UTF8StringLength];

		if ([string isKindOfClass: [OFString_UTF8 class]] ||
		    [string isKindOfClass: [OFMutableString_UTF8 class]])
			_s->isUTF8 = ((OFString_UTF8 *)string)->_s->isUTF8;
		else
			_s->isUTF8 = true;

		_s->length = [string length];

		_s->cString = [self allocMemoryWithSize: _s->cStringLength + 1];
		memcpy(_s->cString, [string UTF8String], _s->cStringLength + 1);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- initWithCharacters: (const of_unichar_t *)characters
	      length: (size_t)length
{
	self = [super init];

	@try {
		size_t j;

493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
		[self release];
		@throw e;
	}

	return self;
}

- initWithUTF16String: (const of_char16_t*)string
	       length: (size_t)length
	    byteOrder: (of_byte_order_t)byteOrder
{
	self = [super init];

	@try {
		size_t j;







|







493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
		[self release];
		@throw e;
	}

	return self;
}

- initWithUTF16String: (const of_char16_t *)string
	       length: (size_t)length
	    byteOrder: (of_byte_order_t)byteOrder
{
	self = [super init];

	@try {
		size_t j;
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
		[self release];
		@throw e;
	}

	return self;
}

- initWithUTF32String: (const of_char32_t*)characters
	       length: (size_t)length
	    byteOrder: (of_byte_order_t)byteOrder
{
	self = [super init];

	@try {
		size_t j;







|







578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
		[self release];
		@throw e;
	}

	return self;
}

- initWithUTF32String: (const of_char32_t *)characters
	       length: (size_t)length
	    byteOrder: (of_byte_order_t)byteOrder
{
	self = [super init];

	@try {
		size_t j;
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
		[self release];
		@throw e;
	}

	return self;
}

- initWithFormat: (OFConstantString*)format
       arguments: (va_list)arguments
{
	self = [super init];

	@try {
		char *tmp;
		int cStringLength;







|







645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
		[self release];
		@throw e;
	}

	return self;
}

- initWithFormat: (OFConstantString *)format
       arguments: (va_list)arguments
{
	self = [super init];

	@try {
		char *tmp;
		int cStringLength;
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
{
	if (_s != NULL && _s->freeWhenDone != NULL)
		free(_s->freeWhenDone);

	[super dealloc];
}

- (size_t)getCString: (char*)cString
	   maxLength: (size_t)maxLength
	    encoding: (of_string_encoding_t)encoding
{
	switch (encoding) {
	case OF_STRING_ENCODING_ASCII:
		if (_s->isUTF8)
			@throw [OFInvalidEncodingException exception];







|







697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
{
	if (_s != NULL && _s->freeWhenDone != NULL)
		free(_s->freeWhenDone);

	[super dealloc];
}

- (size_t)getCString: (char *)cString
	   maxLength: (size_t)maxLength
	    encoding: (of_string_encoding_t)encoding
{
	switch (encoding) {
	case OF_STRING_ENCODING_ASCII:
		if (_s->isUTF8)
			@throw [OFInvalidEncodingException exception];
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
	default:
		return [super getCString: cString
			       maxLength: maxLength
				encoding: encoding];
	}
}

- (const char*)cStringWithEncoding: (of_string_encoding_t)encoding
{
	switch (encoding) {
	case OF_STRING_ENCODING_ASCII:
		if (_s->isUTF8)
			@throw [OFInvalidEncodingException exception];
		/* intentional fall-through */
	case OF_STRING_ENCODING_UTF_8:
		return _s->cString;
	default:
		return [super cStringWithEncoding: encoding];
	}
}

- (const char*)UTF8String
{
	return _s->cString;
}

- (size_t)length
{
	return _s->length;







|













|







720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
	default:
		return [super getCString: cString
			       maxLength: maxLength
				encoding: encoding];
	}
}

- (const char *)cStringWithEncoding: (of_string_encoding_t)encoding
{
	switch (encoding) {
	case OF_STRING_ENCODING_ASCII:
		if (_s->isUTF8)
			@throw [OFInvalidEncodingException exception];
		/* intentional fall-through */
	case OF_STRING_ENCODING_UTF_8:
		return _s->cString;
	default:
		return [super cStringWithEncoding: encoding];
	}
}

- (const char *)UTF8String
{
	return _s->cString;
}

- (size_t)length
{
	return _s->length;
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834

	if (object == self)
		return OF_ORDERED_SAME;

	if (![object isKindOfClass: [OFString class]])
		@throw [OFInvalidArgumentException exception];

	otherString = (OFString*)object;
	otherCStringLength = [otherString UTF8StringLength];
	minimumCStringLength = (_s->cStringLength > otherCStringLength
	    ? otherCStringLength : _s->cStringLength);

	if ((compare = memcmp(_s->cString, [otherString UTF8String],
	    minimumCStringLength)) == 0) {
		if (_s->cStringLength > otherCStringLength)
			return OF_ORDERED_DESCENDING;
		if (_s->cStringLength < otherCStringLength)
			return OF_ORDERED_ASCENDING;
		return OF_ORDERED_SAME;
	}

	if (compare > 0)
		return OF_ORDERED_DESCENDING;
	else
		return OF_ORDERED_ASCENDING;
}

- (of_comparison_result_t)caseInsensitiveCompare: (OFString*)otherString
{
	const char *otherCString;
	size_t otherCStringLength, minimumCStringLength;
#ifdef OF_HAVE_UNICODE_TABLES
	size_t i, j;
#endif
	int compare;







|



















|







800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834

	if (object == self)
		return OF_ORDERED_SAME;

	if (![object isKindOfClass: [OFString class]])
		@throw [OFInvalidArgumentException exception];

	otherString = (OFString *)object;
	otherCStringLength = [otherString UTF8StringLength];
	minimumCStringLength = (_s->cStringLength > otherCStringLength
	    ? otherCStringLength : _s->cStringLength);

	if ((compare = memcmp(_s->cString, [otherString UTF8String],
	    minimumCStringLength)) == 0) {
		if (_s->cStringLength > otherCStringLength)
			return OF_ORDERED_DESCENDING;
		if (_s->cStringLength < otherCStringLength)
			return OF_ORDERED_ASCENDING;
		return OF_ORDERED_SAME;
	}

	if (compare > 0)
		return OF_ORDERED_DESCENDING;
	else
		return OF_ORDERED_ASCENDING;
}

- (of_comparison_result_t)caseInsensitiveCompare: (OFString *)otherString
{
	const char *otherCString;
	size_t otherCStringLength, minimumCStringLength;
#ifdef OF_HAVE_UNICODE_TABLES
	size_t i, j;
#endif
	int compare;
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
	if (of_string_utf8_decode(_s->cString + index,
	    _s->cStringLength - index, &character) <= 0)
		@throw [OFInvalidEncodingException exception];

	return character;
}

- (void)getCharacters: (of_unichar_t*)buffer
	      inRange: (of_range_t)range
{
	/* TODO: Could be slightly optimized */
	void *pool = objc_autoreleasePoolPush();
	const of_unichar_t *characters = [self characters];

	if (range.length > SIZE_MAX - range.location ||
	    range.location + range.length > _s->length)
		@throw [OFOutOfRangeException exception];

	memcpy(buffer, characters + range.location,
	    range.length * sizeof(of_unichar_t));

	objc_autoreleasePoolPop(pool);
}

- (of_range_t)rangeOfString: (OFString*)string
		    options: (int)options
		      range: (of_range_t)range
{
	const char *cString = [string UTF8String];
	size_t cStringLength = [string UTF8StringLength];
	size_t rangeLocation, rangeLength;








|
















|







960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
	if (of_string_utf8_decode(_s->cString + index,
	    _s->cStringLength - index, &character) <= 0)
		@throw [OFInvalidEncodingException exception];

	return character;
}

- (void)getCharacters: (of_unichar_t *)buffer
	      inRange: (of_range_t)range
{
	/* TODO: Could be slightly optimized */
	void *pool = objc_autoreleasePoolPush();
	const of_unichar_t *characters = [self characters];

	if (range.length > SIZE_MAX - range.location ||
	    range.location + range.length > _s->length)
		@throw [OFOutOfRangeException exception];

	memcpy(buffer, characters + range.location,
	    range.length * sizeof(of_unichar_t));

	objc_autoreleasePoolPop(pool);
}

- (of_range_t)rangeOfString: (OFString *)string
		    options: (int)options
		      range: (of_range_t)range
{
	const char *cString = [string UTF8String];
	size_t cStringLength = [string UTF8StringLength];
	size_t rangeLocation, rangeLength;

1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
			}
		}
	}

	return of_range(OF_NOT_FOUND, 0);
}

- (bool)containsString: (OFString*)string
{
	const char *cString = [string UTF8String];
	size_t cStringLength = [string UTF8StringLength];

	if (cStringLength == 0)
		return true;

	if (cStringLength > _s->cStringLength)
		return false;

	for (size_t i = 0; i <= _s->cStringLength - cStringLength; i++)
		if (memcmp(_s->cString + i, cString, cStringLength) == 0)
			return true;

	return false;
}

- (OFString*)substringWithRange: (of_range_t)range
{
	size_t start = range.location;
	size_t end = range.location + range.length;

	if (range.length > SIZE_MAX - range.location || end > _s->length)
		@throw [OFOutOfRangeException exception];

	if (_s->isUTF8) {
		start = of_string_utf8_get_position(_s->cString, start,
		    _s->cStringLength);
		end = of_string_utf8_get_position(_s->cString, end,
		    _s->cStringLength);
	}

	return [OFString stringWithUTF8String: _s->cString + start
				       length: end - start];
}

- (bool)hasPrefix: (OFString*)prefix
{
	size_t cStringLength = [prefix UTF8StringLength];

	if (cStringLength > _s->cStringLength)
		return false;

	return (memcmp(_s->cString, [prefix UTF8String], cStringLength) == 0);
}

- (bool)hasSuffix: (OFString*)suffix
{
	size_t cStringLength = [suffix UTF8StringLength];

	if (cStringLength > _s->cStringLength)
		return false;

	return (memcmp(_s->cString + (_s->cStringLength - cStringLength),
	    [suffix UTF8String], cStringLength) == 0);
}

- (OFArray*)componentsSeparatedByString: (OFString*)delimiter
				options: (int)options
{
	void *pool;
	OFMutableArray *array;
	const char *cString = [delimiter UTF8String];
	size_t cStringLength = [delimiter UTF8StringLength];
	bool skipEmpty = (options & OF_STRING_SKIP_EMPTY);
	size_t last;







|

















|


















|









|










|
|







1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
			}
		}
	}

	return of_range(OF_NOT_FOUND, 0);
}

- (bool)containsString: (OFString *)string
{
	const char *cString = [string UTF8String];
	size_t cStringLength = [string UTF8StringLength];

	if (cStringLength == 0)
		return true;

	if (cStringLength > _s->cStringLength)
		return false;

	for (size_t i = 0; i <= _s->cStringLength - cStringLength; i++)
		if (memcmp(_s->cString + i, cString, cStringLength) == 0)
			return true;

	return false;
}

- (OFString *)substringWithRange: (of_range_t)range
{
	size_t start = range.location;
	size_t end = range.location + range.length;

	if (range.length > SIZE_MAX - range.location || end > _s->length)
		@throw [OFOutOfRangeException exception];

	if (_s->isUTF8) {
		start = of_string_utf8_get_position(_s->cString, start,
		    _s->cStringLength);
		end = of_string_utf8_get_position(_s->cString, end,
		    _s->cStringLength);
	}

	return [OFString stringWithUTF8String: _s->cString + start
				       length: end - start];
}

- (bool)hasPrefix: (OFString *)prefix
{
	size_t cStringLength = [prefix UTF8StringLength];

	if (cStringLength > _s->cStringLength)
		return false;

	return (memcmp(_s->cString, [prefix UTF8String], cStringLength) == 0);
}

- (bool)hasSuffix: (OFString *)suffix
{
	size_t cStringLength = [suffix UTF8StringLength];

	if (cStringLength > _s->cStringLength)
		return false;

	return (memcmp(_s->cString + (_s->cStringLength - cStringLength),
	    [suffix UTF8String], cStringLength) == 0);
}

- (OFArray *)componentsSeparatedByString: (OFString *)delimiter
				 options: (int)options
{
	void *pool;
	OFMutableArray *array;
	const char *cString = [delimiter UTF8String];
	size_t cStringLength = [delimiter UTF8StringLength];
	bool skipEmpty = (options & OF_STRING_SKIP_EMPTY);
	size_t last;
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
	[array makeImmutable];

	objc_autoreleasePoolPop(pool);

	return array;
}

- (OFArray*)pathComponents
{
	OFMutableArray *ret;
	void *pool;
	size_t i, last = 0, pathCStringLength = _s->cStringLength;

	ret = [OFMutableArray array];








|







1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
	[array makeImmutable];

	objc_autoreleasePoolPop(pool);

	return array;
}

- (OFArray *)pathComponents
{
	OFMutableArray *ret;
	void *pool;
	size_t i, last = 0, pathCStringLength = _s->cStringLength;

	ret = [OFMutableArray array];

1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
	[ret makeImmutable];

	objc_autoreleasePoolPop(pool);

	return ret;
}

- (OFString*)lastPathComponent
{
	size_t pathCStringLength = _s->cStringLength;
	ssize_t i;

	if (pathCStringLength == 0)
		return @"";








|







1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
	[ret makeImmutable];

	objc_autoreleasePoolPop(pool);

	return ret;
}

- (OFString *)lastPathComponent
{
	size_t pathCStringLength = _s->cStringLength;
	ssize_t i;

	if (pathCStringLength == 0)
		return @"";

1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
	if (i < 0)
		i = 0;

	return [OFString stringWithUTF8String: _s->cString + i
				       length: pathCStringLength - i];
}

- (OFString*)stringByDeletingLastPathComponent
{
	size_t pathCStringLength = _s->cStringLength;

	if (pathCStringLength == 0)
		return @"";

	if (OF_IS_PATH_DELIMITER(_s->cString[pathCStringLength - 1]))







|







1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
	if (i < 0)
		i = 0;

	return [OFString stringWithUTF8String: _s->cString + i
				       length: pathCStringLength - i];
}

- (OFString *)stringByDeletingLastPathComponent
{
	size_t pathCStringLength = _s->cStringLength;

	if (pathCStringLength == 0)
		return @"";

	if (OF_IS_PATH_DELIMITER(_s->cString[pathCStringLength - 1]))
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
	if (OF_IS_PATH_DELIMITER(_s->cString[0]))
		return [OFString stringWithUTF8String: _s->cString
					       length: 1];

	return OF_PATH_CURRENT_DIRECTORY;
}

- (const of_unichar_t*)characters
{
	OFObject *object = [[[OFObject alloc] init] autorelease];
	of_unichar_t *ret;
	size_t i, j;

	ret = [object allocMemoryWithSize: sizeof(of_unichar_t)
				    count: _s->length];







|







1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
	if (OF_IS_PATH_DELIMITER(_s->cString[0]))
		return [OFString stringWithUTF8String: _s->cString
					       length: 1];

	return OF_PATH_CURRENT_DIRECTORY;
}

- (const of_unichar_t *)characters
{
	OFObject *object = [[[OFObject alloc] init] autorelease];
	of_unichar_t *ret;
	size_t i, j;

	ret = [object allocMemoryWithSize: sizeof(of_unichar_t)
				    count: _s->length];
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
		ret[j++] = c;
		i += cLen;
	}

	return ret;
}

- (const of_char32_t*)UTF32StringWithByteOrder: (of_byte_order_t)byteOrder
{
	OFObject *object = [[[OFObject alloc] init] autorelease];
	of_char32_t *ret;
	size_t i, j;

	ret = [object allocMemoryWithSize: sizeof(of_unichar_t)
				    count: _s->length + 1];







|







1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
		ret[j++] = c;
		i += cLen;
	}

	return ret;
}

- (const of_char32_t *)UTF32StringWithByteOrder: (of_byte_order_t)byteOrder
{
	OFObject *object = [[[OFObject alloc] init] autorelease];
	of_char32_t *ret;
	size_t i, j;

	ret = [object allocMemoryWithSize: sizeof(of_unichar_t)
				    count: _s->length + 1];