ObjFW  Check-in [6a92704355]

Overview
Comment:Key Value Coding: Implement auto-wrapping
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 6a9270435531511ba53003bd13ef0b824ea46a6ac0f189230330cbbfecb5f4ad
User & Date: js on 2016-06-05 13:18:49
Other Links: manifest | tags
Context
2016-06-05
13:32
configure: Use -Wobjc-missing-property-synthesis check-in: 9a0fd366ad user: js tags: trunk
13:18
Key Value Coding: Implement auto-wrapping check-in: 6a92704355 user: js tags: trunk
00:01
Add OFKeyValueCoding check-in: 3ad1f2b268 user: js tags: trunk
Changes

Modified src/OFObject+KeyValueCoding.m from [76ddc597a2] to [8b1cd7f8e8].

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

#include <stdlib.h>
#include <ctype.h>

#import "OFObject.h"
#import "OFObject+KeyValueCoding.h"
#import "OFString.h"
#import "OFNull.h"

#import "OFOutOfMemoryException.h"
#import "OFUndefinedKeyException.h"

int _OFObject_KeyValueCoding_reference;

static bool
checkTypeEncoding(const char *typeEncoding, char returnType, ...)
{
	va_list args;
	char type;

	if (typeEncoding == NULL)
		return false;

	if (*typeEncoding++ != returnType)
		return false;

	while (*typeEncoding >= '0' && *typeEncoding <= '9')
		typeEncoding++;

	va_start(args, returnType);

	while ((type = va_arg(args, int)) != 0) {
		if (*typeEncoding++ != type)
			return false;

		while (*typeEncoding >= '0' && *typeEncoding <= '9')
			typeEncoding++;
	}

	if (*typeEncoding != '\0')
		return false;

	return true;
}

@implementation OFObject (KeyValueCoding)
- (id)valueForKey: (OFString*)key
{
	SEL selector = sel_registerName([key UTF8String]);
	const char *typeEncoding = [self typeEncodingForSelector: selector];































	if (!checkTypeEncoding(typeEncoding, '@', '@', ':', 0))


		return [self valueForUndefinedKey: key];

	return [self performSelector: selector];
}

- (id)valueForUndefinedKey: (OFString*)key
{
	@throw [OFUndefinedKeyException exceptionWithObject: self
							key: key];
}

