Index: ObjFW.xcodeproj/project.pbxproj ================================================================== --- ObjFW.xcodeproj/project.pbxproj +++ ObjFW.xcodeproj/project.pbxproj @@ -185,10 +185,12 @@ 4B3D23E91337FCB000DD29B8 /* of_asprintf.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BB50DCF12F863C700C9393F /* of_asprintf.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B3D23EA1337FCB000DD29B8 /* threading.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B67998B1099E7C50041064A /* threading.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B3D23EB1337FCB000DD29B8 /* unicode.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B67998C1099E7C50041064A /* unicode.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B3D23EE1337FFD000DD29B8 /* of_asprintf.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BB50DD012F863C700C9393F /* of_asprintf.m */; }; 4B3D5694139A617D0010A78F /* OFSerializationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B3D5693139A617D0010A78F /* OFSerializationTests.m */; }; + 4B511B7C139C0A34003764A5 /* OFNull.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B511B7A139C0A34003764A5 /* OFNull.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4B511B7D139C0A34003764A5 /* OFNull.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B511B7B139C0A34003764A5 /* OFNull.m */; }; 4B55A0FF133ABEA900B58A93 /* OFThreadJoinFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B55A0F9133ABEA900B58A93 /* OFThreadJoinFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B55A100133ABEA900B58A93 /* OFThreadJoinFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B55A0FA133ABEA900B58A93 /* OFThreadJoinFailedException.m */; }; 4B55A101133ABEA900B58A93 /* OFThreadStartFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B55A0FB133ABEA900B58A93 /* OFThreadStartFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B55A102133ABEA900B58A93 /* OFThreadStartFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B55A0FC133ABEA900B58A93 /* OFThreadStartFailedException.m */; }; 4B55A103133ABEA900B58A93 /* OFThreadStillRunningException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B55A0FD133ABEA900B58A93 /* OFThreadStillRunningException.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -399,10 +401,12 @@ 4B3D23EF1338008000DD29B8 /* mach_alias_list */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = mach_alias_list; path = src/mach_alias_list; sourceTree = SOURCE_ROOT; }; 4B3D5693139A617D0010A78F /* OFSerializationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFSerializationTests.m; path = tests/OFSerializationTests.m; sourceTree = ""; }; 4B4986DF1101F64500A2CFDA /* objc_properties.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = objc_properties.m; path = src/objc_properties.m; sourceTree = ""; }; 4B4A61F212DF5EA20048F3F2 /* OFURL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFURL.h; path = src/OFURL.h; sourceTree = SOURCE_ROOT; }; 4B4A61F312DF5EA20048F3F2 /* OFURL.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFURL.m; path = src/OFURL.m; sourceTree = SOURCE_ROOT; }; + 4B511B7A139C0A34003764A5 /* OFNull.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFNull.h; path = src/OFNull.h; sourceTree = ""; }; + 4B511B7B139C0A34003764A5 /* OFNull.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFNull.m; path = src/OFNull.m; sourceTree = ""; }; 4B55A0F9133ABEA900B58A93 /* OFThreadJoinFailedException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFThreadJoinFailedException.h; path = src/exceptions/OFThreadJoinFailedException.h; sourceTree = ""; }; 4B55A0FA133ABEA900B58A93 /* OFThreadJoinFailedException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFThreadJoinFailedException.m; path = src/exceptions/OFThreadJoinFailedException.m; sourceTree = ""; }; 4B55A0FB133ABEA900B58A93 /* OFThreadStartFailedException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFThreadStartFailedException.h; path = src/exceptions/OFThreadStartFailedException.h; sourceTree = ""; }; 4B55A0FC133ABEA900B58A93 /* OFThreadStartFailedException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFThreadStartFailedException.m; path = src/exceptions/OFThreadStartFailedException.m; sourceTree = ""; }; 4B55A0FD133ABEA900B58A93 /* OFThreadStillRunningException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFThreadStillRunningException.h; path = src/exceptions/OFThreadStillRunningException.h; sourceTree = ""; }; @@ -784,10 +788,12 @@ 4B6799701099E7C50041064A /* OFMutableArray.m */, 4B6799711099E7C50041064A /* OFMutableDictionary.h */, 4B6799721099E7C50041064A /* OFMutableDictionary.m */, 4B6799731099E7C50041064A /* OFMutableString.h */, 4B6799741099E7C50041064A /* OFMutableString.m */, + 4B511B7A139C0A34003764A5 /* OFNull.h */, + 4B511B7B139C0A34003764A5 /* OFNull.m */, 4B6799751099E7C50041064A /* OFNumber.h */, 4B6799761099E7C50041064A /* OFNumber.m */, 4B6799771099E7C50041064A /* OFObject.h */, 4B6799781099E7C50041064A /* OFObject.m */, 4B6799791099E7C50041064A /* OFPlugin.h */, @@ -950,10 +956,11 @@ 4B3D23CB1337FCB000DD29B8 /* OFList.h in Headers */, 4B3D23CC1337FCB000DD29B8 /* OFMD5Hash.h in Headers */, 4B3D23CD1337FCB000DD29B8 /* OFMutableArray.h in Headers */, 4B3D23CE1337FCB000DD29B8 /* OFMutableDictionary.h in Headers */, 4B3D23CF1337FCB000DD29B8 /* OFMutableString.h in Headers */, + 4B511B7C139C0A34003764A5 /* OFNull.h in Headers */, 4B3D23D01337FCB000DD29B8 /* OFNumber.h in Headers */, 4B3D23D11337FCB000DD29B8 /* OFObject.h in Headers */, 4B3D23D21337FCB000DD29B8 /* OFPlugin.h in Headers */, 4B3D23D31337FCB000DD29B8 /* OFSeekableStream.h in Headers */, 4B989C2F13771A3700109A30 /* OFSerialization.h in Headers */, @@ -1275,10 +1282,11 @@ 4B17FFAA133A34E7003E6DCD /* OFTruncatedDataException.m in Sources */, 4B17FFB6133A375B003E6DCD /* OFUnboundNamespaceException.m in Sources */, 4B17FFB2133A3664003E6DCD /* OFUnsupportedProtocolException.m in Sources */, 4B55A117133AC24600B58A93 /* OFWriteFailedException.m in Sources */, 4BC5E7D6137F0D0E0076F962 /* OFSerialization.m in Sources */, + 4B511B7D139C0A34003764A5 /* OFNull.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 4BF33AEC133807310059CEF7 /* Sources */ = { isa = PBXSourcesBuildPhase; Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -23,10 +23,11 @@ OFList.m \ OFMD5Hash.m \ OFMutableArray.m \ OFMutableDictionary.m \ OFMutableString.m \ + OFNull.m \ OFNumber.m \ OFObject.m \ ${OFPLUGIN_M} \ OFSeekableStream.m \ OFSerialization.m \ Index: src/OFArray.m ================================================================== --- src/OFArray.m +++ src/OFArray.m @@ -238,11 +238,11 @@ pool = [[OFAutoreleasePool alloc] init]; if (![[element name] isEqual: @"object"] || ![[element namespace] isEqual: OF_SERIALIZATION_NS] || ![[[element attributeForName: @"class"] stringValue] - isEqual: [isa className]]) + isEqual: [self className]]) @throw [OFInvalidArgumentException newWithClass: isa selector: _cmd]; enumerator = [[element elementsForName: @"object" Index: src/OFDate.m ================================================================== --- src/OFDate.m +++ src/OFDate.m @@ -253,11 +253,11 @@ OFXMLElement *secondsElement, *microsecondsElement; if (![[element name] isEqual: @"object"] || ![[element namespace] isEqual: OF_SERIALIZATION_NS] || ![[[element attributeForName: @"class"] stringValue] - isEqual: [isa className]]) + isEqual: [self className]]) @throw [OFInvalidArgumentException newWithClass: isa selector: _cmd]; secondsElement = [element elementForName: @"seconds" namespace: OF_SERIALIZATION_NS]; Index: src/OFDictionary.m ================================================================== --- src/OFDictionary.m +++ src/OFDictionary.m @@ -487,11 +487,11 @@ pool = [[OFAutoreleasePool alloc] init]; if (![[element name] isEqual: @"object"] || ![[element namespace] isEqual: OF_SERIALIZATION_NS] || ![[[element attributeForName: @"class"] stringValue] - isEqual: [isa className]]) + isEqual: [self className]]) @throw [OFInvalidArgumentException newWithClass: isa selector: _cmd]; dictionary = [OFMutableDictionary dictionary]; pairs = [element elementsForName: @"pair" Index: src/OFList.m ================================================================== --- src/OFList.m +++ src/OFList.m @@ -46,11 +46,11 @@ pool = [[OFAutoreleasePool alloc] init]; if (![[element name] isEqual: @"object"] || ![[element namespace] isEqual: OF_SERIALIZATION_NS] || ![[[element attributeForName: @"class"] stringValue] - isEqual: [isa className]]) + isEqual: [self className]]) @throw [OFInvalidArgumentException newWithClass: isa selector: _cmd]; enumerator = [[element elementsForName: @"object" ADDED src/OFNull.h Index: src/OFNull.h ================================================================== --- src/OFNull.h +++ src/OFNull.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * 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. + */ + +#import "OFObject.h" +#import "OFSerialization.h" + +/** + * \brief A class for representing null values in collections. + */ +@interface OFNull: OFObject +/** + * \brief Returns an OFNull singleton. + * + * \return An OFNull singleton + */ ++ null; +@end ADDED src/OFNull.m Index: src/OFNull.m ================================================================== --- src/OFNull.m +++ src/OFNull.m @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * 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. + */ + +#include "config.h" + +#import "OFNull.h" +#import "OFString.h" +#import "OFXMLElement.h" +#import "OFAutoreleasePool.h" + +#import "OFInvalidArgumentException.h" +#import "OFNotImplementedException.h" + +static OFNull *null = nil; + +@implementation OFNull ++ null +{ + if (null != nil) + return null; + + null = [[self alloc] init]; + + return null; +} + +- initWithSerialization: (OFXMLElement*)element +{ + OFAutoreleasePool *pool; + + [self release]; + + pool = [[OFAutoreleasePool alloc] init]; + + if (![[element name] isEqual: @"object"] || + ![[element namespace] isEqual: OF_SERIALIZATION_NS] || + ![[[element attributeForName: @"class"] stringValue] + isEqual: [self className]]) + @throw [OFInvalidArgumentException newWithClass: isa + selector: _cmd]; + + [pool release]; + + return [OFNull null]; +} + +- (OFString*)description +{ + return @""; +} + +- copy +{ + return self; +} + +- (OFXMLElement*)XMLElementBySerializing +{ + OFXMLElement *element; + + element = [OFXMLElement elementWithName: @"object" + namespace: OF_SERIALIZATION_NS]; + [element addAttributeWithName: @"class" + stringValue: [self className]]; + + return element; +} + +- autorelease +{ + return self; +} + +- retain +{ + return self; +} + +- (void)release +{ +} + +- (unsigned int)retainCount +{ + return OF_RETAIN_COUNT_MAX; +} + +- (void)dealloc +{ + @throw [OFNotImplementedException newWithClass: isa + selector: _cmd]; + [super dealloc]; /* Get rid of a stupid warning */ +} +@end Index: src/OFNumber.m ================================================================== --- src/OFNumber.m +++ src/OFNumber.m @@ -717,11 +717,11 @@ OFString *typeString; if (![[element name] isEqual: @"object"] || ![[element namespace] isEqual: OF_SERIALIZATION_NS] || ![[[element attributeForName: @"class"] stringValue] - isEqual: [isa className]]) + isEqual: [self className]]) @throw [OFInvalidArgumentException newWithClass: isa selector: _cmd]; typeString = [[element attributeForName: @"type"] stringValue]; Index: src/OFString.m ================================================================== --- src/OFString.m +++ src/OFString.m @@ -1080,11 +1080,11 @@ OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; if (![[element name] isEqual: @"object"] || ![[element namespace] isEqual: OF_SERIALIZATION_NS] || ![[[element attributeForName: @"class"] stringValue] - isEqual: [isa className]]) + isEqual: [self className]]) @throw [OFInvalidArgumentException newWithClass: isa selector: _cmd]; self = [self initWithString: [element stringValue]]; Index: src/OFURL.m ================================================================== --- src/OFURL.m +++ src/OFURL.m @@ -290,11 +290,11 @@ OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; if (![[element name] isEqual: @"object"] || ![[element namespace] isEqual: OF_SERIALIZATION_NS] || ![[[element attributeForName: @"class"] stringValue] - isEqual: [isa className]]) + isEqual: [self className]]) @throw [OFInvalidArgumentException newWithClass: isa selector: _cmd]; self = [self initWithString: [element stringValue]]; Index: src/OFXMLAttribute.m ================================================================== --- src/OFXMLAttribute.m +++ src/OFXMLAttribute.m @@ -62,11 +62,11 @@ OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; if (![[element name] isEqual: @"object"] || ![[element namespace] isEqual: OF_SERIALIZATION_NS] || ![[[element attributeForName: @"class"] stringValue] - isEqual: [isa className]]) + isEqual: [self className]]) @throw [OFInvalidArgumentException newWithClass: isa selector: _cmd]; name = [[[element elementForName: @"name" Index: src/OFXMLElement.m ================================================================== --- src/OFXMLElement.m +++ src/OFXMLElement.m @@ -287,11 +287,11 @@ OFXMLElement *childrenElement; if (![[element name] isEqual: @"object"] || ![[element namespace] isEqual: OF_SERIALIZATION_NS] || ![[[element attributeForName: @"class"] stringValue] - isEqual: [isa className]]) + isEqual: [self className]]) @throw [OFInvalidArgumentException newWithClass: isa selector: _cmd]; name = [[[element elementForName: @"name" Index: src/ObjFW.h ================================================================== --- src/ObjFW.h +++ src/ObjFW.h @@ -27,10 +27,12 @@ #import "OFList.h" #import "OFDictionary.h" #import "OFEnumerator.h" + +#import "OFNull.h" #import "OFNumber.h" #import "OFDate.h" #import "OFURL.h"