ObjFW  Check-in [494dca4ae4]

Overview
Comment:Use XML for serialization.

This way, we don't need a new parser and don't use a new format.

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 494dca4ae4a4ab7343ea13b6f7f3cee6bd0f9922173c684f3f8d55bc0a22b7ed
User & Date: js on 2011-05-14 12:26:39
Other Links: manifest | tags
Context
2011-05-14
19:48
Ignore whitespaces around the root element in -[initWithXMLString]. check-in: 12a8ac4cb3 user: js tags: trunk
12:26
Use XML for serialization. check-in: 494dca4ae4 user: js tags: trunk
2011-05-12
19:58
Style improvements. check-in: 85ffbaabbb user: js tags: trunk
Changes

Deleted SERIALIZATION version [0e6d0b7c8b].

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
1.) Basic Concept

This document describes the serialization used by ObjFW. It is designed to be
easy parsable and usable in other programming languages while still supporting
ObjFW-specific features, which are all optional.

Every object can have a set of parameters which are optional and can be ignored
if they don't exist in the language for which parsing is done. These parameters
are written in the form (parameter1,parameter2) and precede the object.
Parameters not known by the implementation should be ignored - they are
completely optional except for the extension type.

All spaces (except those in strings, of course) are optional and only to improve
readability - they are by no means required, but they are still recommended.

ObjFW serialization supports 4 basic types: Strings, arrays and dictionaries.
It is limited to those 4 types because those are available in all languages.
Lists are a special case of arrays in ObjFW serialization. For all objects
that can not be serialized with those 4 basic types, there is the extension
type [], which can be used for any object but is not portable between languages.
This type is described in 6.).


2.) Strings

Strings are very similar to how strings are done in C. They start with a " and
end with a ". The escape sequences \", \\, \n, \r and \t exist, like in C
strings. It is required to use \", \\, \n and \r. The reason for this is that
using an actual newline would modify the string when indention is done. However,
using \t is recommended.
Strings can be split just like in C. For example "Hello " "World" is equivalent
to "Hello World". Because this is possible, it is recommended to end the string
after \n and continue it in a new line to increase readability.

Strings are required to be UTF-8 encoded.

The only accepted parameter for strings is mutable. If the language for which
parsing is done does not know the concept of mutable and immutable objects, this
parameter should be ignored.

Examples for strings:

	"This is a \"string!\""

	"This is a string containing a\n"
	    "new line!"

	"This is\ta string\tcontaining tabs!"

	(mutable)"This string is mutable!"


3.) Arrays

Arrays start with a [ and end with an ]. The elements are separated by a comma.
Whitespaces are allowed between objects and after the inital [ and before the
final ].

It allows the mutable parameter, which should be handled the same way like it
should be for strings.

It also has the list parameter. Specifying this parameter creates a
double-linked list instead of an array.

It also allows specifying a number as a parameter. This number is considered
the expected size of the array. It is by no means required and it should by no
means be assumed to be reliable. If the number is not equal to the actual size,
the parser should error out. The parser should also make sure to ignore the
number if it is too big to prevent a possible DoS.

Examples for arrays:

	["This", "is", "an", "array", "with", "7", "strings"]

	(mutable)["This array", "is mutable"]

	(3)["This array specifies", "the number of elements", "for performance"]

	(mutable,2)["Parameters can be", "combined"]


4.) Dictionaries

Dictionary start with a { and end with a }. The elements are written in the form
key = value and each entry ends with an ;.

It allows the mutable parameter, which should be handled the same way like it
should be for strings.

It also allows specifying a number as a parameter, which should be handled
exactly like for arrays.

Examples for dictionaries:

	{"This is a key" = "This is a value"}

	(mutable){"mutable" = (BOOL)1}

	(2){
		"key1" = "value1",
		"key2" = "value2"
	}

	{
		["Mapping", "an", "array"] = "To a string";
		{ "mapping" = "a dictionary" } = ["To", "an", "array"];
	}


5.) Numbers

Numbers are written by just writing a number. The type of a number may be
specified by a parameter. If it is not specified, the implementation should
choose are type which fits the number. If the specified type is not big enough
for the number, the implementation should use another type that fits.

Known parameters are:
	BOOL
	char		(signed!)
	short		(signed!)
	int		(signed!)
	long		(signed!)
	int8_t
	int16_t
	int32_t
	int64_t
	unsigned char,
	unsigned short,
	unsigned int,
	unsigned long
	uint8_t
	uint16_t
	uint32_t
	uint64_t
	size_t
	ssize_t
	intmax_t
	uintmax_t
	intptr_t
	uintptr_t
	float
	double

Examples for numbers:

	1
	2.6
	(BOOL)0
	(intmax_t)1234567
	(double)2.5


6.) Extension Type

The extension type allows adding new objects to ObjFW serialization. The
extension type has a parameter class= which specifies the class which should
handle deserialization and a version= parameter which specifies the version of
the class serialization as a single integer. The extension type starts with a [
and ends with a ]. Inside those brackets can be arbitray basic types, which
should be passed unmodified to the class for deserialization.
If an implementation can't deserialize an extension type, it is required to
error out. Other languages are allowed to parse extension types of classes which
are in ObjFW, like OFXMLElement, but are by no means required to do so. Other
languages may also add their own extension types, but are required to add the
foreign= parameter and set it to their name, so other implementations don't try
to deserialize it, but error out instead. Other implementations are allowed to
serialize to ObjFW objects if they know them. For example, it might be desirable
to also create OFXMLElements from other languages.

