ObjFW  Check-in [d1258ca0b6]

Overview
Comment:OFString+URLEncoding: Small optimization
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: d1258ca0b6ce06582a22c57085af3cf5d0c4fe58cc587cf72edf54fb57d0d30e
User & Date: js on 2017-11-04 22:02:53
Other Links: manifest | tags
Context
2017-11-05
02:58
Add OF_WARN_UNUSED_RESULT check-in: 7c79db860d user: js tags: trunk
2017-11-04
22:02
OFString+URLEncoding: Small optimization check-in: d1258ca0b6 user: js tags: trunk
21:09
OFString: Improve freeWhenDone in case of error check-in: 9f3a4dfbc0 user: js tags: trunk
Changes

Modified src/OFString+URLEncoding.m from [92e75db2c6] to [cf9f67ae6e].

34
35
36
37
38
39
40

41
42
43
44
45
46
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
123
	    "-._~!$&'()*+,;="];
}

- (OFString *)stringByURLEncodingWithAllowedCharacters: (const char *)allowed
{
	void *pool = objc_autoreleasePoolPush();
	const char *string = [self UTF8String];

	char *retCString;
	size_t i;
	OFString *ret;

	/*
	 * Worst case: 3 times longer than before.
	 * Oh, and we can't use [self allocWithSize:] here as self might be a
	 * @"" literal.
	 */
	if ((retCString = malloc(([self UTF8StringLength] * 3) + 1)) == NULL)
		@throw [OFOutOfMemoryException exceptionWithRequestedSize:
		    ([self UTF8StringLength] * 3) + 1];

	for (i = 0; *string != '\0'; string++) {
		unsigned char c = *string;

		if (of_ascii_isalnum(c) || strchr(allowed, c) != NULL)
			retCString[i++] = c;
		else {
			unsigned char high, low;

			high = c >> 4;
			low = c & 0x0F;

			retCString[i++] = '%';
			retCString[i++] =
			    (high > 9 ? high - 10 + 'A' : high + '0');
			retCString[i++] =
			    (low  > 9 ? low  - 10 + 'A' : low  + '0');
		}
	}


	objc_autoreleasePoolPop(pool);

	@try {
		ret = [OFString stringWithUTF8String: retCString
					      length: i];
	} @finally {
		free(retCString);
	}


	return ret;
}

- (OFString *)stringByURLDecoding
{
	void *pool = objc_autoreleasePoolPush();
	OFString *ret;
	const char *string = [self UTF8String];

	char *retCString;
	char byte = 0;
	int state = 0;
	size_t i;

	if ((retCString = malloc([self UTF8StringLength] + 1)) == NULL)
		@throw [OFOutOfMemoryException
		    exceptionWithRequestedSize: [self UTF8StringLength] + 1];



	for (i = 0; *string; string++) {
		switch (state) {
		case 0:
			if (*string == '%')
				state = 1;
			else
				retCString[i++] = *string;
			break;
		case 1:
		case 2:;
			uint8_t shift = (state == 1 ? 4 : 0);

			if (*string >= '0' && *string <= '9')
				byte += (*string - '0') << shift;
			else if (*string >= 'A' && *string <= 'F')
				byte += (*string - 'A' + 10) << shift;
			else if (*string >= 'a' && *string <= 'f')
				byte += (*string - 'a' + 10) << shift;
			else {
				free(retCString);
				@throw [OFInvalidFormatException exception];
			}

			if (++state == 3) {
				retCString[i++] = byte;







>
|
|
<






|

|

|
|
















>



|
|
<
<
|
|
|
>
|





<

>
|


|

|

|

>
>
|


|


|





|
|
|
|
|
|







34
35
36
37
38
39
40
41
42
43

44
45
46
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
123
124
125
	    "-._~!$&'()*+,;="];
}

- (OFString *)stringByURLEncodingWithAllowedCharacters: (const char *)allowed
{
	void *pool = objc_autoreleasePoolPush();
	const char *string = [self UTF8String];
	size_t length = [self UTF8StringLength];
	char *retCString, *retCString2;
	size_t i = 0;


	/*
	 * Worst case: 3 times longer than before.
	 * Oh, and we can't use [self allocWithSize:] here as self might be a
	 * @"" literal.
	 */
	if ((retCString = malloc(length * 3 + 1)) == NULL)
		@throw [OFOutOfMemoryException exceptionWithRequestedSize:
		    length * 3 + 1];

	while (length--) {
		unsigned char c = *string++;

		if (of_ascii_isalnum(c) || strchr(allowed, c) != NULL)
			retCString[i++] = c;
		else {
			unsigned char high, low;

			high = c >> 4;
			low = c & 0x0F;

			retCString[i++] = '%';
			retCString[i++] =
			    (high > 9 ? high - 10 + 'A' : high + '0');
			retCString[i++] =
			    (low  > 9 ? low  - 10 + 'A' : low  + '0');
		}
	}
	retCString[i] = '\0';

	objc_autoreleasePoolPop(pool);

	/* We don't care if it fails, as we only made it smaller. */
	if ((retCString2 = realloc(retCString, i + 1)) == NULL)


		retCString2 = retCString;

	return [OFString stringWithUTF8StringNoCopy: retCString2
					     length: i
				       freeWhenDone: true];
}

- (OFString *)stringByURLDecoding
{
	void *pool = objc_autoreleasePoolPush();

	const char *string = [self UTF8String];
	size_t length = [self UTF8StringLength];
	char *retCString, *retCString2;
	char byte = 0;
	int state = 0;
	size_t i = 0;

	if ((retCString = malloc(length + 1)) == NULL)
		@throw [OFOutOfMemoryException
		    exceptionWithRequestedSize: length + 1];

	while (length--) {
		char c = *string++;

		switch (state) {
		case 0:
			if (c == '%')
				state = 1;
			else
				retCString[i++] = c;
			break;
		case 1:
		case 2:;
			uint8_t shift = (state == 1 ? 4 : 0);

			if (c >= '0' && c <= '9')
				byte += (c - '0') << shift;
			else if (c >= 'A' && c <= 'F')
				byte += (c - 'A' + 10) << shift;
			else if (c >= 'a' && c <= 'f')
				byte += (c - 'a' + 10) << shift;
			else {
				free(retCString);
				@throw [OFInvalidFormatException exception];
			}

			if (++state == 3) {
				retCString[i++] = byte;
133
134
135
136
137
138
139
140
141
142
143
144
145
146


147
148
	objc_autoreleasePoolPop(pool);

	if (state != 0) {
		free(retCString);
		@throw [OFInvalidFormatException exception];
	}

	@try {
		ret = [OFString stringWithUTF8String: retCString
					      length: i];
	} @finally {
		free(retCString);
	}
	return ret;


}
@end







|
|
<
<
|
|
|
>
>


135
136
137
138
139
140
141
142
143


144
145
146
147
148
149
150
	objc_autoreleasePoolPop(pool);

	if (state != 0) {
		free(retCString);
		@throw [OFInvalidFormatException exception];
	}

	/* We don't care if it fails, as we only made it smaller. */
	if ((retCString2 = realloc(retCString, i + 1)) == NULL)


		retCString2 = retCString;

	return [OFString stringWithUTF8StringNoCopy: retCString2
					     length: i
				       freeWhenDone: true];
}
@end