ObjFW  Check-in [f9c673f241]

Overview
Comment:Preliminary OFXMLElement implementation.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: f9c673f241858ecb4837f20a43c2a9f7b8d55313f5969afda72b0dca52b26b4f
User & Date: js on 2009-06-18 18:42:16
Other Links: manifest | tags
Context
2009-06-18
19:08
Get rid of OFXMLFactory. check-in: 612bc150e5 user: js tags: trunk
18:42
Preliminary OFXMLElement implementation. check-in: f9c673f241 user: js tags: trunk
18:26
Add -[appendCStringWithoutUTF8Checking:]. check-in: 47e65e5a97 user: js tags: trunk
Changes

Modified src/Makefile from [a44f2314dd] to [8ef38350d8].

22
23
24
25
26
27
28

29
30
31
32
33
34
35
       ${OFPLUGIN_M}		\
       OFSocket.m		\
       OFStream.m		\
       OFString.m		\
       OFTCPSocket.m		\
       OFThread.m		\
       OFURLEncoding.m		\

       OFXMLFactory.m		\

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







>







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
       ${OFPLUGIN_M}		\
       OFSocket.m		\
       OFStream.m		\
       OFString.m		\
       OFTCPSocket.m		\
       OFThread.m		\
       OFURLEncoding.m		\
       OFXMLElement.m		\
       OFXMLFactory.m		\

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

Modified src/OFDictionary.m from [3ec4eb0e31] to [ea26220ad7].

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

#include <string.h>

#import "OFDictionary.h"
#import "OFIterator.h"
#import "OFExceptions.h"

/* Reference for static linking */
void _references_to_categories_of_OFDictionary()
{
	_OFIterator_reference = 1;
}

@implementation OFDictionary
+ dictionary;







|







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

#include <string.h>

#import "OFDictionary.h"
#import "OFIterator.h"
#import "OFExceptions.h"

/* References for static linking */
void _references_to_categories_of_OFDictionary()
{
	_OFIterator_reference = 1;
}

@implementation OFDictionary
+ dictionary;

Modified src/OFString.h from [c66ab2551c] to [bbf5506e5d].

150
151
152
153
154
155
156

- removeTrailingWhitespaces;
- removeLeadingAndTrailingWhitespaces;
@end

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








>
150
151
152
153
154
155
156
157
- removeTrailingWhitespaces;
- removeLeadingAndTrailingWhitespaces;
@end

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

Modified src/OFString.m from [f0f301f9d4] to [1b2b877044].

21
22
23
24
25
26
27

28
29
30
31
32
33
34
35
36

37
38
39
40
41
42
43
#else
#define madvise(addr, len, advise)
#endif

#import "OFString.h"
#import "OFAutoreleasePool.h"
#import "OFURLEncoding.h"

#import "OFExceptions.h"
#import "OFMacros.h"

#import "asprintf.h"

/* Reference for static linking */
void _references_to_categories_of_OFString()
{
	_OFURLEncoding_reference = 1;

};

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







>





|



>







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
#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;
};

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

Added src/OFXMLElement.h version [d7c56955ee].



















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * 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"
#import "OFArray.h"

extern int _OFXMLElement_reference;

@interface OFXMLElement: OFObject
{
	OFString *name;
	OFDictionary *attrs;
	OFString *stringval;
	OFArray *children;
}

+ elementWithName: (OFString*)name;
+ elementWithName: (OFString*)name
   andStringValue: (OFString*)stringval;
- initWithName: (OFString*)name;
-   initWithName: (OFString*)name
  andStringValue: (OFString*)stringval;
- (OFString*)string;
- addAttributeWithName: (OFString*)name
	      andValue: (OFString*)value;
- addChild: (OFXMLElement*)child;
@end

@interface OFString (OFXMLEscaping)
- stringByXMLEscaping;
@end