Examples for using the extension type:

	(class=OFXMLElement)<"<some-xml/>">

 	(class=OFURL)<
		"https://webkeks.org/objfw/"
	>

 	(class=Foo,foreign=Foolang)<
		{
			"property1" = "value1"
		}
	>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<












































































































































































































































































































































































Modified src/OFArray.m from [40c18091bb] to [7df94bcaeb].

17
18
19
20
21
22
23

24
25
26
27
28
29
30
#include "config.h"

#include <stdarg.h>

#import "OFArray.h"
#import "OFDataArray.h"
#import "OFString.h"

#import "OFAutoreleasePool.h"

#import "OFEnumerationMutationException.h"
#import "OFOutOfRangeException.h"

#import "macros.h"








>







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include "config.h"

#include <stdarg.h>

#import "OFArray.h"
#import "OFDataArray.h"
#import "OFString.h"
#import "OFXMLElement.h"
#import "OFAutoreleasePool.h"

#import "OFEnumerationMutationException.h"
#import "OFOutOfRangeException.h"

#import "macros.h"

428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456


457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
	 * to be OFString*, so it can't be modified anyway. But not swizzling it
	 * would create a real copy each time -[copy] is called.
	 */
	ret->isa = [OFString class];
	return ret;
}

- (OFString*)stringBySerializing
{
	OFAutoreleasePool *pool;
	OFMutableString *ret;
	OFObject <OFSerialization> **cArray;
	size_t i, count;

	if ([array count] == 0) {
		if ([self isKindOfClass: [OFMutableArray class]])
			return @"(mutable,0)[]";
		else
			return @"(0)[]";
	}

	cArray = [array cArray];
	count = [array count];
	if ([self isKindOfClass: [OFMutableArray class]])
		ret = [OFMutableString stringWithFormat: @"(mutable,%zd)[\n",
							 count];
	else
		ret = [OFMutableString stringWithFormat: @"(%zd)[\n", count];
	pool = [[OFAutoreleasePool alloc] init];



	for (i = 0; i < count - 1; i++) {
		[ret appendString: [cArray[i] stringBySerializing]];
		[ret appendString: @",\n"];

		[pool releaseObjects];
	}
	[ret appendString: [cArray[i] stringBySerializing]];
	[ret replaceOccurrencesOfString: @"\n"
			     withString: @"\n\t"];
	[ret appendString: @"\n]"];

	[pool release];

	/*
	 * Class swizzle the string to be immutable. We declared the return type
	 * to be OFString*, so it can't be modified anyway. But not swizzling it
	 * would create a real copy each time -[copy] is called.
	 */
	ret->isa = [OFString class];
	return ret;
}

- (void)makeObjectsPerformSelector: (SEL)selector
{
	id *cArray = [array cArray];
	size_t i, count = [array count];








|


|
|
|

|
|
<
<
<
|
<
<
<
<
<
<
<
<

>
>

|
<
<
|


<
<
<
<



<
<
<
<
<
<
|







429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444



445








446
447
448
449
450


451
452
453




454
455
456






457
458
459
460
461
462
463
464
	 * to be OFString*, so it can't be modified anyway. But not swizzling it
	 * would create a real copy each time -[copy] is called.
	 */
	ret->isa = [OFString class];
	return ret;
}

- (OFXMLElement*)XMLElementBySerializing
{
	OFAutoreleasePool *pool;
	OFXMLElement *element;
	id <OFSerialization> *cArray = [array cArray];
	size_t i, count = [array count];

	element = [OFXMLElement elementWithName: @"object"
				      namespace: OF_SERIALIZATION_NS];












	pool = [[OFAutoreleasePool alloc] init];
	[element addAttributeWithName: @"class"
			  stringValue: [self className]];

	for (i = 0; i < count; i++) {


		[element addChild: [cArray[i] XMLElementBySerializing]];
		[pool releaseObjects];
	}





	[pool release];







	return element;
}

- (void)makeObjectsPerformSelector: (SEL)selector
{
	id *cArray = [array cArray];
	size_t i, count = [array count];

Modified src/OFDate.m from [879a67dcaa] to [1c6620e225].

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <time.h>

#include <sys/time.h>

#import "OFDate.h"
#import "OFString.h"
#import "OFDictionary.h"
#import "OFNumber.h"
#import "OFAutoreleasePool.h"
#ifdef OF_THREADS
# import "OFThread.h"
#endif

#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"







|







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <time.h>

#include <sys/time.h>

#import "OFDate.h"
#import "OFString.h"
#import "OFDictionary.h"
#import "OFXMLElement.h"
#import "OFAutoreleasePool.h"
#ifdef OF_THREADS
# import "OFThread.h"
#endif

#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"
287
288
289
290
291
292
293
294
295
296
297
298


299
300
301
302
303
304
305

306


307




308

309
310
311
312
313
314
315
316
317
}

- (OFString*)description
{
	return [self dateStringWithFormat: @"%Y-%m-%dT%H:%M:%SZ"];
}

- (OFString*)stringBySerializing
{
	OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
	OFDictionary *dictionary = [OFDictionary dictionaryWithKeysAndObjects:
	    @"seconds", [OFNumber numberWithInt64: seconds],


	    @"microseconds", [OFNumber numberWithUInt32: microseconds], nil];
	OFString *ret = [[OFString alloc]
	    initWithFormat: @"(class=OFDate,version=0)<%@>",
			    [dictionary stringBySerializing]];

	@try {
		[pool release];

	} @finally {


		[ret autorelease];




	}


	return ret;
}

