ObjFW  Diff

Differences From Artifact [eb8762e376]:

To Artifact [c99ccfd8e4]:


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







-
+












-
+












-
+







		/* We're missing a start byte here */
		if (OF_UNLIKELY(!(string[i] & 0x40))) {
			madvise((void*)string, length, MADV_NORMAL);
			return -1;
		}

		/* We have at minimum a 2 byte character -> check next byte */
		if (OF_UNLIKELY(length < i + 1 ||
		if (OF_UNLIKELY(length <= i + 1 ||
		    (string[i + 1] & 0xC0) != 0x80)) {
			madvise((void*)string, length, MADV_NORMAL);
			return -1;
		}

		/* Check if we have at minimum a 3 byte character */
		if (OF_LIKELY(!(string[i] & 0x20))) {
			i++;
			continue;
		}

		/* We have at minimum a 3 byte char -> check second next byte */
		if (OF_UNLIKELY(length < i + 2 ||
		if (OF_UNLIKELY(length <= i + 2 ||
		    (string[i + 2] & 0xC0) != 0x80)) {
			madvise((void*)string, length, MADV_NORMAL);
			return -1;
		}

		/* Check if we have a 4 byte character */
		if (OF_LIKELY(!(string[i] & 0x10))) {
			i += 2;
			continue;
		}

		/* We have a 4 byte character -> check third next byte */
		if (OF_UNLIKELY(length < i + 3 ||
		if (OF_UNLIKELY(length <= i + 3 ||
		    (string[i + 3] & 0xC0) != 0x80)) {
			madvise((void*)string, length, MADV_NORMAL);
			return -1;
		}

		/*
		 * Just in case, check if there's a 5th character, which is
704
705
706
707
708
709
710
711

712
713
714
715
716
717
718
719
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
749

750
751
752


753
754
755
756
757
758
759
704
705
706
707
708
709
710

711
712
713
714
715
716
717
718
719
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

749
750


751
752
753
754
755
756
757
758
759







-
+
















-
-
+
+


-
+











-
-
-
+
+
+


-
+

-
-
+
+







- initWithPath: (OFString*)firstComponent
     arguments: (va_list)arguments
{
	self = [super init];

	@try {
		OFString *component;
		size_t len, i;
		size_t i, length_;
		va_list argumentsCopy;

		length = [firstComponent cStringLength];

		switch (of_string_check_utf8([firstComponent cString],
		    length)) {
		case 1:
			isUTF8 = YES;
			break;
		case -1:
			@throw [OFInvalidEncodingException newWithClass: isa];
		}

		/* Calculate length */
		va_copy(argumentsCopy, arguments);
		while ((component = va_arg(argumentsCopy, OFString*)) != nil) {
			len = [component cStringLength];
			length += 1 + len;
			length_ = [component cStringLength];
			length += 1 + length_;

			switch (of_string_check_utf8([component cString],
			    len)) {
			    length_)) {
			case 1:
				isUTF8 = YES;
				break;
			case -1:
				@throw [OFInvalidEncodingException
				    newWithClass: isa];
			}
		}

		string = [self allocMemoryWithSize: length + 1];

		len = [firstComponent cStringLength];
		memcpy(string, [firstComponent cString], len);
		i = len;
		length_ = [firstComponent cStringLength];
		memcpy(string, [firstComponent cString], length_);
		i = length_;

		while ((component = va_arg(arguments, OFString*)) != nil) {
			len = [component cStringLength];
			length_ = [component cStringLength];
			string[i] = OF_PATH_DELIM;
			memcpy(string + i + 1, [component cString], len);
			i += len + 1;
			memcpy(string + i + 1, [component cString], length_);
			i += 1 + length_;
		}

		string[i] = '\0';
	} @catch (id e) {
		[self release];
		@throw e;
	}
1272
1273
1274
1275
1276
1277
1278
1279

1280
1281

1282
1283
1284

1285
1286
1287
1288
1289

1290
1291

1292
1293
1294

1295
1296
1297
1298
1299
1300
1301
1272
1273
1274
1275
1276
1277
1278

1279
1280

1281
1282
1283

1284
1285
1286
1287
1288

1289
1290

1291
1292
1293

1294
1295
1296
1297
1298
1299
1300
1301







-
+

-
+


-
+




-
+

-
+


-
+







	 */
	new->isa = [OFString class];
	return new;
}

- (BOOL)hasPrefix: (OFString*)prefix
{
	size_t len = [prefix cStringLength];
	size_t length_ = [prefix cStringLength];

	if (len > length)
	if (length_ > length)
		return NO;

	return !memcmp(string, [prefix cString], len);
	return !memcmp(string, [prefix cString], length_);
}

- (BOOL)hasSuffix: (OFString*)suffix
{
	size_t len = [suffix cStringLength];
	size_t length_ = [suffix cStringLength];

	if (len > length)
	if (length_ > length)
		return NO;

	return !memcmp(string + (length - len), [suffix cString], len);
	return !memcmp(string + (length - length_), [suffix cString], length_);
}

- (OFArray*)componentsSeparatedByString: (OFString*)delimiter
{
	OFAutoreleasePool *pool;
	OFMutableArray *array;
	const char *delim = [delimiter cString];
1454
1455
1456
1457
1458
1459
1460
1461
1462


1463
1464
1465
1466

1467
1468
1469



1470
1471
1472

1473
1474
1475

1476
1477
1478


1479
1480
1481
1482
1483
1484

1485
1486

1487
1488
1489
1490
1491
1492



1493
1494
1495
1496
1497
1498

1499
1500
1501
1502
1503
1504
1505
1506
1507


1508
1509
1510
1511

1512
1513
1514



1515
1516
1517

1518
1519
1520

1521
1522

1523
1524
1525
1526


1527
1528
1529
1530


1531
1532
1533
1534
1535
1536
1537


1538
1539
1540


1541
1542
1543


1544
1545
1546



1547
1548
1549
1550
1551
1552

1553
1554
1555

1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567


1568
1569
1570
1571
1572



1573
1574

1575
1576
1577
1578
1579
1580




1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591


1592
1593
1594
1595
1596



1597
1598

1599
1600
1601
1602
1603
1604




1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1454
1455
1456
1457
1458
1459
1460


1461
1462
1463
1464
1465
1466
1467



1468
1469
1470
1471
1472

1473
1474
1475

1476
1477


1478
1479
1480
1481
1482
1483
1484

1485
1486

1487
1488
1489
1490



1491
1492
1493
1494
1495
1496
1497
1498

1499
1500
1501
1502
1503
1504
1505
1506


1507
1508
1509
1510
1511
1512
1513



1514
1515
1516
1517
1518

1519
1520
1521

1522
1523

1524
1525
1526


1527
1528
1529
1530


1531
1532
1533
1534
1535
1536
1537


1538
1539
1540


1541
1542
1543


1544
1545
1546


1547
1548
1549
1550
1551
1552
1553
1554

1555
1556
1557

1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568


1569
1570
1571
1572



1573
1574
1575
1576

1577
1578
1579




1580
1581
1582
1583
1584
1585

1586
1587
1588
1589
1590
1591


1592
1593
1594
1595



1596
1597
1598
1599

1600
1601
1602




1603
1604
1605
1606
1607
1608

1609
1610
1611
1612
1613
1614
1615







-
-
+
+




+
-
-
-
+
+
+


-
+


-
+

-
-
+
+





-
+

-
+



-
-
-
+
+
+





-
+







-
-
+
+




+
-
-
-
+
+
+


-
+


-
+

-
+


-
-
+
+


-
-
+
+





-
-
+
+

-
-
+
+

-
-
+
+

-
-
+
+
+





-
+


-
+










-
-
+
+


-
-
-
+
+
+

-
+


-
-
-
-
+
+
+
+


-






-
-
+
+


-
-
-
+
+
+

-
+


-
-
-
-
+
+
+
+


-







					    length: 1];

	return @".";
}

- (intmax_t)decimalValue
{
	const char *str = string;
	size_t len = length;
	const char *string_ = string;
	size_t length_ = length;
	int i = 0;
	intmax_t num = 0;
	BOOL expectWhitespace = NO;

	while (*string_ == ' ' || *string_ == '\t' || *string_ == '\n' ||
	while (*str == ' ' || *str == '\t' || *str == '\n' || *str == '\r') {
		str++;
		len--;
	    *string_ == '\r') {
		string_++;
		length_--;
	}

	if (str[0] == '-' || str[0] == '+')
	if (string_[0] == '-' || string_[0] == '+')
		i++;

	for (; i < len; i++) {
	for (; i < length_; i++) {
		if (expectWhitespace) {
			if (str[i] != ' ' && str[i] != '\t' &&
			    str[i] != '\n' && str[i] != '\r')
			if (string_[i] != ' ' && string_[i] != '\t' &&
			    string_[i] != '\n' && string_[i] != '\r')
				@throw [OFInvalidFormatException
				    newWithClass: isa];
			continue;
		}

		if (str[i] >= '0' && str[i] <= '9') {
		if (string_[i] >= '0' && string_[i] <= '9') {
			if (INTMAX_MAX / 10 < num ||
			    INTMAX_MAX - num * 10 < str[i] - '0')
			    INTMAX_MAX - num * 10 < string_[i] - '0')
				@throw [OFOutOfRangeException
				    newWithClass: isa];

			num = (num * 10) + (str[i] - '0');
		} else if (str[i] == ' ' || str[i] == '\t' ||
		    str[i] == '\n' || str[i] == '\r')
			num = (num * 10) + (string_[i] - '0');
		} else if (string_[i] == ' ' || string_[i] == '\t' ||
		    string_[i] == '\n' || string_[i] == '\r')
			expectWhitespace = YES;
		else
			@throw [OFInvalidFormatException newWithClass: isa];
	}

	if (str[0] == '-')
	if (string_[0] == '-')
		num *= -1;

	return num;
}

- (uintmax_t)hexadecimalValue
{
	const char *str = string;
	size_t len = length;
	const char *string_ = string;
	size_t length_ = length;
	int i = 0;
	uintmax_t num = 0;
	BOOL expectWhitespace = NO, gotNumber = NO;

	while (*string_ == ' ' || *string_ == '\t' || *string_ == '\n' ||
	while (*str == ' ' || *str == '\t' || *str == '\n' || *str == '\r') {
		str++;
		len--;
	    *string_ == '\r') {
		string_++;
		length_--;
	}

	if (len == 0)
	if (length_ == 0)
		return 0;

	if (len >= 2 && str[0] == '0' && str[1] == 'x')
	if (length_ >= 2 && string_[0] == '0' && string_[1] == 'x')
		i = 2;
	else if (len >= 1 && (str[0] == 'x' || str[0] == '$'))
	else if (length_ >= 1 && (string_[0] == 'x' || string_[0] == '$'))
		i = 1;

	for (; i < len; i++) {
		uintmax_t newnum;
	for (; i < length_; i++) {
		uintmax_t newNum;

		if (expectWhitespace) {
			if (str[i] != ' ' && str[i] != '\t' &&
			    str[i] != '\n' && str[i] != '\r')
			if (string_[i] != ' ' && string_[i] != '\t' &&
			    string_[i] != '\n' && string_[i] != '\r')
				@throw [OFInvalidFormatException
				    newWithClass: isa];
			continue;
		}

		if (str[i] >= '0' && str[i] <= '9') {
			newnum = (num << 4) | (str[i] - '0');
		if (string_[i] >= '0' && string_[i] <= '9') {
			newNum = (num << 4) | (string_[i] - '0');
			gotNumber = YES;
		} else if (str[i] >= 'A' && str[i] <= 'F') {
			newnum = (num << 4) | (str[i] - 'A' + 10);
		} else if (string_[i] >= 'A' && string_[i] <= 'F') {
			newNum = (num << 4) | (string_[i] - 'A' + 10);
			gotNumber = YES;
		} else if (str[i] >= 'a' && str[i] <= 'f') {
			newnum = (num << 4) | (str[i] - 'a' + 10);
		} else if (string_[i] >= 'a' && string_[i] <= 'f') {
			newNum = (num << 4) | (string_[i] - 'a' + 10);
			gotNumber = YES;
		} else if (str[i] == 'h' || str[i] == ' ' || str[i] == '\t' ||
		    str[i] == '\n' || str[i] == '\r') {
		} else if (string_[i] == 'h' || string_[i] == ' ' ||
		    string_[i] == '\t' || string_[i] == '\n' ||
		    string_[i] == '\r') {
			expectWhitespace = YES;
			continue;
		} else
			@throw [OFInvalidFormatException newWithClass: isa];

		if (newnum < num)
		if (newNum < num)
			@throw [OFOutOfRangeException newWithClass: isa];

		num = newnum;
		num = newNum;
	}

	if (!gotNumber)
		@throw [OFInvalidFormatException newWithClass: isa];

	return num;
}

- (float)floatValue
{
	const char *str = string;
	char *endPtr;
	const char *string_ = string;
	char *endPointer = NULL;
	float value;

	/* Don't depend on isspace and thus the used locale */
	while (*str == ' ' || *str == '\t' || *str == '\n' || *str == '\r')
		str++;
	while (*string_ == ' ' || *string_ == '\t' || *string_ == '\n' ||
	    *string_ == '\r')
		string_++;

	value = strtof(str, &endPtr);
	value = strtof(string_, &endPointer);

	/* Check if there are any invalid chars left */
	if (endPtr != NULL) {
		for (; *endPtr != '\0'; endPtr++)
			if (*endPtr != ' ' && *endPtr != '\t' &&
			    *endPtr != '\n' && *endPtr != '\r')
	if (endPointer != NULL)
		for (; *endPointer != '\0'; endPointer++)
			if (*endPointer != ' ' && *endPointer != '\t' &&
			    *endPointer != '\n' && *endPointer != '\r')
				@throw [OFInvalidFormatException
				    newWithClass: isa];
	}

	return value;
}

- (double)doubleValue
{
	const char *str = string;
	char *endPtr;
	const char *string_ = string;
	char *endPointer = NULL;
	double value;

	/* Don't depend on isspace and thus the used locale */
	while (*str == ' ' || *str == '\t' || *str == '\n' || *str == '\r')
		str++;
	while (*string_ == ' ' || *string_ == '\t' || *string_ == '\n' ||
	    *string_ == '\r')
		string_++;

	value = strtod(str, &endPtr);
	value = strtod(string_, &endPointer);

	/* Check if there are any invalid chars left */
	if (endPtr != NULL) {
		for (; *endPtr != '\0'; endPtr++)
			if (*endPtr != ' ' && *endPtr != '\t' &&
			    *endPtr != '\n' && *endPtr != '\r')
	if (endPointer != NULL)
		for (; *endPointer != '\0'; endPointer++)
			if (*endPointer != ' ' && *endPointer != '\t' &&
			    *endPointer != '\n' && *endPointer != '\r')
				@throw [OFInvalidFormatException
				    newWithClass: isa];
	}

	return value;
}

- (of_unichar_t*)unicodeString
{
	OFObject *object = [[[OFObject alloc] init] autorelease];