ObjFW  Check-in [d8684fc232]

Overview
Comment:Add OFString (OFXMLUnescaping) category and API for OFXMLParser.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: d8684fc2321ed8fb306401b3335dabd5eb2f8da2a8e55f55a1cd355ba60750da
User & Date: js on 2009-07-14 18:57:38
Other Links: manifest | tags
Context
2009-07-14
21:22
Add of_string_unicode_to_utf8 which converts unicode to UTF-8. check-in: de937a62e4 user: js tags: trunk
18:57
Add OFString (OFXMLUnescaping) category and API for OFXMLParser. check-in: d8684fc232 user: js tags: trunk
17:51
Optimize some code by using the new stringWithCString:andLength: method. check-in: 7bb3494ef9 user: js tags: trunk
Changes

Modified src/Makefile from [ec70c1ba34] to [862b2d6a24].

22
23
24
25
26
27
28
29


30
31
32
33
34
35
36
22
23
24
25
26
27
28

29
30
31
32
33
34
35
36
37







-
+
+







       ${OFPLUGIN_M}		\
       OFSocket.m		\
       OFStream.m		\
       OFString.m		\
       OFTCPSocket.m		\
       OFThread.m		\
       OFURLEncoding.m		\
       OFXMLElement.m
       OFXMLElement.m		\
       OFXMLParser.m

INCLUDESTMP := ${SRCS:.c=.h}
INCLUDES := ${INCLUDESTMP:.m=.h}	\
	    OFMacros.h			\
	    asprintf.h			\
	    objfw.h

Modified src/OFString.h from [1adde179e3] to [dedea52274].

199
200
201
202
203
204
205

199
200
201
202
203
204
205
206







+
- removeLeadingAndTrailingWhitespaces;
@end

#import "OFConstString.h"
#import "OFMutableString.h"
#import "OFURLEncoding.h"
#import "OFXMLElement.h"
#import "OFXMLParser.h"

Modified src/OFString.m from [b0bbce5a9e] to [c51d9e7bc3].

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

39
40
41
42
43
44
45
20
21
22
23
24
25
26


27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44







-
-










+







#include <sys/mman.h>
#else
#define madvise(addr, len, advise)
#endif

#import "OFString.h"
#import "OFAutoreleasePool.h"
#import "OFURLEncoding.h"
#import "OFXMLElement.h"
#import "OFExceptions.h"
#import "OFMacros.h"

#import "asprintf.h"

/* References for static linking */
void _references_to_categories_of_OFString()
{
	_OFURLEncoding_reference = 1;
	_OFXMLElement_reference = 1;
	_OFXMLParser_reference = 1;
};