- (uint32_t)microsecond
{
	return microseconds;
}








|

|
|
|
>
>
|
|
|
|

<
|
>
|
>
>
|
>
>
>
>
|
>

|







287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305

306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
}

- (OFString*)description
{
	return [self dateStringWithFormat: @"%Y-%m-%dT%H:%M:%SZ"];
}

- (OFXMLElement*)XMLElementBySerializing
{
	OFAutoreleasePool *pool;
	OFXMLElement *element;

	element = [OFXMLElement elementWithName: @"object"
				      namespace: OF_SERIALIZATION_NS];

	pool = [[OFAutoreleasePool alloc] init];
	[element addAttributeWithName: @"class"
			  stringValue: [self className]];


	[element addChild:
	    [OFXMLElement elementWithName: @"seconds"
				namespace: OF_SERIALIZATION_NS
			      stringValue: [OFString stringWithFormat:
					       @"%" PRId64, seconds]]];
	[element addChild:
	    [OFXMLElement elementWithName: @"microseconds"
				namespace: OF_SERIALIZATION_NS
			      stringValue: [OFString stringWithFormat:
					       @"%" PRIu32, microseconds]]];

	[pool release];

	return element;
}

- (uint32_t)microsecond
{
	return microseconds;
}

Modified src/OFDictionary.m from [167e60e6d6] to [5f45c17283].

18
19
20
21
22
23
24

25
26
27
28
29
30
31

#include <string.h>

#import "OFDictionary.h"
#import "OFEnumerator.h"
#import "OFArray.h"
#import "OFString.h"

#import "OFAutoreleasePool.h"

#import "OFEnumerationMutationException.h"
#import "OFInvalidArgumentException.h"
#import "OFOutOfRangeException.h"

#import "macros.h"







>







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

#include <string.h>

#import "OFDictionary.h"
#import "OFEnumerator.h"
#import "OFArray.h"
#import "OFString.h"
#import "OFXMLElement.h"
#import "OFAutoreleasePool.h"

#import "OFEnumerationMutationException.h"
#import "OFInvalidArgumentException.h"
#import "OFOutOfRangeException.h"

#import "macros.h"
753
754
755
756
757
758
759
760
761
762
763

764
765
766
767
768
769
770
771
772

773
774
775
776
777
778
779
780



781
782
783
784
785
786
787
788

789


790



791

792





793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
	 * to be OFString*, so it can't be modified anyway. But not swizzling it
	 * would create a real copy each time -[copy] is called.
	 */
	ret->isa = [OFString class];
	return ret;
}

- (OFString*)stringBySerializing
{
	OFMutableString *ret;
	OFAutoreleasePool *pool, *pool2;

	OFEnumerator *keyEnumerator, *objectEnumerator;
	id key, object;
	size_t i;

	if (count == 0) {
		if ([self isKindOfClass: [OFMutableDictionary class]])
			return @"(mutable,0){}";
		else
			return @"(0){}";

	}

	if ([self isKindOfClass: [OFMutableDictionary class]])
		ret = [OFMutableString stringWithFormat: @"(mutable,%zd){\n",
							 count];
	else
		ret = [OFMutableString stringWithFormat: @"(%zd){\n", count];
	pool = [[OFAutoreleasePool alloc] init];



	keyEnumerator = [self keyEnumerator];
	objectEnumerator = [self objectEnumerator];

	i = 0;
	pool2 = [[OFAutoreleasePool alloc] init];

	while ((key = [keyEnumerator nextObject]) != nil &&
	    (object = [objectEnumerator nextObject]) != nil) {

		[ret appendString: [key stringBySerializing]];


		[ret appendString: @" = "];



		[ret appendString: [object stringBySerializing]];







		if (++i < count)
			[ret appendString: @",\n"];

		[pool2 releaseObjects];
	}
	[ret replaceOccurrencesOfString: @"\n"
			     withString: @"\n\t"];
	[ret appendString: @"\n}"];

	[pool release];

	/*
	 * Class swizzle the string to be immutable. We declared the return type
	 * to be OFString*, so it can't be modified anyway. But not swizzling it
	 * would create a real copy each time -[copy] is called.
	 */
	ret->isa = [OFString class];
	return ret;
}
@end

@implementation OFDictionaryEnumerator
- initWithDictionary: (OFDictionary*)dictionary_
		data: (struct of_dictionary_bucket**)data_
		size: (uint32_t)size_







|

<

>

|
<

|
<
<
<
<
>
|
<
<
<
<
<
<

>
>
>



<

<

|
>
|
>
>
|
>
>
>
|
>

>
>
>
>
>
|
|



<
<
<



<
<
<
<
<
<
|







754
755
756
757
758
759
760
761
762

763
764
765
766

767
768




769
770






771
772
773
774
775
776
777

778

779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801



802
803
804






805
806
807
808
809
810
811
812
	 * to be OFString*, so it can't be modified anyway. But not swizzling it
	 * would create a real copy each time -[copy] is called.
	 */
	ret->isa = [OFString class];
	return ret;
}