Added src/OFXMLElement.m version [61f052da6e].



























































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
/*
 * 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 <assert.h>
#include <stdlib.h>
#include <string.h>

#import "OFXMLElement.h"
#import "OFAutoreleasePool.h"
#import "OFExceptions.h"

int _OFXMLElement_reference;

@implementation OFXMLElement
+ elementWithName: (OFString*)name_
{
	return [[[self alloc] initWithName: name_] autorelease];
}

+ elementWithName: (OFString*)name_
   andStringValue: (OFString*)stringval_
{
	return [[[self alloc] initWithName: name_
			    andStringValue: stringval_] autorelease];
}

- initWithName: (OFString*)name_
{
	self = [super init];

	name = [name_ retain];

	return self;
}

-   initWithName: (OFString*)name_
  andStringValue: (OFString*)stringval_
{
	self = [super init];

	name = [name_ retain];
	stringval = [stringval_ retain];

	return self;
}

- (OFString*)string
{
	OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
	char *str_c;
	size_t len, i, j;
	OFString *ret, *tmp;
	OFIterator *iter;

	len = [name length] + 4;
	str_c = [self allocMemoryWithSize: len];

	/* Start of tag */
	*str_c = '<';
	memcpy(str_c + 1, [name cString], [name length]);
	i = [name length] + 1;

	/* Attributes */
	iter = [attrs iterator];
	for (;;) {
		OFString *key, *val;

		key = [iter nextObject];
		val = [iter nextObject];

		if (key == nil || val == nil)
			break;

		tmp = [val stringByXMLEscaping];

		len += [key length] + [tmp length] + 4;
		@try {
			str_c = [self resizeMemory: str_c
					    toSize: len];
		} @catch (OFException *e) {
			[self freeMemory: str_c];
			@throw e;
		}

		str_c[i++] = ' ';
		memcpy(str_c + i, [key cString], [key length]);
		i += [key length];
		str_c[i++] = '=';
		str_c[i++] = '\'';
		memcpy(str_c + i, [tmp cString], [tmp length]);
		i += [tmp length];
		str_c[i++] = '\'';

		[pool releaseObjects];
	}

	/* Childen */
	if (stringval != nil || children != nil) {
		if (stringval != nil)
			tmp = [stringval stringByXMLEscaping];
		else if (children != nil) {
			OFXMLElement **data = [children data];
			size_t count = [children count];
			IMP append;

			tmp = [OFMutableString string];
			append = [tmp methodFor: @selector(
			    appendCStringWithoutUTF8Checking:)];

			for (j = 0; j < count; j++)
				append(tmp, @selector(
				    appendCStringWithoutUTF8Checking:),
				    [[data[j] string] cString]);
		}

		len += [tmp length] + [name length] + 2;
		@try {
			str_c = [self resizeMemory: str_c
					    toSize: len];
		} @catch (OFException *e) {
			[self freeMemory: str_c];
			@throw e;
		}

		str_c[i++] = '>';
		memcpy(str_c + i, [tmp cString], [tmp length]);
		i += [tmp length];
		str_c[i++] = '<';
		str_c[i++] = '/';
		memcpy(str_c + i, [name cString], [name length]);
		i += [name length];
	} else
		str_c[i++] = '/';

	str_c[i++] = '>';
	str_c[i++] = '\0';
	assert(i == len);

	[pool release];

	@try {
		ret = [OFString stringWithCString: str_c];
	} @finally {
		[self freeMemory: str_c];
	}

	return ret;
}

- addAttributeWithName: (OFString*)name_
	      andValue: (OFString*)value_
{
	if (attrs == nil)
		attrs = [[OFMutableDictionary alloc] init];

	[attrs setObject: value_
		  forKey: name_];

	return self;
}

- addChild: (OFXMLElement*)child
{
	if (stringval != nil)
		@throw [OFInvalidArgumentException newWithClass: isa
						    andSelector: _cmd];

	if (children == nil)
		children = [[OFMutableArray alloc] init];

	[children addObject: child];

	return self;
}

- (void)dealloc
{
	[name release];
	[attrs release];
	[stringval release];
	[children release];

	[super dealloc];
}
@end

@implementation OFString (OFXMLEscaping)
- stringByXMLEscaping
{
	char *str_c, *append, *tmp;
	size_t len, append_len;
	size_t i, j;
	OFString *ret;

	j = 0;
	len = length + 1;

	/*
	 * We can't use allocMemoryWithSize: here as it might be a @"" literal
	 */
	if ((str_c = malloc(len + 1)) == NULL)
		@throw [OFOutOfMemoryException newWithClass: isa
						    andSize: len];

	for (i = 0; i < length; i++) {
		switch (string[i]) {
			case '<':
				append = "&lt;";
				append_len = 4;
				break;
			case '>':
				append = "&gt;";
				append_len = 4;
				break;
			case '"':
				append = "&quot;";
				append_len = 6;
				break;
			case '\'':
				append = "&apos;";
				append_len = 6;
				break;
			case '&':
				append = "&amp;";
				append_len = 5;
				break;
			default:
				append = NULL;
				append_len = 0;
		}

		if (append != NULL) {
			if ((tmp = realloc(str_c, len + append_len)) == NULL) {
				free(str_c);
				@throw [OFOutOfMemoryException
				    newWithClass: isa
					 andSize: len + append_len];
			}
			str_c = tmp;
			len += append_len - 1;

			memcpy(str_c + j, append, append_len);
			j += append_len;
		} else
			str_c[j++] = string[i];
	}

	str_c[j++] = '\0';
	assert(j == len);

	@try {
		ret = [OFString stringWithCString: str_c];
	} @finally {
		free(str_c);
	}

	return ret;
}
@end