int
of_string_check_utf8(const char *str, size_t len)
{
	size_t i;
	int utf8 = 0;

Added src/OFXMLParser.h version [dba56f762f].





















































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * Copyright (c) 2008 - 2009
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of libobjfw. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#import "OFObject.h"
#import "OFString.h"
#import "OFDictionary.h"

extern int _OFXMLParser_reference;

@class OFXMLParser;

@protocol OFXMLParserDelegate
-     (BOOL)xmlParser: (OFXMLParser*)parser
  didStartTagWithName: (OFString*)name
	    andPrefix: (OFString*)prefix
	 andNamespace: (OFString*)ns
	andAttributes: (OFDictionary*)attrs;
-   (BOOL)xmlParser: (OFXMLParser*)parser
  didEndTagWithName: (OFString*)name
	  andPrefix: (OFString*)prefix
       andNamespace: (OFString*)ns;
- (BOOL)xmlParser: (OFXMLParser*)parser
      foundString: (OFString*)string;
@end

@interface OFXMLParser: OFObject
{
	OFObject <OFXMLParserDelegate> *delegate;
	int state;
}

+ xmlParser;
- (id)delegate;
- setDelegate: (OFObject <OFXMLParserDelegate>*)delegate;
@end

@protocol OFXMLUnescapingDelegate
- (OFString*)foundUnknownEntityNamed: (OFString*)entitiy;
@end

@interface OFString (OFXMLUnescaping)
- stringByXMLUnescaping;
- stringByXMLUnescapingWithHandler: (OFObject <OFXMLUnescapingDelegate>*)h;
@end

Added src/OFXMLParser.m version [b77468664e].
















































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * Copyright (c) 2008 - 2009
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of libobjfw. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE included in
 * the packaging of this file.
 */

#include "config.h"

#include <string.h>

#import "OFXMLParser.h"
#import "OFAutoreleasePool.h"
#import "OFExceptions.h"

int _OFXMLParser_reference;

@implementation OFXMLParser
+ xmlParser
{
	return [[[self alloc] init] autorelease];
}

- (id)delegate
{
	return [[delegate retain] autorelease];
}

- setDelegate: (OFObject <OFXMLParserDelegate>*)delegate_
{
	[delegate release];
	delegate = [delegate_ retain];

	return self;
}
@end

@implementation OFString (OFXMLUnescaping)
- stringByXMLUnescaping
{
	return [self stringByXMLUnescapingWithHandler: nil];
}

- stringByXMLUnescapingWithHandler: (OFObject <OFXMLUnescapingDelegate>*)h
{
	size_t i, last;
	BOOL in_entity;
	OFString *ret;

	last = 0;
	in_entity = NO;
	ret = [OFMutableString string];

	for (i = 0; i < length; i++) {
		if (!in_entity && string[i] == '&') {
			[ret appendCStringWithoutUTF8Checking: string + last
						    andLength: i - last];

			last = i + 1;
			in_entity = YES;
		} else if (in_entity && string[i] == ';') {
			size_t len = i - last;

			if (len == 2 && !memcmp(string + last, "lt", 2))
				[ret appendString: @"<"];
			else if (len == 2 && !memcmp(string + last, "gt", 2))
				[ret appendString: @">"];
			else if (len == 4 && !memcmp(string + last, "quot", 4))
				[ret appendString: @"\""];
			else if (len == 4 && !memcmp(string + last, "apos", 4))
				[ret appendString: @"'"];
			else if (len == 3 && !memcmp(string + last, "amp", 3))
				[ret appendString: @"&"];
			else if (h != nil) {
				OFAutoreleasePool *pool;
				OFString *n, *tmp;

				pool = [[OFAutoreleasePool alloc] init];

				n = [OFString stringWithCString: string + last
						      andLength: len];
				tmp = [h foundUnknownEntityNamed: n];

				if (tmp == nil)
					@throw [OFInvalidEncodingException
					    newWithClass: isa];

				[ret appendString: tmp];
				[pool release];
			} else
				@throw [OFInvalidEncodingException
				    newWithClass: isa];

			last = i + 1;
			in_entity = NO;
		}
	}

	if (in_entity)
		@throw [OFInvalidEncodingException newWithClass: isa];

	[ret appendCStringWithoutUTF8Checking: string + last
				    andLength: i - last];

	return ret;
}
@end

Modified tests/OFString/OFString.m from [b1315ec8f9] to [b49062f26b].

20
21
22
23
24
25
26
27

28
29
30
31
32
33
34
20
21
22
23
24
25
26

27
28
29
30
31
32
33
34







-
+








#ifndef _WIN32
#define ZD "%zd"
#else
#define ZD "%u"
#endif

#define NUM_TESTS 49
#define NUM_TESTS 53
#define SUCCESS								\
	printf("\r\033[1;%dmTests successful: " ZD "/%d\033[0m",	\
	    (i == NUM_TESTS - 1 ? 32 : 33), i + 1, NUM_TESTS);		\
	fflush(stdout);
#define FAIL								\
	printf("\r\033[K\033[1;31mTest " ZD "/%d failed!\033[m\n",	\
	    i + 1, NUM_TESTS);						\
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
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







+
+
+
+
+
+
+
+
+
+
+
+
+












+







		code;							\
		FAIL							\
	} @catch (exception *e) {					\
		SUCCESS							\
	}								\
	i++;

@interface EntityHandler: OFObject <OFXMLUnescapingDelegate>
@end

@implementation EntityHandler
- (OFString*)foundUnknownEntityNamed: (OFString*)entity
{
	if ([entity isEqual: @"foo"])
		return @"bar";

	return nil;
}
@end

int
main()
{
	size_t i = 0;
	size_t j = 0;

	OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
	OFString *s1 = [OFMutableString stringWithCString: "test"];
	OFString *s2 = [OFMutableString stringWithCString: ""];
	OFString *s3;
	OFString *s4 = [OFMutableString string];
	OFArray *a;
	EntityHandler *h;

	s3 = [s1 copy];

	CHECK([s1 isEqual: s3])
	CHECK(![s1 isEqual: [[OFObject alloc] init]])
	CHECK([s1 hash] == [s3 hash])

172
173
174
175
176
177
178












179
180
181
182
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208







+
+
+
+
+
+
+
+
+
+
+
+




	CHECK([[s2 removeTrailingWhitespaces] isEqual: @""])
	CHECK([[s3 removeLeadingAndTrailingWhitespaces] isEqual: @""])

	/* XML escaping tests */
	s1 = [@"<hello> &world'\"!&" stringByXMLEscaping];
	CHECK([s1 isEqual: @"&lt;hello&gt; &amp;world&apos;&quot;!&amp;"])

	/* XML unescaping tests */
	CHECK([[s1 stringByXMLUnescaping] isEqual: @"<hello> &world'\"!&"]);
	CHECK_EXCEPT([@"&foo;" stringByXMLUnescaping],
	    OFInvalidEncodingException)

	h = [[EntityHandler alloc] init];
	s1 = [@"x&foo;y" stringByXMLUnescapingWithHandler: h];
	CHECK([s1 isEqual: @"xbary"]);

	CHECK_EXCEPT([@"x&amp" stringByXMLUnescaping],
	    OFInvalidEncodingException)

	puts("");

	return 0;
}