- (OFXMLElement*)XMLElementBySerializing
{

	OFAutoreleasePool *pool, *pool2;
	OFXMLElement *element;
	OFEnumerator *keyEnumerator, *objectEnumerator;
	id <OFSerialization> key, object;


	element = [OFXMLElement elementWithName: @"object"




				      namespace: OF_SERIALIZATION_NS];







	pool = [[OFAutoreleasePool alloc] init];
	[element addAttributeWithName: @"class"
			  stringValue: [self className]];

	keyEnumerator = [self keyEnumerator];
	objectEnumerator = [self objectEnumerator];


	pool2 = [[OFAutoreleasePool alloc] init];

	while ((key = [keyEnumerator nextObject]) != nil &&
	       (object = [objectEnumerator nextObject]) != nil) {
		OFXMLElement *pair, *keyElement, *valueElement;

		pair = [OFXMLElement elementWithName: @"pair"
					   namespace: OF_SERIALIZATION_NS];

		keyElement = [OFXMLElement
		    elementWithName: @"key"
			  namespace: OF_SERIALIZATION_NS];
		[keyElement addChild: [key XMLElementBySerializing]];
		[pair addChild: keyElement];

		valueElement = [OFXMLElement
		    elementWithName: @"value"
			  namespace: OF_SERIALIZATION_NS];
		[valueElement addChild: [object XMLElementBySerializing]];
		[pair addChild: valueElement];

		[element addChild: pair];

		[pool2 releaseObjects];
	}




	[pool release];







	return element;
}
@end

@implementation OFDictionaryEnumerator
- initWithDictionary: (OFDictionary*)dictionary_
		data: (struct of_dictionary_bucket**)data_
		size: (uint32_t)size_

Modified src/OFList.m from [75df3d0578] to [60c8cd9af5].

16
17
18
19
20
21
22

23
24
25
26
27
28
29

#include "config.h"

#include "assert.h"

#import "OFList.h"
#import "OFString.h"

#import "OFAutoreleasePool.h"

#import "OFEnumerationMutationException.h"

#import "macros.h"

@implementation OFList







>







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

#include "config.h"

#include "assert.h"

#import "OFList.h"
#import "OFString.h"
#import "OFXMLElement.h"
#import "OFAutoreleasePool.h"

#import "OFEnumerationMutationException.h"

#import "macros.h"

@implementation OFList
319
320
321
322
323
324
325
326
327
328
329

330
331
332
333
334
335
336


337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
	 * to be OFString*, so it can't be modified anyway. But not swizzling it
	 * would create a real copy each time -[copy] is called.
	 */
	ret->isa = [OFString class];
	return ret;
}

- (OFString*)stringBySerializing
{
	OFMutableString *ret;
	OFAutoreleasePool *pool;

	of_list_object_t *iter;

	if (count == 0)
		return @"(list,mutable)[]";

	ret = [OFMutableString stringWithString: @"(list,mutable)[\n"];
	pool = [[OFAutoreleasePool alloc] init];



	for (iter = firstListObject; iter != NULL; iter = iter->next) {
		[ret appendString: [iter->object stringBySerializing]];

		if (iter->next != NULL)
			[ret appendString: @",\n"];

		[pool releaseObjects];
	}
	[ret replaceOccurrencesOfString: @"\n"
			     withString: @"\n\t"];
	[ret appendString: @"\n]"];

	[pool release];

	/*
	 * Class swizzle the string to be immutable. We declared the return type
	 * to be OFString*, so it can't be modified anyway. But not swizzling it
	 * would create a real copy each time -[copy] is called.
	 */
	ret->isa = [OFString class];
	return ret;
}

- (int)countByEnumeratingWithState: (of_fast_enumeration_state_t*)state
			   objects: (id*)objects
			     count: (int)count_
{
	of_list_object_t **list_obj = (of_list_object_t**)state->extra;

	state->itemsPtr = objects;
	state->mutationsPtr = &mutations;

	if (state->state == 0) {
		*list_obj = firstListObject;
		state->state = 1;
	}

	if (*list_obj == NULL)
		return 0;

	objects[0] = (*list_obj)->object;
	*list_obj = (*list_obj)->next;
	return 1;
}

