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
|
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;
size_t i;
char *retCString, *retCString2;
size_t i = 0;
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)
if ((retCString = malloc(length * 3 + 1)) == NULL)
@throw [OFOutOfMemoryException exceptionWithRequestedSize:
([self UTF8StringLength] * 3) + 1];
length * 3 + 1];
for (i = 0; *string != '\0'; string++) {
unsigned char c = *string;
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);
@try {
ret = [OFString stringWithUTF8String: retCString
/* We don't care if it fails, as we only made it smaller. */
if ((retCString2 = realloc(retCString, i + 1)) == NULL)
length: i];
} @finally {
free(retCString);
}
return ret;
retCString2 = retCString;
return [OFString stringWithUTF8StringNoCopy: retCString2
length: i
freeWhenDone: true];
}
- (OFString *)stringByURLDecoding
{
void *pool = objc_autoreleasePoolPush();
OFString *ret;
const char *string = [self UTF8String];
size_t length = [self UTF8StringLength];
char *retCString;
char *retCString, *retCString2;
char byte = 0;
int state = 0;
size_t i;
size_t i = 0;
if ((retCString = malloc([self UTF8StringLength] + 1)) == NULL)
if ((retCString = malloc(length + 1)) == NULL)
@throw [OFOutOfMemoryException
exceptionWithRequestedSize: [self UTF8StringLength] + 1];
exceptionWithRequestedSize: length + 1];
while (length--) {
char c = *string++;
for (i = 0; *string; string++) {
switch (state) {
case 0:
if (*string == '%')
if (c == '%')
state = 1;
else
retCString[i++] = *string;
retCString[i++] = c;
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;
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
|
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];
}
@try {
ret = [OFString stringWithUTF8String: retCString
/* We don't care if it fails, as we only made it smaller. */
if ((retCString2 = realloc(retCString, i + 1)) == NULL)
length: i];
} @finally {
free(retCString);
}
return ret;
retCString2 = retCString;
return [OFString stringWithUTF8StringNoCopy: retCString2
length: i
freeWhenDone: true];
}
@end
|