- (void)setValue: (id)value
	  forKey: (OFString*)key
{
	char *name;
	size_t keyLength;

	SEL selector;
	const char *typeEncoding;
	id (*setter)(id, SEL, id);

	keyLength = [key UTF8StringLength];

	if (keyLength < 1) {
		[self	 setValue: value
		  forUndefinedKey: key];
		return;
	}

	if ((name = malloc(keyLength + 5)) == NULL)
		@throw [OFOutOfMemoryException







|






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

|
|
|
<
<
|
<
<







>

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


|











<

>


|

|
<
<







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

#include <stdlib.h>
#include <ctype.h>

#import "OFObject.h"
#import "OFObject+KeyValueCoding.h"
#import "OFString.h"
#import "OFNumber.h"

#import "OFOutOfMemoryException.h"
#import "OFUndefinedKeyException.h"

int _OFObject_KeyValueCoding_reference;

static char OF_INLINE












nextType(const char **typeEncoding)
{



	char ret = *(*typeEncoding)++;


	while (**typeEncoding >= '0' && **typeEncoding <= '9')
		(*typeEncoding)++;



	return ret;


}

@implementation OFObject (KeyValueCoding)
- (id)valueForKey: (OFString*)key
{
	SEL selector = sel_registerName([key UTF8String]);
	const char *typeEncoding = [self typeEncodingForSelector: selector];
	id ret;

	switch (nextType(&typeEncoding)) {
	case '@':
		ret = [self performSelector: selector];
		break;
#define CASE(encoding, type, method)					  \
	case encoding:							  \
		{							  \
			type (*getter)(id, SEL) = (type(*)(id, SEL))	  \
			    [self methodForSelector: selector];		  \
			ret = [OFNumber method getter(self, selector)]; \
		}							  \
		break;
	CASE('B', bool, numberWithBool:)
	CASE('c', char, numberWithChar:)
	CASE('s', short, numberWithShort:)
	CASE('i', int, numberWithInt:)
	CASE('l', long, numberWithLong:)
	CASE('q', long long, numberWithLongLong:)
	CASE('C', unsigned char, numberWithUnsignedChar:)
	CASE('S', unsigned short, numberWithUnsignedShort:)
	CASE('I', unsigned int, numberWithUnsignedInt:)
	CASE('L', unsigned long, numberWithUnsignedLong:)
	CASE('Q', unsigned long long, numberWithUnsignedLongLong:)
	CASE('f', float, numberWithFloat:)
	CASE('d', double, numberWithDouble:)
#undef CASE
	default:
		return [self valueForUndefinedKey: key];
	}

	if (nextType(&typeEncoding) != '@' || nextType(&typeEncoding) != ':' ||
	    *typeEncoding != 0)
		return [self valueForUndefinedKey: key];

	return ret;
}

- (id)valueForUndefinedKey: (OFString*)key
{
	@throw [OFUndefinedKeyException exceptionWithObject: self
							key: key];
}

- (void)setValue: (id)value
	  forKey: (OFString*)key
{

	size_t keyLength;
	char *name;
	SEL selector;
	const char *typeEncoding;
	char valueType;

	if ((keyLength = [key UTF8StringLength]) < 1) {


		[self	 setValue: value
		  forUndefinedKey: key];
		return;
	}

	if ((name = malloc(keyLength + 5)) == NULL)
		@throw [OFOutOfMemoryException
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

	selector = sel_registerName(name);

	free(name);

	typeEncoding = [self typeEncodingForSelector: selector];







	if (!checkTypeEncoding(typeEncoding, 'v', '@', ':', '@', 0)) {



		[self	 setValue: value
		  forUndefinedKey: key];
		return;
	}





	setter = (id(*)(id, SEL, id))[self methodForSelector: selector];
	setter(self, selector, value);






























}

-  (void)setValue: (id)value
  forUndefinedKey: (OFString*)key
{
	@throw [OFUndefinedKeyException exceptionWithObject: self
							key: key
						      value: value];
}
@end







>
>
>
>
>
>
|
>
>
>
|




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










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

	selector = sel_registerName(name);

	free(name);

	typeEncoding = [self typeEncodingForSelector: selector];

	if (nextType(&typeEncoding) != 'v' || nextType(&typeEncoding) != '@' ||
	    nextType(&typeEncoding) != ':') {
		[self    setValue: value
		  forUndefinedKey: key];
		return;
	}

	valueType = nextType(&typeEncoding);

	if (*typeEncoding != 0) {
		[self    setValue: value
		  forUndefinedKey: key];
		return;
	}

	switch (valueType) {
	case '@':
		{
			void (*setter)(id, SEL, id) = (void(*)(id, SEL, id))
			    [self methodForSelector: selector];
			setter(self, selector, value);
		}
		break;
#define CASE(encoding, type, method) \
	case encoding:						\
		{						\
			void (*setter)(id, SEL, type) =		\
			    (void(*)(id, SEL, type))		\
			    [self methodForSelector: selector];	\
			setter(self, selector, [value method]);	\
		}						\
		break;
	CASE('B', bool, boolValue)
	CASE('c', char, charValue)
	CASE('s', short, shortValue)
	CASE('i', int, intValue)
	CASE('l', long, longValue)
	CASE('q', long long, longLongValue)
	CASE('C', unsigned char, unsignedCharValue)
	CASE('S', unsigned short, unsignedShortValue)
	CASE('I', unsigned int, unsignedIntValue)
	CASE('L', unsigned long, unsignedLongValue)
	CASE('Q', unsigned long long, unsignedLongLongValue)
	CASE('f', float, floatValue)
	CASE('d', double, doubleValue)
#undef CASE
	default:
		[self    setValue: value
		  forUndefinedKey: key];
		return;
	}
}

-  (void)setValue: (id)value
  forUndefinedKey: (OFString*)key
{
	@throw [OFUndefinedKeyException exceptionWithObject: self
							key: key
						      value: value];
}
@end

Modified src/ObjFW.h from [c7a3d9e2ec] to [24be143b49].

159
160
161
162
163
164
165

166
167
168
169
170
171
172
#ifdef OF_HAVE_THREADS
# import "OFThreadJoinFailedException.h"
# import "OFThreadStartFailedException.h"
# import "OFThreadStillRunningException.h"
#endif
#import "OFTruncatedDataException.h"
#import "OFUnboundNamespaceException.h"

#import "OFUnlockFailedException.h"
#import "OFUnsupportedProtocolException.h"
#import "OFUnsupportedVersionException.h"
#import "OFWriteFailedException.h"

#ifdef OF_HAVE_PLUGINS
# import "OFPlugin.h"







>







159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#ifdef OF_HAVE_THREADS
# import "OFThreadJoinFailedException.h"
# import "OFThreadStartFailedException.h"
# import "OFThreadStillRunningException.h"
#endif
#import "OFTruncatedDataException.h"
#import "OFUnboundNamespaceException.h"
#import "OFUndefinedKeyException.h"
#import "OFUnlockFailedException.h"
#import "OFUnsupportedProtocolException.h"
#import "OFUnsupportedVersionException.h"
#import "OFWriteFailedException.h"

#ifdef OF_HAVE_PLUGINS
# import "OFPlugin.h"