- (OFEnumerator*)objectEnumerator
{
	return [[[OFListEnumerator alloc]
	        initWithList: self







|

<

>


|
|

<

>
>


<
|
<
<
<


<
<
<



<
<
<
<
<
<
|






|





|



|


|
|







320
321
322
323
324
325
326
327
328

329
330
331
332
333
334
335

336
337
338
339
340

341



342
343



344
345
346






347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
	 * to be OFString*, so it can't be modified anyway. But not swizzling it
	 * would create a real copy each time -[copy] is called.
	 */
	ret->isa = [OFString class];
	return ret;
}

- (OFXMLElement*)XMLElementBySerializing
{

	OFAutoreleasePool *pool;
	OFXMLElement *element;
	of_list_object_t *iter;

	element = [OFXMLElement elementWithName: @"object"
				      namespace: OF_SERIALIZATION_NS];


	pool = [[OFAutoreleasePool alloc] init];
	[element addAttributeWithName: @"class"
			  stringValue: [self className]];

	for (iter = firstListObject; iter != NULL; iter = iter->next) {

		[element addChild: [iter->object XMLElementBySerializing]];



		[pool releaseObjects];
	}




	[pool release];







	return element;
}

- (int)countByEnumeratingWithState: (of_fast_enumeration_state_t*)state
			   objects: (id*)objects
			     count: (int)count_
{
	of_list_object_t **listObject = (of_list_object_t**)state->extra;

	state->itemsPtr = objects;
	state->mutationsPtr = &mutations;

	if (state->state == 0) {
		*listObject = firstListObject;
		state->state = 1;
	}

	if (*listObject == NULL)
		return 0;

	objects[0] = (*listObject)->object;
	*listObject = (*listObject)->next;
	return 1;
}

- (OFEnumerator*)objectEnumerator
{
	return [[[OFListEnumerator alloc]
	        initWithList: self

Modified src/OFNumber.m from [2324ed47e6] to [01b0cb5868].

16
17
18
19
20
21
22


23
24
25
26
27
28
29

#include "config.h"

#include <math.h>

#import "OFNumber.h"
#import "OFString.h"



#import "OFInvalidFormatException.h"
#import "OFNotImplementedException.h"

#import "macros.h"

#define RETURN_AS(t)							\







>
>







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

#include "config.h"

#include <math.h>

#import "OFNumber.h"
#import "OFString.h"
#import "OFXMLElement.h"
#import "OFAutoreleasePool.h"

#import "OFInvalidFormatException.h"
#import "OFNotImplementedException.h"

#import "macros.h"

#define RETURN_AS(t)							\
1086
1087
1088
1089
1090
1091
1092
1093
1094












1095
1096

1097

1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130

1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164

1165
1166
1167
1168

1169

1170
1171

1172

1173
1174
1175
1176




1177
	case OF_NUMBER_DOUBLE:
		return [OFString stringWithFormat: @"%lf", value.double_];
	default:
		@throw [OFInvalidFormatException newWithClass: isa];
	}
}

- (OFString*)stringBySerializing
{












	switch (type) {
	case OF_NUMBER_BOOL:

		return (value.bool_ ? @"<BOOL>1" : @"<BOOL>0");

	case OF_NUMBER_UCHAR:
		return [OFString stringWithFormat: @"<unsigned char>%hhu",
						   value.uchar];
	case OF_NUMBER_USHORT:
		return [OFString stringWithFormat: @"<unsigned short>%hu",
						   value.ushort];
	case OF_NUMBER_UINT:
		return [OFString stringWithFormat: @"<unsigned int>%u",
						   value.uint];
	case OF_NUMBER_ULONG:
		return [OFString stringWithFormat: @"<unsigned long>%lu",
						   value.ulong];
	case OF_NUMBER_UINT8:
		return [OFString stringWithFormat: @"<uint8_t>%" @PRIu8,
						   value.uint8];
	case OF_NUMBER_UINT16:
		return [OFString stringWithFormat: @"<uint16_t>%" @PRIu16,
						   value.uint16];
	case OF_NUMBER_UINT32:
		return [OFString stringWithFormat: @"<uint32_t>%" @PRIu32,
						   value.uint32];
	case OF_NUMBER_UINT64:
		return [OFString stringWithFormat: @"<uint64_t>%" @PRIu64,
						   value.uint64];
	case OF_NUMBER_SIZE:
		return [OFString stringWithFormat: @"<size_t>%ju",
						   (uintmax_t)value.size];
	case OF_NUMBER_UINTMAX:
		return [OFString stringWithFormat: @"<uintmax_t>%ju",
						   value.uintmax];
	case OF_NUMBER_UINTPTR:
		return [OFString stringWithFormat: @"<uintptr_t>%" @PRIuPTR,
						   value.uintptr];

	case OF_NUMBER_CHAR:
		return [OFString stringWithFormat: @"<char>%hhd",
						   value.char_];
	case OF_NUMBER_SHORT:
		return [OFString stringWithFormat: @"<short>%hd",
						   value.short_];
	case OF_NUMBER_INT:
		return [OFString stringWithFormat: @"<int>%d",
						   value.int_];
	case OF_NUMBER_LONG:
		return [OFString stringWithFormat: @"<long>%ld",
						   value.long_];
	case OF_NUMBER_INT8:
		return [OFString stringWithFormat: @"<int8_t>%" @PRId8,
						   value.int8];
	case OF_NUMBER_INT16:
		return [OFString stringWithFormat: @"<int16_t>%" @PRId16,
						   value.int16];
	case OF_NUMBER_INT32:
		return [OFString stringWithFormat: @"<int32_t>%" @PRId32,
						   value.int32];
	case OF_NUMBER_INT64:
		return [OFString stringWithFormat: @"<int64_t>%" @PRId64,
						   value.int64];
	case OF_NUMBER_SSIZE:
		return [OFString stringWithFormat: @"<ssize_t>%jd",
						   (intmax_t)value.ssize];
	case OF_NUMBER_INTMAX:
		return [OFString stringWithFormat: @"<intmax_t>%jd",
						   value.intmax];
	case OF_NUMBER_PTRDIFF:
		return [OFString stringWithFormat: @"<ptrdiff_t>%td" @PRIdPTR,
						   value.ptrdiff];
	case OF_NUMBER_INTPTR:

		return [OFString stringWithFormat: @"<intptr_t>%" @PRIdPTR,
						   value.intptr];
	case OF_NUMBER_FLOAT:
		return [OFString stringWithFormat: @"<float>%f",

						   value.float_];

	case OF_NUMBER_DOUBLE:
		return [OFString stringWithFormat: @"<double>%lf",

						   value.double_];

	default:
		@throw [OFInvalidFormatException newWithClass: isa];
	}
}




@end







|

>
>
>
>
>
>
>
>
>
>
>
>


>
|
>

<
<

<
<

<
<

<
<

<
<

<
<

<
<

<
<

<
<

<
<

|
|
>

<
<

<
<

<
<

<
<

<
<

<
<

<
<

<
<

<
<

<
<

<
<

>
|
|

<
>
|
>

<
>
|
>



|
>
>
>
>

1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114


1115


1116


1117


1118


1119


1120


1121


1122


1123


1124
1125
1126
1127
1128


1129


1130


1131


1132


1133


1134


1135


1136


1137


1138


1139
1140
1141
1142
1143

1144
1145
1146
1147

1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
	case OF_NUMBER_DOUBLE:
		return [OFString stringWithFormat: @"%lf", value.double_];
	default:
		@throw [OFInvalidFormatException newWithClass: isa];
	}
}

- (OFXMLElement*)XMLElementBySerializing
{
	OFAutoreleasePool *pool;
	OFXMLElement *element;

	element = [OFXMLElement elementWithName: @"object"
				      namespace: OF_SERIALIZATION_NS];

	pool = [[OFAutoreleasePool alloc] init];

	[element addAttributeWithName: @"class"
			  stringValue: [self className]];
	[element setStringValue: [self description]];

	switch (type) {
	case OF_NUMBER_BOOL:
		[element addAttributeWithName: @"type"
				  stringValue: @"boolean"];
		break;
	case OF_NUMBER_UCHAR:


	case OF_NUMBER_USHORT:


	case OF_NUMBER_UINT:


	case OF_NUMBER_ULONG:


	case OF_NUMBER_UINT8:


	case OF_NUMBER_UINT16:


	case OF_NUMBER_UINT32:


	case OF_NUMBER_UINT64:


	case OF_NUMBER_SIZE:


	case OF_NUMBER_UINTMAX:


	case OF_NUMBER_UINTPTR:
		[element addAttributeWithName: @"type"
				  stringValue: @"unsigned"];
		break;
	case OF_NUMBER_CHAR:


	case OF_NUMBER_SHORT:


	case OF_NUMBER_INT:


	case OF_NUMBER_LONG:


	case OF_NUMBER_INT8:


	case OF_NUMBER_INT16:


	case OF_NUMBER_INT32:


	case OF_NUMBER_INT64:


	case OF_NUMBER_SSIZE:


	case OF_NUMBER_INTMAX:


	case OF_NUMBER_PTRDIFF:


	case OF_NUMBER_INTPTR:
		[element addAttributeWithName: @"type"
				  stringValue: @"signed"];
		break;
	case OF_NUMBER_FLOAT:

		[element addAttributeWithName: @"type"
				  stringValue: @"float"];
		break;
	case OF_NUMBER_DOUBLE:

		[element addAttributeWithName: @"type"
				  stringValue: @"double"];
		break;
	default:
		@throw [OFInvalidFormatException newWithClass: isa];
	}

	[pool release];

	return element;
}
@end

Modified src/OFSerialization.h from [c6e17d739a] to [14e103c34d].

11
12
13
14
15
16
17



18
19
20
21
22
23
24


25
26
27
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

@class OFString;




/**
 * \brief A protocol for serializing objects.
 */
@protocol OFSerialization <OFObject>
/**
 * \brief Serializes the object into a string.


 */
- (OFString*)stringBySerializing;
@end







>
>
>






|
>
>

|

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

@class OFString;
@class OFXMLElement;

#define OF_SERIALIZATION_NS @"https://webkeks.org/objfw/serialization"

/**
 * \brief A protocol for serializing objects.
 */
@protocol OFSerialization <OFObject>
/**
 * \brief Serializes the object into an XML element.
 *
 * \return The object serialized into an XML element
 */
- (OFXMLElement*)XMLElementBySerializing;
@end

Modified src/OFString.m from [bb52ca9d4f] to [47a649e523].

32
33
34
35
36
37
38

39
40
41
42
43
44
45

#import "OFString.h"
#import "OFArray.h"
#import "OFDictionary.h"
#import "OFFile.h"
#import "OFURL.h"
#import "OFHTTPRequest.h"

#import "OFAutoreleasePool.h"

#import "OFHTTPRequestFailedException.h"
#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFInvalidEncodingException.h"
#import "OFInvalidFormatException.h"







>







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

#import "OFString.h"
#import "OFArray.h"
#import "OFDictionary.h"
#import "OFFile.h"
#import "OFURL.h"
#import "OFHTTPRequest.h"
#import "OFXMLElement.h"
#import "OFAutoreleasePool.h"

#import "OFHTTPRequestFailedException.h"
#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFInvalidEncodingException.h"
#import "OFInvalidFormatException.h"
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070

1071
1072

1073
1074
1075
1076
1077

1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
}