Modified tests/Makefile from [d93b2a7df0] to [819d55b057].

1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
include ../extra.mk

SUBDIRS = OFObject		\
	  OFAutoreleasePool	\
	  OFDataArray		\
	  OFArray		\
	  OFDictionary		\
	  OFHashes		\
	  ${OFPLUGIN}		\
	  OFString		\
	  OFTCPSocket		\
	  OFThread		\
	  OFList		\

	  OFXMLFactory		\
	  ${OBJC_SYNC}

include ../buildsys.mk













>




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
include ../extra.mk

SUBDIRS = OFObject		\
	  OFAutoreleasePool	\
	  OFDataArray		\
	  OFArray		\
	  OFDictionary		\
	  OFHashes		\
	  ${OFPLUGIN}		\
	  OFString		\
	  OFTCPSocket		\
	  OFThread		\
	  OFList		\
	  OFXMLElement		\
	  OFXMLFactory		\
	  ${OBJC_SYNC}

include ../buildsys.mk

Modified tests/OFString/OFString.m from [8785c62127] to [fa55c2ad9d].

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

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

#define NUM_TESTS 33
#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);						\







|







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

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

#define NUM_TESTS 34
#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);						\
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
138
139
140
141




142
143
144
145
	/* Format tests */
	s1 = [OFMutableString stringWithFormat: @"%s: %d", "test", 123];
	CHECK(!strcmp([s1 cString], "test: 123"))

	[s1 appendWithFormat: @"%02X", 15];
	CHECK(!strcmp([s1 cString], "test: 1230F"))


	a = [@"fooXXbarXXXXbazXXXX" splitWithDelimiter: @"XX"];
	CHECK([[a objectAtIndex: j++] isEqual: @"foo"])
	CHECK([[a objectAtIndex: j++] isEqual: @"bar"])
	CHECK([[a objectAtIndex: j++] isEqual: @""])
	CHECK([[a objectAtIndex: j++] isEqual: @"baz"])
	CHECK([[a objectAtIndex: j++] isEqual: @""])
	CHECK([[a objectAtIndex: j++] isEqual: @""])


	CHECK([[@"foo\"ba'_$" stringByURLEncoding] isEqual: @"foo%22ba%27_%24"])
	CHECK([[@"foo%20bar%22%24" stringByURLDecoding] isEqual: @"foo bar\"$"])
	CHECK_EXCEPT([@"foo%bar" stringByURLDecoding],
	    OFInvalidEncodingException)
	CHECK_EXCEPT([@"foo%FFbar" stringByURLDecoding],
	    OFInvalidEncodingException)


	s1 = [@"asd fo asd fofo asd" mutableCopy];
	[s1 replaceOccurrencesOfString: @"fo"
			    withString: @"foo"];
	CHECK([s1 isEqual: @"asd foo asd foofoo asd"])
	s1 = [@"XX" mutableCopy];
	[s1 replaceOccurrencesOfString: @"X"
			    withString: @"XX"];
	CHECK([s1 isEqual: @"XXXX"])


	s1 = [@"  \t\t \tasd  \t \t\t" mutableCopy];
	s2 = [s1 mutableCopy];
	s3 = [s1 mutableCopy];
	CHECK([[s1 removeLeadingWhitespaces] isEqual: @"asd  \t \t\t"])
	CHECK([[s2 removeTrailingWhitespaces] isEqual: @"  \t\t \tasd"])
	CHECK([[s3 removeLeadingAndTrailingWhitespaces] isEqual: @"asd"])

	s1 = [@" \t\t  \t\t  \t \t" mutableCopy];
	s2 = [s1 mutableCopy];
	s3 = [s1 mutableCopy];
	CHECK([[s1 removeLeadingWhitespaces] isEqual: @""])
	CHECK([[s2 removeTrailingWhitespaces] isEqual: @""])
	CHECK([[s3 removeLeadingAndTrailingWhitespaces] isEqual: @""])





	puts("");

	return 0;
}







>








>







>









>