- (OFString*)description
{
	return [[self copy] autorelease];
}

- (OFString*)stringBySerializing
{
	OFMutableString *serialization = [[self mutableCopy] autorelease];
	[serialization replaceOccurrencesOfString: @"\\"
				       withString: @"\\\\"];
	[serialization replaceOccurrencesOfString: @"\""
				       withString: @"\\\""];
	[serialization replaceOccurrencesOfString: @"\n"
				       withString: @"\\n\"\n    \""];
	[serialization replaceOccurrencesOfString: @"\r"
				       withString: @"\\r"];
	[serialization replaceOccurrencesOfString: @"\t"
				       withString: @"\\t"];


	if ([self isKindOfClass: [OFMutableString class]])

		[serialization prependString: @"(mutable)\""];
	else
		[serialization prependString: @"\""];
	[serialization appendString: @"\""];


	/*
	 * Class swizzle the string to be immutable. We declared the return type
	 * to be OFString*, so it can't be modified anyway. But not swizzling it
	 * would create a real copy each time -[copy] is called.
	 */
	serialization->isa = [OFString class];
	return serialization;
}

- (of_unichar_t)characterAtIndex: (size_t)index
{
	of_unichar_t c;

	if (![self isUTF8]) {







|

|
|
|
|
|
<
<
<
|
|
<
>

|
>
|

|
|

>
|
<
<
<
<
<
|







1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065



1066
1067

1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078





1079
1080
1081
1082
1083
1084
1085
1086
}

- (OFString*)description
{
	return [[self copy] autorelease];
}

- (OFXMLElement*)XMLElementBySerializing
{
	OFAutoreleasePool *pool;
	OFXMLElement *element;

	element = [OFXMLElement elementWithName: @"object"
				      namespace: OF_SERIALIZATION_NS



				    stringValue: self];


	pool = [[OFAutoreleasePool alloc] init];

	if ([self isKindOfClass: [OFConstantString class]])
		[element addAttributeWithName: @"class"
				  stringValue: @"OFString"];
	else
		[element addAttributeWithName: @"class"
				  stringValue: [self className]];

	[pool release];






	return element;
}

- (of_unichar_t)characterAtIndex: (size_t)index
{
	of_unichar_t c;

	if (![self isUTF8]) {

Modified src/OFURL.m from [267c53672b] to [8362d51987].

19
20
21
22
23
24
25

26
27
28
29
30
31
32
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#import "OFURL.h"
#import "OFString.h"
#import "OFArray.h"

#import "OFAutoreleasePool.h"

#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFOutOfMemoryException.h"

#import "macros.h"







>







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#import "OFURL.h"
#import "OFString.h"
#import "OFArray.h"
#import "OFXMLElement.h"
#import "OFAutoreleasePool.h"

#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFOutOfMemoryException.h"

#import "macros.h"
526
527
528
529
530
531
532
533
534
535
536
537
538

539
540
541
542
543


544

545
546
547
548
}

- (OFString*)description
{
	return [self string];
}

- (OFString*)stringBySerializing
{
	OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
	OFString *ret = [[OFString alloc]
	    initWithFormat: @"(class=OFURL,version=0)<%@>",
			    [[self string] stringBySerializing]];


	@try {
		[pool release];
	} @finally {
		[ret autorelease];


	}


	return ret;
}
@end







|

|
|
|
|
>

<
|
|
|
>
>
|
>

|


527
528
529
530
531
532
533
534
535
536
537
538
539
540
541

542
543
544
545
546
547
548
549
550
551
552
}

- (OFString*)description
{
	return [self string];
}

- (OFXMLElement*)XMLElementBySerializing
{
	OFAutoreleasePool *pool;
	OFXMLElement *element;

	element = [OFXMLElement elementWithName: @"object"
				      namespace: OF_SERIALIZATION_NS];


	pool = [[OFAutoreleasePool alloc] init];

	[element addAttributeWithName: @"class"
			  stringValue: [self className]];
	[element setStringValue: [self string]];

	[pool release];

	return element;
}
@end

Modified src/OFXMLAttribute.m from [a0cfce89af] to [be193dc061].

15
16
17
18
19
20
21

22
23
24
25
26
27
28
 */

#include "config.h"

#import "OFXMLAttribute.h"
#import "OFString.h"
#import "OFDictionary.h"

#import "OFAutoreleasePool.h"

@implementation OFXMLAttribute
+ attributeWithName: (OFString*)name
	  namespace: (OFString*)ns
	stringValue: (OFString*)value
{







>







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 */

#include "config.h"

#import "OFXMLAttribute.h"
#import "OFString.h"
#import "OFDictionary.h"
#import "OFXMLElement.h"
#import "OFAutoreleasePool.h"

@implementation OFXMLAttribute
+ attributeWithName: (OFString*)name
	  namespace: (OFString*)ns
	stringValue: (OFString*)value
{
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
}

- (OFString*)stringValue
{
	return [[stringValue copy] autorelease];
}

- (OFString*)stringBySerializing
{
	OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];

	OFMutableDictionary *dictionary = [OFMutableDictionary dictionary];


	OFString *ret;


	if (name != nil)

		[dictionary setObject: name

			       forKey: @"name"];


	if (ns != nil)
		[dictionary setObject: ns

			       forKey: @"namespace"];

	if (stringValue != nil)
		[dictionary setObject: stringValue

			       forKey: @"stringValue"];

	dictionary->isa = [OFDictionary class];

	ret = [[OFString alloc]
	    initWithFormat: @"(class=OFXMLElement,version=0)<%@>",
			    [dictionary stringBySerializing]];

	@try {
		[pool release];
	} @finally {
		[ret autorelease];
	}

	return ret;
}
@end







|

|
>
|
>
>
|
>

|
>
|
>
|
>
>

<
>
|
>
|
<
>
|
|
<
|
<
<
<

<
|
<
<
|
<
|


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
}

- (OFString*)stringValue
{
	return [[stringValue copy] autorelease];
}

- (OFXMLElement*)XMLElementBySerializing
{
	OFAutoreleasePool *pool;
	OFXMLElement *element;

	element = [OFXMLElement elementWithName: @"object"
				      namespace: OF_SERIALIZATION_NS];

	pool = [[OFAutoreleasePool alloc] init];

	[element addAttributeWithName: @"class"
			  stringValue: [self className]];

	[element addChild:
	    [OFXMLElement elementWithName: @"name"
				namespace: OF_SERIALIZATION_NS
			      stringValue: name]];
	if (ns != nil)

		[element addChild:
		    [OFXMLElement elementWithName: @"namespace"
					namespace: OF_SERIALIZATION_NS
				      stringValue: ns]];

	[element addChild:
	    [OFXMLElement elementWithName: @"stringValue"
				namespace: OF_SERIALIZATION_NS

			      stringValue: stringValue]];





	[pool release];




	return element;
}
@end

Modified src/OFXMLElement.m from [dfde4a28b8] to [d290a6e873].

564
565
566
567
568
569
570
571
572
573

574


575




576
577



578
579
580



581
582
583

584

585

586


587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605


606
607
608


609

610
611


612






613





614





615





616


617
618
619
620
621
622
623
624
}