>
>
>
>




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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
	/* Format tests */
	s1 = [OFMutableString stringWithFormat: @"%s: %d", "test", 123];
	CHECK(!strcmp([s1 cString], "test: 123"))

	[s1 appendWithFormat: @"%02X", 15];
	CHECK(!strcmp([s1 cString], "test: 1230F"))

	/* Split tests */
	a = [@"fooXXbarXXXXbazXXXX" splitWithDelimiter: @"XX"];
	CHECK([[a objectAtIndex: j++] isEqual: @"foo"])
	CHECK([[a objectAtIndex: j++] isEqual: @"bar"])
	CHECK([[a objectAtIndex: j++] isEqual: @""])
	CHECK([[a objectAtIndex: j++] isEqual: @"baz"])
	CHECK([[a objectAtIndex: j++] isEqual: @""])
	CHECK([[a objectAtIndex: j++] isEqual: @""])

	/* URL encoding tests */
	CHECK([[@"foo\"ba'_$" stringByURLEncoding] isEqual: @"foo%22ba%27_%24"])
	CHECK([[@"foo%20bar%22%24" stringByURLDecoding] isEqual: @"foo bar\"$"])
	CHECK_EXCEPT([@"foo%bar" stringByURLDecoding],
	    OFInvalidEncodingException)
	CHECK_EXCEPT([@"foo%FFbar" stringByURLDecoding],
	    OFInvalidEncodingException)

	/* Replace tests */
	s1 = [@"asd fo asd fofo asd" mutableCopy];
	[s1 replaceOccurrencesOfString: @"fo"
			    withString: @"foo"];
	CHECK([s1 isEqual: @"asd foo asd foofoo asd"])
	s1 = [@"XX" mutableCopy];
	[s1 replaceOccurrencesOfString: @"X"
			    withString: @"XX"];
	CHECK([s1 isEqual: @"XXXX"])

	/* Whitespace removing tests */
	s1 = [@"  \t\t \tasd  \t \t\t" mutableCopy];
	s2 = [s1 mutableCopy];
	s3 = [s1 mutableCopy];
	CHECK([[s1 removeLeadingWhitespaces] isEqual: @"asd  \t \t\t"])
	CHECK([[s2 removeTrailingWhitespaces] isEqual: @"  \t\t \tasd"])
	CHECK([[s3 removeLeadingAndTrailingWhitespaces] isEqual: @"asd"])

	s1 = [@" \t\t  \t\t  \t \t" mutableCopy];
	s2 = [s1 mutableCopy];
	s3 = [s1 mutableCopy];
	CHECK([[s1 removeLeadingWhitespaces] isEqual: @""])
	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;"])

	puts("");

	return 0;
}

Added tests/OFXMLElement/Makefile version [280a3ac556].



















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
PROG_NOINST = ofxmlelement${PROG_SUFFIX}
SRCS = OFXMLElement.m

include ../../buildsys.mk
include ../../extra.mk

CPPFLAGS += -I../../src -I../..
LIBS := -L../../src -lobjfw ${LIBS}

.PHONY: run

all: run
run: ${PROG_NOINST}
	rm -f libobjfw.so.0 libobjfw.so.0.1 libobjfw.dll libobjfw.dylib
	ln -s ../../src/libobjfw.so libobjfw.so.0
	ln -s ../../src/libobjfw.so libobjfw.so.0.1
	if test -f ../../src/libobjfw.dll; then \
		ln ../../src/libobjfw.dll libobjfw.dll; \
	fi
	ln -s ../../src/libobjfw.dylib libobjfw.dylib
	LD_LIBRARY_PATH=.$${LD_LIBRARY_PATH+:}$$LD_LIBRARY_PATH \
	DYLD_LIBRARY_PATH=.$${DYLD_LIBRARY_PATH+:}$$DYLD_LIBRARY_PATH \
	${TEST_LAUNCHER} ./${PROG_NOINST}; EXIT=$$?; \
	rm -f libobjfw.so.0 libobjfw.so.0.1 libobjfw.dll libobjfw.dylib; \
	exit $$EXIT

Added tests/OFXMLElement/OFXMLElement.m version [0ba42ffac8].



























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * 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 <stdio.h>

#import "OFXMLElement.h"

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

#define NUM_TESTS 5
#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);						\
	return 1;
#define CHECK(cond)							\
	if (cond) {							\
		SUCCESS							\
	} else {							\
		FAIL							\
	}								\
	i++;
#define CHECK_EXCEPT(code, exception)					\
	@try {								\
		code;							\
		FAIL							\
	} @catch (exception *e) {					\
		SUCCESS							\
	}								\
	i++;

int
main()
{
	size_t i = 0;

	OFXMLElement *elem;

	elem = [OFXMLElement elementWithName: @"foo"];
	CHECK([[elem string] isEqual: @"<foo/>"]);

	[elem addAttributeWithName: @"foo"
			  andValue: @"b&ar"];
	CHECK([[elem string] isEqual: @"<foo foo='b&amp;ar'/>"])

	[elem addChild: [OFXMLElement elementWithName: @"bar"]];
	CHECK([[elem string] isEqual: @"<foo foo='b&amp;ar'><bar/></foo>"])

	elem = [OFXMLElement elementWithName: @"foo"
			      andStringValue: @"b&ar"];
	CHECK([[elem string] isEqual: @"<foo>b&amp;ar</foo>"])

	[elem addAttributeWithName: @"foo"
			  andValue: @"b&ar"];
	CHECK([[elem string] isEqual: @"<foo foo='b&amp;ar'>b&amp;ar</foo>"])

	puts("");

	return 0;
}