- (OFString*)description
{
	return [self XMLString];
}

- (OFString*)stringBySerializing
{
	OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];

	OFMutableDictionary *dictionary = [OFMutableDictionary dictionary];


	OFString *ret;





	if (name != nil)



		[dictionary setObject: name
			       forKey: @"name"];
	if (ns != nil)



		[dictionary setObject: ns
			       forKey: @"namespace"];
	if (defaultNamespace != nil)

		[dictionary setObject: defaultNamespace

			       forKey: @"defaultNamespace"];

	if (attributes != nil)


		[dictionary setObject: attributes
			       forKey: @"attributes"];
	if (namespaces != nil)
		[dictionary setObject: namespaces
			       forKey: @"namespaces"];
	if (children != nil)
		[dictionary setObject: children
			       forKey: @"children"];
	if (characters != nil)
		[dictionary setObject: characters
			       forKey: @"characters"];
	if (CDATA != nil)
		[dictionary setObject: CDATA
			       forKey: @"CDATA"];
	if (comment != nil)
		[dictionary setObject: comment
			       forKey: @"comment"];

	dictionary->isa = [OFDictionary class];



	ret = [[OFString alloc]
	    initWithFormat: @"(class=OFXMLElement,version=0)<%@>",


			    [dictionary stringBySerializing]];


	@try {


		[pool release];






	} @finally {





		[ret autorelease];





	}








	return ret;
}

- (void)addAttribute: (OFXMLAttribute*)attribute
{
	if (name == nil)
		@throw [OFInvalidArgumentException newWithClass: isa
						       selector: _cmd];







|

|
>
|
>
>
|
>
>
>
>


>
>
>
|
|

>
>
>
|
|

>
|
>
|
>
|
>
>
|
|
|
<
<
<
<
<
<
<
<
<
<
<
|
|
|
|
|
>
>

|
|
>
>
|
>
|
|
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>

>
>
|







564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607











608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
}

- (OFString*)description
{
	return [self XMLString];
}

- (OFXMLElement*)XMLElementBySerializing
{
	OFAutoreleasePool *pool;
	OFXMLElement *element;

	element = [OFXMLElement elementWithName: @"object"
				      namespace: OF_SERIALIZATION_NS];

	pool = [[OFAutoreleasePool alloc] init];

	[element addAttributeWithName: @"class"
			  stringValue: [self className]];

	if (name != nil)
		[element addChild:
		    [OFXMLElement elementWithName: @"name"
					namespace: OF_SERIALIZATION_NS
				      stringValue: name]];

	if (ns != nil)
		[element addChild:
		    [OFXMLElement elementWithName: @"namespace"
					namespace: OF_SERIALIZATION_NS
				      stringValue: ns]];

	if (defaultNamespace != nil)
		[element addChild:
		    [OFXMLElement elementWithName: @"defaultNamespace"
					namespace: OF_SERIALIZATION_NS
				      stringValue: defaultNamespace]];

	if (attributes != nil) {
		OFXMLElement *attributesElement;

		attributesElement =
		    [OFXMLElement elementWithName: @"attributes"
					namespace: OF_SERIALIZATION_NS];











		[attributesElement addChild:
		    [attributes XMLElementBySerializing]];
		[element addChild: attributesElement];
	}

	if (namespaces != nil) {
		OFXMLElement *namespacesElement;

		namespacesElement =
		    [OFXMLElement elementWithName: @"namespaces"
					namespace: OF_SERIALIZATION_NS];
		[namespacesElement addChild:
		    [namespaces XMLElementBySerializing]];
		[element addChild: namespacesElement];
	}

	if (children != nil) {
		OFXMLElement *childrenElement;

		childrenElement =
		    [OFXMLElement elementWithName: @"children"
					namespace: OF_SERIALIZATION_NS];
		[childrenElement addChild: [children XMLElementBySerializing]];
		[element addChild: childrenElement];
	}

	if (characters != nil)
		[element addChild:
		    [OFXMLElement elementWithName: @"characters"
					namespace: OF_SERIALIZATION_NS
				      stringValue: characters]];

	if (CDATA != nil)
		[element addChild:
		    [OFXMLElement elementWithName: @"CDATA"
					namespace: OF_SERIALIZATION_NS
				      stringValue: CDATA]];

	if (comment != nil)
		[element addChild:
		    [OFXMLElement elementWithName: @"comment"
					namespace: OF_SERIALIZATION_NS
				      stringValue: comment]];

	[pool release];

	return element;
}

- (void)addAttribute: (OFXMLAttribute*)attribute
{
	if (name == nil)
		@throw [OFInvalidArgumentException newWithClass: isa
						       selector: _cmd];