ADDED .gitignore Index: .gitignore ================================================================== --- .gitignore +++ .gitignore @@ -0,0 +1,37 @@ +*.a +*.bundle +*.dll +*.dylib +*.o +*.orig +*.so +*~ +.deps +aclocal.m4 +autom4te.cache +build +buildsys.mk +config.h +config.h.in +config.log +config.status +configure +DerivedData +docs +extra.mk +generators/gen_tables +generators/gen_tables.exe +generators/CaseFolding.txt +generators/UnicodeData.txt +Info.plist +ObjFW.xcodeproj/*.mode1v3 +ObjFW.xcodeproj/*.pbxuser +ObjFW.xcodeproj/project.xcworkspace +ObjFW.xcodeproj/xcuserdata +src/objfw-defs.h +src/ObjFW +tests/tests +tests/tests.exe +tests/EBOOT.PBP +tests/PARAM.SFO +utils/objfw-config DELETED .hgignore Index: .hgignore ================================================================== --- .hgignore +++ .hgignore @@ -1,37 +0,0 @@ -syntax: glob -*.a -*.dll -*.dylib -*.impl -*.o -*.orig -*.so -*~ -.deps -aclocal.m4 -autom4te.cache -build -buildsys.mk -config.h -config.h.in -config.log -config.status -configure -DerivedData -docs -extra.mk -generators/gen_tables -generators/gen_tables.exe -generators/CaseFolding.txt -generators/UnicodeData.txt -objfw-config -ObjFW.xcodeproj/*.mode1v3 -ObjFW.xcodeproj/*.pbxuser -ObjFW.xcodeproj/project.xcworkspace -ObjFW.xcodeproj/xcuserdata -src/objfw-defs.h -src/ObjFW -tests/tests -tests/tests.exe -tests/EBOOT.PBP -tests/PARAM.SFO Index: ChangeLog ================================================================== --- ChangeLog +++ ChangeLog @@ -1,18 +1,34 @@ Legend: * Changes of existing features or bugfixes. + New features. + +ObjFW 0.5.4 -> ObjFW 0.6, 27.02.2012 + The differences between 0.5.4 and 0.6 are too big to list them all. However, + the major new features are: + * OFString, OFArray, OFDictionary, OFSet and OFCountedSet are now class + clusters. + + Serialization and deserialization of objects into/from XML and JSON. + + New class OFIntrospection for introspecting classes. + + New class OFProcess for working with and controlling child processes. + * Lots of OFXMLParser and OFXMLElement improvements. + + OFHTTPRequests can have a delegate now for status updates and processing + data as soon as it arrives. + + There are several backends for OFStreamObserver now, including kqueue, poll + and select. + + SOCKS5 support for OFTCPSockets (client only). + * Several API changes. ObjFW 0.5.3 -> ObjFW 0.5.4, 30.08.2011 * The blocks runtime is now working correctly. * Documentation fixes. * -framework works with objfw-compile now. + Support for QNX. * Various small fixes. ObjFW 0.5.2 -> ObjFW 0.5.3, 01.07.2011 - * Lots of bugfixes, see Mercurial log for details. (hg log -b 0.5) + * Lots of bugfixes, see Git log for details. ObjFW 0.5.1 -> ObjFW 0.5.2, 25.04.2011 * Fix double-retain in OFList. * Don't ignore the timeout in OFStreamObserver when using select(). * Do -[OFURL copy] in a try block to prevent a leak when an exception occurs. DELETED Info.plist Index: Info.plist ================================================================== --- Info.plist +++ Info.plist @@ -1,24 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleExecutable - ObjFW - CFBundleName - ObjFW - CFBundleIdentifier - org.webkeks.objfw - CFBundleInfoDictionaryVersion - 6.0 - CFBundlePackageType - FMWK - CFBundleSignature - OBJFW - CFBundleVersion - 0.6-dev - CFBundleShortVersionString - 0.6-dev - - ADDED Info.plist.in Index: Info.plist.in ================================================================== --- Info.plist.in +++ Info.plist.in @@ -0,0 +1,22 @@ + + + + + CFBundleExecutable + ObjFW + CFBundleName + ObjFW + CFBundleIdentifier + org.webkeks.objfw + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleSignature + OBJFW + CFBundleVersion + @PACKAGE_VERSION@ + CFBundleShortVersionString + @PACKAGE_VERSION@ + + Index: Makefile ================================================================== --- Makefile +++ Makefile @@ -10,29 +10,16 @@ extra.mk include buildsys.mk tarball: - V=$$(fgrep VERSION= utils/objfw-config.in | \ - sed 's/VERSION="\(.*\)"/\1/'); \ - V2=$$(fgrep AC_INIT configure.ac | \ - sed 's/AC_INIT([^,]*,\([^,]*\),.*/\1/' | sed 's/ //'); \ - V3=$$(fgrep -A1 CFBundleVersion Info.plist | tail -1 | \ - sed 's/.*>\(.*\)<.*/\1/'); \ - V4=$$(fgrep -A1 CFBundleShortVersion Info.plist | tail -1 | \ - sed 's/.*>\(.*\)<.*/\1/'); \ - if test x"$$V2" != x"$$V" \ - -o x"$$V3" != x"$$V" \ - -o x"$$V4" != x"$$V4"; then \ - echo "Not all files have the same version number!"; \ - echo "Files: util/objfw-config.in configure.ac Info.plist"; \ - exit 1; \ - fi; \ - echo "Generating tarball for version $$V..."; \ - rm -f objfw-$$V.tar.gz; \ - rm -fr objfw-$$V; \ - hg archive objfw-$$V; \ - cp configure config.h.in objfw-$$V; \ - cd objfw-$$V && rm -f .hg_archival.txt .hgignore .hgtags && cd ..; \ - tar cf objfw-$$V.tar objfw-$$V; \ - gzip -9 objfw-$$V.tar; \ - rm -fr objfw-$$V + echo "Generating tarball for version ${PACKAGE_VERSION}..." + rm -fr tmp.tar objfw-${PACKAGE_VERSION} objfw-${PACKAGE_VERSION}.tar \ + objfw-${PACKAGE_VERSION}.tar.gz + git archive HEAD --prefix objfw-${PACKAGE_VERSION}/ -o tmp.tar + tar xf tmp.tar + rm -f tmp.tar objfw-${PACKAGE_VERSION}/.gitignore + cp configure config.h.in objfw-${PACKAGE_VERSION}/ + tar cf objfw-${PACKAGE_VERSION}.tar objfw-${PACKAGE_VERSION} + rm -fr objfw-${PACKAGE_VERSION} + gzip -9 objfw-${PACKAGE_VERSION}.tar + rm -f objfw-${PACKAGE_VERSION}.tar Index: ObjFW.xcodeproj/project.pbxproj ================================================================== --- ObjFW.xcodeproj/project.pbxproj +++ ObjFW.xcodeproj/project.pbxproj @@ -202,11 +202,11 @@ 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 */; }; 4B45355313DCFE1E0037AB4D /* OFCountedSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B45355113DCFE1E0037AB4D /* OFCountedSet.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B45355413DCFE1E0037AB4D /* OFCountedSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B45355213DCFE1E0037AB4D /* OFCountedSet.m */; }; - 4B48B95414DC23B100546D39 /* OFXMLProcessingInstructions.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B48B95214DC23B100546D39 /* OFXMLProcessingInstructions.h */; }; + 4B48B95414DC23B100546D39 /* OFXMLProcessingInstructions.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B48B95214DC23B100546D39 /* OFXMLProcessingInstructions.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B48B95514DC23B100546D39 /* OFXMLProcessingInstructions.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B48B95314DC23B100546D39 /* OFXMLProcessingInstructions.m */; }; 4B49EA66143B39CE0005BBC6 /* OFXMLNodeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B49EA65143B39CE0005BBC6 /* OFXMLNodeTests.m */; }; 4B49EA6D143B3A090005BBC6 /* OFXMLCDATA.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B49EA67143B3A090005BBC6 /* OFXMLCDATA.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B49EA6E143B3A090005BBC6 /* OFXMLCDATA.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B49EA68143B3A090005BBC6 /* OFXMLCDATA.m */; }; 4B49EA6F143B3A090005BBC6 /* OFXMLCharacters.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B49EA69143B3A090005BBC6 /* OFXMLCharacters.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -232,11 +232,10 @@ 4B55A113133AC24600B58A93 /* OFReadFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B55A10D133AC24500B58A93 /* OFReadFailedException.m */; }; 4B55A114133AC24600B58A93 /* OFReadOrWriteFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B55A10E133AC24500B58A93 /* OFReadOrWriteFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B55A115133AC24600B58A93 /* OFReadOrWriteFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B55A10F133AC24500B58A93 /* OFReadOrWriteFailedException.m */; }; 4B55A116133AC24600B58A93 /* OFWriteFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B55A110133AC24500B58A93 /* OFWriteFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B55A117133AC24600B58A93 /* OFWriteFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B55A111133AC24600B58A93 /* OFWriteFailedException.m */; }; - 4B5CF8F814940BD2007AA324 /* OFJSONEncoding.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B5CF8F514940BD2007AA324 /* OFJSONEncoding.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B5CF8F914940BD2007AA324 /* OFString+JSONValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B5CF8F614940BD2007AA324 /* OFString+JSONValue.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B5CF8FA14940BD2007AA324 /* OFString+JSONValue.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B5CF8F714940BD2007AA324 /* OFString+JSONValue.m */; }; 4B64D6EF1425381E007BDFB1 /* OFStreamObserver_poll.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B64D6EB1425381E007BDFB1 /* OFStreamObserver_poll.h */; }; 4B64D6F01425381E007BDFB1 /* OFStreamObserver_poll.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B64D6EC1425381E007BDFB1 /* OFStreamObserver_poll.m */; }; 4B64D6F11425381E007BDFB1 /* OFStreamObserver_select.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B64D6ED1425381E007BDFB1 /* OFStreamObserver_select.h */; }; @@ -270,15 +269,19 @@ 4B90B7A3133AD87D00BD33CB /* OFBindFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B90B799133AD87D00BD33CB /* OFBindFailedException.m */; }; 4B90B7A4133AD87D00BD33CB /* OFConnectionFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B90B79A133AD87D00BD33CB /* OFConnectionFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B90B7A5133AD87D00BD33CB /* OFConnectionFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B90B79B133AD87D00BD33CB /* OFConnectionFailedException.m */; }; 4B90B7A6133AD87D00BD33CB /* OFListenFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B90B79C133AD87D00BD33CB /* OFListenFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B90B7A7133AD87D00BD33CB /* OFListenFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B90B79D133AD87D00BD33CB /* OFListenFailedException.m */; }; + 4B9361A81511000C00DCD16B /* OFThreadPool.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B9361A61511000C00DCD16B /* OFThreadPool.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4B9361A91511000C00DCD16B /* OFThreadPool.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B9361A71511000C00DCD16B /* OFThreadPool.m */; }; 4B989C2F13771A3700109A30 /* OFSerialization.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B989C2E13771A3700109A30 /* OFSerialization.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B9BB7BD141CDE2D000AD1CC /* OFArray_adjacentSubarray.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B9BB7B9141CDE2D000AD1CC /* OFArray_adjacentSubarray.h */; }; 4B9BB7BE141CDE2D000AD1CC /* OFArray_adjacentSubarray.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B9BB7BA141CDE2D000AD1CC /* OFArray_adjacentSubarray.m */; }; 4B9BB7BF141CDE2D000AD1CC /* OFArray_subarray.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B9BB7BB141CDE2D000AD1CC /* OFArray_subarray.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B9BB7C0141CDE2D000AD1CC /* OFArray_subarray.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B9BB7BC141CDE2D000AD1CC /* OFArray_subarray.m */; }; + 4BA02BA115041F5900002F84 /* OFJSONRepresentation.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BA02B9F15041F5900002F84 /* OFJSONRepresentation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4BA02BA215041F5900002F84 /* OFTLSSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BA02BA015041F5900002F84 /* OFTLSSocket.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4BA355BA14879BDD00442EF4 /* of_strptime.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BA355B914879BDD00442EF4 /* of_strptime.m */; }; 4BA355BD14879BF700442EF4 /* of_strptime.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BA355BC14879BF700442EF4 /* of_strptime.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4BA49D9013DB113B00381CDB /* OFIntrospection.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BA49D8E13DB113B00381CDB /* OFIntrospection.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4BA49D9113DB113B00381CDB /* OFIntrospection.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BA49D8F13DB113B00381CDB /* OFIntrospection.m */; }; 4BA85BCA140ECCE800E91D51 /* OFCountedSet_hashtable.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BA85BC4140ECCE800E91D51 /* OFCountedSet_hashtable.h */; }; @@ -512,11 +515,10 @@ 4B55A10D133AC24500B58A93 /* OFReadFailedException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFReadFailedException.m; path = src/exceptions/OFReadFailedException.m; sourceTree = ""; }; 4B55A10E133AC24500B58A93 /* OFReadOrWriteFailedException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFReadOrWriteFailedException.h; path = src/exceptions/OFReadOrWriteFailedException.h; sourceTree = ""; }; 4B55A10F133AC24500B58A93 /* OFReadOrWriteFailedException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFReadOrWriteFailedException.m; path = src/exceptions/OFReadOrWriteFailedException.m; sourceTree = ""; }; 4B55A110133AC24500B58A93 /* OFWriteFailedException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFWriteFailedException.h; path = src/exceptions/OFWriteFailedException.h; sourceTree = ""; }; 4B55A111133AC24600B58A93 /* OFWriteFailedException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFWriteFailedException.m; path = src/exceptions/OFWriteFailedException.m; sourceTree = ""; }; - 4B5CF8F514940BD2007AA324 /* OFJSONEncoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFJSONEncoding.h; path = src/OFJSONEncoding.h; sourceTree = ""; }; 4B5CF8F614940BD2007AA324 /* OFString+JSONValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "OFString+JSONValue.h"; path = "src/OFString+JSONValue.h"; sourceTree = ""; }; 4B5CF8F714940BD2007AA324 /* OFString+JSONValue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "OFString+JSONValue.m"; path = "src/OFString+JSONValue.m"; sourceTree = ""; }; 4B64D6EB1425381E007BDFB1 /* OFStreamObserver_poll.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFStreamObserver_poll.h; path = src/OFStreamObserver_poll.h; sourceTree = ""; }; 4B64D6EC1425381E007BDFB1 /* OFStreamObserver_poll.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFStreamObserver_poll.m; path = src/OFStreamObserver_poll.m; sourceTree = ""; }; 4B64D6ED1425381E007BDFB1 /* OFStreamObserver_select.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFStreamObserver_select.h; path = src/OFStreamObserver_select.h; sourceTree = ""; }; @@ -617,19 +619,23 @@ 4B90B799133AD87D00BD33CB /* OFBindFailedException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFBindFailedException.m; path = src/exceptions/OFBindFailedException.m; sourceTree = ""; }; 4B90B79A133AD87D00BD33CB /* OFConnectionFailedException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFConnectionFailedException.h; path = src/exceptions/OFConnectionFailedException.h; sourceTree = ""; }; 4B90B79B133AD87D00BD33CB /* OFConnectionFailedException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFConnectionFailedException.m; path = src/exceptions/OFConnectionFailedException.m; sourceTree = ""; }; 4B90B79C133AD87D00BD33CB /* OFListenFailedException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFListenFailedException.h; path = src/exceptions/OFListenFailedException.h; sourceTree = ""; }; 4B90B79D133AD87D00BD33CB /* OFListenFailedException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFListenFailedException.m; path = src/exceptions/OFListenFailedException.m; sourceTree = ""; }; + 4B9361A61511000C00DCD16B /* OFThreadPool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFThreadPool.h; path = src/OFThreadPool.h; sourceTree = ""; }; + 4B9361A71511000C00DCD16B /* OFThreadPool.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFThreadPool.m; path = src/OFThreadPool.m; sourceTree = ""; }; 4B981CDE116F71DD00294DB7 /* OFSeekableStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFSeekableStream.h; path = src/OFSeekableStream.h; sourceTree = ""; }; 4B981CDF116F71DD00294DB7 /* OFSeekableStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFSeekableStream.m; path = src/OFSeekableStream.m; sourceTree = ""; }; 4B989C2E13771A3700109A30 /* OFSerialization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFSerialization.h; path = src/OFSerialization.h; sourceTree = ""; }; 4B99250F12E0780000215DBE /* OFHTTPRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFHTTPRequest.h; path = src/OFHTTPRequest.h; sourceTree = ""; }; 4B99251012E0780000215DBE /* OFHTTPRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFHTTPRequest.m; path = src/OFHTTPRequest.m; sourceTree = ""; }; 4B9BB7B9141CDE2D000AD1CC /* OFArray_adjacentSubarray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFArray_adjacentSubarray.h; path = src/OFArray_adjacentSubarray.h; sourceTree = ""; }; 4B9BB7BA141CDE2D000AD1CC /* OFArray_adjacentSubarray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFArray_adjacentSubarray.m; path = src/OFArray_adjacentSubarray.m; sourceTree = ""; }; 4B9BB7BB141CDE2D000AD1CC /* OFArray_subarray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFArray_subarray.h; path = src/OFArray_subarray.h; sourceTree = ""; }; 4B9BB7BC141CDE2D000AD1CC /* OFArray_subarray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFArray_subarray.m; path = src/OFArray_subarray.m; sourceTree = ""; }; + 4BA02B9F15041F5900002F84 /* OFJSONRepresentation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFJSONRepresentation.h; path = src/OFJSONRepresentation.h; sourceTree = ""; }; + 4BA02BA015041F5900002F84 /* OFTLSSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFTLSSocket.h; path = src/OFTLSSocket.h; sourceTree = ""; }; 4BA355B914879BDD00442EF4 /* of_strptime.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = of_strptime.m; path = src/of_strptime.m; sourceTree = ""; }; 4BA355BC14879BF700442EF4 /* of_strptime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = of_strptime.h; path = src/of_strptime.h; sourceTree = ""; }; 4BA49D8E13DB113B00381CDB /* OFIntrospection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFIntrospection.h; path = src/OFIntrospection.h; sourceTree = ""; }; 4BA49D8F13DB113B00381CDB /* OFIntrospection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFIntrospection.m; path = src/OFIntrospection.m; sourceTree = ""; }; 4BA85BC4140ECCE800E91D51 /* OFCountedSet_hashtable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFCountedSet_hashtable.h; path = src/OFCountedSet_hashtable.h; sourceTree = ""; }; @@ -919,11 +925,11 @@ 4BF1BCC111C9663F0025511F /* OFHash.m */, 4B99250F12E0780000215DBE /* OFHTTPRequest.h */, 4B99251012E0780000215DBE /* OFHTTPRequest.m */, 4BA49D8E13DB113B00381CDB /* OFIntrospection.h */, 4BA49D8F13DB113B00381CDB /* OFIntrospection.m */, - 4B5CF8F514940BD2007AA324 /* OFJSONEncoding.h */, + 4BA02B9F15041F5900002F84 /* OFJSONRepresentation.h */, 4B67996C1099E7C50041064A /* OFList.h */, 4B67996D1099E7C50041064A /* OFList.m */, 4BF1BCC211C9663F0025511F /* OFMD5Hash.h */, 4BF1BCC311C9663F0025511F /* OFMD5Hash.m */, 4B67996F1099E7C50041064A /* OFMutableArray.h */, @@ -995,10 +1001,13 @@ 4B6799821099E7C50041064A /* OFTCPSocket.m */, 4BD653C3143B8489006182F0 /* OFTCPSocket+SOCKS5.h */, 4BD653C4143B8489006182F0 /* OFTCPSocket+SOCKS5.m */, 4B6799831099E7C50041064A /* OFThread.h */, 4B6799841099E7C50041064A /* OFThread.m */, + 4B9361A61511000C00DCD16B /* OFThreadPool.h */, + 4B9361A71511000C00DCD16B /* OFThreadPool.m */, + 4BA02BA015041F5900002F84 /* OFTLSSocket.h */, 4B4A61F212DF5EA20048F3F2 /* OFURL.h */, 4B4A61F312DF5EA20048F3F2 /* OFURL.m */, 4BF1BCCE11C9663F0025511F /* OFXMLAttribute.h */, 4BF1BCCF11C9663F0025511F /* OFXMLAttribute.m */, 4B49EA67143B3A090005BBC6 /* OFXMLCDATA.h */, @@ -1144,11 +1153,11 @@ 4B17FF74133A2AAB003E6DCD /* OFException.h in Headers */, 4B3D23C81337FCB000DD29B8 /* OFFile.h in Headers */, 4B3D23C91337FCB000DD29B8 /* OFHash.h in Headers */, 4B3D23CA1337FCB000DD29B8 /* OFHTTPRequest.h in Headers */, 4BA49D9013DB113B00381CDB /* OFIntrospection.h in Headers */, - 4B5CF8F814940BD2007AA324 /* OFJSONEncoding.h in Headers */, + 4BA02BA115041F5900002F84 /* OFJSONRepresentation.h in Headers */, 4B3D23CB1337FCB000DD29B8 /* OFList.h in Headers */, 4B3D23CC1337FCB000DD29B8 /* OFMD5Hash.h in Headers */, 4B3D23CD1337FCB000DD29B8 /* OFMutableArray.h in Headers */, 4B3D23CE1337FCB000DD29B8 /* OFMutableDictionary.h in Headers */, 4B39844713D3AFB400E6F825 /* OFMutableSet.h in Headers */, @@ -1173,10 +1182,12 @@ 4B3D23DA1337FCB000DD29B8 /* OFString+URLEncoding.h in Headers */, 4B3D23DB1337FCB000DD29B8 /* OFString+XMLEscaping.h in Headers */, 4B3D23DC1337FCB000DD29B8 /* OFString+XMLUnescaping.h in Headers */, 4B3D23DD1337FCB000DD29B8 /* OFTCPSocket.h in Headers */, 4B3D23DE1337FCB000DD29B8 /* OFThread.h in Headers */, + 4B9361A81511000C00DCD16B /* OFThreadPool.h in Headers */, + 4BA02BA215041F5900002F84 /* OFTLSSocket.h in Headers */, 4B3D23DF1337FCB000DD29B8 /* OFURL.h in Headers */, 4B3D23E01337FCB000DD29B8 /* OFXMLAttribute.h in Headers */, 4B49EA6D143B3A090005BBC6 /* OFXMLCDATA.h in Headers */, 4B49EA6F143B3A090005BBC6 /* OFXMLCharacters.h in Headers */, 4B49EA71143B3A090005BBC6 /* OFXMLComment.h in Headers */, @@ -1183,10 +1194,11 @@ 4B3D23E11337FCB000DD29B8 /* OFXMLElement.h in Headers */, 4BB25E8C139C388A00F574EA /* OFXMLElement+Serialization.h in Headers */, 4B3D23E21337FCB000DD29B8 /* OFXMLElementBuilder.h in Headers */, 4B11005C14329B9A003A45D8 /* OFXMLNode.h in Headers */, 4B3D23E31337FCB000DD29B8 /* OFXMLParser.h in Headers */, + 4B48B95414DC23B100546D39 /* OFXMLProcessingInstructions.h in Headers */, 4B3D23E41337FCB000DD29B8 /* ObjFW.h in Headers */, 4B3D23E51337FCB000DD29B8 /* asprintf.h in Headers */, 4B3D23E61337FCB000DD29B8 /* atomic.h in Headers */, 4B3D23E71337FCB000DD29B8 /* base64.h in Headers */, 4B3D23E81337FCB000DD29B8 /* macros.h in Headers */, @@ -1259,11 +1271,10 @@ 4B83F0F4142FDEFD00E4A821 /* OFStreamObserver_kqueue.h in Headers */, 4B64D6EF1425381E007BDFB1 /* OFStreamObserver_poll.h in Headers */, 4B64D6F11425381E007BDFB1 /* OFStreamObserver_select.h in Headers */, 4B552554147AA5DB0003BF47 /* OFString_UTF8.h in Headers */, 4BD653C5143B8489006182F0 /* OFTCPSocket+SOCKS5.h in Headers */, - 4B48B95414DC23B100546D39 /* OFXMLProcessingInstructions.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ @@ -1307,12 +1318,12 @@ }; 4BF33AEF133807310059CEF7 /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 4BF33AF6133807310059CEF7 /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( - 4BF33AEC133807310059CEF7 /* Sources */, 4BF33AED133807310059CEF7 /* Frameworks */, + 4BF33AEC133807310059CEF7 /* Sources */, 4BF33AEE133807310059CEF7 /* CopyFiles */, 4BF33B4013380CA40059CEF7 /* CopyFiles */, ); buildRules = ( ); @@ -1467,10 +1478,11 @@ 4B3D23AA1337FC0D00DD29B8 /* OFString+XMLUnescaping.m in Sources */, 4B552555147AA5DB0003BF47 /* OFString_UTF8.m in Sources */, 4B3D23AB1337FC0D00DD29B8 /* OFTCPSocket.m in Sources */, 4BD653C6143B8489006182F0 /* OFTCPSocket+SOCKS5.m in Sources */, 4B3D23AC1337FC0D00DD29B8 /* OFThread.m in Sources */, + 4B9361A91511000C00DCD16B /* OFThreadPool.m in Sources */, 4B3D23AD1337FC0D00DD29B8 /* OFURL.m in Sources */, 4B3D23AE1337FC0D00DD29B8 /* OFXMLAttribute.m in Sources */, 4B49EA6E143B3A090005BBC6 /* OFXMLCDATA.m in Sources */, 4B49EA70143B3A090005BBC6 /* OFXMLCharacters.m in Sources */, 4B49EA72143B3A090005BBC6 /* OFXMLComment.m in Sources */, @@ -1477,10 +1489,11 @@ 4B3D23AF1337FC0D00DD29B8 /* OFXMLElement.m in Sources */, 4BB25E8D139C388A00F574EA /* OFXMLElement+Serialization.m in Sources */, 4B3D23B01337FC0D00DD29B8 /* OFXMLElementBuilder.m in Sources */, 4B11005D14329B9A003A45D8 /* OFXMLNode.m in Sources */, 4B3D23B11337FC0D00DD29B8 /* OFXMLParser.m in Sources */, + 4B48B95514DC23B100546D39 /* OFXMLProcessingInstructions.m in Sources */, 4B3D23B31337FC0D00DD29B8 /* base64.m in Sources */, 4B3D23B41337FC0D00DD29B8 /* iso_8859_15.m in Sources */, 4B3D23B51337FC0D00DD29B8 /* foundation-compat.m in Sources */, 4B3D23EE1337FFD000DD29B8 /* of_asprintf.m in Sources */, 4BA355BA14879BDD00442EF4 /* of_strptime.m in Sources */, @@ -1535,11 +1548,10 @@ 4B55A104133ABEA900B58A93 /* OFThreadStillRunningException.m in Sources */, 4B17FFAA133A34E7003E6DCD /* OFTruncatedDataException.m in Sources */, 4B17FFB6133A375B003E6DCD /* OFUnboundNamespaceException.m in Sources */, 4B17FFB2133A3664003E6DCD /* OFUnsupportedProtocolException.m in Sources */, 4B55A117133AC24600B58A93 /* OFWriteFailedException.m in Sources */, - 4B48B95514DC23B100546D39 /* OFXMLProcessingInstructions.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 4BF33AEC133807310059CEF7 /* Sources */ = { isa = PBXSourcesBuildPhase; @@ -1549,10 +1561,11 @@ 4BF33AFD133807A20059CEF7 /* OFBlockTests.m in Sources */, 4BF33AFE133807A20059CEF7 /* OFDataArrayTests.m in Sources */, 4BF33AFF133807A20059CEF7 /* OFDateTests.m in Sources */, 4BF33B00133807A20059CEF7 /* OFDictionaryTests.m in Sources */, 4BF33B02133807A20059CEF7 /* OFHTTPRequestTests.m in Sources */, + 4BAA60C814D09699006F068D /* OFJSONTests.m in Sources */, 4BF33B03133807A20059CEF7 /* OFListTests.m in Sources */, 4BF33B04133807A20059CEF7 /* OFMD5HashTests.m in Sources */, 4BF33B05133807A20059CEF7 /* OFNumberTests.m in Sources */, 4BF33B06133807A20059CEF7 /* OFObjectTests.m in Sources */, 4BF33B07133807A20059CEF7 /* OFPluginTests.m in Sources */, @@ -1567,11 +1580,10 @@ 4BF33B0E133807A20059CEF7 /* OFXMLElementBuilderTests.m in Sources */, 4B49EA66143B39CE0005BBC6 /* OFXMLNodeTests.m in Sources */, 4BF33B10133807A20059CEF7 /* OFXMLParserTests.m in Sources */, 4BF33B11133807A20059CEF7 /* PropertiesTests.m in Sources */, 4BF33B12133807A20059CEF7 /* TestsAppDelegate.m in Sources */, - 4BAA60C814D09699006F068D /* OFJSONTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ Index: PLATFORMS ================================================================== --- PLATFORMS +++ PLATFORMS @@ -6,31 +6,33 @@ +--------------------------+--------------+----------------------+---------+ | FreeBSD 8.0 | x86 | | old GNU | +--------------------------+--------------+----------------------+---------+ | Haiku r41078 | x86 | GCC 4.4.4 | old GNU | +--------------------------+--------------+----------------------+---------+ - | Linux 2.6.* | x86 | GCC 4.4.1 | old GNU | - | Linux 2.6.* | x86 | GCC 4.6 | GNU | - | Linux 2.6.* | x86 | LLVM/Clang r83252 | old GNU | - | Linux 2.6.* | x86_64 | GCC 4.4.1 | old GNU | + | Linux 2.6.* / 3.* | x86 | GCC 4.4.1 | old GNU | + | Linux 2.6.* / 3.* | x86 | GCC 4.6 | GNU | + | Linux 2.6.* / 3.* | x86 | LLVM/Clang r83252 | old GNU | + | Linux 2.6.* / 3.* | x86_64 | GCC 4.4.1 | old GNU | | Maemo 5 | arm | GCC 4.5.1 | old GNU | +--------------------------+--------------+----------------------+---------+ - | iPhone OS 2.2.1 - 4.2 | arm | GCC 4.2 | Apple | + | iPhone OS 2.2.1 - 5.0 | arm | GCC 4.2 | Apple | | Mac OS X 10.5 | ppc | GCC 4.0 + 4.2 | Apple | | Mac OS X 10.5 | ppc64 | GCC 4.0 + 4.2 | Apple | - | Mac OS X 10.5 - 10.6 | x86 | GCC 4.0 + 4.2 | Apple | - | Mac OS X 10.5 - 10.6 | x86_64 | GCC 4.0 + 4.2 | Apple | + | Mac OS X 10.5 - 10.7 | x86 | GCC 4.0 + 4.2 | Apple | + | Mac OS X 10.5 - 10.7 | x86_64 | GCC 4.0 + 4.2 | Apple | +--------------------------+--------------+----------------------+---------+ | MirBSD 10uAB - 10uAD | x86 | GCC 4.4.2 | old GNU | | MirBSD 10uAD | x86 | LLVM/Clang r90573 | old GNU | +--------------------------+--------------+----------------------+---------+ | NetBSD 4.0 | x86 | GCC 4.1.2 prerelease | old GNU | | NetBSD 5.1 | x86_64 | GCC 4.1.3 prerelease | old GNU | | NetBSD 5.1 | x86_64 | GCC 4.6 | GNU | | NetBSD 5.1 | x86_64 | LLVM/Clang r134860 | old GNU | + | NetBSD 5.99.56 | x86_64 | GCC 4.5.3 | old GNU | + | NetBSD 5.99.56 | x86_64 | LLVM/Clang 2.9 | old GNU | +--------------------------+--------------+----------------------+---------+ - | OpenBSD 4.6 - 4.7 | x86_64 | GCC 4.2.1 - 4.2.4 | old GNU | + | OpenBSD 4.6 - 5.0 | x86_64 | GCC 4.2.1 - 4.2.4 | old GNU | +--------------------------+--------------+----------------------+---------+ | OpenSolaris 2009.06 | x86 | | old GNU | | OpenSolaris 2009.06 | x86_64 | | old GNU | +--------------------------+--------------+----------------------+---------+ | QNX 6.5.0 | x86 | GCC 4.6.1 | GNU | DELETED README Index: README ================================================================== --- README +++ README @@ -1,51 +0,0 @@ -ObjFW is a portable, lightweight framework for the Objective C language. -It enables you to write an application in Objective C that will run on -any platform supported by ObjFW without having to worry about -differences between operating systems or various frameworks that you -would otherwise need if you want to be portable. - -See https://webkeks.org/objfw for more information. - - -INSTALLATION - - To install ObjFW, just run the following commands: - - $ ./configure - $ make - $ make install - - In case you checked out ObjFW from the Mercurial repository, you need - to run the following command first: - - $ ./autogen.sh - - -BUILDING AS A MAC OS X FRAMEWORK - - It is also possible to build ObjFW as a Mac OS X framework. To do so, - just execute xcodebuild -target ObjFW in the root directory of ObjFW or open - the .xcodeproj in Xcode and choose Build -> Build from the menu. Copy the - resulting ObjFW.framework to /Library/Frameworks and you are done. - - -USING THE MAC OS X FRAMEWORK IN XCODE - - To use the Mac OS X framework in Xcode, you need to add the .framework - to your project and add the following flags to "Other C Flags": - - -fconstant-string-class=OFConstantString -fno-constant-cfstrings - - Additionally, since Xcode 4, you need to manually set the compiler to GCC - or LLVM-GCC due to bugs in Clang on OS X with using a different constant - string class. - - Optionally, if you want to use blocks, you also need to add: - - -fblocks - - -BUGS AND FEATURE REQUESTS - - If you find any bugs or have feature requests, feel free to send a - mail to js-spam@webkeks.org (remove -spam from the address!). ADDED README.md Index: README.md ================================================================== --- README.md +++ README.md @@ -0,0 +1,52 @@ +ObjFW is a portable, lightweight framework for the Objective C language. +It enables you to write an application in Objective C that will run on +any platform supported by ObjFW without having to worry about +differences between operating systems or various frameworks that you +would otherwise need if you want to be portable. + +See https://webkeks.org/objfw for more information. + + +Installation +============ + + To install ObjFW, just run the following commands: + + $ ./configure + $ make + $ make install + + In case you checked out ObjFW from the Git repository, you need to run + the following command first: + + $ ./autogen.sh + + +Building as a Mac OS X framework +================================ + + It is also possible to build ObjFW as a Mac OS X framework. To do so, + just execute xcodebuild -target ObjFW in the root directory of ObjFW + or open the .xcodeproj in Xcode and choose Build -> Build from the + menu. Copy the resulting ObjFW.framework to `/Library/Frameworks` and + you are done. + + +Using the Mac OS X framework in Xcode +===================================== + + To use the Mac OS X framework in Xcode, you need to add the .framework + to your project and add the following flags to "Other C Flags": + + -fconstant-string-class=OFConstantString -fno-constant-cfstrings + + Optionally, if you want to use blocks, you also need to add: + + -fblocks + + +Bugs and feature requests +========================= + + If you find any bugs or have feature requests, feel free to send a + mail to js-spam@webkeks.org (remove -spam from the address!). Index: buildsys.mk.in ================================================================== --- buildsys.mk.in +++ buildsys.mk.in @@ -1,10 +1,10 @@ # -# Copyright (c) 2007, 2008, 2009, 2010, 2011 +# Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012 # Jonathan Schleifer # -# https://webkeks.org/hg/buildsys/ +# https://webkeks.org/git/?p=buildsys.git # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice is present in all copies. # @@ -19,11 +19,12 @@ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # -PACKAGE = @PACKAGE@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ AS = @AS@ CC = @CC@ CXX = @CXX@ CPP = @CPP@ DC = @DC@ @@ -70,17 +71,17 @@ WINDRES = @WINDRES@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ libdir = @libdir@ -plugindir ?= ${libdir}/${PACKAGE} +plugindir ?= ${libdir}/${PACKAGE_NAME} datarootdir = @datarootdir@ datadir = @datadir@ includedir = @includedir@ -includesubdir ?= ${PACKAGE} +includesubdir ?= ${PACKAGE_NAME} localedir = @localedir@ -localename ?= ${PACKAGE} +localename ?= ${PACKAGE_NAME} mandir = @mandir@ mansubdir ?= man1 OBJS1 = ${SRCS:.c=.o} OBJS2 = ${OBJS1:.cc=.o} @@ -146,56 +147,147 @@ sed 's/^\([^\.]*\)\.o:/\1.o \1.lib.o \1.plugin.o:/' >$@ || \ { rm -f $@; false; } pre-depend: -${PROG} ${PROG_NOINST}: ${EXT_DEPS} ${OBJS} +${PROG} ${PROG_NOINST}: ${EXT_DEPS} ${OBJS} ${OBJS_EXTRA} ${LINK_STATUS} - if ${LD} -o $@ ${OBJS} ${LDFLAGS} ${LIBS}; then \ + if ${LD} -o $@ ${OBJS} ${OBJS_EXTRA} ${LDFLAGS} ${LIBS}; then \ ${LINK_OK}; \ else \ ${LINK_FAILED}; \ fi -${JARFILE}: ${EXT_DEPS} ${JAR_MANIFEST} ${OBJS} +${JARFILE}: ${EXT_DEPS} ${JAR_MANIFEST} ${OBJS} ${OBJS_EXTRA} ${LINK_STATUS} if test x"${JAR_MANIFEST}" != x""; then \ - if ${JAR} cfm ${JARFILE} ${JAR_MANIFEST} ${OBJS}; then \ + if ${JAR} cfm ${JARFILE} ${JAR_MANIFEST} ${OBJS} ${OBJS_EXTRA}; then \ ${LINK_OK}; \ else \ ${LINK_FAILED}; \ fi \ else \ - if ${JAR} cf ${JARFILE} ${OBJS}; then \ + if ${JAR} cf ${JARFILE} ${OBJS} ${OBJS_EXTRA}; then \ ${LINK_OK}; \ else \ ${LINK_FAILED}; \ fi \ fi -${SHARED_LIB} ${SHARED_LIB_NOINST}: ${EXT_DEPS} ${LIB_OBJS} +${SHARED_LIB} ${SHARED_LIB_NOINST}: ${EXT_DEPS} ${LIB_OBJS} ${LIB_OBJS_EXTRA} ${LINK_STATUS}; \ - if ${LD} -o $@ ${LIB_OBJS} ${LIB_LDFLAGS} ${LDFLAGS} ${LIBS}; then \ + objs=""; \ + ars=""; \ + for i in ${LIB_OBJS} ${LIB_OBJS_EXTRA}; do \ + case $$i in \ + *.a) \ + ars="$$ars $$i" \ + ;; \ + *.o) \ + objs="$$objs $$i" \ + ;; \ + esac \ + done; \ + for i in $$ars; do \ + dir=".$$(echo $$i | sed 's/\//_/g').objs"; \ + rm -fr $$dir; \ + mkdir -p $$dir; \ + cd $$dir; \ + ${AR} x ../$$i; \ + for j in *.o; do \ + objs="$$objs $$dir/$$j"; \ + done; \ + cd ..; \ + done; \ + if ${LD} -o $@ $$objs ${LIB_LDFLAGS} ${LDFLAGS} ${LIBS}; then \ ${LINK_OK}; \ else \ ${LINK_FAILED}; \ - fi \ + fi; \ + for i in $$ars; do \ + dir=".$$(echo $$i | sed 's/\//_/g').objs"; \ + rm -fr $$dir; \ + done ${PLUGIN} ${PLUGIN_NOINST}: ${EXT_DEPS} ${PLUGIN_OBJS} ${LINK_STATUS} - if ${LD} -o $@ ${PLUGIN_OBJS} ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS}; then \ + objs=""; \ + ars=""; \ + for i in ${PLUGIN_OBJS}; do \ + case $$i in \ + *.a) \ + ars="$$ars $$i" \ + ;; \ + *.o) \ + objs="$$objs $$i" \ + ;; \ + esac \ + done; \ + for i in $$ars; do \ + dir=".$$(echo $$i | sed 's/\//_/g').objs"; \ + rm -fr $$dir; \ + mkdir -p $$dir; \ + cd $$dir; \ + ${AR} x ../$$i; \ + for j in *.o; do \ + objs="$$objs $$dir/$$j"; \ + done; \ + cd ..; \ + done; \ + if ${LD} -o $@ $$objs ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS}; then \ + ${LINK_OK}; \ + else \ + ${LINK_FAILED}; \ + fi; \ + for i in $$ars; do \ + dir=".$$(echo $$i | sed 's/\//_/g').objs"; \ + rm -fr $$dir; \ + done + +${STATIC_LIB} ${STATIC_LIB_NOINST}: ${EXT_DEPS} ${OBJS} ${OBJS_EXTRA} + ${LINK_STATUS} + rm -f $@ + objs=""; \ + ars=""; \ + for i in ${OBJS} ${OBJS_EXTRA}; do \ + case $$i in \ + *.a) \ + ars="$$ars $$i" \ + ;; \ + *.o) \ + objs="$$objs $$i" \ + ;; \ + esac \ + done; \ + for i in $$ars; do \ + dir=".$$(echo $$i | sed 's/\//_/g').objs"; \ + rm -fr $$dir; \ + mkdir -p $$dir; \ + cd $$dir; \ + ${AR} x ../$$i; \ + for j in *.o; do \ + objs="$$objs $$dir/$$j"; \ + done; \ + cd ..; \ + done; \ + if ${AR} cr $@ $$objs && ${RANLIB} $@; then \ ${LINK_OK}; \ else \ ${LINK_FAILED}; \ - fi + rm -f $@; \ + fi; \ + for i in $$ars; do \ + dir=".$$(echo $$i | sed 's/\//_/g').objs"; \ + rm -fr $$dir; \ + done -${STATIC_LIB} ${STATIC_LIB_NOINST}: ${EXT_DEPS} ${OBJS} +${STATIC_PIC_LIB} ${STATIC_PIC_LIB_NOINST}: ${EXT_DEPS} ${LIB_OBJS} ${LIB_OBJS_EXTRA} ${LINK_STATUS} rm -f $@ objs=""; \ ars=""; \ - for i in ${OBJS}; do \ + for i in ${LIB_OBJS} ${LIB_OBJS_EXTRA}; do \ case $$i in \ *.a) \ ars="$$ars $$i" \ ;; \ *.o) \ @@ -223,20 +315,10 @@ for i in $$ars; do \ dir=".$$(echo $$i | sed 's/\//_/g').objs"; \ rm -fr $$dir; \ done -${STATIC_PIC_LIB} ${STATIC_PIC_LIB_NOINST}: ${EXT_DEPS} ${LIB_OBJS} - ${LINK_STATUS} - rm -f $@ - if ${AR} cr $@ ${LIB_OBJS} && ${RANLIB} $@; then \ - ${LINK_OK}; \ - else \ - ${LINK_FAILED}; \ - rm -f $@; \ - fi - locales: ${MO_FILES} .c.o: ${COMPILE_STATUS} if ${CC} ${CFLAGS} ${CPPFLAGS} -c -o $@ $<; then \ @@ -459,11 +541,11 @@ fi \ done for i in ${DATA}; do \ ${INSTALL_STATUS}; \ - if ${MKDIR_P} $$(dirname ${DESTDIR}${datadir}/${PACKAGE}/$$i) && ${INSTALL} -m 644 $$i ${DESTDIR}${datadir}/${PACKAGE}/$$i; then \ + if ${MKDIR_P} $$(dirname ${DESTDIR}${datadir}/${PACKAGE_NAME}/$$i) && ${INSTALL} -m 644 $$i ${DESTDIR}${datadir}/${PACKAGE_NAME}/$$i; then \ ${INSTALL_OK}; \ else \ ${INSTALL_FAILED}; \ fi \ done @@ -543,20 +625,20 @@ fi \ done -rmdir ${DESTDIR}${plugindir} >/dev/null 2>&1 for i in ${DATA}; do \ - if test -f ${DESTDIR}${datadir}/${PACKAGE}/$$i; then \ - if rm -f ${DESTDIR}${datadir}/${PACKAGE}/$$i; then \ + if test -f ${DESTDIR}${datadir}/${PACKAGE_NAME}/$$i; then \ + if rm -f ${DESTDIR}${datadir}/${PACKAGE_NAME}/$$i; then \ ${DELETE_OK}; \ else \ ${DELETE_FAILED}; \ fi \ fi; \ - rmdir "$$(dirname ${DESTDIR}${datadir}/${PACKAGE}/$$i)" >/dev/null 2>&1 || true; \ + rmdir "$$(dirname ${DESTDIR}${datadir}/${PACKAGE_NAME}/$$i)" >/dev/null 2>&1 || true; \ done - -rmdir ${DESTDIR}${datadir}/${PACKAGE} >/dev/null 2>&1 + -rmdir ${DESTDIR}${datadir}/${PACKAGE_NAME} >/dev/null 2>&1 for i in ${PROG}; do \ if test -f ${DESTDIR}${bindir}/$$i; then \ if rm -f ${DESTDIR}${bindir}/$$i; then \ ${DELETE_OK}; \ @@ -604,11 +686,11 @@ ${DIR_ENTER}; \ ${MAKE} ${MFLAGS} clean || exit $$?; \ ${DIR_LEAVE}; \ done - for i in ${DEPS} ${OBJS} ${LIB_OBJS} ${PLUGIN_OBJS} ${PROG} ${PROG_NOINST} ${SHARED_LIB} ${SHARED_LIB_NOINST} ${STATIC_LIB} ${STATIC_LIB_NOINST} ${STATIC_PIC_LIB} ${STATIC_PIC_LIB_NOINST} ${PLUGIN} ${PLUGIN_NOINST} ${CLEAN_LIB} ${MO_FILES} ${CLEAN}; do \ + for i in ${DEPS} ${OBJS} ${OBJS_EXTRA} ${LIB_OBJS} ${LIB_OBJS_EXTRA} ${PLUGIN_OBJS} ${PROG} ${PROG_NOINST} ${SHARED_LIB} ${SHARED_LIB_NOINST} ${STATIC_LIB} ${STATIC_LIB_NOINST} ${STATIC_PIC_LIB} ${STATIC_PIC_LIB_NOINST} ${PLUGIN} ${PLUGIN_NOINST} ${CLEAN_LIB} ${MO_FILES} ${CLEAN}; do \ if test -f $$i -o -d $$i; then \ if rm -fr $$i; then \ ${DELETE_OK}; \ else \ ${DELETE_FAILED}; \ Index: configure.ac ================================================================== --- configure.ac +++ configure.ac @@ -1,6 +1,6 @@ -AC_INIT(ObjFW, 0.6-dev, js@webkeks.org) +AC_INIT(ObjFW, 0.7-dev, js@webkeks.org) AC_CONFIG_SRCDIR(src) AS_IF([test x"$host" = x"psp"], [ OBJCFLAGS="-G0 $OBJCFLAGS" LIBS="$LIBS -lpspdebug -lpspdisplay -lpspge -lpspctrl -lpspsdk -lc" @@ -478,24 +478,10 @@ ]) AC_CHECK_FUNC(localtime_r, [ AC_DEFINE(HAVE_LOCALTIME_R, 1, [Whether we have localtime_r]) ]) -AC_MSG_CHECKING(for tm_gmtoff in struct tm) -AC_TRY_COMPILE([ - #define _GNU_SOURCE - #include -], [ - struct tm tm; - tm.tm_gmtoff = 0; -], [ - AC_DEFINE(STRUCT_TM_HAS_TM_GMTOFF, 1, [Whether struct tm has tm_gmtoff]) - AC_MSG_RESULT(yes) -], [ - AC_MSG_RESULT(no) -]) - AC_CHECK_FUNC(kqueue, [ AC_DEFINE(HAVE_KQUEUE, 1, [Whether we have kqueue]) AC_SUBST(OFSTREAMOBSERVER_KQUEUE_M, "OFStreamObserver_kqueue.m") ]) AC_CHECK_HEADER(poll.h, [ @@ -698,8 +684,8 @@ dnl and add OBJCPPFLAGS to CPPFLAGS, thus we need to AC_SUBST these ourself. AC_SUBST(CPP) AC_SUBST(CPPFLAGS) AC_SUBST(PACKAGE, ObjFW) -AC_CONFIG_FILES([buildsys.mk extra.mk utils/objfw-config]) +AC_CONFIG_FILES([buildsys.mk extra.mk utils/objfw-config Info.plist]) AC_CONFIG_HEADERS([config.h src/objfw-defs.h]) AC_OUTPUT Index: extra.mk.in ================================================================== --- extra.mk.in +++ extra.mk.in @@ -1,8 +1,8 @@ OBJFW_SHARED_LIB = @OBJFW_SHARED_LIB@ OBJFW_STATIC_LIB = @OBJFW_STATIC_LIB@ -OBJFW_LIB_MAJOR = 5 +OBJFW_LIB_MAJOR = 6 OBJFW_LIB_MINOR = 0 OBJFW_LIB_MAJOR_MINOR = ${OBJFW_LIB_MAJOR}.${OBJFW_LIB_MINOR} OBJFW_BRIDGE_SHARED_LIB = @OBJFW_BRIDGE_SHARED_LIB@ OBJFW_BRIDGE_STATIC_LIB = @OBJFW_BRIDGE_STATIC_LIB@ Index: generators/TableGenerator.m ================================================================== --- generators/TableGenerator.m +++ generators/TableGenerator.m @@ -60,25 +60,25 @@ OFString *line; pool2 = [[OFAutoreleasePool alloc] init]; while ((line = [file readLine])) { OFArray *split; - OFString **splitCArray; + OFString **splitObjects; of_unichar_t codep; split = [line componentsSeparatedByString: @";"]; if ([split count] != 15) { of_log(@"Invalid line: %@\n", line); [OFApplication terminateWithStatus: 1]; } - splitCArray = [split cArray]; + splitObjects = [split objects]; - codep = (of_unichar_t)[splitCArray[0] hexadecimalValue]; + codep = (of_unichar_t)[splitObjects[0] hexadecimalValue]; upperTable[codep] = - (of_unichar_t)[splitCArray[12] hexadecimalValue]; + (of_unichar_t)[splitObjects[12] hexadecimalValue]; lowerTable[codep] = - (of_unichar_t)[splitCArray[13] hexadecimalValue]; + (of_unichar_t)[splitObjects[13] hexadecimalValue]; [pool2 releaseObjects]; } [pool release]; @@ -90,32 +90,32 @@ OFFile *file = [OFFile fileWithPath: path mode: @"rb"]; OFString *line; pool2 = [[OFAutoreleasePool alloc] init]; - while ((line = [file readLine])) { + while ((line = [file readLine]) != nil) { OFArray *split; - OFString **splitCArray; + OFString **splitObjects; of_unichar_t codep; - if ([line characterAtIndex: 0] == '#') + if ([line length] == 0 || [line hasPrefix: @"#"]) continue; split = [line componentsSeparatedByString: @"; "]; if ([split count] != 4) { of_log(@"Invalid line: %s\n", line); [OFApplication terminateWithStatus: 1]; } - splitCArray = [split cArray]; + splitObjects = [split objects]; - if (![splitCArray[1] isEqual: @"S"] && - ![splitCArray[1] isEqual: @"C"]) + if (![splitObjects[1] isEqual: @"S"] && + ![splitObjects[1] isEqual: @"C"]) continue; - codep = (of_unichar_t)[splitCArray[0] hexadecimalValue]; + codep = (of_unichar_t)[splitObjects[0] hexadecimalValue]; casefoldingTable[codep] = - (of_unichar_t)[splitCArray[2] hexadecimalValue]; + (of_unichar_t)[splitObjects[2] hexadecimalValue]; [pool2 releaseObjects]; } [pool release]; Index: m4/buildsys.m4 ================================================================== --- m4/buildsys.m4 +++ m4/buildsys.m4 @@ -1,9 +1,10 @@ dnl -dnl Copyright (c) 2007 - 2009, Jonathan Schleifer +dnl Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012 +dnl Jonathan Schleifer dnl -dnl https://webkeks.org/hg/buildsys/ +dnl https://webkeks.org/git/?p=buildsys.git dnl dnl Permission to use, copy, modify, and/or distribute this software for any dnl purpose with or without fee is hereby granted, provided that the above dnl copyright notice and this permission notice is present in all copies. dnl @@ -98,12 +99,12 @@ LIB_PREFIX='lib' LIB_SUFFIX='.dylib' LDFLAGS_RPATH='-Wl,-rpath,${libdir}' PLUGIN_CFLAGS='-fPIC -DPIC' PLUGIN_LDFLAGS='-bundle -undefined dynamic_lookup' - PLUGIN_SUFFIX='.impl' - INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib && ${LN_S} -f $${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.dylib && ${LN_S} -f $${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib ${DESTDIR}${libdir}/$$i' + PLUGIN_SUFFIX='.bundle' + INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib && install_name_tool -id ${libdir}/$${i%.dylib}.${LIB_MAJOR}.dylib ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib && ${LN_S} -f $${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.dylib && ${LN_S} -f $${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib ${DESTDIR}${libdir}/$$i' UNINSTALL_LIB='&& rm -f ${DESTDIR}${libdir}/$$i ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.dylib ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib' CLEAN_LIB='' ;; solaris*) AC_MSG_RESULT(Solaris) Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -48,10 +48,11 @@ OFString+URLEncoding.m \ OFString+XMLEscaping.m \ OFString+XMLUnescaping.m \ OFTCPSocket.m \ ${OFTHREAD_M} \ + OFThreadPool.m \ OFURL.m \ OFXMLAttribute.m \ OFXMLCDATA.m \ OFXMLCharacters.m \ OFXMLComment.m \ @@ -64,19 +65,20 @@ base64.m \ of_asprintf.m \ of_strptime.m \ unicode.m -INCLUDES := ${SRCS:.m=.h} \ - OFCollection.h \ - OFJSONEncoding.h \ - OFSerialization.h \ - ObjFW.h \ - asprintf.h \ - ${ATOMIC_H} \ - macros.h \ - objfw-defs.h \ +INCLUDES := ${SRCS:.m=.h} \ + OFCollection.h \ + OFJSONRepresentation.h \ + OFSerialization.h \ + OFTLSSocket.h \ + ObjFW.h \ + asprintf.h \ + ${ATOMIC_H} \ + macros.h \ + objfw-defs.h \ ${THREADING_H} SRCS += OFArray_adjacent.m \ OFArray_adjacentSubarray.m \ OFCountedSet_hashtable.m \ @@ -96,13 +98,13 @@ iso_8859_15.m \ windows_1252.m \ ${OBJC_PROPERTIES_M} \ ${OBJC_SYNC_M} +OBJS_EXTRA = ${EXCEPTIONS_EXCEPTIONS_A} +LIB_OBJS_EXTRA = ${EXCEPTIONS_EXCEPTIONS_LIB_A} + include ../buildsys.mk CPPFLAGS += -I. -I.. -Iexceptions LD = ${OBJC} LDFLAGS += ${REEXPORT_LIBOBJC} ${MACH_ALIAS_LIST} - -LIB_OBJS := ${LIB_OBJS} ${EXCEPTIONS_EXCEPTIONS_LIB_A} -OBJS += ${EXCEPTIONS_EXCEPTIONS_A} Index: src/OFApplication.h ================================================================== --- src/OFApplication.h +++ src/OFApplication.h @@ -59,12 +59,15 @@ * signal-safe operations like setting a variable or calling a * signal-safe function! */ - (void)applicationDidReceiveSIGINT; +#ifndef _WIN32 /** * \brief A method which is called when the application received a SIGHUP. + * + * This signal is not available on Windows. * * \warning You are not allowed to send any messages inside this method, as * message dispatching is not signal-safe! You are only allowed to do * signal-safe operations like setting a variable or calling a * signal-safe function! @@ -71,10 +74,12 @@ */ - (void)applicationDidReceiveSIGHUP; /** * \brief A method which is called when the application received a SIGUSR1. + * + * This signal is not available on Windows. * * \warning You are not allowed to send any messages inside this method, as * message dispatching is not signal-safe! You are only allowed to do * signal-safe operations like setting a variable or calling a * signal-safe function! @@ -81,17 +86,20 @@ */ - (void)applicationDidReceiveSIGUSR1; /** * \brief A method which is called when the application received a SIGUSR2. + * + * This signal is not available on Windows. * * \warning You are not allowed to send any messages inside this method, as * message dispatching is not signal-safe! You are only allowed to do * signal-safe operations like setting a variable or calling a * signal-safe function! */ - (void)applicationDidReceiveSIGUSR2; +#endif @end /** * \brief Represents the application as an object. */ @@ -103,13 +111,15 @@ int *argc; char ***argv; @public id delegate; void (*SIGINTHandler)(id, SEL); +#ifndef _WIN32 void (*SIGHUPHandler)(id, SEL); void (*SIGUSR1Handler)(id, SEL); void (*SIGUSR2Handler)(id, SEL); +#endif } #ifdef OF_HAVE_PROPERTIES @property (readonly, assign) OFString *programName; @property (readonly, assign) OFArray *arguments; Index: src/OFApplication.m ================================================================== --- src/OFApplication.m +++ src/OFApplication.m @@ -16,12 +16,15 @@ #include "config.h" #define OF_APPLICATION_M +#include #include #include + +#include #import "OFApplication.h" #import "OFString.h" #import "OFArray.h" #import "OFDictionary.h" @@ -53,13 +56,15 @@ { \ app->sig##Handler(app->delegate, \ @selector(applicationDidReceive##sig)); \ } SIGNAL_HANDLER(SIGINT) +#ifndef _WIN32 SIGNAL_HANDLER(SIGHUP) SIGNAL_HANDLER(SIGUSR1) SIGNAL_HANDLER(SIGUSR2) +#endif #undef SIGNAL_HANDLER int of_application_main(int *argc, char **argv[], Class cls) { @@ -258,13 +263,15 @@ @selector(applicationDidReceive##sig)]) \ signal(sig, handle##sig); \ else \ signal(sig, SIG_DFL); REGISTER_SIGNAL(SIGINT) +#ifndef _WIN32 REGISTER_SIGNAL(SIGHUP) REGISTER_SIGNAL(SIGUSR1) REGISTER_SIGNAL(SIGUSR2) +#endif #undef REGISTER_SIGNAL } - (void)run { Index: src/OFArray.h ================================================================== --- src/OFArray.h +++ src/OFArray.h @@ -11,18 +11,25 @@ * 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. */ + +#ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS +#endif +#ifndef __STDC_CONSTANT_MACROS +# define __STDC_CONSTANT_MACROS +#endif #include #import "OFObject.h" #import "OFCollection.h" #import "OFEnumerator.h" #import "OFSerialization.h" -#import "OFJSONEncoding.h" +#import "OFJSONRepresentation.h" @class OFString; #ifdef OF_HAVE_BLOCKS typedef void (^of_array_enumeration_block_t)(id object, size_t index, @@ -34,11 +41,11 @@ /** * \brief An abstract class for storing objects in an array. */ @interface OFArray: OFObject + OFSerialization, OFJSONRepresentation> #ifdef OF_HAVE_PROPERTIES @property (readonly) size_t count; #endif /** @@ -70,28 +77,20 @@ * \param array An array * \return A new autoreleased OFArray */ + arrayWithArray: (OFArray*)array; -/** - * \brief Creates a new OFArray with the objects from the specified C array. - * - * \param objects A C array of objects, terminated with nil - * \return A new autoreleased OFArray - */ -+ arrayWithCArray: (id*)objects; - /** * \brief Creates a new OFArray with the objects from the specified C array of * the specified length. * * \param objects A C array of objects * \param length The length of the C array * \return A new autoreleased OFArray */ -+ arrayWithCArray: (id*)objects - length: (size_t)length; ++ arrayWithObjects: (id*)objects + count: (size_t)count; /** * \brief Initializes an OFArray with the specified object. * * \param object An object @@ -123,28 +122,20 @@ * \param array An array * \return An initialized OFArray */ - initWithArray: (OFArray*)array; -/** - * \brief Initializes an OFArray with the objects from the specified C array. - * - * \param objects A C array of objects, terminated with nil - * \return An initialized OFArray - */ -- initWithCArray: (id*)objects; - /** * \brief Initializes an OFArray with the objects from the specified C array of * the specified length. * * \param objects A C array of objects * \param length The length of the C array * \return An initialized OFArray */ -- initWithCArray: (id*)objects - length: (size_t)length; +- initWithObjects: (id*)objects + count: (size_t)count; /** * \brief Returns a specified object of the array. * * The returned object is not retained and autoreleased for performance @@ -152,10 +143,11 @@ * * \param index The number of the object to return * \return The specified object of the OFArray */ - (id)objectAtIndex: (size_t)index; +- (id)objectAtIndexedSubscript: (size_t)index; /** * \brief Copies the objects at the specified range to the specified buffer. * * \param buffer The buffer to copy the objects to @@ -167,11 +159,11 @@ /** * \brief Returns the objects of the array as a C array. * * \return The objects of the array as a C array */ -- (id*)cArray; +- (id*)objects; /** * \brief Returns the index of the first object that is equivalent to the * specified object or OF_INVALID_INDEX if it was not found. * @@ -338,5 +330,10 @@ - initWithArray: (OFArray*)data mutationsPtr: (unsigned long*)mutationsPtr; @end #import "OFMutableArray.h" + +#ifndef NSINTEGER_DEFINED +/* Required for array literals to work */ +@compatibility_alias NSArray OFArray; +#endif Index: src/OFArray.m ================================================================== --- src/OFArray.m +++ src/OFArray.m @@ -73,20 +73,15 @@ - initWithArray: (OFArray*)array { return (id)[[OFArray_adjacent alloc] initWithArray: array]; } -- initWithCArray: (id*)objects -{ - return (id)[[OFArray_adjacent alloc] initWithCArray: objects]; -} - -- initWithCArray: (id*)objects - length: (size_t)length -{ - return (id)[[OFArray_adjacent alloc] initWithCArray: objects - length: length]; +- initWithObjects: (id*)objects + count: (size_t)count +{ + return (id)[[OFArray_adjacent alloc] initWithObjects: objects + count: count]; } - initWithSerialization: (OFXMLElement*)element { return (id)[[OFArray_adjacent alloc] initWithSerialization: element]; @@ -155,20 +150,15 @@ + arrayWithArray: (OFArray*)array { return [[[self alloc] initWithArray: array] autorelease]; } -+ arrayWithCArray: (id*)objects -{ - return [[[self alloc] initWithCArray: objects] autorelease]; -} - -+ arrayWithCArray: (id*)objects - length: (size_t)length -{ - return [[[self alloc] initWithCArray: objects - length: length] autorelease]; ++ arrayWithObjects: (id*)objects + count: (size_t)count +{ + return [[[self alloc] initWithObjects: objects + count: count] autorelease]; } - init { if (isa == [OFArray class]) { @@ -214,20 +204,12 @@ [self release]; @throw [OFNotImplementedException exceptionWithClass: c selector: _cmd]; } -- initWithCArray: (id*)objects -{ - Class c = isa; - [self release]; - @throw [OFNotImplementedException exceptionWithClass: c - selector: _cmd]; -} - -- initWithCArray: (id*)objects - length: (size_t)length +- initWithObjects: (id*)objects + count: (size_t)count { Class c = isa; [self release]; @throw [OFNotImplementedException exceptionWithClass: c selector: _cmd]; @@ -254,11 +236,11 @@ for (i = 0; i < range.length; i++) buffer[i] = [self objectAtIndex: range.start + i]; } -- (id*)cArray +- (id*)objects { OFObject *container; size_t count; id *buffer; @@ -286,10 +268,15 @@ - (id)objectAtIndex: (size_t)index { @throw [OFNotImplementedException exceptionWithClass: isa selector: _cmd]; } + +- (id)objectAtIndexedSubscript: (size_t)index +{ + return [self objectAtIndex: index]; +} - (size_t)indexOfObject: (id)object { size_t i, count = [self count]; @@ -353,12 +340,12 @@ @try { [self getObjects: buffer inRange: range]; - ret = [OFArray arrayWithCArray: buffer - length: range.length]; + ret = [OFArray arrayWithObjects: buffer + count: range.length]; } @finally { [self freeMemory: buffer]; } return ret; @@ -373,11 +360,11 @@ - (OFString*)componentsJoinedByString: (OFString*)separator usingSelector: (SEL)selector { OFAutoreleasePool *pool, *pool2; OFMutableString *ret; - id *cArray; + id *objects; size_t i, count = [self count]; IMP append; if (count == 0) return @""; @@ -386,23 +373,23 @@ ret = [OFMutableString string]; append = [ret methodForSelector: @selector(appendString:)]; pool = [[OFAutoreleasePool alloc] init]; - cArray = [self cArray]; + objects = [self objects]; pool2 = [[OFAutoreleasePool alloc] init]; for (i = 0; i < count - 1; i++) { append(ret, @selector(appendString:), - [cArray[i] performSelector: selector]); + [objects[i] performSelector: selector]); append(ret, @selector(appendString:), separator); [pool2 releaseObjects]; } append(ret, @selector(appendString:), - [cArray[i] performSelector: selector]); + [objects[i] performSelector: selector]); [ret makeImmutable]; [pool release]; @@ -433,18 +420,18 @@ return YES; } - (uint32_t)hash { - id *cArray = [self cArray]; + id *objects = [self objects]; size_t i, count = [self count]; uint32_t hash; OF_HASH_INIT(hash); for (i = 0; i < count; i++) { - uint32_t h = [cArray[i] hash]; + uint32_t h = [objects[i] hash]; OF_HASH_ADD(hash, h >> 24); OF_HASH_ADD(hash, (h >> 16) & 0xFF); OF_HASH_ADD(hash, (h >> 8) & 0xFF); OF_HASH_ADD(hash, h & 0xFF); @@ -487,11 +474,11 @@ - (OFXMLElement*)XMLElementBySerializing { OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; OFAutoreleasePool *pool2; OFXMLElement *element; - id *cArray = [self cArray]; + id *objects = [self objects]; size_t i, count = [self count]; if ([self isKindOfClass: [OFMutableArray class]]) element = [OFXMLElement elementWithName: @"OFMutableArray" namespace: OF_SERIALIZATION_NS]; @@ -500,11 +487,11 @@ namespace: OF_SERIALIZATION_NS]; pool2 = [[OFAutoreleasePool alloc] init]; for (i = 0; i < count; i++) { - [element addChild: [cArray[i] XMLElementBySerializing]]; + [element addChild: [objects[i] XMLElementBySerializing]]; [pool2 releaseObjects]; } [element retain]; @@ -533,27 +520,27 @@ return JSON; } - (void)makeObjectsPerformSelector: (SEL)selector { - id *cArray = [self cArray]; + id *objects = [self objects]; size_t i, count = [self count]; for (i = 0; i < count; i++) - ((void(*)(id, SEL))[cArray[i] - methodForSelector: selector])(cArray[i], selector); + ((void(*)(id, SEL))[objects[i] + methodForSelector: selector])(objects[i], selector); } - (void)makeObjectsPerformSelector: (SEL)selector withObject: (id)object { - id *cArray = [self cArray]; + id *objects = [self objects]; size_t i, count = [self count]; for (i = 0; i < count; i++) - ((void(*)(id, SEL, id))[cArray[i] - methodForSelector: selector])(cArray[i], selector, object); + ((void(*)(id, SEL, id))[objects[i] + methodForSelector: selector])(objects[i], selector, object); } - (OFArray*)sortedArray { OFMutableArray *new = [[self mutableCopy] autorelease]; @@ -588,11 +575,11 @@ if (state->state >= count) return 0; state->state = count; - state->itemsPtr = [self cArray]; + state->itemsPtr = [self objects]; state->mutationsPtr = (unsigned long*)self; return (int)count; } @@ -629,12 +616,12 @@ [self enumerateObjectsUsingBlock: ^ (id object, size_t index, BOOL *stop) { tmp[index] = block(object, index); }]; - ret = [OFArray arrayWithCArray: tmp - length: count]; + ret = [OFArray arrayWithObjects: tmp + count: count]; } @finally { [self freeMemory: tmp]; } return ret; @@ -654,12 +641,12 @@ BOOL *stop) { if (block(object, index)) tmp[i++] = object; }]; - ret = [OFArray arrayWithCArray: tmp - length: i]; + ret = [OFArray arrayWithObjects: tmp + count: i]; } @finally { [self freeMemory: tmp]; } return ret; Index: src/OFArray_adjacent.m ================================================================== --- src/OFArray_adjacent.m +++ src/OFArray_adjacent.m @@ -85,32 +85,32 @@ return self; } - initWithArray: (OFArray*)array_ { - id *cArray; + id *objects; size_t i, count; self = [self init]; @try { - cArray = [array_ cArray]; + objects = [array_ objects]; count = [array_ count]; } @catch (id e) { [self release]; @throw e; } @try { for (i = 0; i < count; i++) - [cArray[i] retain]; + [objects[i] retain]; [array addNItems: count - fromCArray: cArray]; + fromCArray: objects]; } @catch (id e) { for (i = 0; i < count; i++) - [cArray[i] release]; + [objects[i] release]; /* Prevent double-release of objects */ [array release]; array = nil; @@ -119,55 +119,27 @@ } return self; } -- initWithCArray: (id*)objects -{ - self = [self init]; - - @try { - id *object; - size_t count = 0; - - for (object = objects; *object != nil; object++) { - [*object retain]; - count++; - } - - [array addNItems: count - fromCArray: objects]; - } @catch (id e) { - id *object; - - for (object = objects; *object != nil; object++) - [*object release]; - - [self release]; - @throw e; - } - - return self; -} - -- initWithCArray: (id*)objects - length: (size_t)length +- initWithObjects: (id*)objects + count: (size_t)count { self = [self init]; @try { size_t i; - for (i = 0; i < length; i++) + for (i = 0; i < count; i++) [objects[i] retain]; - [array addNItems: length + [array addNItems: count fromCArray: objects]; } @catch (id e) { size_t i; - for (i = 0; i < length; i++) + for (i = 0; i < count; i++) [objects[i] release]; [self release]; @throw e; } @@ -217,52 +189,57 @@ - (size_t)count { return [array count]; } -- (id*)cArray +- (id*)objects { return [array cArray]; } - (id)objectAtIndex: (size_t)index { return *((id*)[array itemAtIndex: index]); } + +- (id)objectAtIndexedSubscript: (size_t)index +{ + return *((id*)[array itemAtIndex: index]); +} - (void)getObjects: (id*)buffer inRange: (of_range_t)range { - id *cArray = [array cArray]; + id *objects = [array cArray]; size_t i, count = [array count]; if (range.start + range.length > count) @throw [OFOutOfRangeException exceptionWithClass: isa]; for (i = 0; i < range.length; i++) - buffer[i] = cArray[range.start + i]; + buffer[i] = objects[range.start + i]; } - (size_t)indexOfObject: (id)object { - id *cArray = [array cArray]; + id *objects = [array cArray]; size_t i, count = [array count]; for (i = 0; i < count; i++) - if ([cArray[i] isEqual: object]) + if ([objects[i] isEqual: object]) return i; return OF_INVALID_INDEX; } - (size_t)indexOfObjectIdenticalTo: (id)object { - id *cArray = [array cArray]; + id *objects = [array cArray]; size_t i, count = [array count]; for (i = 0; i < count; i++) - if (cArray[i] == object) + if (objects[i] == object) return i; return OF_INVALID_INDEX; } @@ -278,18 +255,18 @@ count = [array count]; if (range.start + range.length > count) @throw [OFOutOfRangeException exceptionWithClass: isa]; - return [OFArray arrayWithCArray: (id*)[array cArray] + range.start - length: range.length]; + return [OFArray arrayWithObjects: (id*)[array cArray] + range.start + count: range.length]; } - (BOOL)isEqual: (id)object { OFArray *otherArray; - id *cArray, *otherCArray; + id *objects, *otherObjects; size_t i, count; if ([object class] != [OFArray_adjacent class] && [object class] != [OFMutableArray_adjacent class] && [object class] != [OFArray_adjacentSubarray class]) @@ -300,30 +277,30 @@ count = [array count]; if (count != [otherArray count]) return NO; - cArray = [array cArray]; - otherCArray = [otherArray cArray]; + objects = [array cArray]; + otherObjects = [otherArray objects]; for (i = 0; i < count; i++) - if (![cArray[i] isEqual: otherCArray[i]]) + if (![objects[i] isEqual: otherObjects[i]]) return NO; return YES; } - (uint32_t)hash { - id *cArray = [array cArray]; + id *objects = [array cArray]; size_t i, count = [array count]; uint32_t hash; OF_HASH_INIT(hash); for (i = 0; i < count; i++) { - uint32_t h = [cArray[i] hash]; + uint32_t h = [objects[i] hash]; OF_HASH_ADD(hash, h >> 24); OF_HASH_ADD(hash, (h >> 16) & 0xFF); OF_HASH_ADD(hash, (h >> 8) & 0xFF); OF_HASH_ADD(hash, h & 0xFF); @@ -335,27 +312,27 @@ } #ifdef OF_HAVE_BLOCKS - (void)enumerateObjectsUsingBlock: (of_array_enumeration_block_t)block { - id *cArray = [array cArray]; + id *objects = [array cArray]; size_t i, count = [array count]; BOOL stop = NO; for (i = 0; i < count && !stop; i++) - block(cArray[i], i, &stop); + block(objects[i], i, &stop); } #endif - (void)dealloc { - id *cArray = [array cArray]; + id *objects = [array cArray]; size_t i, count = [array count]; for (i = 0; i < count; i++) - [cArray[i] release]; + [objects[i] release]; [array release]; [super dealloc]; } @end Index: src/OFArray_adjacentSubarray.m ================================================================== --- src/OFArray_adjacentSubarray.m +++ src/OFArray_adjacentSubarray.m @@ -19,19 +19,19 @@ #import "OFArray_adjacentSubarray.h" #import "OFArray_adjacent.h" #import "OFMutableArray_adjacent.h" @implementation OFArray_adjacentSubarray -- (id*)cArray +- (id*)objects { - return [array cArray] + range.start; + return [array objects] + range.start; } - (BOOL)isEqual: (id)object { OFArray *otherArray; - id *cArray, *otherCArray; + id *objects, *otherObjects; size_t i; if ([object class] != [OFArray_adjacent class] && [object class] != [OFMutableArray_adjacent class] && [object class] != [OFArray_adjacentSubarray class]) @@ -40,27 +40,27 @@ otherArray = object; if (range.length != [otherArray count]) return NO; - cArray = [self cArray]; - otherCArray = [otherArray cArray]; + objects = [self objects]; + otherObjects = [otherArray objects]; for (i = 0; i < range.length; i++) - if (![cArray[i] isEqual: otherCArray[i]]) + if (![objects[i] isEqual: otherObjects[i]]) return NO; return YES; } #ifdef OF_HAVE_BLOCKS - (void)enumerateObjectsUsingBlock: (of_array_enumeration_block_t)block { - id *cArray = [self cArray]; + id *objects = [self objects]; size_t i; BOOL stop = NO; for (i = 0; i < range.length && !stop; i++) - block(cArray[i], i, &stop); + block(objects[i], i, &stop); } #endif @end Index: src/OFAutoreleasePool.h ================================================================== --- src/OFAutoreleasePool.h +++ src/OFAutoreleasePool.h @@ -37,14 +37,12 @@ * * \param object The object to add to the autorelease pool */ + (void)addObject: (id)object; -/// \cond internal + (void)_releaseAll; - (void)_addObject: (id)object; -/// \endcond /** * \brief Releases all objects in the autorelease pool. * * This does not free the memory allocated to store pointers to the objects in Index: src/OFBlock.m ================================================================== --- src/OFBlock.m +++ src/OFBlock.m @@ -392,16 +392,10 @@ selector: _cmd]; } - init { - @throw [OFNotImplementedException exceptionWithClass: isa - selector: _cmd]; -} - -- (void)addMemoryToPool: (void*)ptr -{ @throw [OFNotImplementedException exceptionWithClass: isa selector: _cmd]; } - (void*)allocMemoryWithSize: (size_t)size Index: src/OFConstantString.m ================================================================== --- src/OFConstantString.m +++ src/OFConstantString.m @@ -53,15 +53,10 @@ { @throw [OFNotImplementedException exceptionWithClass: self selector: _cmd]; } -- (void)addMemoryToPool: (void*)ptr -{ - @throw [OFNotImplementedException exceptionWithClass: isa - selector: _cmd]; -} - (void*)allocMemoryWithSize: (size_t)size { @throw [OFNotImplementedException exceptionWithClass: isa selector: _cmd]; @@ -179,16 +174,10 @@ { @throw [OFNotImplementedException exceptionWithClass: self selector: _cmd]; } -- (void)addMemoryToPool: (void*)ptr -{ - @throw [OFNotImplementedException exceptionWithClass: isa - selector: _cmd]; -} - - (void*)allocMemoryWithSize: (size_t)size { @throw [OFNotImplementedException exceptionWithClass: isa selector: _cmd]; } Index: src/OFCountedSet_hashtable.m ================================================================== --- src/OFCountedSet_hashtable.m +++ src/OFCountedSet_hashtable.m @@ -79,15 +79,15 @@ - initWithArray: (OFArray*)array { self = [self init]; @try { - id *cArray = [array cArray]; + id *objects = [array objects]; size_t i, count = [array count]; for (i = 0; i < count; i++) - [self addObject: cArray[i]]; + [self addObject: objects[i]]; } @catch (id e) { [self release]; @throw e; } Index: src/OFDataArray.m ================================================================== --- src/OFDataArray.m +++ src/OFDataArray.m @@ -538,12 +538,11 @@ lastPageByte = of_pagesize - 1; newSize = ((count + nItems) * itemSize + lastPageByte) & ~lastPageByte; if (size != newSize) data = [self resizeMemory: data - toNItems: newSize - ofSize: itemSize]; + toSize: newSize]; memmove(data + (index + nItems) * itemSize, data + index * itemSize, (count - index) * itemSize); memcpy(data + index * itemSize, cArray, nItems * itemSize); Index: src/OFDate.h ================================================================== --- src/OFDate.h +++ src/OFDate.h @@ -54,13 +54,12 @@ /** * \brief Creates a new OFDate with the specified string in the specified * format. * - * The time zone used is UTC. If a time zone is specified anyway, an - * OFInvalidFormatException is thrown. See +[dateWithLocalDateString:format:] - * if you want to specify a time zone. + * The time zone used is UTC. See +[dateWithLocalDateString:format:] if you + * want local time. * * See the manpage for strftime for information on the format. * * \warning The format is currently limited to the following format specifiers: * %%d, %%e, %%H, %%m, %%M, %%S, %%y, %%Y, %%, %%n and %%t. @@ -74,12 +73,10 @@ /** * \brief Creates a new OFDate with the specified string in the specified * format. * - * If no time zone is specified, local time is assumed. - * * See the manpage for strftime for information on the format. * * \warning The format is currently limited to the following format specifiers: * %%d, %%e, %%H, %%m, %%M, %%S, %%y, %%Y, %%, %%n and %%t. * Index: src/OFDate.m ================================================================== --- src/OFDate.m +++ src/OFDate.m @@ -248,16 +248,10 @@ if (of_strptime([string UTF8String], [format UTF8String], &tm) == NULL) @throw [OFInvalidFormatException exceptionWithClass: isa]; -#ifdef STRUCT_TM_HAS_TM_GMTOFF - if (tm.tm_gmtoff != 0) - @throw [OFInvalidFormatException - exceptionWithClass: isa]; -#endif - /* Years */ seconds = (int64_t)(tm.tm_year - 70) * 31536000; /* Days of leap years, excluding the year to look at */ seconds += (((tm.tm_year + 1899) / 4) - 492) * 86400; seconds -= (((tm.tm_year + 1899) / 100) - 19) * 86400; Index: src/OFDictionary.h ================================================================== --- src/OFDictionary.h +++ src/OFDictionary.h @@ -11,18 +11,25 @@ * 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. */ + +#ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS +#endif +#ifndef __STDC_CONSTANT_MACROS +# define __STDC_CONSTANT_MACROS +#endif #include #import "OFObject.h" #import "OFCollection.h" #import "OFEnumerator.h" #import "OFSerialization.h" -#import "OFJSONEncoding.h" +#import "OFJSONRepresentation.h" @class OFArray; #ifdef OF_HAVE_BLOCKS typedef void (^of_dictionary_enumeration_block_t)(id key, id object, @@ -38,11 +45,11 @@ * * Note: Fast enumeration on a dictionary enumerates through the keys of the * dictionary. */ @interface OFDictionary: OFObject + OFSerialization, OFJSONRepresentation> /** * \brief Creates a new OFDictionary. * * \return A new autoreleased OFDictionary */ @@ -74,10 +81,22 @@ * \return A new autoreleased OFDictionary */ + dictionaryWithObjects: (OFArray*)objects forKeys: (OFArray*)keys; +/** + * \brief Creates a new OFDictionary with the specified keys and objects. + * + * \param keys An array of keys + * \param objects An array of objects + * \param count The number of objects in the arrays + * \return A new autoreleased OFDictionary + */ ++ dictionaryWithObjects: (id*)objects + forKeys: (id*)keys + count: (size_t)count; + /** * \brief Creates a new OFDictionary with the specified keys objects. * * \param firstKey The first key * \return A new autoreleased OFDictionary @@ -123,10 +142,23 @@ forKeys: (OFArray*)keys; /** * \brief Initializes an already allocated OFDictionary with the specified keys * and objects. + * + * \param keys An array of keys + * \param objects An array of objects + * \param count The number of objects in the arrays + * \return A new initialized OFDictionary + */ +- initWithObjects: (id*)objects + forKeys: (id*)keys + count: (size_t)count; + +/** + * \brief Initializes an already allocated OFDictionary with the specified keys + * and objects. * * \param firstKey The first key * \return A new initialized OFDictionary */ - initWithKeysAndObjects: (id)firstKey, ...; @@ -150,10 +182,11 @@ * * \param key The key whose object should be returned * \return The object for the given key or nil if the key was not found */ - (id)objectForKey: (id)key; +- (id)objectForKeyedSubscript: (id)key; /** * \brief Checks whether the dictionary contains an object with the specified * address. * @@ -219,5 +252,10 @@ copyKeys: (BOOL)copyKeys; #endif @end #import "OFMutableDictionary.h" + +#ifndef NSINTEGER_DEFINED +/* Required for dictionary literals to work */ +@compatibility_alias NSDictionary OFDictionary; +#endif Index: src/OFDictionary.m ================================================================== --- src/OFDictionary.m +++ src/OFDictionary.m @@ -57,10 +57,19 @@ forKeys: (OFArray*)keys { return (id)[[OFDictionary_hashtable alloc] initWithObjects: objects forKeys: keys]; } + +- initWithObjects: (id*)objects + forKeys: (id*)keys + count: (size_t)count +{ + return (id)[[OFDictionary_hashtable alloc] initWithObjects: objects + forKeys: keys + count: count]; +} - initWithKeysAndObjects: (id )firstKey, ... { id ret; va_list arguments; @@ -144,10 +153,19 @@ forKeys: (OFArray*)keys { return [[[self alloc] initWithObjects: objects forKeys: keys] autorelease]; } + ++ dictionaryWithObjects: (id*)objects + forKeys: (id*)keys + count: (size_t)count +{ + return [[[self alloc] initWithObjects: objects + forKeys: keys + count: count] autorelease]; +} + dictionaryWithKeysAndObjects: (id)firstKey, ... { id ret; va_list arguments; @@ -192,10 +210,20 @@ Class c = isa; [self release]; @throw [OFNotImplementedException exceptionWithClass: c selector: _cmd]; } + +- initWithObjects: (id*)objects + forKeys: (id*)keys + count: (size_t)count +{ + Class c = isa; + [self release]; + @throw [OFNotImplementedException exceptionWithClass: c + selector: _cmd]; +} - initWithKeysAndObjects: (id)firstKey, ... { id ret; va_list arguments; @@ -228,10 +256,15 @@ - (id)objectForKey: (id)key { @throw [OFNotImplementedException exceptionWithClass: isa selector: _cmd]; } + +- (id)objectForKeyedSubscript: (id)key +{ + return [self objectForKey: key]; +} - (size_t)count { @throw [OFNotImplementedException exceptionWithClass: isa selector: _cmd]; @@ -245,24 +278,30 @@ - mutableCopy { return [[OFMutableDictionary alloc] initWithDictionary: self]; } -- (BOOL)isEqual: (id)dictionary +- (BOOL)isEqual: (id)object { + OFDictionary *otherDictionary; OFAutoreleasePool *pool; OFEnumerator *enumerator; id key; - if ([dictionary count] != [self count]) + if (![object isKindOfClass: [OFDictionary class]]) + return NO; + + otherDictionary = object; + + if ([otherDictionary count] != [self count]) return NO; pool = [[OFAutoreleasePool alloc] init]; enumerator = [self keyEnumerator]; while ((key = [enumerator nextObject]) != nil) { - id object = [dictionary objectForKey: key]; + id object = [otherDictionary objectForKey: key]; if (object == nil || ![object isEqual: [self objectForKey: key]]) { [pool release]; return NO; @@ -311,62 +350,62 @@ } - (OFArray*)allKeys { OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; - id *cArray = [self allocMemoryForNItems: [self count] - ofSize: sizeof(id)]; + id *keys = [self allocMemoryForNItems: [self count] + ofSize: sizeof(id)]; OFArray *ret; OFEnumerator *enumerator; id key; size_t i = 0; pool = [[OFAutoreleasePool alloc] init]; enumerator = [self keyEnumerator]; while ((key = [enumerator nextObject]) != nil) - cArray[i++] = key; + keys[i++] = key; assert(i == [self count]); [pool release]; @try { - ret = [OFArray arrayWithCArray: cArray - length: [self count]]; + ret = [OFArray arrayWithObjects: keys + count: [self count]]; } @finally { - [self freeMemory: cArray]; + [self freeMemory: keys]; } return ret; } - (OFArray*)allObjects { OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; - id *cArray = [self allocMemoryForNItems: [self count] - ofSize: sizeof(id)]; + id *objects = [self allocMemoryForNItems: [self count] + ofSize: sizeof(id)]; OFArray *ret; OFEnumerator *enumerator; id object; size_t i = 0; pool = [[OFAutoreleasePool alloc] init]; enumerator = [self objectEnumerator]; while ((object = [enumerator nextObject]) != nil) - cArray[i++] = object; + objects[i++] = object; assert(i == [self count]); [pool release]; @try { - ret = [OFArray arrayWithCArray: cArray - length: [self count]]; + ret = [OFArray arrayWithObjects: objects + count: [self count]]; } @finally { - [self freeMemory: cArray]; + [self freeMemory: objects]; } return ret; } Index: src/OFDictionary_hashtable.m ================================================================== --- src/OFDictionary_hashtable.m +++ src/OFDictionary_hashtable.m @@ -233,19 +233,38 @@ } - initWithObjects: (OFArray*)objects forKeys: (OFArray*)keys { + id ret; + + @try { + if ([objects count] != [keys count]) + @throw [OFInvalidArgumentException + exceptionWithClass: isa]; + + ret = [self initWithObjects: [objects objects] + forKeys: [keys objects] + count: [objects count]]; + } @catch (id e) { + [self release]; + @throw e; + } + + return ret; +} + +- initWithObjects: (id*)objects + forKeys: (id*)keys + count: (size_t)count_ +{ self = [super init]; @try { - id *objectsCArray, *keysCArray; uint32_t i, j, newSize; - keysCArray = [keys cArray]; - objectsCArray = [objects cArray]; - count = [keys count]; + count = count_; if (count > UINT32_MAX) @throw [OFOutOfRangeException exceptionWithClass: isa]; for (newSize = 1; newSize < count; newSize <<= 1); @@ -264,31 +283,30 @@ size = newSize; for (i = 0; i < count; i++) { uint32_t hash, last; - hash = [keysCArray[i] hash]; + hash = [keys[i] hash]; last = size; for (j = hash & (size - 1); j < last && data[j] != NULL; j++) - if ([data[j]->key isEqual: keysCArray[i]]) + if ([data[j]->key isEqual: keys[i]]) break; /* In case the last bucket is already used */ if (j >= last) { last = hash & (size - 1); for (j = 0; j < last && data[j] != NULL; j++) - if ([data[j]->key - isEqual: keysCArray[i]]) + if ([data[j]->key isEqual: keys[i]]) break; } /* Key not in dictionary */ if (j >= last || data[j] == NULL || - ![data[j]->key isEqual: keysCArray[i]]) { + ![data[j]->key isEqual: keys[i]]) { struct of_dictionary_hashtable_bucket *bucket; id key; last = size; @@ -307,14 +325,14 @@ @throw [OFOutOfRangeException exceptionWithClass: isa]; bucket = [self allocMemoryWithSize: sizeof(*bucket)]; - key = [keysCArray[i] copy]; + key = [keys[i] copy]; bucket->key = key; - bucket->object = [objectsCArray[i] retain]; + bucket->object = [objects[i] retain]; bucket->hash = hash; data[j] = bucket; continue; @@ -324,13 +342,13 @@ * The key is already in the dictionary. However, we * just replace it so that the programmer gets the same * behavior as if he'd call setObject:forKey: for each * key/object pair. */ - [objectsCArray[i] retain]; + [objects[i] retain]; [data[j]->object release]; - data[j]->object = objectsCArray[i]; + data[j]->object = objects[i]; } } @catch (id e) { [self release]; @throw e; } @@ -628,48 +646,48 @@ } - (OFArray*)allKeys { OFArray *ret; - id *cArray = [self allocMemoryForNItems: count - ofSize: sizeof(id)]; + id *keys = [self allocMemoryForNItems: count + ofSize: sizeof(id)]; size_t i, j; for (i = j = 0; i < size; i++) if (data[i] != NULL && data[i] != DELETED) - cArray[j++] = data[i]->key; + keys[j++] = data[i]->key; assert(j == count); @try { - ret = [OFArray arrayWithCArray: cArray - length: count]; + ret = [OFArray arrayWithObjects: keys + count: count]; } @finally { - [self freeMemory: cArray]; + [self freeMemory: keys]; } return ret; } - (OFArray*)allObjects { OFArray *ret; - id *cArray = [self allocMemoryForNItems: count - ofSize: sizeof(id)]; + id *objects = [self allocMemoryForNItems: count + ofSize: sizeof(id)]; size_t i, j; for (i = j = 0; i < size; i++) if (data[i] != NULL && data[i] != DELETED) - cArray[j++] = data[i]->object; + objects[j++] = data[i]->object; assert(j == count); @try { - ret = [OFArray arrayWithCArray: cArray - length: count]; + ret = [OFArray arrayWithObjects: objects + count: count]; } @finally { - [self freeMemory: cArray]; + [self freeMemory: objects]; } return ret; } Index: src/OFFile.h ================================================================== --- src/OFFile.h +++ src/OFFile.h @@ -11,10 +11,17 @@ * 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. */ + +#ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS +#endif +#ifndef __STDC_CONSTANT_MACROS +# define __STDC_CONSTANT_MACROS +#endif #include #import "OFSeekableStream.h" @@ -86,10 +93,19 @@ * * \param path The path of the directory */ + (void)createDirectoryAtPath: (OFString*)path; +/** + * \brief Creates a directory at the specified path. + * + * \param path The path of the directory + * \param createParents Whether to create the parents of the directory + */ ++ (void)createDirectoryAtPath: (OFString*)path + createParents: (BOOL)createParents; + /** * \brief Returns an array with the files in the specified directory. * * \param path The path of the directory * \return An array of OFStrings with the files at the specified path @@ -101,10 +117,17 @@ * * \param path The new directory to change to */ + (void)changeToDirectory: (OFString*)path; +/** + * \brief Returns the size of the specified file. + * + * \return The size of the specified file + */ ++ (off_t)sizeOfFile: (OFString*)path; + /** * \brief Returns the date of the last modification of the file. * * \return The date of the last modification of the file */ Index: src/OFFile.m ================================================================== --- src/OFFile.m +++ src/OFFile.m @@ -246,10 +246,47 @@ #endif @throw [OFCreateDirectoryFailedException exceptionWithClass: self path: path]; } + ++ (void)createDirectoryAtPath: (OFString*)path + createParents: (BOOL)createParents +{ + OFAutoreleasePool *pool, *pool2; + OFArray *pathComponents; + OFString *currentPath = nil, *component; + OFEnumerator *enumerator; + + if (!createParents) { + [OFFile createDirectoryAtPath: path]; + return; + } + + pool = [[OFAutoreleasePool alloc] init]; + + pathComponents = [path pathComponents]; + enumerator = [pathComponents objectEnumerator]; + pool2 = [[OFAutoreleasePool alloc] init]; + while ((component = [enumerator nextObject]) != nil) { + if (currentPath != nil) + currentPath = [OFString + stringWithPath: currentPath, component, nil]; + else + currentPath = component; + + if (![currentPath isEqual: @""] && + ![OFFile directoryExistsAtPath: currentPath]) + [OFFile createDirectoryAtPath: currentPath]; + + [currentPath retain]; + [pool2 releaseObjects]; + [currentPath autorelease]; + } + + [pool release]; +} + (OFArray*)filesInDirectoryAtPath: (OFString*)path { OFAutoreleasePool *pool; OFMutableArray *files = [OFMutableArray array]; @@ -370,10 +407,24 @@ path: path mode: mode]; # endif } #endif + ++ (off_t)sizeOfFile: (OFString*)path +{ + struct stat s; + + if (stat([path cStringWithEncoding: OF_STRING_ENCODING_NATIVE], + &s) == -1) + /* FIXME: Maybe use another exception? */ + @throw [OFOpenFileFailedException exceptionWithClass: self + path: path + mode: @"r"]; + + return s.st_size; +} + (OFDate*)modificationDateOfFile: (OFString*)path { struct stat s; Index: src/OFHTTPRequest.h ================================================================== --- src/OFHTTPRequest.h +++ src/OFHTTPRequest.h @@ -280,15 +280,13 @@ @property (readonly) short statusCode; @property (readonly, copy) OFDictionary *headers; @property (readonly, retain) OFDataArray *data; #endif -/// \cond internal - initWithStatusCode: (short)status headers: (OFDictionary*)headers data: (OFDataArray*)data; -/// \endcond /** * \brief Returns the state code of the result of the HTTP request. * * \return The status code of the result of the HTTP request Index: src/OFHTTPRequest.m ================================================================== --- src/OFHTTPRequest.m +++ src/OFHTTPRequest.m @@ -28,10 +28,12 @@ #import "OFDictionary.h" #import "OFDataArray.h" #import "OFAutoreleasePool.h" #import "OFHTTPRequestFailedException.h" +#import "OFInvalidEncodingException.h" +#import "OFInvalidFormatException.h" #import "OFInvalidServerReplyException.h" #import "OFOutOfRangeException.h" #import "OFTruncatedDataException.h" #import "OFUnsupportedProtocolException.h" @@ -38,11 +40,11 @@ #import "macros.h" Class of_http_request_tls_socket_class = Nil; static OF_INLINE void -normalize_key(OFString *key) +normalizeKey(OFString *key) { uint8_t *str = (uint8_t*)[key UTF8String]; BOOL firstLetter = YES; while (*str != '\0') { @@ -73,14 +75,14 @@ - init { self = [super init]; requestType = OF_HTTP_REQUEST_TYPE_GET; - headers = [[OFDictionary alloc] - initWithObject: @"Something using ObjFW " - @"" - forKey: @"User-Agent"]; + headers = [[OFDictionary alloc] initWithKeysAndObjects: + @"Connection", @"close", + @"User-Agent", @"Something using ObjFW " + @"", nil]; storesData = YES; return self; } @@ -107,11 +109,11 @@ [super dealloc]; } - (void)setURL: (OFURL*)URL_ { - OF_SETTER(URL, URL_, YES, YES) + OF_SETTER(URL, URL_, YES, 1) } - (OFURL*)URL { OF_GETTER(URL, YES) @@ -127,21 +129,21 @@ return requestType; } - (void)setQueryString: (OFString*)queryString_ { - OF_SETTER(queryString, queryString_, YES, YES) + OF_SETTER(queryString, queryString_, YES, 1) } - (OFString*)queryString { OF_GETTER(queryString, YES) } - (void)setHeaders: (OFDictionary*)headers_ { - OF_SETTER(headers, headers_, YES, YES) + OF_SETTER(headers, headers_, YES, 1) } - (OFDictionary*)headers { OF_GETTER(headers, YES) @@ -186,10 +188,21 @@ { OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; OFString *scheme = [URL scheme]; OFTCPSocket *sock; OFHTTPRequestResult *result; + OFString *line, *path; + OFMutableDictionary *serverHeaders; + OFDataArray *data; + OFEnumerator *keyEnumerator, *objectEnumerator; + OFString *key, *object, *contentLengthHeader; + int status; + const char *type = NULL; + size_t contentLength = 0; + BOOL chunked; + char *buffer; + size_t bytesReceived; if (![scheme isEqual: @"http"] && ![scheme isEqual: @"https"]) @throw [OFUnsupportedProtocolException exceptionWithClass: isa URL: URL]; @@ -206,219 +219,297 @@ } [delegate request: self didCreateSocket: sock]; - @try { - OFString *line, *path; - OFMutableDictionary *serverHeaders; - OFDataArray *data; - OFEnumerator *keyEnumerator, *objectEnumerator; - OFString *key, *object, *contentLengthHeader; - int status; - const char *type = NULL; - char *buffer; - size_t bytesReceived; - - [sock connectToHost: [URL host] - port: [URL port]]; - - /* - * Work around a bug with packet bisection in lighttpd when - * using HTTPS. - */ - [sock setBuffersWrites: YES]; - - if (requestType == OF_HTTP_REQUEST_TYPE_GET) - type = "GET"; - if (requestType == OF_HTTP_REQUEST_TYPE_HEAD) - type = "HEAD"; - if (requestType == OF_HTTP_REQUEST_TYPE_POST) - type = "POST"; - - if ([(path = [URL path]) isEqual: @""]) - path = @"/"; - - if ([URL query] != nil) - [sock writeFormat: @"%s %@?%@ HTTP/1.0\r\n", - type, path, [URL query]]; - else - [sock writeFormat: @"%s %@ HTTP/1.0\r\n", type, path]; - - if ([URL port] == 80) - [sock writeFormat: @"Host: %@\r\n", [URL host]]; - else - [sock writeFormat: @"Host: %@:%d\r\n", [URL host], - [URL port]]; - - keyEnumerator = [headers keyEnumerator]; - objectEnumerator = [headers objectEnumerator]; - - while ((key = [keyEnumerator nextObject]) != nil && - (object = [objectEnumerator nextObject]) != nil) - [sock writeFormat: @"%@: %@\r\n", key, object]; - - if (requestType == OF_HTTP_REQUEST_TYPE_POST) { - if ([headers objectForKey: @"Content-Type"] == nil) - [sock writeString: @"Content-Type: " - @"application/x-www-form-urlencoded; " - @"charset=UTF-8\r\n"]; - - if ([headers objectForKey: @"Content-Length"] == nil) - [sock writeFormat: @"Content-Length: %d\r\n", - [queryString UTF8StringLength]]; - } - - [sock writeString: @"\r\n"]; - - /* Work around a bug in lighttpd, see above */ - [sock flushWriteBuffer]; - [sock setBuffersWrites: NO]; - - if (requestType == OF_HTTP_REQUEST_TYPE_POST) - [sock writeString: queryString]; - - /* - * We also need to check for HTTP/1.1 since Apache always - * declares the reply to be HTTP/1.1. - */ - line = [sock readLine]; - if (![line hasPrefix: @"HTTP/1.0 "] && - ![line hasPrefix: @"HTTP/1.1 "]) - @throw [OFInvalidServerReplyException - exceptionWithClass: isa]; - - status = (int)[[line substringWithRange: - of_range(9, 3)] decimalValue]; - - serverHeaders = [OFMutableDictionary dictionary]; - - while ((line = [sock readLine]) != nil) { - OFString *key, *value; - const char *line_c = [line UTF8String], *tmp; - - if ([line isEqual: @""]) - break; - - if ((tmp = strchr(line_c, ':')) == NULL) - @throw [OFInvalidServerReplyException - exceptionWithClass: isa]; - - key = [OFString stringWithUTF8String: line_c - length: tmp - line_c]; - normalize_key(key); - - do { - tmp++; - } while (*tmp == ' '); - - value = [OFString stringWithUTF8String: tmp]; - - if ((redirects > 0 && (status == 301 || status == 302 || - status == 303) && [key isEqual: @"Location"]) && - (redirectsFromHTTPSToHTTPAllowed || - [scheme isEqual: @"http"] || - ![value hasPrefix: @"http://"])) { - OFURL *new; - BOOL follow; - - new = [OFURL URLWithString: value - relativeToURL: URL]; - - follow = [delegate request: self - willFollowRedirectTo: new]; - - if (!follow && delegate != nil) { - [serverHeaders setObject: value - forKey: key]; - continue; - } - - new = [new retain]; - [URL release]; - URL = new; - - if (status == 303) { - requestType = OF_HTTP_REQUEST_TYPE_GET; - [queryString release]; - queryString = nil; - } - - [pool release]; - pool = nil; - - return [self performWithRedirects: - redirects - 1]; - } - - [serverHeaders setObject: value - forKey: key]; - } - - [delegate request: self - didReceiveHeaders: serverHeaders - withStatusCode: status]; - - if (storesData) - data = [OFDataArray dataArray]; - else - data = nil; - - buffer = [self allocMemoryWithSize: of_pagesize]; - bytesReceived = 0; - @try { - size_t len; - - while ((len = [sock readNBytes: of_pagesize - intoBuffer: buffer]) > 0) { - [delegate request: self - didReceiveData: buffer - withLength: len]; - - bytesReceived += len; - [data addNItems: len - fromCArray: buffer]; - } - } @finally { - [self freeMemory: buffer]; - } - - if ((contentLengthHeader = - [serverHeaders objectForKey: @"Content-Length"]) != nil) { - intmax_t cl = [contentLengthHeader decimalValue]; - - if (cl > SIZE_MAX) - @throw [OFOutOfRangeException - exceptionWithClass: isa]; - - /* - * We only want to throw on these status codes as we - * will throw an OFHTTPRequestFailedException for all - * other status codes later. - */ - if (cl != bytesReceived && (status == 200 || - status == 301 || status == 302 || status == 303)) - @throw [OFTruncatedDataException - exceptionWithClass: isa]; - } - - [serverHeaders makeImmutable]; - - result = [[OFHTTPRequestResult alloc] - initWithStatusCode: status - headers: serverHeaders - data: data]; - - if (status != 200 && status != 301 && status != 302 && - status != 303) - @throw [OFHTTPRequestFailedException - exceptionWithClass: isa - HTTPRequest: self - result: result]; - } @finally { - [pool release]; - } + [sock connectToHost: [URL host] + port: [URL port]]; + + /* + * Work around a bug with packet bisection in lighttpd when using + * HTTPS. + */ + [sock setBuffersWrites: YES]; + + if (requestType == OF_HTTP_REQUEST_TYPE_GET) + type = "GET"; + if (requestType == OF_HTTP_REQUEST_TYPE_HEAD) + type = "HEAD"; + if (requestType == OF_HTTP_REQUEST_TYPE_POST) + type = "POST"; + + if ([(path = [URL path]) isEqual: @""]) + path = @"/"; + + if ([URL query] != nil) + [sock writeFormat: @"%s %@?%@ HTTP/1.1\r\n", + type, path, [URL query]]; + else + [sock writeFormat: @"%s %@ HTTP/1.1\r\n", type, path]; + + if ([URL port] == 80) + [sock writeFormat: @"Host: %@\r\n", [URL host]]; + else + [sock writeFormat: @"Host: %@:%d\r\n", [URL host], + [URL port]]; + + keyEnumerator = [headers keyEnumerator]; + objectEnumerator = [headers objectEnumerator]; + + while ((key = [keyEnumerator nextObject]) != nil && + (object = [objectEnumerator nextObject]) != nil) + [sock writeFormat: @"%@: %@\r\n", key, object]; + + if (requestType == OF_HTTP_REQUEST_TYPE_POST) { + if ([headers objectForKey: @"Content-Type"] == nil) + [sock writeString: @"Content-Type: " + @"application/x-www-form-urlencoded; " + @"charset=UTF-8\r\n"]; + + if ([headers objectForKey: @"Content-Length"] == nil) + [sock writeFormat: @"Content-Length: %d\r\n", + [queryString UTF8StringLength]]; + } + + [sock writeString: @"\r\n"]; + + /* Work around a bug in lighttpd, see above */ + [sock flushWriteBuffer]; + [sock setBuffersWrites: NO]; + + if (requestType == OF_HTTP_REQUEST_TYPE_POST) + [sock writeString: queryString]; + + @try { + line = [sock readLine]; + } @catch (OFInvalidEncodingException *e) { + @throw [OFInvalidServerReplyException exceptionWithClass: isa]; + } + + if (![line hasPrefix: @"HTTP/1.0 "] && ![line hasPrefix: @"HTTP/1.1 "]) + @throw [OFInvalidServerReplyException exceptionWithClass: isa]; + + status = (int)[[line substringWithRange: of_range(9, 3)] decimalValue]; + + serverHeaders = [OFMutableDictionary dictionary]; + + for (;;) { + OFString *key, *value; + const char *line_c, *tmp; + + @try { + line = [sock readLine]; + } @catch (OFInvalidEncodingException *e) { + @throw [OFInvalidServerReplyException + exceptionWithClass: isa]; + } + + if (line == nil) + @throw [OFInvalidServerReplyException + exceptionWithClass: isa]; + + if ([line isEqual: @""]) + break; + + line_c = [line UTF8String]; + + if ((tmp = strchr(line_c, ':')) == NULL) + @throw [OFInvalidServerReplyException + exceptionWithClass: isa]; + + key = [OFString stringWithUTF8String: line_c + length: tmp - line_c]; + normalizeKey(key); + + do { + tmp++; + } while (*tmp == ' '); + + value = [OFString stringWithUTF8String: tmp]; + + if ((redirects > 0 && (status == 301 || status == 302 || + status == 303 || status == 307) && + [key isEqual: @"Location"]) && + (redirectsFromHTTPSToHTTPAllowed || + [scheme isEqual: @"http"] || + ![value hasPrefix: @"http://"])) { + OFURL *new; + BOOL follow; + + new = [OFURL URLWithString: value + relativeToURL: URL]; + + follow = [delegate request: self + willFollowRedirectTo: new]; + + if (!follow && delegate != nil) { + [serverHeaders setObject: value + forKey: key]; + continue; + } + + new = [new retain]; + [URL release]; + URL = new; + + if (status == 303) { + requestType = OF_HTTP_REQUEST_TYPE_GET; + [queryString release]; + queryString = nil; + } + + [pool release]; + + return [self performWithRedirects: redirects - 1]; + } + + [serverHeaders setObject: value + forKey: key]; + } + + [delegate request: self + didReceiveHeaders: serverHeaders + withStatusCode: status]; + + data = (storesData ? [OFDataArray dataArray] : nil); + chunked = [[serverHeaders objectForKey: @"Transfer-Encoding"] + isEqual: @"chunked"]; + + contentLengthHeader = [serverHeaders objectForKey: @"Content-Length"]; + + if (contentLengthHeader != nil) { + contentLength = (size_t)[contentLengthHeader decimalValue]; + + if (contentLength > SIZE_MAX) + @throw [OFOutOfRangeException exceptionWithClass: isa]; + } + + buffer = [self allocMemoryWithSize: of_pagesize]; + bytesReceived = 0; + @try { + OFAutoreleasePool *pool2 = [[OFAutoreleasePool alloc] init]; + + if (chunked) { + for (;;) { + size_t pos, toRead; + + @try { + line = [sock readLine]; + } @catch (OFInvalidEncodingException *e) { + @throw [OFInvalidServerReplyException + exceptionWithClass: isa]; + } + + pos = [line + indexOfFirstOccurrenceOfString: @";"]; + if (pos != OF_INVALID_INDEX) + line = [line substringWithRange: + of_range(0, pos)]; + + @try { + toRead = + (size_t)[line hexadecimalValue]; + } @catch (OFInvalidFormatException *e) { + @throw [OFInvalidServerReplyException + exceptionWithClass: isa]; + } + + if (toRead == 0 || + (contentLengthHeader != nil && + contentLength >= bytesReceived)) + break; + + while (toRead > 0) { + size_t length = (toRead < of_pagesize + ? toRead : of_pagesize); + + length = [sock readNBytes: length + intoBuffer: buffer]; + + [delegate request: self + didReceiveData: buffer + withLength: length]; + [pool2 releaseObjects]; + + bytesReceived += length; + [data addNItems: length + fromCArray: buffer]; + + toRead -= length; + } + + @try { + line = [sock readLine]; + } @catch (OFInvalidEncodingException *e) { + @throw [OFInvalidServerReplyException + exceptionWithClass: isa]; + } + + if (![line isEqual: @""]) + @throw [OFInvalidServerReplyException + exceptionWithClass: isa]; + + [pool2 releaseObjects]; + } + } else { + size_t length; + + while ((length = [sock readNBytes: of_pagesize + intoBuffer: buffer]) > 0) { + [delegate request: self + didReceiveData: buffer + withLength: length]; + [pool2 releaseObjects]; + + bytesReceived += length; + [data addNItems: length + fromCArray: buffer]; + + if (contentLengthHeader != nil && + bytesReceived >= contentLength) + break; + } + } + + [pool2 release]; + } @finally { + [self freeMemory: buffer]; + } + + [sock close]; + + /* + * We only want to throw on these status codes as we will throw an + * OFHTTPRequestFailedException for all other status codes later. + */ + if (contentLengthHeader != nil && contentLength != bytesReceived && + (status == 200 || status == 301 || status == 302 || status == 303 || + status == 307)) + @throw [OFTruncatedDataException exceptionWithClass: isa]; + + [serverHeaders makeImmutable]; + + result = [[OFHTTPRequestResult alloc] initWithStatusCode: status + headers: serverHeaders + data: data]; + + switch (status) { + case 200: + case 301: + case 302: + case 303: + case 307: + break; + default: + [result release]; + @throw [OFHTTPRequestFailedException + exceptionWithClass: isa + HTTPRequest: self + result: result]; + } + + [pool release]; return [result autorelease]; } @end DELETED src/OFJSONEncoding.h Index: src/OFJSONEncoding.h ================================================================== --- src/OFJSONEncoding.h +++ src/OFJSONEncoding.h @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2011, 2012 - * 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. - */ - -@class OFString; - -/** - * \brief A category implemented by classes that support encoding to a JSON - * representation. - * - * \warning Although this method can be called directly on classes other than - * OFArray and OFDictionary, this will generate invalid JSON, as JSON - * requires all data to be encapsulated in an array or a dictionary! - */ -@protocol OFJSON -/** - * \brief Returns the JSON representation of the object as a string. - * - * \return The JSON representation of the object as a string. - */ -- (OFString*)JSONRepresentation; -@end ADDED src/OFJSONRepresentation.h Index: src/OFJSONRepresentation.h ================================================================== --- src/OFJSONRepresentation.h +++ src/OFJSONRepresentation.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012 + * 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. + */ + +@class OFString; + +/** + * \brief A protocol implemented by classes that support encoding to a JSON + * representation. + * + * \warning Although this method can be called directly on classes other than + * OFArray and OFDictionary, this will generate invalid JSON, as JSON + * requires all data to be encapsulated in an array or a dictionary! + */ +@protocol OFJSONRepresentation +/** + * \brief Returns the JSON representation of the object as a string. + * + * \return The JSON representation of the object as a string. + */ +- (OFString*)JSONRepresentation; +@end Index: src/OFMutableArray.h ================================================================== --- src/OFMutableArray.h +++ src/OFMutableArray.h @@ -57,10 +57,12 @@ * \param index The index of the object to replace * \param object The replacement object */ - (void)replaceObjectAtIndex: (size_t)index withObject: (id)object; +- (void)setObject: (id)object + atIndexedSubscript: (size_t)index; /** * \brief Replaces the first object that has the same address as the specified * object with the other specified object. * Index: src/OFMutableArray.m ================================================================== --- src/OFMutableArray.m +++ src/OFMutableArray.m @@ -106,20 +106,15 @@ - initWithArray: (OFArray*)array { return (id)[[OFMutableArray_adjacent alloc] initWithArray: array]; } -- initWithCArray: (id*)objects -{ - return (id)[[OFMutableArray_adjacent alloc] initWithCArray: objects]; -} - -- initWithCArray: (id*)objects - length: (size_t)length -{ - return (id)[[OFMutableArray_adjacent alloc] initWithCArray: objects - length: length]; +- initWithObjects: (id*)objects + count: (size_t)count +{ + return (id)[[OFMutableArray_adjacent alloc] initWithObjects: objects + count: count]; } - initWithSerialization: (OFXMLElement*)element { return (id)[[OFMutableArray_adjacent alloc] @@ -197,10 +192,17 @@ withObject: (id)object { @throw [OFNotImplementedException exceptionWithClass: isa selector: _cmd]; } + +- (void)setObject: (id)object + atIndexedSubscript: (size_t)index +{ + [self replaceObjectAtIndex: index + withObject: object]; +} - (void)replaceObject: (id)oldObject withObject: (id)newObject { size_t i, count = [self count]; Index: src/OFMutableArray_adjacent.m ================================================================== --- src/OFMutableArray_adjacent.m +++ src/OFMutableArray_adjacent.m @@ -53,63 +53,63 @@ } - (void)replaceObject: (id)oldObject withObject: (id)newObject { - id *cArray = [array cArray]; + id *objects = [array cArray]; size_t i, count = [array count]; for (i = 0; i < count; i++) { - if ([cArray[i] isEqual: oldObject]) { + if ([objects[i] isEqual: oldObject]) { [newObject retain]; - [cArray[i] release]; - cArray[i] = newObject; + [objects[i] release]; + objects[i] = newObject; return; } } } - (void)replaceObjectAtIndex: (size_t)index withObject: (id)object { - id *cArray = [array cArray]; + id *objects = [array cArray]; id oldObject; if (index >= [array count]) @throw [OFOutOfRangeException exceptionWithClass: isa]; - oldObject = cArray[index]; - cArray[index] = [object retain]; + oldObject = objects[index]; + objects[index] = [object retain]; [oldObject release]; } - (void)replaceObjectIdenticalTo: (id)oldObject withObject: (id)newObject { - id *cArray = [array cArray]; + id *objects = [array cArray]; size_t i, count = [array count]; for (i = 0; i < count; i++) { - if (cArray[i] == oldObject) { + if (objects[i] == oldObject) { [newObject retain]; - [cArray[i] release]; - cArray[i] = newObject; + [objects[i] release]; + objects[i] = newObject; return; } } } - (void)removeObject: (id)object { - id *cArray = [array cArray]; + id *objects = [array cArray]; size_t i, count = [array count]; for (i = 0; i < count; i++) { - if ([cArray[i] isEqual: object]) { - object = cArray[i]; + if ([objects[i] isEqual: object]) { + object = objects[i]; [array removeItemAtIndex: i]; mutations++; [object release]; @@ -119,15 +119,15 @@ } } - (void)removeObjectIdenticalTo: (id)object { - id *cArray = [array cArray]; + id *objects = [array cArray]; size_t i, count = [array count]; for (i = 0; i < count; i++) { - if (cArray[i] == object) { + if (objects[i] == object) { [array removeItemAtIndex: i]; mutations++; [object release]; @@ -145,19 +145,19 @@ mutations++; } - (void)removeNObjects: (size_t)nObjects { - id *cArray = [array cArray], *copy; + id *objects = [array cArray], *copy; size_t i, count = [array count]; if (nObjects > count) @throw [OFOutOfRangeException exceptionWithClass: isa]; copy = [self allocMemoryForNItems: nObjects ofSize: sizeof(id)]; - memcpy(copy, cArray + (count - nObjects), nObjects * sizeof(id)); + memcpy(copy, objects + (count - nObjects), nObjects * sizeof(id)); @try { [array removeNItems: nObjects]; mutations++; @@ -168,30 +168,30 @@ } } - (void)removeAllObjects { - id *cArray = [array cArray]; + id *objects = [array cArray]; size_t i, count = [array count]; for (i = 0; i < count; i++) - [cArray[i] release]; + [objects[i] release]; [array removeAllItems]; } - (void)removeObjectsInRange: (of_range_t)range { - id *cArray = [array cArray], *copy; + id *objects = [array cArray], *copy; size_t i, count = [array count]; if (range.length > count - range.start) @throw [OFOutOfRangeException exceptionWithClass: isa]; copy = [self allocMemoryForNItems: range.length ofSize: sizeof(id)]; - memcpy(copy, cArray + range.start, range.length * sizeof(id)); + memcpy(copy, objects + range.start, range.length * sizeof(id)); @try { [array removeNItems: range.length atIndex: range.start]; mutations++; @@ -213,34 +213,34 @@ } - (void)swapObjectAtIndex: (size_t)index1 withObjectAtIndex: (size_t)index2 { - id *cArray = [array cArray]; + id *objects = [array cArray]; size_t count = [array count]; id tmp; if (index1 >= count || index2 >= count) @throw [OFOutOfRangeException exceptionWithClass: isa]; - tmp = cArray[index1]; - cArray[index1] = cArray[index2]; - cArray[index2] = tmp; + tmp = objects[index1]; + objects[index1] = objects[index2]; + objects[index2] = tmp; } - (void)reverse { - id *cArray = [array cArray]; + id *objects = [array cArray]; size_t i, j, count = [array count]; if (count == 0 || count == 1) return; for (i = 0, j = count - 1; i < j; i++, j--) { - id tmp = cArray[i]; - cArray[i] = cArray[j]; - cArray[j] = tmp; + id tmp = objects[i]; + objects[i] = objects[j]; + objects[j] = tmp; } } - (int)countByEnumeratingWithState: (of_fast_enumeration_state_t*)state objects: (id*)objects @@ -268,11 +268,11 @@ } #ifdef OF_HAVE_BLOCKS - (void)enumerateObjectsUsingBlock: (of_array_enumeration_block_t)block { - id *cArray = [array cArray]; + id *objects = [array cArray]; size_t i, count = [array count]; BOOL stop = NO; unsigned long mutations2 = mutations; for (i = 0; i < count && !stop; i++) { @@ -279,17 +279,17 @@ if (mutations != mutations2) @throw [OFEnumerationMutationException exceptionWithClass: isa object: self]; - block(cArray[i], i, &stop); + block(objects[i], i, &stop); } } - (void)replaceObjectsUsingBlock: (of_array_replace_block_t)block { - id *cArray = [array cArray]; + id *objects = [array cArray]; size_t i, count = [array count]; BOOL stop = NO; unsigned long mutations2 = mutations; for (i = 0; i < count && !stop; i++) { @@ -298,24 +298,24 @@ if (mutations != mutations2) @throw [OFEnumerationMutationException exceptionWithClass: isa object: self]; - newObject = block(cArray[i], i, &stop); + newObject = block(objects[i], i, &stop); if (newObject == nil) @throw [OFInvalidArgumentException exceptionWithClass: isa selector: _cmd]; [newObject retain]; - [cArray[i] release]; - cArray[i] = newObject; + [objects[i] release]; + objects[i] = newObject; } } #endif - (void)makeImmutable { isa = [OFArray_adjacent class]; } @end Index: src/OFMutableDictionary.h ================================================================== --- src/OFMutableDictionary.h +++ src/OFMutableDictionary.h @@ -32,10 +32,12 @@ * \param key The key to set * \param object The object to set the key to */ - (void)setObject: (id)object forKey: (id)key; +- (void)setObject: (id)object + forKeyedSubscript: (id)key; /** * \brief Removes the object for the specified key from the dictionary. * * \param key The key whose object should be removed Index: src/OFMutableDictionary.m ================================================================== --- src/OFMutableDictionary.m +++ src/OFMutableDictionary.m @@ -52,10 +52,20 @@ { return (id)[[OFMutableDictionary_hashtable alloc] initWithObjects: objects forKeys: keys]; } + +- initWithObjects: (id*)objects + forKeys: (id*)keys + count: (size_t)count +{ + return (id)[[OFMutableDictionary_hashtable alloc] + initWithObjects: objects + forKeys: keys + count: count]; +} - initWithKeysAndObjects: (id)firstKey, ... { id ret; va_list arguments; @@ -136,10 +146,17 @@ forKey: (id)key { @throw [OFNotImplementedException exceptionWithClass: isa selector: _cmd]; } + +- (void)setObject: (id)object + forKeyedSubscript: (id)key +{ + [self setObject: object + forKey: key]; +} - (void)removeObjectForKey: (id)key { @throw [OFNotImplementedException exceptionWithClass: isa selector: _cmd]; Index: src/OFMutableString.h ================================================================== --- src/OFMutableString.h +++ src/OFMutableString.h @@ -12,13 +12,10 @@ * 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 -#include - #import "OFString.h" /** * \brief A class for storing and modifying strings. */ Index: src/OFMutableString.m ================================================================== --- src/OFMutableString.m +++ src/OFMutableString.m @@ -17,10 +17,12 @@ #include "config.h" #include #include #include + +#include #import "OFString.h" #import "OFMutableString_UTF8.h" #import "OFAutoreleasePool.h" Index: src/OFMutableString_UTF8.h ================================================================== --- src/OFMutableString_UTF8.h +++ src/OFMutableString_UTF8.h @@ -13,12 +13,14 @@ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #import "OFMutableString.h" +#import "OFString_UTF8.h" @interface OFMutableString_UTF8: OFMutableString { @public struct of_string_utf8_ivars *restrict s; + struct of_string_utf8_ivars s_store; } @end Index: src/OFNull.h ================================================================== --- src/OFNull.h +++ src/OFNull.h @@ -14,18 +14,18 @@ * file. */ #import "OFObject.h" #import "OFSerialization.h" -#import "OFJSONEncoding.h" +#import "OFJSONRepresentation.h" /** * \brief A class for representing null values in collections. */ -@interface OFNull: OFObject +@interface OFNull: OFObject /** * \brief Returns an OFNull singleton. * * \return An OFNull singleton */ + null; @end Index: src/OFNumber.h ================================================================== --- src/OFNumber.h +++ src/OFNumber.h @@ -11,16 +11,23 @@ * 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. */ + +#ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS +#endif +#ifndef __STDC_CONSTANT_MACROS +# define __STDC_CONSTANT_MACROS +#endif #include #import "OFObject.h" #import "OFSerialization.h" -#import "OFJSONEncoding.h" +#import "OFJSONRepresentation.h" /** * \brief The type of a number. */ typedef enum of_number_type_t { @@ -53,11 +60,11 @@ } of_number_type_t; /** * \brief Provides a way to store a number in an object. */ -@interface OFNumber: OFObject +@interface OFNumber: OFObject { union of_number_value { BOOL bool_; signed char char_; signed short short_; Index: src/OFObject.h ================================================================== --- src/OFObject.h +++ src/OFObject.h @@ -110,10 +110,19 @@ * \param class_ The class whose kind is checked * \return A boolean whether the object is of the specified kind */ - (BOOL)isKindOfClass: (Class)class_; +/** + * \brief Returns a boolean whether the object is a member of the specified + * class. + * + * \param class_ The class for which the receiver is checked + * \return A boolean whether the object is a member of the specified class + */ +- (BOOL)isMemberOfClass: (Class)class_; + /** * \brief Returns a boolean whether the object responds to the specified * selector. * * \param selector The selector which should be checked for respondance @@ -234,10 +243,17 @@ * \brief Returns the receiver. * * \return The receiver */ - self; + +/** + * \brief Returns whether the object is a proxy object. + * + * \return A boolean whether the object is a proxy object + */ +- (BOOL)isProxy; @end /** * \brief The root class for all other classes inside ObjFW. */ @@ -358,20 +374,10 @@ * * \return A description for the class, which is usually the class name */ + (OFString*)description; -/** - * \brief Replaces a class method implementation with another implementation. - * - * \param newImp The new implementation for the class method - * \param selector The selector of the class method to replace - * \return The old implementation - */ -+ (IMP)setImplementation: (IMP)newImp - forClassMethod: (SEL)selector; - /** * \brief Replaces a class method with a class method from another class. * * \param selector The selector of the class method to replace * \param class_ The class from which the new class method should be taken @@ -378,21 +384,10 @@ * \return The old implementation */ + (IMP)replaceClassMethod: (SEL)selector withMethodFromClass: (Class)class_; -/** - * \brief Replaces an instance method implementation with another - * implementation. - * - * \param newImp The new implementation for the instance method - * \param selector The selector of the instance method to replace - * \return The old implementation - */ -+ (IMP)setImplementation: (IMP)newImp - forInstanceMethod: (SEL)selector; - /** * \brief Replaces an instance method with an instance method from another * class. * * \param selector The selector of the instance method to replace @@ -401,40 +396,40 @@ */ + (IMP)replaceInstanceMethod: (SEL)selector withMethodFromClass: (Class)class_; /** - * \brief Adds a class method to the class. - * - * If the method already exists, nothing is done and NO is returned. If you want - * to change the implementation of a method, use - * setImplementation:forClassMethod:. - * - * \param selector The selector for the new method - * \param typeEncoding The type encoding for the new method - * \param implementation The implementation for the new method - * \return Whether the method has been added - */ -+ (BOOL)addClassMethod: (SEL)selector - withTypeEncoding: (const char*)typeEncoding - implementation: (IMP)implementation; - -/** - * \brief Adds an instance method to the class. - * - * If the method already exists, nothing is done and NO is returned. If you want - * to change the implementation of a method, use - * setImplementation:forInstanceMethod:. - * - * \param selector The selector for the new method - * \param typeEncoding The type encoding for the new method - * \param implementation The implementation for the new method - * \return Whether the method has been added - */ -+ (BOOL)addInstanceMethod: (SEL)selector - withTypeEncoding: (const char*)typeEncoding - implementation: (IMP)implementation; + * \brief Replaces or adds a class method. + * + * If the method already exists, it is replaced and the old implementation + * returned. If the method does not exist, it is added with the specified type + * encoding. + * + * \param selector The selector for the new method + * \param implementation The implementation for the new method + * \param typeEncoding The type encoding for the new method + * \return The old implementation or nil if the method was added + */ ++ (IMP)replaceClassMethod: (SEL)selector + withImplementation: (IMP)implementation + typeEncoding: (const char*)typeEncoding; + +/** + * \brief Replaces or adds an instance method. + * + * If the method already exists, it is replaced and the old implementation + * returned. If the method does not exist, it is added with the specified type + * encoding. + * + * \param selector The selector for the new method + * \param implementation The implementation for the new method + * \param typeEncoding The type encoding for the new method + * \return The old implementation or nil if the method was added + */ ++ (IMP)replaceInstanceMethod: (SEL)selector + withImplementation: (IMP)implementation + typeEncoding: (const char*)typeEncoding; /** * \brief Adds all methods from the specified class to the class that is the * receiver. * @@ -479,20 +474,10 @@ * * \return A description for the object */ - (OFString*)description; -/** - * \brief Adds a pointer to the object's memory pool. - * - * This is useful to add memory allocated by functions such as asprintf to the - * pool so it gets free'd automatically when the object is deallocated. - * - * \param pointer A pointer to add to the memory pool - */ -- (void)addMemoryToPool: (void*)pointer; - /** * \brief Allocates memory and stores it in the object's memory pool. * * It will be free'd automatically when the object is deallocated. * @@ -611,11 +596,12 @@ #import "OFObject+Serialization.h" #ifdef __cplusplus extern "C" { #endif -extern id objc_getProperty(id, SEL, ptrdiff_t, BOOL); -extern void objc_setProperty(id, SEL, ptrdiff_t, id, BOOL, BOOL); extern size_t of_pagesize; +extern size_t of_num_cpus; +extern id of_alloc_object(Class class_, size_t extraSize, size_t extraAlignment, + void **extra); #ifdef __cplusplus } #endif Index: src/OFObject.m ================================================================== --- src/OFObject.m +++ src/OFObject.m @@ -59,27 +59,30 @@ #elif defined(OF_THREADS) # import "threading.h" #endif struct pre_ivar { - int32_t retainCount; - void **memoryChunks; - unsigned int memoryChunksSize; + int32_t retainCount; + struct pre_mem *firstMem, *lastMem; #if !defined(OF_ATOMIC_OPS) && defined(OF_THREADS) of_spinlock_t retainCountSpinlock; #endif }; -/* Hopefully no arch needs more than 16 bytes padding */ -#ifndef __BIGGEST_ALIGNMENT__ -# define __BIGGEST_ALIGNMENT__ 16 -#endif +struct pre_mem { + struct pre_mem *prev, *next; + id owner; +}; #define PRE_IVAR_ALIGN ((sizeof(struct pre_ivar) + \ (__BIGGEST_ALIGNMENT__ - 1)) & ~(__BIGGEST_ALIGNMENT__ - 1)) #define PRE_IVAR ((struct pre_ivar*)(void*)((char*)self - PRE_IVAR_ALIGN)) +#define PRE_MEM_ALIGN ((sizeof(struct pre_mem) + \ + (__BIGGEST_ALIGNMENT__ - 1)) & ~(__BIGGEST_ALIGNMENT__ - 1)) +#define PRE_MEM(mem) ((struct pre_mem*)(void*)((char*)mem - PRE_MEM_ALIGN)) + #ifdef OF_OLD_GNU_RUNTIME extern void __objc_update_dispatch_table_for_class(Class); #endif static struct { @@ -89,10 +92,11 @@ static SEL cxx_construct = NULL; static SEL cxx_destruct = NULL; size_t of_pagesize; +size_t of_num_cpus; #ifdef NEED_OBJC_SYNC_INIT extern BOOL objc_sync_init(); #endif @@ -126,10 +130,56 @@ #endif #if defined(HAVE_OBJC_ENUMERATIONMUTATION) && defined(OF_OLD_GNU_RUNTIME) extern void objc_setEnumerationMutationHandler(void(*handler)(id)); #endif + +id +of_alloc_object(Class class, size_t extraSize, size_t extraAlignment, + void **extra) +{ + OFObject *instance; + size_t instanceSize; + + instanceSize = class_getInstanceSize(class); + + if (OF_UNLIKELY(extraAlignment > 0)) + extraAlignment = ((instanceSize + extraAlignment - 1) & + ~(extraAlignment - 1)) - extraAlignment; + + instance = malloc(PRE_IVAR_ALIGN + instanceSize + + extraAlignment + extraSize); + + if (OF_UNLIKELY(instance == nil)) { + alloc_failed_exception.isa = [OFAllocFailedException class]; + @throw (OFAllocFailedException*)&alloc_failed_exception; + } + + ((struct pre_ivar*)instance)->retainCount = 1; + ((struct pre_ivar*)instance)->firstMem = NULL; + ((struct pre_ivar*)instance)->lastMem = NULL; + +#if !defined(OF_ATOMIC_OPS) && defined(OF_THREADS) + if (OF_UNLIKELY(!of_spinlock_new( + &((struct pre_ivar*)instance)->retainCountSpinlock))) { + free(instance); + @throw [OFInitializationFailedException + exceptionWithClass: class]; + } +#endif + + instance = (OFObject*)((char*)instance + PRE_IVAR_ALIGN); + + instance->isa = class; + memset((char*)instance + sizeof(instance->isa), 0, + instanceSize - sizeof(instance->isa)); + + if (OF_UNLIKELY(extra != NULL)) + *extra = (char*)instance + instanceSize + extraAlignment; + + return instance; +} const char* _NSPrintForDebugger(id object) { return [[object description] @@ -209,65 +259,29 @@ #if defined(_WIN32) SYSTEM_INFO si; GetSystemInfo(&si); of_pagesize = si.dwPageSize; + of_num_cpus = si.dwNumberOfProcessors; #elif defined(_PSP) of_pagesize = 4096; + of_num_cpus = 1; #else if ((of_pagesize = sysconf(_SC_PAGESIZE)) < 1) of_pagesize = 4096; + if ((of_num_cpus = sysconf(_SC_NPROCESSORS_CONF)) < 1) + of_num_cpus = 1; #endif } + (void)initialize { } + alloc { - OFObject *instance; - size_t instanceSize = class_getInstanceSize(self); - Class class; - void (*last)(id, SEL) = NULL; - - if ((instance = malloc(instanceSize + PRE_IVAR_ALIGN)) == NULL) { - alloc_failed_exception.isa = [OFAllocFailedException class]; - @throw (OFAllocFailedException*)&alloc_failed_exception; - } - - ((struct pre_ivar*)instance)->memoryChunks = NULL; - ((struct pre_ivar*)instance)->memoryChunksSize = 0; - ((struct pre_ivar*)instance)->retainCount = 1; - -#if !defined(OF_ATOMIC_OPS) && defined(OF_THREADS) - if (!of_spinlock_new( - &((struct pre_ivar*)instance)->retainCountSpinlock)) { - free(instance); - @throw [OFInitializationFailedException - exceptionWithClass: self]; - } -#endif - - instance = (OFObject*)((char*)instance + PRE_IVAR_ALIGN); - memset(instance, 0, instanceSize); - instance->isa = self; - - for (class = self; class != Nil; class = class_getSuperclass(class)) { - void (*construct)(id, SEL); - - if ([class instancesRespondToSelector: cxx_construct]) { - if ((construct = (void(*)(id, SEL))[class - instanceMethodForSelector: cxx_construct]) != last) - construct(instance, cxx_construct); - - last = construct; - } else - break; - } - - return instance; + return of_alloc_object(self, 0, 0, NULL); } + new { return [[self alloc] init]; @@ -381,172 +395,66 @@ + (OFString*)description { return [self className]; } -+ (IMP)setImplementation: (IMP)newImp - forClassMethod: (SEL)selector -{ -#if defined(OF_OBJFW_RUNTIME) - if (newImp == (IMP)0 || !class_respondsToSelector(self->isa, selector)) - @throw [OFInvalidArgumentException exceptionWithClass: self - selector: _cmd]; - - return objc_replace_class_method(self, selector, newImp); -#elif defined(OF_OLD_GNU_RUNTIME) - Method_t method; - MethodList_t iter; - - method = class_get_class_method(self->class_pointer, selector); - - if (newImp == (IMP)0 || method == METHOD_NULL) - @throw [OFInvalidArgumentException exceptionWithClass: self - selector: _cmd]; - - for (iter = ((Class)self->class_pointer)->methods; iter != NULL; - iter = iter->method_next) { - int i; - - for (i = 0; i < iter->method_count; i++) - if (sel_eq(iter->method_list[i].method_name, - selector)) { - IMP oldImp; - - oldImp = iter->method_list[i].method_imp; - iter->method_list[i].method_imp = newImp; - - __objc_update_dispatch_table_for_class( - (Class)self->class_pointer); - - return oldImp; - } - } - - assert([self addClassMethod: selector - withTypeEncoding: method->method_types - implementation: newImp]); - - return (IMP)0; -#else - Method method; - - if (newImp == (IMP)0 || - (method = class_getClassMethod(self, selector)) == NULL) - @throw [OFInvalidArgumentException exceptionWithClass: self - selector: _cmd]; - - /* - * Cast needed because it's isa in the Apple runtime, but class_pointer - * in the GNU runtime. - */ - return class_replaceMethod(((OFObject*)self)->isa, selector, newImp, - method_getTypeEncoding(method)); -#endif -} - + (IMP)replaceClassMethod: (SEL)selector withMethodFromClass: (Class)class { IMP newImp; - - if (![class isSubclassOfClass: self]) - @throw [OFInvalidArgumentException exceptionWithClass: self - selector: _cmd]; + const char *typeEncoding; newImp = [class methodForSelector: selector]; - - return [self setImplementation: newImp - forClassMethod: selector]; -} - -+ (IMP)setImplementation: (IMP)newImp - forInstanceMethod: (SEL)selector -{ -#if defined(OF_OBJFW_RUNTIME) - if (newImp == (IMP)0 || !class_respondsToSelector(self, selector)) - @throw [OFInvalidArgumentException exceptionWithClass: self - selector: _cmd]; - - return objc_replace_instance_method(self, selector, newImp); -#elif defined(OF_OLD_GNU_RUNTIME) - Method_t method; - MethodList_t iter; - - method = class_get_instance_method(self, selector); - - if (newImp == (IMP)0 || method == METHOD_NULL) - @throw [OFInvalidArgumentException exceptionWithClass: self - selector: _cmd]; - - for (iter = ((Class)self)->methods; iter != NULL; - iter = iter->method_next) { - int i; - - for (i = 0; i < iter->method_count; i++) - if (sel_eq(iter->method_list[i].method_name, - selector)) { - IMP oldImp; - - oldImp = iter->method_list[i].method_imp; - iter->method_list[i].method_imp = newImp; - - __objc_update_dispatch_table_for_class(self); - - return oldImp; - } - } - - assert([self addInstanceMethod: selector - withTypeEncoding: method->method_types - implementation: newImp]); - - return (IMP)0; -#else - Method method; - - if (newImp == (IMP)0 || - (method = class_getInstanceMethod(self, selector)) == NULL) - @throw [OFInvalidArgumentException exceptionWithClass: self - selector: _cmd]; - - return class_replaceMethod(self, selector, newImp, - method_getTypeEncoding(method)); -#endif + typeEncoding = [class typeEncodingForSelector: selector]; + + return [self replaceClassMethod: selector + withImplementation: newImp + typeEncoding: typeEncoding]; } + (IMP)replaceInstanceMethod: (SEL)selector withMethodFromClass: (Class)class { IMP newImp; - - if (![class isSubclassOfClass: self]) - @throw [OFInvalidArgumentException exceptionWithClass: self - selector: _cmd]; + const char *typeEncoding; newImp = [class instanceMethodForSelector: selector]; + typeEncoding = [class typeEncodingForInstanceSelector: selector]; - return [self setImplementation: newImp - forInstanceMethod: selector]; + return [self replaceInstanceMethod: selector + withImplementation: newImp + typeEncoding: typeEncoding]; } -+ (BOOL)addInstanceMethod: (SEL)selector - withTypeEncoding: (const char*)typeEncoding - implementation: (IMP)implementation ++ (IMP)replaceInstanceMethod: (SEL)selector + withImplementation: (IMP)implementation + typeEncoding: (const char*)typeEncoding { #if defined(OF_APPLE_RUNTIME) || defined(OF_GNU_RUNTIME) - return class_addMethod(self, selector, implementation, typeEncoding); + return class_replaceMethod(self, selector, implementation, + typeEncoding); #elif defined(OF_OLD_GNU_RUNTIME) MethodList_t methodList; for (methodList = ((Class)self)->methods; methodList != NULL; methodList = methodList->method_next) { int i; - for (i = 0; i < methodList->method_count; i++) + for (i = 0; i < methodList->method_count; i++) { if (sel_eq(methodList->method_list[i].method_name, - selector)) - return NO; + selector)) { + IMP oldImp; + oldImp = methodList->method_list[i].method_imp; + + methodList->method_list[i].method_imp = + implementation; + + __objc_update_dispatch_table_for_class(self); + + return oldImp; + } + } } if ((methodList = malloc(sizeof(*methodList))) == NULL) @throw [OFOutOfMemoryException exceptionWithClass: self @@ -561,35 +469,46 @@ ((Class)self)->methods = methodList; __objc_update_dispatch_table_for_class(self); - return YES; + return (IMP)nil; #else @throw [OFNotImplementedException exceptionWithClass: self selector: _cmd]; #endif } -+ (BOOL)addClassMethod: (SEL)selector - withTypeEncoding: (const char*)typeEncoding - implementation: (IMP)implementation ++ (IMP)replaceClassMethod: (SEL)selector + withImplementation: (IMP)implementation + typeEncoding: (const char*)typeEncoding { #if defined(OF_APPLE_RUNTIME) || defined(OF_GNU_RUNTIME) - return class_addMethod(((OFObject*)self)->isa, selector, implementation, - typeEncoding); + return class_replaceMethod(((OFObject*)self)->isa, selector, + implementation, typeEncoding); #elif defined(OF_OLD_GNU_RUNTIME) MethodList_t methodList; for (methodList = ((Class)self->class_pointer)->methods; methodList != NULL; methodList = methodList->method_next) { int i; - for (i = 0; i < methodList->method_count; i++) + for (i = 0; i < methodList->method_count; i++) { if (sel_eq(methodList->method_list[i].method_name, - selector)) - return NO; + selector)) { + IMP oldImp; + oldImp = methodList->method_list[i].method_imp; + + methodList->method_list[i].method_imp = + implementation; + + __objc_update_dispatch_table_for_class( + (Class)self->class_pointer); + + return oldImp; + } + } } if ((methodList = malloc(sizeof(*methodList))) == NULL) @throw [OFOutOfMemoryException exceptionWithClass: self @@ -604,11 +523,11 @@ ((Class)self->class_pointer)->methods = methodList; __objc_update_dispatch_table_for_class((Class)self->class_pointer); - return YES; + return (IMP)nil; #else @throw [OFNotImplementedException exceptionWithClass: self selector: _cmd]; #endif } @@ -626,62 +545,39 @@ methodList = class_copyMethodList(((OFObject*)class)->isa, &count); @try { for (i = 0; i < count; i++) { SEL selector = method_getName(methodList[i]); - IMP implementation; /* * Don't replace methods implemented in receiving class. */ if ([self methodForSelector: selector] != [superclass methodForSelector: selector]) continue; - implementation = [class methodForSelector: selector]; - - if ([self respondsToSelector: selector]) - [self setImplementation: implementation - forClassMethod: selector]; - else { - const char *typeEncoding = - method_getTypeEncoding(methodList[i]); - [self addClassMethod: selector - withTypeEncoding: typeEncoding - implementation: implementation]; - } + [self replaceClassMethod: selector + withMethodFromClass: class]; } } @finally { free(methodList); } methodList = class_copyMethodList(class, &count); @try { for (i = 0; i < count; i++) { SEL selector = method_getName(methodList[i]); - IMP implementation; /* * Don't replace methods implemented in receiving class. */ if ([self instanceMethodForSelector: selector] != [superclass instanceMethodForSelector: selector]) continue; - implementation = - [class instanceMethodForSelector: selector]; - - if ([self instancesRespondToSelector: selector]) - [self setImplementation: implementation - forInstanceMethod: selector]; - else { - const char *typeEncoding = - method_getTypeEncoding(methodList[i]); - [self addInstanceMethod: selector - withTypeEncoding: typeEncoding - implementation: implementation]; - } + [self replaceInstanceMethod: selector + withMethodFromClass: class]; } } @finally { free(methodList); } #elif defined(OF_OLD_GNU_RUNTIME) @@ -691,62 +587,39 @@ methodList != NULL; methodList = methodList->method_next) { int i; for (i = 0; i < methodList->method_count; i++) { SEL selector = methodList->method_list[i].method_name; - IMP implementation; /* * Don't replace methods implemented in receiving class. */ if ([self methodForSelector: selector] != [superclass methodForSelector: selector]) continue; - implementation = [class methodForSelector: selector]; - - if ([self respondsToSelector: selector]) - [self setImplementation: implementation - forClassMethod: selector]; - else { - const char *typeEncoding = - methodList->method_list[i].method_types; - [self addClassMethod: selector - withTypeEncoding: typeEncoding - implementation: implementation]; - } + [self replaceClassMethod: selector + withMethodFromClass: class]; } } for (methodList = class->methods; methodList != NULL; methodList = methodList->method_next) { int i; for (i = 0; i < methodList->method_count; i++) { SEL selector = methodList->method_list[i].method_name; - IMP implementation; /* * Don't replace methods implemented in receiving class. */ if ([self instanceMethodForSelector: selector] != [superclass instanceMethodForSelector: selector]) continue; - implementation = - [class instanceMethodForSelector: selector]; - - if ([self instancesRespondToSelector: selector]) - [self setImplementation: implementation - forInstanceMethod: selector]; - else { - const char *typeEncoding = - methodList->method_list[i].method_types; - [self addInstanceMethod: selector - withTypeEncoding: typeEncoding - implementation: implementation]; - } + [self replaceInstanceMethod: selector + withMethodFromClass: class]; } } #else @throw [OFNotImplementedException exceptionWithClass: self selector: _cmd]; @@ -755,10 +628,26 @@ [self inheritMethodsFromClass: [class superclass]]; } - init { + Class class; + void (*last)(id, SEL) = NULL; + + for (class = isa; class != Nil; class = class_getSuperclass(class)) { + void (*construct)(id, SEL); + + if ([class instancesRespondToSelector: cxx_construct]) { + if ((construct = (void(*)(id, SEL))[class + instanceMethodForSelector: cxx_construct]) != last) + construct(self, cxx_construct); + + last = construct; + } else + break; + } + return self; } - (Class)class { @@ -779,10 +668,15 @@ if (iter == class) return YES; return NO; } + +- (BOOL)isMemberOfClass: (Class)class +{ + return (isa == class); +} - (BOOL)respondsToSelector: (SEL)selector { #ifdef OF_OLD_GNU_RUNTIME if (object_is_instance(self)) @@ -882,63 +776,33 @@ { /* Classes containing data should reimplement this! */ return [OFString stringWithFormat: @"<%@: %p>", [self className], self]; } -- (void)addMemoryToPool: (void*)pointer -{ - void **memoryChunks; - unsigned int memoryChunksSize; - - memoryChunksSize = PRE_IVAR->memoryChunksSize + 1; - - if (UINT_MAX - PRE_IVAR->memoryChunksSize < 1 || - memoryChunksSize > UINT_MAX / sizeof(void*)) - @throw [OFOutOfRangeException exceptionWithClass: isa]; - - if ((memoryChunks = realloc(PRE_IVAR->memoryChunks, - memoryChunksSize * sizeof(void*))) == NULL) - @throw [OFOutOfMemoryException - exceptionWithClass: isa - requestedSize: memoryChunksSize]; - - PRE_IVAR->memoryChunks = memoryChunks; - PRE_IVAR->memoryChunks[PRE_IVAR->memoryChunksSize] = pointer; - PRE_IVAR->memoryChunksSize = memoryChunksSize; -} - -- (void*)allocMemoryWithSize: (size_t)size -{ - void *pointer, **memoryChunks; - unsigned int memoryChunksSize; - - if (size == 0) - return NULL; - - memoryChunksSize = PRE_IVAR->memoryChunksSize + 1; - - if (UINT_MAX - PRE_IVAR->memoryChunksSize == 0 || - memoryChunksSize > UINT_MAX / sizeof(void*)) - @throw [OFOutOfRangeException exceptionWithClass: isa]; - - if ((pointer = malloc(size)) == NULL) - @throw [OFOutOfMemoryException exceptionWithClass: isa - requestedSize: size]; - - if ((memoryChunks = realloc(PRE_IVAR->memoryChunks, - memoryChunksSize * sizeof(void*))) == NULL) { - free(pointer); - @throw [OFOutOfMemoryException - exceptionWithClass: isa - requestedSize: memoryChunksSize]; - } - - PRE_IVAR->memoryChunks = memoryChunks; - PRE_IVAR->memoryChunks[PRE_IVAR->memoryChunksSize] = pointer; - PRE_IVAR->memoryChunksSize = memoryChunksSize; - - return pointer; +- (void*)allocMemoryWithSize: (size_t)size +{ + void *pointer; + struct pre_mem *preMem; + + if (size > SIZE_MAX - PRE_IVAR_ALIGN) + @throw [OFOutOfRangeException exceptionWithClass: isa]; + + if ((pointer = malloc(PRE_MEM_ALIGN + size)) == NULL) + @throw [OFOutOfMemoryException exceptionWithClass: isa + requestedSize: size]; + preMem = pointer; + + preMem->owner = self; + preMem->prev = PRE_IVAR->lastMem; + preMem->next = NULL; + + if (PRE_IVAR->lastMem != NULL) + PRE_IVAR->lastMem->next = preMem; + + PRE_IVAR->lastMem = preMem; + + return (char*)pointer + PRE_MEM_ALIGN; } - (void*)allocMemoryForNItems: (size_t)nItems ofSize: (size_t)size { @@ -952,37 +816,44 @@ } - (void*)resizeMemory: (void*)pointer toSize: (size_t)size { - void **iter; + void *new; + struct pre_mem *preMem; if (pointer == NULL) return [self allocMemoryWithSize: size]; if (size == 0) { [self freeMemory: pointer]; return NULL; } - iter = PRE_IVAR->memoryChunks + PRE_IVAR->memoryChunksSize; - - while (iter-- > PRE_IVAR->memoryChunks) { - if (OF_UNLIKELY(*iter == pointer)) { - if (OF_UNLIKELY((pointer = realloc(pointer, - size)) == NULL)) - @throw [OFOutOfMemoryException - exceptionWithClass: isa - requestedSize: size]; - - *iter = pointer; - return pointer; - } - } - - @throw [OFMemoryNotPartOfObjectException exceptionWithClass: isa - pointer: pointer]; + if (PRE_MEM(pointer)->owner != self) + @throw [OFMemoryNotPartOfObjectException + exceptionWithClass: isa + pointer: pointer]; + + if ((new = realloc(PRE_MEM(pointer), PRE_MEM_ALIGN + size)) == NULL) + @throw [OFOutOfMemoryException exceptionWithClass: isa + requestedSize: size]; + preMem = new; + + if (preMem != PRE_MEM(pointer)) { + if (preMem->prev != NULL) + preMem->prev->next = preMem; + if (preMem->next != NULL) + preMem->next->prev = preMem; + + if (PRE_IVAR->firstMem == PRE_MEM(pointer)) + PRE_IVAR->firstMem = preMem; + if (PRE_IVAR->lastMem == PRE_MEM(pointer)) + PRE_IVAR->lastMem = preMem; + } + + return (char*)new + PRE_MEM_ALIGN; } - (void*)resizeMemory: (void*)pointer toNItems: (size_t)nItems ofSize: (size_t)size @@ -1003,56 +874,32 @@ toSize: nItems * size]; } - (void)freeMemory: (void*)pointer { - void **iter, *last, **memoryChunks; - unsigned int i, memoryChunksSize; - if (pointer == NULL) return; - iter = PRE_IVAR->memoryChunks + PRE_IVAR->memoryChunksSize; - i = PRE_IVAR->memoryChunksSize; - - while (iter-- > PRE_IVAR->memoryChunks) { - i--; - - if (OF_UNLIKELY(*iter == pointer)) { - memoryChunksSize = PRE_IVAR->memoryChunksSize - 1; - last = PRE_IVAR->memoryChunks[memoryChunksSize]; - - assert(PRE_IVAR->memoryChunksSize != 0 && - memoryChunksSize <= UINT_MAX / sizeof(void*)); - - if (OF_UNLIKELY(memoryChunksSize == 0)) { - free(pointer); - free(PRE_IVAR->memoryChunks); - - PRE_IVAR->memoryChunks = NULL; - PRE_IVAR->memoryChunksSize = 0; - - return; - } - - free(pointer); - PRE_IVAR->memoryChunks[i] = last; - PRE_IVAR->memoryChunksSize = memoryChunksSize; - - if (OF_UNLIKELY((memoryChunks = realloc( - PRE_IVAR->memoryChunks, memoryChunksSize * - sizeof(void*))) == NULL)) - return; - - PRE_IVAR->memoryChunks = memoryChunks; - - return; - } - } - - @throw [OFMemoryNotPartOfObjectException exceptionWithClass: isa - pointer: pointer]; + if (PRE_MEM(pointer)->owner != self) + @throw [OFMemoryNotPartOfObjectException + exceptionWithClass: isa + pointer: pointer]; + + if (PRE_MEM(pointer)->prev != NULL) + PRE_MEM(pointer)->prev->next = PRE_MEM(pointer)->next; + if (PRE_MEM(pointer)->next != NULL) + PRE_MEM(pointer)->next->prev = PRE_MEM(pointer)->prev; + + if (PRE_IVAR->firstMem == PRE_MEM(pointer)) + PRE_IVAR->firstMem = PRE_MEM(pointer)->next; + if (PRE_IVAR->lastMem == PRE_MEM(pointer)) + PRE_IVAR->lastMem = PRE_MEM(pointer)->prev; + + /* To detect double-free */ + PRE_MEM(pointer)->owner = nil; + + free(PRE_MEM(pointer)); } - retain { #if defined(OF_ATOMIC_OPS) @@ -1110,16 +957,21 @@ - self { return self; } + +- (BOOL)isProxy +{ + return NO; +} - (void)dealloc { Class class; void (*last)(id, SEL) = NULL; - void **iter; + struct pre_mem *iter; for (class = isa; class != Nil; class = class_getSuperclass(class)) { void (*destruct)(id, SEL); if ([class instancesRespondToSelector: cxx_destruct]) { @@ -1130,16 +982,25 @@ last = destruct; } else break; } - iter = PRE_IVAR->memoryChunks + PRE_IVAR->memoryChunksSize; - while (iter-- > PRE_IVAR->memoryChunks) - free(*iter); + iter = PRE_IVAR->firstMem; + while (iter != NULL) { + struct pre_mem *next = iter->next; + + /* + * We can use owner as a sentinel to prevent exploitation in + * case there is a buffer underflow somewhere. + */ + if (iter->owner != self) + abort(); + + free(iter); - if (PRE_IVAR->memoryChunks != NULL) - free(PRE_IVAR->memoryChunks); + iter = next; + } free((char*)self - PRE_IVAR_ALIGN); } /* Required to use properties with the Apple runtime */ @@ -1163,16 +1024,10 @@ /* * Those are needed as the root class is the superclass of the root class's * metaclass and thus instance methods can be sent to class objects as well. */ -+ (void)addMemoryToPool: (void*)pointer -{ - @throw [OFNotImplementedException exceptionWithClass: self - selector: _cmd]; -} - + (void*)allocMemoryWithSize: (size_t)size { @throw [OFNotImplementedException exceptionWithClass: self selector: _cmd]; } Index: src/OFPlugin.h ================================================================== --- src/OFPlugin.h +++ src/OFPlugin.h @@ -32,12 +32,12 @@ { of_plugin_handle_t handle; } /** - * \brief Loads an OFPlugin from a file. + * \brief Loads a plugin from a file. * - * \param path Path to the OFPlugin file. The suffix is appended automatically. - * \return The loaded OFPlugin + * \param path Path to the plugin file. The suffix is appended automatically. + * \return The loaded plugin */ -+ pluginFromFile: (OFString*)path; ++ (id)pluginFromFile: (OFString*)path; @end Index: src/OFPlugin.m ================================================================== --- src/OFPlugin.m +++ src/OFPlugin.m @@ -35,16 +35,16 @@ # define dlsym(handle, symbol) GetProcAddress(handle, symbol) # define dlclose(handle) FreeLibrary(handle) #endif @implementation OFPlugin -+ pluginFromFile: (OFString*)path ++ (id)pluginFromFile: (OFString*)path { OFAutoreleasePool *pool; OFMutableString *file; of_plugin_handle_t handle; - OFPlugin *(*initPlugin)(); + OFPlugin *(*initPlugin)(void); OFPlugin *plugin; pool = [[OFAutoreleasePool alloc] init]; file = [OFMutableString stringWithString: path]; [file appendString: @PLUGIN_SUFFIX]; @@ -54,11 +54,11 @@ @throw [OFInitializationFailedException exceptionWithClass: self]; [pool release]; - initPlugin = (OFPlugin*(*)())dlsym(handle, "init_plugin"); + initPlugin = (OFPlugin*(*)(void))dlsym(handle, "init_plugin"); if (initPlugin == NULL || (plugin = initPlugin()) == nil) { dlclose(handle); @throw [OFInitializationFailedException exceptionWithClass: self]; } Index: src/OFProcess.h ================================================================== --- src/OFProcess.h +++ src/OFProcess.h @@ -12,13 +12,18 @@ * 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. */ -#ifndef _WIN32 -# include +#ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS +#endif +#ifndef __STDC_CONSTANT_MACROS +# define __STDC_CONSTANT_MACROS #endif + +#include #import "OFStream.h" #ifdef _WIN32 # include Index: src/OFProcess.m ================================================================== --- src/OFProcess.m +++ src/OFProcess.m @@ -85,19 +85,22 @@ @throw [OFInitializationFailedException exceptionWithClass: isa]; switch ((pid = fork())) { case 0:; - OFString **cArray = [arguments cArray]; + OFString **objects = [arguments objects]; size_t i, count = [arguments count]; - char **argv = alloca((count + 2) * sizeof(char*)); + char **argv; + + argv = [self allocMemoryForNItems: count + 2 + ofSize: sizeof(char*)]; argv[0] = (char*)[programName cStringWithEncoding: OF_STRING_ENCODING_NATIVE]; for (i = 0; i < count; i++) - argv[i + 1] = (char*)[cArray[i] + argv[i + 1] = (char*)[objects[i] cStringWithEncoding: OF_STRING_ENCODING_NATIVE]; argv[i + 1] = NULL; Index: src/OFSeekableStream.h ================================================================== --- src/OFSeekableStream.h +++ src/OFSeekableStream.h @@ -11,10 +11,17 @@ * 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. */ + +#ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS +#endif +#ifndef __STDC_CONSTANT_MACROS +# define __STDC_CONSTANT_MACROS +#endif #include #import "OFStream.h" Index: src/OFSet.h ================================================================== --- src/OFSet.h +++ src/OFSet.h @@ -11,10 +11,17 @@ * 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. */ + +#ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS +#endif +#ifndef __STDC_CONSTANT_MACROS +# define __STDC_CONSTANT_MACROS +#endif #include #import "OFObject.h" #import "OFCollection.h" Index: src/OFSet_hashtable.m ================================================================== --- src/OFSet_hashtable.m +++ src/OFSet_hashtable.m @@ -78,16 +78,16 @@ self = [self init]; @try { OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; OFNumber *one = [OFNumber numberWithSize: 1]; - id *cArray = [array cArray]; + id *objects = [array objects]; size_t i, count = [array count]; for (i = 0; i < count; i++) [dictionary _setObject: one - forKey: cArray[i] + forKey: objects[i] copyKey: NO]; [pool release]; } @catch (id e) { [self release]; Index: src/OFStream.h ================================================================== --- src/OFStream.h +++ src/OFStream.h @@ -11,10 +11,17 @@ * 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. */ + +#ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS +#endif +#ifndef __STDC_CONSTANT_MACROS +# define __STDC_CONSTANT_MACROS +#endif #include #import "OFObject.h" #import "OFString.h" @@ -812,13 +819,11 @@ /** * \brief Closes the stream. */ - (void)close; -/// \cond internal - (size_t)_readNBytes: (size_t)length intoBuffer: (void*)buffer; - (void)_writeNBytes: (size_t)length fromBuffer: (const void*)buffer; - (BOOL)_isWaitingForDelimiter; -/// \endcond @end Index: src/OFStreamObserver.h ================================================================== --- src/OFStreamObserver.h +++ src/OFStreamObserver.h @@ -176,17 +176,15 @@ * \param timeout The time to wait for an event, in milliseconds * \return A boolean whether events occurred during the timeinterval */ - (BOOL)observeWithTimeout: (int)timeout; -/// \cond internal - (void)_addFileDescriptorForReading: (int)fd; - (void)_addFileDescriptorForWriting: (int)fd; - (void)_removeFileDescriptorForReading: (int)fd; - (void)_removeFileDescriptorForWriting: (int)fd; - (void)_processQueue; - (BOOL)_processCache; -/// \endcond @end @interface OFObject (OFStreamObserverDelegate) @end Index: src/OFStreamObserver.m ================================================================== --- src/OFStreamObserver.m +++ src/OFStreamObserver.m @@ -295,17 +295,17 @@ - (void)_processQueue { [mutex lock]; @try { - OFStream **queueCArray = [queue cArray]; + OFStream **queueObjects = [queue objects]; int *queueInfoCArray = [queueInfo cArray]; int *queueFDsCArray = [queueFDs cArray]; size_t i, count = [queue count]; for (i = 0; i < count; i++) { - OFStream *stream = queueCArray[i]; + OFStream *stream = queueObjects[i]; int action = queueInfoCArray[i]; int fd = queueFDsCArray[i]; if ((action & QUEUE_ACTION) == QUEUE_ADD) { if (fd > maxFD) { @@ -374,20 +374,20 @@ } - (BOOL)_processCache { OFAutoreleasePool *pool; - OFStream **cArray = [readStreams cArray]; + OFStream **objects = [readStreams objects]; size_t i, count = [readStreams count]; BOOL foundInCache = NO; pool = [[OFAutoreleasePool alloc] init]; for (i = 0; i < count; i++) { - if ([cArray[i] pendingBytes] > 0 && - ![cArray[i] _isWaitingForDelimiter]) { - [delegate streamIsReadyForReading: cArray[i]]; + if ([objects[i] pendingBytes] > 0 && + ![objects[i] _isWaitingForDelimiter]) { + [delegate streamIsReadyForReading: objects[i]]; foundInCache = YES; [pool releaseObjects]; } } Index: src/OFStreamObserver_select.h ================================================================== --- src/OFStreamObserver_select.h +++ src/OFStreamObserver_select.h @@ -11,10 +11,17 @@ * 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. */ + +#ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS +#endif +#ifndef __STDC_CONSTANT_MACROS +# define __STDC_CONSTANT_MACROS +#endif #ifdef OF_HAVE_SYS_SELECT_H # include #endif Index: src/OFStreamObserver_select.m ================================================================== --- src/OFStreamObserver_select.m +++ src/OFStreamObserver_select.m @@ -69,11 +69,11 @@ } - (BOOL)observeWithTimeout: (int)timeout { OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; - OFStream **cArray; + OFStream **objects; fd_set readFDs_; fd_set writeFDs_; fd_set exceptFDs_; struct timeval time; size_t i, count; @@ -111,23 +111,23 @@ #else assert(recvfrom(cancelFD[0], &buffer, 1, 0, NULL, NULL) > 0); #endif } - cArray = [readStreams cArray]; + objects = [readStreams objects]; count = [readStreams count]; for (i = 0; i < count; i++) { - int fileDescriptor = [cArray[i] fileDescriptor]; + int fileDescriptor = [objects[i] fileDescriptor]; if (FD_ISSET(fileDescriptor, &readFDs_)) { - [delegate streamIsReadyForReading: cArray[i]]; + [delegate streamIsReadyForReading: objects[i]]; [pool releaseObjects]; } if (FD_ISSET(fileDescriptor, &exceptFDs_)) { - [delegate streamDidReceiveException: cArray[i]]; + [delegate streamDidReceiveException: objects[i]]; [pool releaseObjects]; /* * Prevent calling it twice in case the FD is in both * sets. @@ -134,27 +134,27 @@ */ FD_CLR(fileDescriptor, &exceptFDs_); } } - cArray = [writeStreams cArray]; + objects = [writeStreams objects]; count = [writeStreams count]; for (i = 0; i < count; i++) { - int fileDescriptor = [cArray[i] fileDescriptor]; + int fileDescriptor = [objects[i] fileDescriptor]; if (FD_ISSET(fileDescriptor, &writeFDs_)) { - [delegate streamIsReadyForWriting: cArray[i]]; + [delegate streamIsReadyForWriting: objects[i]]; [pool releaseObjects]; } if (FD_ISSET(fileDescriptor, &exceptFDs_)) { - [delegate streamDidReceiveException: cArray[i]]; + [delegate streamDidReceiveException: objects[i]]; [pool releaseObjects]; } } [pool release]; return YES; } @end Index: src/OFString+JSONValue.m ================================================================== --- src/OFString+JSONValue.m +++ src/OFString+JSONValue.m @@ -94,11 +94,11 @@ skipWhitespaces(pointer, stop); skipComment(pointer, stop); } } -static OF_INLINE uint16_t +static inline uint16_t parseUnicodeEscape(const char *pointer, const char *stop) { uint16_t ret = 0; char i; @@ -123,11 +123,11 @@ } return ret; } -static OF_INLINE OFString* +static inline OFString* parseString(const char *restrict *pointer, const char *stop) { char *buffer; size_t i = 0; @@ -257,11 +257,11 @@ free(buffer); return nil; } -static OF_INLINE OFMutableArray* +static inline OFMutableArray* parseArray(const char *restrict *pointer, const char *stop) { OFMutableArray *array = [OFMutableArray array]; if (++(*pointer) >= stop) @@ -299,11 +299,11 @@ (*pointer)++; return array; } -static OF_INLINE OFMutableDictionary* +static inline OFMutableDictionary* parseDictionary(const char *restrict *pointer, const char *stop) { OFMutableDictionary *dictionary = [OFMutableDictionary dictionary]; if (++(*pointer) >= stop) @@ -351,11 +351,11 @@ (*pointer)++; return dictionary; } -static OF_INLINE OFNumber* +static inline OFNumber* parseNumber(const char *restrict *pointer, const char *stop) { BOOL hasDecimal = NO; size_t i; OFString *string; Index: src/OFString.h ================================================================== --- src/OFString.h +++ src/OFString.h @@ -12,17 +12,23 @@ * 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 +#ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS +#endif +#ifndef __STDC_CONSTANT_MACROS +# define __STDC_CONSTANT_MACROS +#endif + #include #include #import "OFObject.h" #import "OFSerialization.h" -#import "OFJSONEncoding.h" +#import "OFJSONRepresentation.h" #import "macros.h" @class OFConstantString; @@ -72,11 +78,11 @@ * for a constant string and get initialized on the first message! Therefore, * you should use the corresponding methods to get the ivars, which ensures the * constant string is initialized. */ @interface OFString: OFObject + OFSerialization, OFJSONRepresentation> #ifdef OF_HAVE_PROPERTIES @property (readonly) size_t length; #endif /** @@ -722,10 +728,20 @@ * \param delimiter The delimiter for splitting * \return An autoreleased OFArray with the split string */ - (OFArray*)componentsSeparatedByString: (OFString*)delimiter; +/** + * \brief Splits an OFString into an OFArray of OFStrings. + * + * \param delimiter The delimiter for splitting + * \param skipEmpty Whether empty components should be skipped + * \return An autoreleased OFArray with the split string + */ +- (OFArray*)componentsSeparatedByString: (OFString*)delimiter + skipEmpty: (BOOL)skipEmpty; + /** * \brief Returns the components of the path. * * \return The components of the path */ Index: src/OFString.m ================================================================== --- src/OFString.m +++ src/OFString.m @@ -20,14 +20,10 @@ #include #include #include -#ifdef _WIN32 -# include -#endif - #import "OFString.h" #import "OFString_UTF8.h" #import "OFArray.h" #import "OFDictionary.h" #import "OFFile.h" @@ -259,31 +255,74 @@ return (id)[[OFString_UTF8 alloc] init]; } - initWithUTF8String: (const char*)UTF8String { - return (id)[[OFString_UTF8 alloc] initWithUTF8String: UTF8String]; + id string; + size_t length; + void *storage; + + length = strlen(UTF8String); + string = of_alloc_object([OFString_UTF8 class], + length + 1, 1, &storage); + + return (id)[string _initWithUTF8String: UTF8String + length: length + storage: storage]; } - initWithUTF8String: (const char*)UTF8String length: (size_t)UTF8StringLength { - return (id)[[OFString_UTF8 alloc] initWithUTF8String: UTF8String - length: UTF8StringLength]; + id string; + void *storage; + + string = of_alloc_object([OFString_UTF8 class], + UTF8StringLength + 1, 1, &storage); + + return (id)[string _initWithUTF8String: UTF8String + length: UTF8StringLength + storage: storage]; } - initWithCString: (const char*)cString encoding: (of_string_encoding_t)encoding { + if (encoding == OF_STRING_ENCODING_UTF_8) { + id string; + size_t length; + void *storage; + + length = strlen(cString); + string = of_alloc_object([OFString_UTF8 class], + length + 1, 1, &storage); + + return (id)[string _initWithUTF8String: cString + length: length + storage: storage]; + } + return (id)[[OFString_UTF8 alloc] initWithCString: cString encoding: encoding]; } - initWithCString: (const char*)cString encoding: (of_string_encoding_t)encoding length: (size_t)cStringLength { + if (encoding == OF_STRING_ENCODING_UTF_8) { + id string; + void *storage; + + string = of_alloc_object([OFString_UTF8 class], + cStringLength + 1, 1, &storage); + + return (id)[string _initWithUTF8String: cString + length: cStringLength + storage: storage]; + } + return (id)[[OFString_UTF8 alloc] initWithCString: cString encoding: encoding length: cStringLength]; } @@ -1469,37 +1508,42 @@ return new; } - (BOOL)hasPrefix: (OFString*)prefix { - OFAutoreleasePool *pool; of_unichar_t *tmp; const of_unichar_t *prefixString; size_t prefixLength; int compare; if ((prefixLength = [prefix length]) > [self length]) return NO; - tmp = alloca(prefixLength * sizeof(of_unichar_t)); - [self getCharacters: tmp - inRange: of_range(0, prefixLength)]; - - pool = [[OFAutoreleasePool alloc] init]; - - prefixString = [prefix unicodeString]; - compare = memcmp(tmp, prefixString, - prefixLength * sizeof(of_unichar_t)); - - [pool release]; + tmp = [self allocMemoryForNItems: prefixLength + ofSize: sizeof(of_unichar_t)]; + @try { + OFAutoreleasePool *pool; + + [self getCharacters: tmp + inRange: of_range(0, prefixLength)]; + + pool = [[OFAutoreleasePool alloc] init]; + + prefixString = [prefix unicodeString]; + compare = memcmp(tmp, prefixString, + prefixLength * sizeof(of_unichar_t)); + + [pool release]; + } @finally { + [self freeMemory: tmp]; + } return !compare; } - (BOOL)hasSuffix: (OFString*)suffix { - OFAutoreleasePool *pool; of_unichar_t *tmp; const of_unichar_t *suffixString; size_t length, suffixLength; int compare; @@ -1506,33 +1550,49 @@ if ((suffixLength = [suffix length]) > [self length]) return NO; length = [self length]; - tmp = alloca(suffixLength * sizeof(of_unichar_t)); - [self getCharacters: tmp - inRange: of_range(length - suffixLength, suffixLength)]; - - pool = [[OFAutoreleasePool alloc] init]; - - suffixString = [suffix unicodeString]; - compare = memcmp(tmp, suffixString, - suffixLength * sizeof(of_unichar_t)); - - [pool release]; + tmp = [self allocMemoryForNItems: suffixLength + ofSize: sizeof(of_unichar_t)]; + @try { + OFAutoreleasePool *pool; + + [self getCharacters: tmp + inRange: of_range(length - suffixLength, + suffixLength)]; + + pool = [[OFAutoreleasePool alloc] init]; + + suffixString = [suffix unicodeString]; + compare = memcmp(tmp, suffixString, + suffixLength * sizeof(of_unichar_t)); + + [pool release]; + } @finally { + [self freeMemory: tmp]; + } return !compare; } - (OFArray*)componentsSeparatedByString: (OFString*)delimiter +{ + return [self componentsSeparatedByString: delimiter + skipEmpty: NO]; +} + +- (OFArray*)componentsSeparatedByString: (OFString*)delimiter + skipEmpty: (BOOL)skipEmpty { OFAutoreleasePool *pool; OFMutableArray *array = [OFMutableArray array]; const of_unichar_t *string, *delimiterString; size_t length = [self length]; size_t delimiterLength = [delimiter length]; size_t i, last; + OFString *component; pool = [[OFAutoreleasePool alloc] init]; string = [self unicodeString]; delimiterString = [delimiter unicodeString]; @@ -1549,18 +1609,20 @@ for (i = 0, last = 0; i <= length - delimiterLength; i++) { if (memcmp(string + i, delimiterString, delimiterLength * sizeof(of_unichar_t))) continue; - [array addObject: [self substringWithRange: - of_range(last, i - last)]]; + component = [self substringWithRange: of_range(last, i - last)]; + if (!skipEmpty || ![component isEqual: @""]) + [array addObject: component]; i += delimiterLength - 1; last = i + 1; } - [array addObject: - [self substringWithRange: of_range(last, length - last)]]; + component = [self substringWithRange: of_range(last, length - last)]; + if (!skipEmpty || ![component isEqual: @""]) + [array addObject: component]; [array makeImmutable]; [pool release]; Index: src/OFString_UTF8.h ================================================================== --- src/OFString_UTF8.h +++ src/OFString_UTF8.h @@ -17,15 +17,27 @@ #import "OFString.h" @interface OFString_UTF8: OFString { @public + /** + * A pointer to the actual data. + * + * Since constant strings don't have s_store, they have to malloc it on + * the first access. Strings created at runtime just set the pointer to + * &s_store. + */ struct of_string_utf8_ivars { char *cString; size_t cStringLength; BOOL UTF8; size_t length; BOOL hashed; uint32_t hash; } *restrict s; + struct of_string_utf8_ivars s_store; } + +- _initWithUTF8String: (const char*)UTF8String + length: (size_t)UTF8StringLength + storage: (char*)storage; @end Index: src/OFString_UTF8.m ================================================================== --- src/OFString_UTF8.m +++ src/OFString_UTF8.m @@ -18,10 +18,12 @@ #include #include #include #include + +#include #import "OFString_UTF8.h" #import "OFMutableString_UTF8.h" #import "OFArray.h" #import "OFAutoreleasePool.h" @@ -60,19 +62,56 @@ - init { self = [super init]; @try { - s = [self allocMemoryWithSize: sizeof(*s)]; - memset(s, 0, sizeof(*s)); + s = &s_store; s->cString = [self allocMemoryWithSize: 1]; s->cString[0] = '\0'; } @catch (id e) { [self release]; @throw e; } + + return self; +} + +- _initWithUTF8String: (const char*)UTF8String + length: (size_t)UTF8StringLength + storage: (char*)storage +{ + self = [super init]; + + @try { + if (UTF8StringLength >= 3 && + !memcmp(UTF8String, "\xEF\xBB\xBF", 3)) { + UTF8String += 3; + UTF8StringLength -= 3; + } + + s = &s_store; + + s->cString = storage; + s->cStringLength = UTF8StringLength; + + switch (of_string_check_utf8(UTF8String, UTF8StringLength, + &s->length)) { + case 1: + s->UTF8 = YES; + break; + case -1: + @throw [OFInvalidEncodingException + exceptionWithClass: isa]; + } + + memcpy(s->cString, UTF8String, UTF8StringLength); + s->cString[UTF8StringLength] = 0; + } @catch (id e) { + [self release]; + @throw e; + } return self; } - initWithCString: (const char*)cString @@ -89,12 +128,11 @@ cStringLength >= 3 && !memcmp(cString, "\xEF\xBB\xBF", 3)) { cString += 3; cStringLength -= 3; } - s = [self allocMemoryWithSize: sizeof(*s)]; - memset(s, 0, sizeof(*s)); + s = &s_store; s->cString = [self allocMemoryWithSize: cStringLength + 1]; s->cStringLength = cStringLength; if (encoding == OF_STRING_ENCODING_UTF_8 || @@ -210,12 +248,11 @@ - initWithString: (OFString*)string { self = [super init]; @try { - s = [self allocMemoryWithSize: sizeof(*s)]; - memset(s, 0, sizeof(*s)); + s = &s_store; s->cStringLength = [string UTF8StringLength]; if ([string isKindOfClass: [OFString_UTF8 class]] || [string isKindOfClass: [OFMutableString_UTF8 class]]) @@ -253,12 +290,11 @@ string++; length--; } else if (byteOrder != OF_ENDIANESS_NATIVE) swap = YES; - s = [self allocMemoryWithSize: sizeof(*s)]; - memset(s, 0, sizeof(*s)); + s = &s_store; s->cStringLength = length; s->cString = [self allocMemoryWithSize: (length * 4) + 1]; s->length = length; @@ -336,12 +372,11 @@ string++; length--; } else if (byteOrder != OF_ENDIANESS_NATIVE) swap = YES; - s = [self allocMemoryWithSize: sizeof(*s)]; - memset(s, 0, sizeof(*s)); + s = &s_store; s->cStringLength = length; s->cString = [self allocMemoryWithSize: (length * 4) + 1]; s->length = length; @@ -431,42 +466,43 @@ arguments: (va_list)arguments { self = [super init]; @try { + char *tmp; int cStringLength; if (format == nil) @throw [OFInvalidArgumentException exceptionWithClass: isa selector: _cmd]; - s = [self allocMemoryWithSize: sizeof(*s)]; - memset(s, 0, sizeof(*s)); + s = &s_store; - if ((cStringLength = of_vasprintf(&s->cString, - [format UTF8String], arguments)) == -1) + if ((cStringLength = of_vasprintf(&tmp, [format UTF8String], + arguments)) == -1) @throw [OFInvalidFormatException exceptionWithClass: isa]; s->cStringLength = cStringLength; @try { - switch (of_string_check_utf8(s->cString, - cStringLength, &s->length)) { + switch (of_string_check_utf8(tmp, cStringLength, + &s->length)) { case 1: s->UTF8 = YES; break; case -1: @throw [OFInvalidEncodingException exceptionWithClass: isa]; } - [self addMemoryToPool: s->cString]; - } @catch (id e) { - free(s->cString); - @throw e; + s->cString = [self + allocMemoryWithSize: cStringLength + 1]; + memcpy(s->cString, tmp, cStringLength + 1); + } @finally { + free(tmp); } } @catch (id e) { [self release]; @throw e; } @@ -482,12 +518,11 @@ @try { OFString *component; size_t i, cStringLength; va_list argumentsCopy; - s = [self allocMemoryWithSize: sizeof(*s)]; - memset(s, 0, sizeof(*s)); + s = &s_store; s->cStringLength = [firstComponent UTF8StringLength]; if ([firstComponent isKindOfClass: [OFString_UTF8 class]] || [firstComponent isKindOfClass: @@ -888,16 +923,18 @@ return !memcmp(s->cString + (s->cStringLength - cStringLength), [suffix UTF8String], cStringLength); } - (OFArray*)componentsSeparatedByString: (OFString*)delimiter + skipEmpty: (BOOL)skipEmpty { OFAutoreleasePool *pool; OFMutableArray *array; const char *cString = [delimiter UTF8String]; size_t cStringLength = [delimiter UTF8StringLength]; size_t i, last; + OFString *component; array = [OFMutableArray array]; pool = [[OFAutoreleasePool alloc] init]; if (cStringLength > s->cStringLength) { @@ -909,17 +946,21 @@ for (i = 0, last = 0; i <= s->cStringLength - cStringLength; i++) { if (memcmp(s->cString + i, cString, cStringLength)) continue; - [array addObject: - [OFString stringWithUTF8String: s->cString + last - length: i - last]]; + component = [OFString stringWithUTF8String: s->cString + last + length: i - last]; + if (!skipEmpty || ![component isEqual: @""]) + [array addObject: component]; + i += cStringLength - 1; last = i + 1; } - [array addObject: [OFString stringWithUTF8String: s->cString + last]]; + component = [OFString stringWithUTF8String: s->cString + last]; + if (!skipEmpty || ![component isEqual: @""]) + [array addObject: component]; [array makeImmutable]; [pool release]; Index: src/OFTCPSocket+SOCKS5.h ================================================================== --- src/OFTCPSocket+SOCKS5.h +++ src/OFTCPSocket+SOCKS5.h @@ -23,10 +23,8 @@ #ifdef __cplusplus } #endif @interface OFTCPSocket (SOCKS5) -/// \cond internal - (void)_SOCKS5ConnectToHost: (OFString*)host port: (uint16_t)port; -/// \endcond @end Index: src/OFTCPSocket.h ================================================================== --- src/OFTCPSocket.h +++ src/OFTCPSocket.h @@ -11,10 +11,17 @@ * 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. */ + +#ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS +#endif +#ifndef __STDC_CONSTANT_MACROS +# define __STDC_CONSTANT_MACROS +#endif #ifndef _WIN32 # include # include # include Index: src/OFTCPSocket.m ================================================================== --- src/OFTCPSocket.m +++ src/OFTCPSocket.m @@ -128,11 +128,11 @@ [super dealloc]; } - (void)setSOCKS5Host: (OFString*)host { - OF_SETTER(SOCKS5Host, host, YES, YES) + OF_SETTER(SOCKS5Host, host, YES, 1) } - (OFString*)SOCKS5Host { OF_GETTER(SOCKS5Host, YES) ADDED src/OFTLSSocket.h Index: src/OFTLSSocket.h ================================================================== --- src/OFTLSSocket.h +++ src/OFTLSSocket.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012 + * 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 "objfw-defs.h" + +@class OFString; +@class OFArray; +@protocol OFTLSSocket; + +/** + * \brief A delegate for classes implementing the OFTLSSocket protocol. + */ +@protocol OFTLSSocketDelegate +/** + * \brief This callback is called when the TLS socket wants to know if it + * should accept the received keychain. + * + * \param certificate An array of objects implementing the OFX509Certificate + * protocol + * \return Whether the TLS socket should accept the received keychain + */ +- (BOOL)socket: (id )socket + shouldAcceptKeychain: (OFArray*)keychain; +@end + +/** + * \brief A protocol that should be implemented by 3rd party libraries + * implementing TLS. + */ +@protocol OFTLSSocket +#ifdef OF_HAVE_PROPERTIES +@property (assign) id delegate; +@property (copy) OFString *certificateFile, *privateKeyFile; +@property const char *privateKeyPassphrase; +#endif + +/** + * \brief Sets a delegate for the TLS socket. + * + * \param delegate The delegate to use + */ +- (void)setDelegate: (id )delegate; + +/** + * \brief Returns the delegate used by the TLS socket. + * + * \return The delegate used by the TLS socket + */ +- (id )delegate; + +/** + * \brief Sets the path to the X.509 certificate file to use. + * + * \param certificateFile The path to the X.509 certificate file + */ +- (void)setCertificateFile: (OFString*)certificateFile; + +/** + * \brief Returns the path of the X.509 certificate file used by the TLS socket. + * + * \return The path of the X.509 certificate file used by the TLS socket + */ +- (OFString*)certificateFile; + +/** + * \brief Sets the path to the PKCS#8 private key file to use. + * + * \param privateKeyFile The path to the PKCS#8 private key file + */ +- (void)setPrivateKeyFile: (OFString*)privateKeyFile; + +/** + * \brief Returns the path of the PKCS#8 private key file used by the TLS + * socket. + * + * \return The path of the PKCS#8 private key file used by the TLS socket + */ +- (OFString*)privateKeyFile; + +/** + * \brief Sets the passphrase to decrypt the PKCS#8 private key file. + * + * \warning You have to ensure that this is in secure memory that is protected + * from swapping! This is also the reason why this is not an OFString. + * + * \param privateKeyPassphrase The passphrase to decrypt the PKCS#8 private + * key file + */ +- (void)setPrivateKeyPassphrase: (const char*)privateKeyPassphrase; + +/** + * \brief Returns the passphrase to decrypt the PKCS#8 private key file. + * + * \warning You should not copy this to insecure memory that is swappable! + * + * \return The passphrase to decrypt the PKCS#8 private key file + */ +- (const char*)privateKeyPassphrase; +@end ADDED src/OFThreadPool.h Index: src/OFThreadPool.h ================================================================== --- src/OFThreadPool.h +++ src/OFThreadPool.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012 + * 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" + +#ifdef OF_HAVE_BLOCKS +typedef void (^of_thread_pool_block_t)(id object); +#endif + +@class OFMutableArray; +@class OFList; +@class OFCondition; +@class OFThreadPoolJob; + +/** + * \brief A class providing a pool of reusable threads. + * + * \note When the thread pool is released, all threads will terminate after + * they finish the job they are currently processing. + */ +@interface OFThreadPool: OFObject +{ + size_t size; + OFMutableArray *threads; + volatile int count; +@public + OFList *queue; + OFCondition *queueCondition; + volatile int doneCount; + OFCondition *countCondition; +} + +/** + * \brief Returns a new thread pool with one thread for each core in the system. + * + * \warning If for some reason the number of cores in the system could not be + * determined, the pool will only have one thread! + * + * \return A new thread pool with one thread for each core in the system + */ ++ threadPool; + +/** + * \brief Returns a new thread pool with the specified number of threads. + * + * \warning If for some reason the number of cores in the system could not be + * determined, the pool will only have one thread! + * + * \param size The number of threads for the pool + * \return A new thread pool with the specified number of threads + */ ++ threadPoolWithSize: (size_t)size; + +/** + * \brief Initializes an already allocated OFThreadPool with one thread for + * each core in the system. + * + * \warning If for some reason the number of cores in the system could not be + * determined, the pool will only have one thread! + * + * \return An initialized OFThreadPool with one thread for each core in the + * system + */ +- init; + +/** + * \brief Initializes an already allocated OFThreadPool with the specified + * number of threads. + * + * \warning If for some reason the number of cores in the system could not be + * determined, the pool will only have one thread! + * + * \param size The number of threads for the pool + * \return An initialized OFThreadPool with the specified number of threads + */ +- initWithSize: (size_t)size; + +/** + * \brief Execute the specified selector on the specified target with the + * specified object as soon as a thread is ready. + * + * \param target The target on which to perform the selector + * \param selector The selector to perform on the target + * \param object THe object with which the selector is performed on the target + */ +- (void)dispatchWithTarget: (id)target + selector: (SEL)selector + object: (id)object; + +#ifdef OF_HAVE_BLOCKS +/** + * \brief Executes the specified block as soon as a thread is ready. + * + * \param block The block to execute + */ +- (void)dispatchWithBlock: (of_thread_pool_block_t)block; + +/** + * \brief Executes the specified block as soon as a thread is ready. + * + * \param block The block to execute + * \param object The object to pass to the block + */ +- (void)dispatchWithBlock: (of_thread_pool_block_t)block + object: (id)object; +#endif + +/** + * \brief Waits until all threads have finished. + */ +- (void)waitUntilFinished; +@end ADDED src/OFThreadPool.m Index: src/OFThreadPool.m ================================================================== --- src/OFThreadPool.m +++ src/OFThreadPool.m @@ -0,0 +1,386 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012 + * 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 "OFThreadPool.h" +#import "OFArray.h" +#import "OFList.h" +#import "OFThread.h" +#import "OFAutoreleasePool.h" + +@interface OFThreadPoolJob: OFObject +{ + id target; + SEL selector; + id object; +#ifdef OF_HAVE_BLOCKS + of_thread_pool_block_t block; +#endif +} + ++ jobWithTarget: (id)target + selector: (SEL)selector + object: (id)object; +#ifdef OF_HAVE_BLOCKS ++ jobWithBlock: (of_thread_pool_block_t)block + object: (id)object; +#endif +- initWithTarget: (id)target + selector: (SEL)selector + object: (id)object; +#ifdef OF_HAVE_BLOCKS +- initWithBlock: (of_thread_pool_block_t)block + object: (id)object; +#endif +- (void)perform; +@end + +@implementation OFThreadPoolJob ++ jobWithTarget: (id)target + selector: (SEL)selector + object: (id)object +{ + return [[[self alloc] initWithTarget: target + selector: selector + object: object] autorelease]; +} + +#ifdef OF_HAVE_BLOCKS ++ jobWithBlock: (of_thread_pool_block_t)block + object: (id)object +{ + return [[(OFThreadPoolJob*)[self alloc] + initWithBlock: block + object: object] autorelease]; +} +#endif + +- initWithTarget: (id)target_ + selector: (SEL)selector_ + object: (id)object_ +{ + self = [super init]; + + @try { + target = [target_ retain]; + selector = selector_; + object = [object_ retain]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +#ifdef OF_HAVE_BLOCKS +- initWithBlock: (of_thread_pool_block_t)block_ + object: (id)object_ +{ + self = [super init]; + + @try { + block = [block_ retain]; + object = [object_ retain]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} +#endif + +- (void)dealloc +{ + [target release]; + [object release]; +#ifdef OF_HAVE_BLOCKS + [block release]; +#endif + + [super dealloc]; +} + +- (void)perform +{ +#ifdef OF_HAVE_BLOCKS + if (block != nil) + block(object); + else +#endif + [object performSelector: selector + withObject: object]; +} +@end + +@interface OFThreadPoolThread: OFThread +{ + OFList *queue; + OFCondition *queueCondition, *countCondition; +@public + volatile BOOL terminate; + volatile int *doneCount; +} + ++ threadWithThreadPool: (OFThreadPool*)threadPool; +- initWithThreadPool: (OFThreadPool*)threadPool; +@end + +@implementation OFThreadPoolThread ++ threadWithThreadPool: (OFThreadPool*)threadPool +{ + return [[[self alloc] initWithThreadPool: threadPool] autorelease]; +} + +- initWithThreadPool: (OFThreadPool*)threadPool +{ + self = [super init]; + + @try { + queue = [threadPool->queue retain]; + queueCondition = [threadPool->queueCondition retain]; + countCondition = [threadPool->countCondition retain]; + doneCount = &threadPool->doneCount; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [queue release]; + [queueCondition release]; + [countCondition release]; + + [super dealloc]; +} + +- (id)main +{ + OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; + + if (terminate) { + [pool release]; + return nil; + } + + for (;;) { + OFThreadPoolJob *job; + + [queueCondition lock]; + @try { + of_list_object_t *listObject; + + if (terminate) { + [pool release]; + return nil; + } + + listObject = [queue firstListObject]; + + while (listObject == NULL) { + [queueCondition wait]; + + if (terminate) { + [pool release]; + return nil; + } + + listObject = [queue firstListObject]; + } + + job = [[listObject->object retain] autorelease]; + [queue removeListObject: listObject]; + } @finally { + [queueCondition unlock]; + } + + if (terminate) { + [pool release]; + return nil; + } + + [job perform]; + + if (terminate) { + [pool release]; + return nil; + } + + [pool releaseObjects]; + + [countCondition lock]; + @try { + if (terminate) { + [pool release]; + return nil; + } + + (*doneCount)++; + + [countCondition signal]; + } @finally { + [countCondition unlock]; + } + } +} +@end + +@implementation OFThreadPool ++ threadPool +{ + return [[[self alloc] init] autorelease]; +} + ++ threadPoolWithSize: (size_t)size +{ + return [[[self alloc] initWithSize: size] autorelease]; +} + +- init +{ + return [self initWithSize: of_num_cpus]; +} + +- initWithSize: (size_t)size_ +{ + self = [super init]; + + @try { + OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; + size_t i; + + size = size_; + threads = [[OFMutableArray alloc] init]; + queue = [[OFList alloc] init]; + queueCondition = [[OFCondition alloc] init]; + countCondition = [[OFCondition alloc] init]; + + for (i = 0; i < size; i++) { + OFThreadPoolThread *thread = + [OFThreadPoolThread threadWithThreadPool: self]; + + [threads addObject: thread]; + + [pool releaseObjects]; + } + + /* + * We need to start the threads in a separate loop to make sure + * threads is not modified anymore to prevent a race condition. + */ + for (i = 0; i < size; i++) { + OFThreadPoolThread *thread = [threads objectAtIndex: i]; + + [thread start]; + } + + [pool release]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; + [queueCondition lock]; + @try { + [countCondition lock]; + @try { + OFEnumerator *enumerator = [threads objectEnumerator]; + OFThreadPoolThread *thread; + + while ((thread = [enumerator nextObject]) != nil) + thread->terminate = YES; + } @finally { + [countCondition unlock]; + } + + [queueCondition broadcast]; + } @finally { + [queueCondition unlock]; + } + [pool release]; + + [threads release]; + [queue release]; + [queueCondition release]; + [countCondition release]; + + [super dealloc]; +} + +- (void)_dispatchJob: (OFThreadPoolJob*)job +{ + of_atomic_inc_int(&count); + + [queueCondition lock]; + @try { + [queue appendObject: job]; + [queueCondition signal]; + } @finally { + [queueCondition unlock]; + } +} + +- (void)waitUntilFinished +{ + for (;;) { + [countCondition lock]; + @try { + if (doneCount == count) + return; + + [countCondition wait]; + } @finally { + [countCondition unlock]; + } + } +} + +- (void)dispatchWithTarget: (id)target + selector: (SEL)selector + object: (id)object +{ + [self _dispatchJob: [OFThreadPoolJob jobWithTarget: target + selector: selector + object: object]]; +} + +#ifdef OF_HAVE_BLOCKS +- (void)dispatchWithBlock: (of_thread_pool_block_t)block +{ + [self _dispatchJob: [OFThreadPoolJob jobWithBlock: block + object: nil]]; +} + +- (void)dispatchWithBlock: (of_thread_pool_block_t)block + object: (id)object +{ + [self _dispatchJob: [OFThreadPoolJob jobWithBlock: block + object: object]]; +} +#endif +@end Index: src/OFURL.m ================================================================== --- src/OFURL.m +++ src/OFURL.m @@ -42,24 +42,24 @@ array = [[[path componentsSeparatedByString: @"/"] mutableCopy] autorelease]; while (!done) { - id *cArray = [array cArray]; + id *objects = [array objects]; size_t i, length = [array count]; done = YES; for (i = 0; i < length; i++) { - if ([cArray[i] isEqual: @"."]) { + if ([objects[i] isEqual: @"."]) { [array removeObjectAtIndex: i]; done = NO; break; } - if ([cArray[i] isEqual: @".."]) { + if ([objects[i] isEqual: @".."]) { [array removeObjectAtIndex: i]; if (i > 0) [array removeObjectAtIndex: i - 1]; @@ -414,21 +414,21 @@ { if (![scheme_ isEqual: @"http"] && ![scheme_ isEqual: @"https"]) @throw [OFInvalidArgumentException exceptionWithClass: isa selector: _cmd]; - OF_SETTER(scheme, scheme_, YES, YES) + OF_SETTER(scheme, scheme_, YES, 1) } - (OFString*)host { OF_GETTER(host, YES) } - (void)setHost: (OFString*)host_ { - OF_SETTER(host, host_, YES, YES) + OF_SETTER(host, host_, YES, 1) } - (uint16_t)port { return port; @@ -444,21 +444,21 @@ OF_GETTER(user, YES) } - (void)setUser: (OFString*)user_ { - OF_SETTER(user, user_, YES, YES) + OF_SETTER(user, user_, YES, 1) } - (OFString*)password { OF_GETTER(password, YES) } - (void)setPassword: (OFString*)password_ { - OF_SETTER(password, password_, YES, YES) + OF_SETTER(password, password_, YES, 1) } - (OFString*)path { OF_GETTER(path, YES) @@ -469,41 +469,41 @@ if (([scheme isEqual: @"http"] || [scheme isEqual: @"https"]) && ![path_ hasPrefix: @"/"]) @throw [OFInvalidArgumentException exceptionWithClass: isa selector: _cmd]; - OF_SETTER(path, path_, YES, YES) + OF_SETTER(path, path_, YES, 1) } - (OFString*)parameters { OF_GETTER(parameters, YES) } - (void)setParameters: (OFString*)parameters_ { - OF_SETTER(parameters, parameters_, YES, YES) + OF_SETTER(parameters, parameters_, YES, 1) } - (OFString*)query { OF_GETTER(query, YES) } - (void)setQuery: (OFString*)query_ { - OF_SETTER(query, query_, YES, YES) + OF_SETTER(query, query_, YES, 1) } - (OFString*)fragment { OF_GETTER(fragment, YES) } - (void)setFragment: (OFString*)fragment_ { - OF_SETTER(fragment, fragment_, YES, YES) + OF_SETTER(fragment, fragment_, YES, 1) } - (OFString*)string { OFMutableString *ret = [OFMutableString stringWithFormat: @"%@://", Index: src/OFXMLElement.m ================================================================== --- src/OFXMLElement.m +++ src/OFXMLElement.m @@ -384,21 +384,21 @@ { if (name_ == nil) @throw [OFInvalidArgumentException exceptionWithClass: isa selector: _cmd]; - OF_SETTER(name, name_, YES, YES) + OF_SETTER(name, name_, YES, 1) } - (OFString*)name { OF_GETTER(name, YES) } - (void)setNamespace: (OFString*)ns_ { - OF_SETTER(ns, ns_, YES, YES) + OF_SETTER(ns, ns_, YES, 1) } - (OFString*)namespace { OF_GETTER(ns, YES) @@ -409,11 +409,10 @@ OF_GETTER(attributes, YES) } - (void)setChildren: (OFArray*)children_ { - /* 2 = mutableCopy */ OF_SETTER(children, children_, YES, 2) } - (OFArray*)children { @@ -432,22 +431,22 @@ - (OFString*)stringValue { OFAutoreleasePool *pool; OFMutableString *ret; - OFXMLElement **cArray; + OFXMLElement **objects; size_t i, count = [children count]; if (count == 0) return @""; ret = [OFMutableString string]; - cArray = [children cArray]; + objects = [children objects]; pool = [[OFAutoreleasePool alloc] init]; for (i = 0; i < count; i++) { - [ret appendString: [cArray[i] stringValue]]; + [ret appendString: [objects[i] stringValue]]; [pool releaseObjects]; } [ret makeImmutable]; @@ -463,11 +462,11 @@ { OFAutoreleasePool *pool, *pool2; char *cString; size_t length, i, j, attributesCount; OFString *prefix, *parentPrefix; - OFXMLAttribute **attributesCArray; + OFXMLAttribute **attributesObjects; OFString *ret; OFString *defaultNS; pool = [[OFAutoreleasePool alloc] init]; @@ -549,26 +548,26 @@ i += [ns UTF8StringLength]; cString[i++] = '\''; } /* Attributes */ - attributesCArray = [attributes cArray]; + attributesObjects = [attributes objects]; attributesCount = [attributes count]; pool2 = [[OFAutoreleasePool alloc] init]; for (j = 0; j < attributesCount; j++) { - OFString *attributeName = [attributesCArray[j] name]; + OFString *attributeName = [attributesObjects[j] name]; OFString *attributePrefix = nil; OFString *tmp = - [[attributesCArray[j] stringValue] stringByXMLEscaping]; + [[attributesObjects[j] stringValue] stringByXMLEscaping]; - if ([attributesCArray[j] namespace] != nil && + if ([attributesObjects[j] namespace] != nil && (attributePrefix = [allNamespaces objectForKey: - [attributesCArray[j] namespace]]) == nil) + [attributesObjects[j] namespace]]) == nil) @throw [OFUnboundNamespaceException exceptionWithClass: isa - namespace: [attributesCArray[j] + namespace: [attributesObjects[j] namespace]]; length += [attributeName UTF8StringLength] + (attributePrefix != nil ? [attributePrefix UTF8StringLength] + 1 : 0) + @@ -601,21 +600,22 @@ [pool2 releaseObjects]; } /* Childen */ if (children != nil) { - OFXMLElement **childrenCArray = [children cArray]; + OFXMLElement **childrenObjects = [children objects]; size_t childrenCount = [children count]; OFDataArray *tmp = [OFDataArray dataArray]; BOOL indent; if (indentation > 0) { indent = YES; for (j = 0; j < childrenCount; j++) { - if (childrenCArray[j]->isa == charactersClass || - childrenCArray[j]->isa == CDATAClass) { + if ([childrenObjects[j] isKindOfClass: + charactersClass] || [childrenObjects[j] + isKindOfClass: CDATAClass]) { indent = NO; break; } } } else @@ -626,19 +626,19 @@ unsigned int ind = (indent ? indentation : 0); if (ind) [tmp addItem: "\n"]; - if ([childrenCArray[j] isKindOfClass: + if ([childrenObjects[j] isKindOfClass: [OFXMLElement class]]) - child = [childrenCArray[j] + child = [childrenObjects[j] _XMLStringWithParent: self namespaces: allNamespaces indentation: ind level: level + 1]; else - child = [childrenCArray[j] + child = [childrenObjects[j] XMLStringWithIndentation: ind level: level + 1]; [tmp addNItems: [child UTF8StringLength] fromCArray: [child UTF8String]]; @@ -827,49 +827,49 @@ [pool release]; } - (OFXMLAttribute*)attributeForName: (OFString*)attributeName { - OFXMLAttribute **cArray = [attributes cArray]; + OFXMLAttribute **objects = [attributes objects]; size_t i, count = [attributes count]; for (i = 0; i < count; i++) - if (cArray[i]->ns == nil && - [cArray[i]->name isEqual: attributeName]) - return cArray[i]; + if (objects[i]->ns == nil && + [objects[i]->name isEqual: attributeName]) + return objects[i]; return nil; } - (OFXMLAttribute*)attributeForName: (OFString*)attributeName namespace: (OFString*)attributeNS { - OFXMLAttribute **cArray; + OFXMLAttribute **objects; size_t i, count; if (attributeNS == nil) return [self attributeForName: attributeName]; - cArray = [attributes cArray]; + objects = [attributes objects]; count = [attributes count]; for (i = 0; i < count; i++) - if ([cArray[i]->ns isEqual: attributeNS] && - [cArray[i]->name isEqual: attributeName]) - return cArray[i]; + if ([objects[i]->ns isEqual: attributeNS] && + [objects[i]->name isEqual: attributeName]) + return objects[i]; return nil; } - (void)removeAttributeForName: (OFString*)attributeName { - OFXMLAttribute **cArray = [attributes cArray]; + OFXMLAttribute **objects = [attributes objects]; size_t i, count = [attributes count]; for (i = 0; i < count; i++) { - if (cArray[i]->ns == nil && - [cArray[i]->name isEqual: attributeName]) { + if (objects[i]->ns == nil && + [objects[i]->name isEqual: attributeName]) { [attributes removeObjectAtIndex: i]; return; } } @@ -876,22 +876,22 @@ } - (void)removeAttributeForName: (OFString*)attributeName namespace: (OFString*)attributeNS { - OFXMLAttribute **cArray; + OFXMLAttribute **objects; size_t i, count; if (attributeNS == nil) return [self removeAttributeForName: attributeName]; - cArray = [attributes cArray]; + objects = [attributes objects]; count = [attributes count]; for (i = 0; i < count; i++) { - if ([cArray[i]->ns isEqual: attributeNS] && - [cArray[i]->name isEqual: attributeName]) { + if ([objects[i]->ns isEqual: attributeNS] && + [objects[i]->name isEqual: attributeName]) { [attributes removeObjectAtIndex: i]; return; } } } @@ -924,11 +924,11 @@ OF_GETTER(defaultNamespace, YES) } - (void)setDefaultNamespace: (OFString*)ns_ { - OF_SETTER(defaultNamespace, ns_, YES, YES) + OF_SETTER(defaultNamespace, ns_, YES, 1) } - (void)addChild: (OFXMLNode*)child { if ([child isKindOfClass: [OFXMLAttribute class]]) @@ -963,50 +963,50 @@ } - (OFArray*)elements { OFMutableArray *ret = [OFMutableArray array]; - OFXMLElement **cArray = [children cArray]; + OFXMLElement **objects = [children objects]; size_t i, count = [children count]; for (i = 0; i < count; i++) - if ([cArray[i] isKindOfClass: [OFXMLElement class]]) - [ret addObject: cArray[i]]; + if ([objects[i] isKindOfClass: [OFXMLElement class]]) + [ret addObject: objects[i]]; [ret makeImmutable]; return ret; } - (OFArray*)elementsForName: (OFString*)elementName { OFMutableArray *ret = [OFMutableArray array]; - OFXMLElement **cArray = [children cArray]; + OFXMLElement **objects = [children objects]; size_t i, count = [children count]; for (i = 0; i < count; i++) - if ([cArray[i] isKindOfClass: [OFXMLElement class]] && - cArray[i]->ns == nil && - [cArray[i]->name isEqual: elementName]) - [ret addObject: cArray[i]]; + if ([objects[i] isKindOfClass: [OFXMLElement class]] && + objects[i]->ns == nil && + [objects[i]->name isEqual: elementName]) + [ret addObject: objects[i]]; [ret makeImmutable]; return ret; } - (OFArray*)elementsForNamespace: (OFString*)elementNS { OFMutableArray *ret = [OFMutableArray array]; - OFXMLElement **cArray = [children cArray]; + OFXMLElement **objects = [children objects]; size_t i, count = [children count]; for (i = 0; i < count; i++) - if ([cArray[i] isKindOfClass: [OFXMLElement class]] && - cArray[i]->name != nil && - [cArray[i]->ns isEqual: elementNS]) - [ret addObject: cArray[i]]; + if ([objects[i] isKindOfClass: [OFXMLElement class]] && + objects[i]->name != nil && + [objects[i]->ns isEqual: elementNS]) + [ret addObject: objects[i]]; [ret makeImmutable]; return ret; } @@ -1013,25 +1013,25 @@ - (OFArray*)elementsForName: (OFString*)elementName namespace: (OFString*)elementNS { OFMutableArray *ret; - OFXMLElement **cArray; + OFXMLElement **objects; size_t i, count; if (elementNS == nil) return [self elementsForName: elementName]; ret = [OFMutableArray array]; - cArray = [children cArray]; + objects = [children objects]; count = [children count]; for (i = 0; i < count; i++) - if ([cArray[i] isKindOfClass: [OFXMLElement class]] && - [cArray[i]->ns isEqual: elementNS] && - [cArray[i]->name isEqual: elementName]) - [ret addObject: cArray[i]]; + if ([objects[i] isKindOfClass: [OFXMLElement class]] && + [objects[i]->ns isEqual: elementNS] && + [objects[i]->name isEqual: elementName]) + [ret addObject: objects[i]]; [ret makeImmutable]; return ret; } Index: src/OFXMLElementBuilder.m ================================================================== --- src/OFXMLElementBuilder.m +++ src/OFXMLElementBuilder.m @@ -88,30 +88,30 @@ withPrefix: (OFString*)prefix namespace: (OFString*)ns attributes: (OFArray*)attributes { OFXMLElement *element; - OFXMLAttribute **cArray; + OFXMLAttribute **objects; size_t i, count; element = [OFXMLElement elementWithName: name namespace: ns]; - cArray = [attributes cArray]; + objects = [attributes objects]; count = [attributes count]; for (i = 0; i < count; i++) { - if ([cArray[i] namespace] == nil && - [[cArray[i] name] isEqual: @"xmlns"]) + if ([objects[i] namespace] == nil && + [[objects[i] name] isEqual: @"xmlns"]) continue; - if ([[cArray[i] namespace] + if ([[objects[i] namespace] isEqual: @"http://www.w3.org/2000/xmlns/"]) - [element setPrefix: [cArray[i] name] - forNamespace: [cArray[i] stringValue]]; + [element setPrefix: [objects[i] name] + forNamespace: [objects[i] stringValue]]; - [element addAttribute: cArray[i]]; + [element addAttribute: objects[i]]; } [[stack lastObject] addChild: element]; [stack addObject: element]; } Index: src/OFXMLParser.m ================================================================== --- src/OFXMLParser.m +++ src/OFXMLParser.m @@ -96,20 +96,20 @@ } static OFString* namespace_for_prefix(OFString *prefix, OFArray *namespaces) { - OFDictionary **cArray = [namespaces cArray]; + OFDictionary **objects = [namespaces objects]; ssize_t i; if (prefix == nil) prefix = @""; for (i = [namespaces count] - 1; i >= 0; i--) { OFString *tmp; - if ((tmp = [cArray[i] objectForKey: prefix]) != nil) + if ((tmp = [objects[i] objectForKey: prefix]) != nil) return tmp; } return nil; } @@ -187,10 +187,11 @@ OFMutableDictionary *dict; cache = [[OFBigDataArray alloc] init]; previous = [[OFMutableArray alloc] init]; namespaces = [[OFMutableArray alloc] init]; + attributes = [[OFMutableArray alloc] init]; pool = [[OFAutoreleasePool alloc] init]; dict = [OFMutableDictionary dictionaryWithKeysAndObjects: @"xml", @"http://www.w3.org/XML/1998/namespace", @"xmlns", @"http://www.w3.org/2000/xmlns/", nil]; @@ -668,11 +669,11 @@ i: (size_t*)i last: (size_t*)last { OFAutoreleasePool *pool; OFString *ns; - OFXMLAttribute **attributesCArray; + OFXMLAttribute **attributesObjects; size_t j, attributesCount; if (buffer[*i] != '>' && buffer[*i] != '/') { if (buffer[*i] != ' ' && buffer[*i] != '\t' && buffer[*i] != '\n' && buffer[*i] != '\r') { @@ -682,21 +683,21 @@ } return; } - attributesCArray = [attributes cArray]; + attributesObjects = [attributes objects]; attributesCount = [attributes count]; ns = namespace_for_prefix(prefix, namespaces); if (prefix != nil && ns == nil) @throw [OFUnboundNamespaceException exceptionWithClass: isa prefix: prefix]; for (j = 0; j < attributesCount; j++) - resolve_attribute_namespace(attributesCArray[j], namespaces, + resolve_attribute_namespace(attributesObjects[j], namespaces, isa); pool = [[OFAutoreleasePool alloc] init]; [delegate parser: self @@ -724,13 +725,12 @@ [pool release]; [name release]; [prefix release]; - [attributes release]; + [attributes removeAllObjects]; name = prefix = nil; - attributes = nil; *last = *i + 1; state = (buffer[*i] == '/' ? OF_XMLPARSER_EXPECT_CLOSE : OF_XMLPARSER_OUTSIDE_TAG); @@ -825,13 +825,10 @@ forKey: @""]; if ([attributePrefix isEqual: @"xmlns"]) [[namespaces lastObject] setObject: attributeValue forKey: attributeName]; - if (attributes == nil) - attributes = [[OFMutableArray alloc] init]; - [attributes addObject: [OFXMLAttribute attributeWithName: attributeName namespace: attributePrefix stringValue: attributeValue]]; Index: src/ObjFW.h ================================================================== --- src/ObjFW.h +++ src/ObjFW.h @@ -44,10 +44,11 @@ #import "OFStream.h" #import "OFFile.h" #import "OFStreamSocket.h" #import "OFTCPSocket.h" +#import "OFTLSSocket.h" #import "OFProcess.h" #import "OFStreamObserver.h" #import "OFHTTPRequest.h" @@ -131,12 +132,13 @@ # import "atomic.h" #endif #ifdef OF_THREADS # import "OFThread.h" +# import "OFThreadPool.h" # import "threading.h" #endif #import "asprintf.h" #import "base64.h" #import "of_asprintf.h" #import "of_strptime.h" Index: src/asprintf.h ================================================================== --- src/asprintf.h +++ src/asprintf.h @@ -13,10 +13,17 @@ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #import "objfw-defs.h" + +#ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS +#endif +#ifndef __STDC_CONSTANT_MACROS +# define __STDC_CONSTANT_MACROS +#endif #ifndef OF_HAVE_ASPRINTF # include # ifdef __cplusplus Index: src/atomic.h ================================================================== --- src/atomic.h +++ src/atomic.h @@ -31,17 +31,30 @@ of_atomic_add_int(volatile int *p, int i) { #if !defined(OF_THREADS) return (*p += i); #elif defined(OF_X86_ASM) || defined(OF_AMD64_ASM) - __asm__ ( - "lock\n\t" - "xaddl %0, %2\n\t" - "addl %1, %0" - : "+&r"(i) - : "r"(i), "m"(*p) - ); + if (sizeof(int) == 4) + __asm__ ( + "lock\n\t" + "xaddl %0, %2\n\t" + "addl %1, %0" + : "+&r"(i) + : "r"(i), "m"(*p) + ); +# ifdef OF_AMD64_ASM + else if (sizeof(int) == 8) + __asm__ ( + "lock\n\t" + "xaddq %0, %2\n\t" + "addq %1, %0" + : "+&r"(i) + : "r"(i), "m"(*p) + ); +# endif + else + abort(); return i; #elif defined(OF_HAVE_GCC_ATOMIC_OPS) return __sync_add_and_fetch(p, i); #elif defined(OF_HAVE_OSATOMIC) @@ -81,15 +94,25 @@ static OF_INLINE void* of_atomic_add_ptr(void* volatile *p, intptr_t i) { #if !defined(OF_THREADS) return (*(char* volatile*)p += i); -#elif defined(OF_X86_ASM) || defined(OF_AMD64_ASM) +#elif defined(OF_X86_ASM) __asm__ ( "lock\n\t" "xaddl %0, %2\n\t" "addl %1, %0" + : "+&r"(i) + : "r"(i), "m"(*p) + ); + + return (void*)i; +#elif defined(OF_AMD64_ASM) + __asm__ ( + "lock\n\t" + "xaddq %0, %2\n\t" + "addq %1, %0" : "+&r"(i) : "r"(i), "m"(*p) ); return (void*)i; @@ -111,18 +134,32 @@ of_atomic_sub_int(volatile int *p, int i) { #if !defined(OF_THREADS) return (*p -= i); #elif defined(OF_X86_ASM) || defined(OF_AMD64_ASM) - __asm__ ( - "negl %0\n\t" - "lock\n\t" - "xaddl %0, %2\n\t" - "subl %1, %0" - : "+&r"(i) - : "r"(i), "m"(*p) - ); + if (sizeof(int) == 4) + __asm__ ( + "negl %0\n\t" + "lock\n\t" + "xaddl %0, %2\n\t" + "subl %1, %0" + : "+&r"(i) + : "r"(i), "m"(*p) + ); +# ifdef OF_AMD64_ASM + else if (sizeof(int) == 8) + __asm__ ( + "negq %0\n\t" + "lock\n\t" + "xaddq %0, %2\n\t" + "subq %1, %0" + : "+&r"(i) + : "r"(i), "m"(*p) + ); +# endif + else + abort(); return i; #elif defined(OF_HAVE_GCC_ATOMIC_OPS) return __sync_sub_and_fetch(p, i); #elif defined(OF_HAVE_OSATOMIC) @@ -163,16 +200,27 @@ static OF_INLINE void* of_atomic_sub_ptr(void* volatile *p, intptr_t i) { #if !defined(OF_THREADS) return (*(char* volatile*)p -= i); -#elif defined(OF_X86_ASM) || defined(OF_AMD64_ASM) +#elif defined(OF_X86_ASM) __asm__ ( "negl %0\n\t" "lock\n\t" "xaddl %0, %2\n\t" "subl %1, %0" + : "+&r"(i) + : "r"(i), "m"(*p) + ); + + return (void*)i; +#elif defined(OF_AMD64_ASM) + __asm__ ( + "negq %0\n\t" + "lock\n\t" + "xaddq %0, %2\n\t" + "subq %1, %0" : "+&r"(i) : "r"(i), "m"(*p) ); return (void*)i; @@ -196,19 +244,34 @@ #if !defined(OF_THREADS) return ++*p; #elif defined(OF_X86_ASM) || defined(OF_AMD64_ASM) uint32_t i; - __asm__ ( - "xorl %0, %0\n\t" - "incl %0\n\t" - "lock\n\t" - "xaddl %0, %1\n\t" - "incl %0" - : "=&r"(i) - : "m"(*p) - ); + if (sizeof(int) == 4) + __asm__ ( + "xorl %0, %0\n\t" + "incl %0\n\t" + "lock\n\t" + "xaddl %0, %1\n\t" + "incl %0" + : "=&r"(i) + : "m"(*p) + ); +# ifdef OF_AMD64_ASM + else if (sizeof(int) == 8) + __asm__ ( + "xorq %0, %0\n\t" + "incq %0\n\t" + "lock\n\t" + "xaddq %0, %1\n\t" + "incq %0" + : "=&r"(i) + : "m"(*p) + ); +# endif + else + abort(); return i; #elif defined(OF_HAVE_GCC_ATOMIC_OPS) return __sync_add_and_fetch(p, 1); #elif defined(OF_HAVE_OSATOMIC) @@ -254,19 +317,34 @@ #if !defined(OF_THREADS) return --*p; #elif defined(OF_X86_ASM) || defined(OF_AMD64_ASM) uint32_t i; - __asm__ ( - "xorl %0, %0\n\t" - "decl %0\n\t" - "lock\n\t" - "xaddl %0, %1\n\t" - "decl %0" - : "=&r"(i) - : "m"(*p) - ); + if (sizeof(int) == 4) + __asm__ ( + "xorl %0, %0\n\t" + "decl %0\n\t" + "lock\n\t" + "xaddl %0, %1\n\t" + "decl %0" + : "=&r"(i) + : "m"(*p) + ); +# ifdef OF_AMD64_ASM + else if (sizeof(int) == 8) + __asm__ ( + "xorq %0, %0\n\t" + "decq %0\n\t" + "lock\n\t" + "xaddq %0, %1\n\t" + "decq %0" + : "=&r"(i) + : "m"(*p) + ); +# endif + else + abort(); return i; #elif defined(OF_HAVE_GCC_ATOMIC_OPS) return __sync_sub_and_fetch(p, 1); #elif defined(OF_HAVE_OSATOMIC) @@ -311,22 +389,40 @@ of_atomic_or_int(volatile unsigned int *p, unsigned int i) { #if !defined(OF_THREADS) return (*p |= i); #elif defined(OF_X86_ASM) || defined(OF_AMD64_ASM) - __asm__ ( - "0:\n\t" - "movl %2, %0\n\t" - "movl %2, %%eax\n\t" - "orl %1, %0\n\t" - "lock\n\t" - "cmpxchg %0, %2\n\t" - "jne 0\n\t" - : "=&r"(i) - : "r"(i), "m"(*p) - : "eax" - ); + if (sizeof(int) == 4) + __asm__ ( + "0:\n\t" + "movl %2, %0\n\t" + "movl %2, %%eax\n\t" + "orl %1, %0\n\t" + "lock\n\t" + "cmpxchg %0, %2\n\t" + "jne 0\n\t" + : "=&r"(i) + : "r"(i), "m"(*p) + : "eax" + ); +# ifdef OF_AMD64_ASM + if (sizeof(int) == 8) + __asm__ ( + "0:\n\t" + "movq %2, %0\n\t" + "movq %2, %%rax\n\t" + "orq %1, %0\n\t" + "lock\n\t" + "cmpxchg %0, %2\n\t" + "jne 0\n\t" + : "=&r"(i) + : "r"(i), "m"(*p) + : "rax" + ); +# endif + else + abort(); return i; #elif defined(OF_HAVE_GCC_ATOMIC_OPS) return __sync_or_and_fetch(p, i); #elif defined(OF_HAVE_OSATOMIC) @@ -372,22 +468,40 @@ of_atomic_and_int(volatile unsigned int *p, unsigned int i) { #if !defined(OF_THREADS) return (*p &= i); #elif defined(OF_X86_ASM) || defined(OF_AMD64_ASM) - __asm__ ( - "0:\n\t" - "movl %2, %0\n\t" - "movl %2, %%eax\n\t" - "andl %1, %0\n\t" - "lock\n\t" - "cmpxchg %0, %2\n\t" - "jne 0\n\t" - : "=&r"(i) - : "r"(i), "m"(*p) - : "eax" - ); + if (sizeof(int) == 4) + __asm__ ( + "0:\n\t" + "movl %2, %0\n\t" + "movl %2, %%eax\n\t" + "andl %1, %0\n\t" + "lock\n\t" + "cmpxchg %0, %2\n\t" + "jne 0\n\t" + : "=&r"(i) + : "r"(i), "m"(*p) + : "eax" + ); +# ifdef OF_AMD64_ASM + if (sizeof(int) == 8) + __asm__ ( + "0:\n\t" + "movq %2, %0\n\t" + "movq %2, %%rax\n\t" + "andq %1, %0\n\t" + "lock\n\t" + "cmpxchg %0, %2\n\t" + "jne 0\n\t" + : "=&r"(i) + : "r"(i), "m"(*p) + : "rax" + ); +# endif + else + abort(); return i; #elif defined(OF_HAVE_GCC_ATOMIC_OPS) return __sync_and_and_fetch(p, i); #elif defined(OF_HAVE_OSATOMIC) @@ -433,22 +547,40 @@ of_atomic_xor_int(volatile unsigned int *p, unsigned int i) { #if !defined(OF_THREADS) return (*p ^= i); #elif defined(OF_X86_ASM) || defined(OF_AMD64_ASM) - __asm__ ( - "0:\n\t" - "movl %2, %0\n\t" - "movl %2, %%eax\n\t" - "xorl %1, %0\n\t" - "lock\n\t" - "cmpxchgl %0, %2\n\t" - "jne 0\n\t" - : "=&r"(i) - : "r"(i), "m"(*p) - : "eax" - ); + if (sizeof(int) == 4) + __asm__ ( + "0:\n\t" + "movl %2, %0\n\t" + "movl %2, %%eax\n\t" + "xorl %1, %0\n\t" + "lock\n\t" + "cmpxchg %0, %2\n\t" + "jne 0\n\t" + : "=&r"(i) + : "r"(i), "m"(*p) + : "eax" + ); +# ifdef OF_AMD64_ASM + if (sizeof(int) == 8) + __asm__ ( + "0:\n\t" + "movq %2, %0\n\t" + "movq %2, %%rax\n\t" + "xorq %1, %0\n\t" + "lock\n\t" + "cmpxchg %0, %2\n\t" + "jne 0\n\t" + : "=&r"(i) + : "r"(i), "m"(*p) + : "rax" + ); +# endif + else + abort(); return i; #elif defined(OF_HAVE_GCC_ATOMIC_OPS) return __sync_xor_and_fetch(p, i); #elif defined(OF_HAVE_OSATOMIC) @@ -499,11 +631,11 @@ return YES; } return NO; #elif defined(OF_X86_ASM) || defined(OF_AMD64_ASM) - int r; + int32_t r; __asm__ ( "xorl %0, %0\n\t" "lock\n\t" "cmpxchg %2, %3\n\t" Index: src/base64.h ================================================================== --- src/base64.h +++ src/base64.h @@ -13,10 +13,17 @@ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #import "objfw-defs.h" + +#ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS +#endif +#ifndef __STDC_CONSTANT_MACROS +# define __STDC_CONSTANT_MACROS +#endif #ifdef OF_OBJFW_RUNTIME # import #else # import Index: src/macros.h ================================================================== --- src/macros.h +++ src/macros.h @@ -14,17 +14,10 @@ * file. */ #import "OFObject.h" -#ifndef __STDC_LIMIT_MACROS -# define __STDC_LIMIT_MACROS -#endif -#ifndef __STDC_CONSTANT_MACROS -# define __STDC_CONSTANT_MACROS -#endif - #include #include #if defined(OF_APPLE_RUNTIME) || defined(OF_GNU_RUNTIME) # import @@ -68,10 +61,15 @@ #ifdef OF_BIG_ENDIAN # define OF_ENDIANESS_NATIVE OF_ENDIANESS_BIG_ENDIAN #else # define OF_ENDIANESS_NATIVE OF_ENDIANESS_LITTLE_ENDIAN #endif + +/* Hopefully no arch needs more than 16 bytes padding */ +#ifndef __BIGGEST_ALIGNMENT__ +# define __BIGGEST_ALIGNMENT__ 16 +#endif #ifdef __GNUC__ # if defined(__amd64__) || defined(__x86_64__) # define OF_AMD64_ASM # elif defined(__i386__) @@ -99,10 +97,13 @@ # define OF_PATH_DELIMITER '/' #else # define OF_PATH_DELIMITER '\\' #endif +extern id objc_getProperty(id, SEL, ptrdiff_t, BOOL); +extern void objc_setProperty(id, SEL, ptrdiff_t, id, BOOL, signed char); + #define OF_IVAR_OFFSET(ivar) ((intptr_t)&ivar - (intptr_t)self) #define OF_GETTER(ivar, atomic) \ return objc_getProperty(self, _cmd, OF_IVAR_OFFSET(ivar), atomic); #define OF_SETTER(ivar, value, atomic, copy) \ objc_setProperty(self, _cmd, OF_IVAR_OFFSET(ivar), value, atomic, copy); Index: src/objc_properties.m ================================================================== --- src/objc_properties.m +++ src/objc_properties.m @@ -64,11 +64,11 @@ return *(id*)(void*)((char*)self + offset); } void objc_setProperty(id self, SEL _cmd, ptrdiff_t offset, id value, BOOL atomic, - BOOL copy) + signed char copy) { if (atomic) { id *ptr = (id*)(void*)((char*)self + offset); #ifdef OF_THREADS unsigned hash = SPINLOCK_HASH(ptr); @@ -82,15 +82,10 @@ switch (copy) { case 0: *ptr = [value retain]; break; case 2: - /* - * Apple uses this to indicate that the copy - * should be mutable. Please hit them for - * abusing a poor BOOL! - */ *ptr = [value mutableCopy]; break; default: *ptr = [value copy]; } Index: src/of_asprintf.h ================================================================== --- src/of_asprintf.h +++ src/of_asprintf.h @@ -11,10 +11,17 @@ * 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. */ + +#ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS +#endif +#ifndef __STDC_CONSTANT_MACROS +# define __STDC_CONSTANT_MACROS +#endif #include #import "macros.h" Index: src/of_strptime.h ================================================================== --- src/of_strptime.h +++ src/of_strptime.h @@ -11,10 +11,17 @@ * 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. */ + +#ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS +#endif +#ifndef __STDC_CONSTANT_MACROS +# define __STDC_CONSTANT_MACROS +#endif #include #ifdef __cplusplus extern "C" { Index: src/unicode.m ================================================================== --- src/unicode.m +++ src/unicode.m @@ -101,11 +101,11 @@ 0, 0, 0, 0, 571, 0, 0, 11390, 11391, 0, 577, 0, 0, 0, 0, 582, 0, 584, 0, 586, 0, 588, 0, 590, 11375, 11373, 11376, 385, 390, 0, 393, 394, 0, 399, 0, 400, 0, 0, 0, 0, - 403, 0, 0, 404, 0, 42893, 0, 0, + 403, 0, 0, 404, 0, 42893, 42922, 0, 407, 406, 0, 11362, 0, 0, 0, 412, 0, 11374, 413, 0, 0, 415, 0, 0, 0, 0, 0, 0, 0, 11364, 0, 0, 422, 0, 0, 425, 0, 0, 0, 0, 430, 580, 433, 434, 581, 0, 0, 0, @@ -434,21 +434,21 @@ 0, 11464, 0, 11466, 0, 11468, 0, 11470, 0, 11472, 0, 11474, 0, 11476, 0, 11478, 0, 11480, 0, 11482, 0, 11484, 0, 11486, 0, 11488, 0, 11490, 0, 0, 0, 0, 0, 0, 0, 0, 11499, 0, 11501, 0, - 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 11506, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; static const of_unichar_t upper_page_45[0x100] = { 4256, 4257, 4258, 4259, 4260, 4261, 4262, 4263, 4264, 4265, 4266, 4267, 4268, 4269, 4270, 4271, 4272, 4273, 4274, 4275, 4276, 4277, 4278, 4279, 4280, 4281, 4282, 4283, 4284, 4285, 4286, 4287, - 4288, 4289, 4290, 4291, 4292, 4293, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, + 4288, 4289, 4290, 4291, 4292, 4293, 0, 4295, + 0, 0, 0, 0, 0, 4301, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -527,11 +527,11 @@ 0, 42856, 0, 42858, 0, 42860, 0, 42862, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42873, 0, 42875, 0, 0, 42878, 0, 42880, 0, 42882, 0, 42884, 0, 42886, 0, 0, 0, 0, 42891, 0, 0, 0, - 0, 42896, 0, 0, 0, 0, 0, 0, + 0, 42896, 0, 42898, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42912, 0, 42914, 0, 42916, 0, 42918, 0, 42920, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -848,12 +848,12 @@ 0, 0, 0, 0, 0, 0, 0, 0, 11520, 11521, 11522, 11523, 11524, 11525, 11526, 11527, 11528, 11529, 11530, 11531, 11532, 11533, 11534, 11535, 11536, 11537, 11538, 11539, 11540, 11541, 11542, 11543, 11544, 11545, 11546, 11547, 11548, 11549, 11550, 11551, - 11552, 11553, 11554, 11555, 11556, 11557, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, + 11552, 11553, 11554, 11555, 11556, 11557, 0, 11559, + 0, 0, 0, 0, 0, 11565, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1029,11 +1029,11 @@ 11465, 0, 11467, 0, 11469, 0, 11471, 0, 11473, 0, 11475, 0, 11477, 0, 11479, 0, 11481, 0, 11483, 0, 11485, 0, 11487, 0, 11489, 0, 11491, 0, 0, 0, 0, 0, 0, 0, 0, 11500, 0, 11502, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 11507, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; static const of_unichar_t lower_page_166[0x100] = { 0, 0, 0, 0, 0, 0, 0, 0, @@ -1087,14 +1087,14 @@ 42857, 0, 42859, 0, 42861, 0, 42863, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42874, 0, 42876, 0, 7545, 42879, 0, 42881, 0, 42883, 0, 42885, 0, 42887, 0, 0, 0, 0, 42892, 0, 613, 0, 0, - 42897, 0, 0, 0, 0, 0, 0, 0, + 42897, 0, 42899, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42913, 0, 42915, 0, 42917, 0, 42919, 0, - 42921, 0, 0, 0, 0, 0, 0, 0, + 42921, 0, 614, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Index: tests/Makefile ================================================================== --- tests/Makefile +++ tests/Makefile @@ -71,11 +71,12 @@ echo "Uploading files to iOS device ${IOS_HOST} at ${IOS_TMP}..." ssh ${IOS_USER}@${IOS_HOST} \ 'rm -fr ${IOS_TMP} && mkdir -p ${IOS_TMP}/plugin' scp -q ../src/libobjfw.dylib tests testfile.bin testfile.txt \ serialization.xml ${IOS_USER}@${IOS_HOST}:${IOS_TMP}/ - scp -q plugin/TestPlugin.impl ${IOS_USER}@${IOS_HOST}:${IOS_TMP}/plugin/ + scp -q plugin/TestPlugin.bundle \ + ${IOS_USER}@${IOS_HOST}:${IOS_TMP}/plugin/ echo "Running tests binary on iOS device ${IOS_HOST}..." ssh ${IOS_USER}@${IOS_HOST} \ 'cd ${IOS_TMP} && ${TEST_LAUNCHER} ./tests' EBOOT.PBP: ${PROG_NOINST} Index: tests/OFArrayTests.m ================================================================== --- tests/OFArrayTests.m +++ tests/OFArrayTests.m @@ -27,12 +27,11 @@ static OFString *module = @"OFArray"; static OFString *c_ary[] = { @"Foo", @"Bar", - @"Baz", - nil + @"Baz" }; @implementation TestsAppDelegate (OFArrayTests) - (void)arrayTests { @@ -47,16 +46,14 @@ TEST(@"+[array]", (m[0] = [OFMutableArray array])) TEST(@"+[arrayWithObjects:]", (a[0] = [OFArray arrayWithObjects: @"Foo", @"Bar", @"Baz", nil])) - TEST(@"+[arrayWithCArray:]", (a[1] = [OFArray arrayWithCArray: c_ary])) - - TEST(@"+[arrayWithCArray:length:]", - (a[2] = [OFArray arrayWithCArray: c_ary - length: 3]) && - [a[2] isEqual: a[1]]) + TEST(@"+[arrayWithObjects:count:]", + (a[1] = [OFArray arrayWithObjects: c_ary + count: 3]) && + [a[1] isEqual: a[0]]) TEST(@"-[description]", [[a[0] description ]isEqual: @"(\n\tFoo,\n\tBar,\n\tBaz\n)"]) TEST(@"-[addObject:]", R([m[0] addObject: c_ary[0]]) && Index: tests/OFHTTPRequestTests.m ================================================================== --- tests/OFHTTPRequestTests.m +++ tests/OFHTTPRequestTests.m @@ -57,24 +57,27 @@ [cond signal]; [cond unlock]; client = [listener accept]; - if (![[client readLine] isEqual: @"GET /foo HTTP/1.0"]) + if (![[client readLine] isEqual: @"GET /foo HTTP/1.1"]) assert(0); if (![[client readLine] isEqual: [OFString stringWithFormat: @"Host: 127.0.0.1:%" @PRIu16, port]]) assert(0); + + if (![[client readLine] isEqual: @"Connection: close"]) + assert(0); if (![[client readLine] hasPrefix: @"User-Agent:"]) assert(0); if (![[client readLine] isEqual: @""]) assert(0); - [client writeString: @"HTTP/1.0 200 OK\r\n" + [client writeString: @"HTTP/1.1 200 OK\r\n" @"cONTeNT-lENgTH: 7\r\n" @"\r\n" @"foo\n" @"bar"]; [client close]; Index: tests/OFObjectTests.m ================================================================== --- tests/OFObjectTests.m +++ tests/OFObjectTests.m @@ -38,49 +38,49 @@ OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; OFObject *obj = [[[OFObject alloc] init] autorelease]; void *p, *q, *r; OFObject *o; MyObj *m; - - EXPECT_EXCEPTION(@"Detect freeing of memory not allocated by object", - OFMemoryNotPartOfObjectException, [obj freeMemory: (void*)1]) + char *tmp; TEST(@"Allocating 4096 bytes", (p = [obj allocMemoryWithSize: 4096]) != NULL) TEST(@"Freeing memory", R([obj freeMemory: p])) - EXPECT_EXCEPTION(@"Detect freeing of memory twice", - OFMemoryNotPartOfObjectException, [obj freeMemory: p]) - TEST(@"Allocating and freeing 4096 bytes 3 times", (p = [obj allocMemoryWithSize: 4096]) != NULL && (q = [obj allocMemoryWithSize: 4096]) != NULL && (r = [obj allocMemoryWithSize: 4096]) != NULL && R([obj freeMemory: p]) && R([obj freeMemory: q]) && R([obj freeMemory: r])) + tmp = [self allocMemoryWithSize: 1024]; + EXPECT_EXCEPTION(@"Detect freeing of memory not allocated by object", + OFMemoryNotPartOfObjectException, [obj freeMemory: tmp]) + EXPECT_EXCEPTION(@"Detect out of memory on alloc", - OFOutOfMemoryException, [obj allocMemoryWithSize: SIZE_MAX]) + OFOutOfMemoryException, [obj allocMemoryWithSize: SIZE_MAX - 128]) EXPECT_EXCEPTION(@"Detect out of memory on resize", OFOutOfMemoryException, { p = [obj allocMemoryWithSize: 1]; [obj resizeMemory: p - toSize: SIZE_MAX]; + toSize: SIZE_MAX - 128]; }) [obj freeMemory: p]; TEST(@"Allocate when trying to resize NULL", (p = [obj resizeMemory: NULL toSize: 1024]) != NULL) [obj freeMemory: p]; EXPECT_EXCEPTION(@"Detect resizing of memory not allocated by object", - OFMemoryNotPartOfObjectException, [obj resizeMemory: (void*)1 - toSize: 1024]) + OFMemoryNotPartOfObjectException, [obj resizeMemory: tmp + toSize: 2048]) + [self freeMemory: tmp]; TEST(@"+[description]", [[OFObject description] isEqual: @"OFObject"] && [[MyObj description] isEqual: @"MyObj"]) Index: tests/OFStringTests.m ================================================================== --- tests/OFStringTests.m +++ tests/OFStringTests.m @@ -247,17 +247,27 @@ ![@"foobar" hasSuffix: @"foobar0"]) i = 0; TEST(@"-[componentsSeparatedByString:]", (a = [@"fooXXbarXXXXbazXXXX" componentsSeparatedByString: @"XX"]) && + [a count] == 6 && [[a objectAtIndex: i++] isEqual: @"foo"] && [[a objectAtIndex: i++] isEqual: @"bar"] && [[a objectAtIndex: i++] isEqual: @""] && [[a objectAtIndex: i++] isEqual: @"baz"] && [[a objectAtIndex: i++] isEqual: @""] && [[a objectAtIndex: i++] isEqual: @""]) + i = 0; + TEST(@"-[componentsSeparatedByString:skipEmpty:]", + (a = [@"fooXXbarXXXXbazXXXX" componentsSeparatedByString: @"XX" + skipEmpty: YES]) && + [a count] == 3 && + [[a objectAtIndex: i++] isEqual: @"foo"] && + [[a objectAtIndex: i++] isEqual: @"bar"] && + [[a objectAtIndex: i++] isEqual: @"baz"]) + TEST(@"+[stringWithPath:]", (s[0] = [OFString stringWithPath: @"foo", @"bar", @"baz", nil]) && #ifndef _WIN32 [s[0] isEqual: @"foo/bar/baz"] && #else Index: tests/plugin/TestPlugin.m ================================================================== --- tests/plugin/TestPlugin.m +++ tests/plugin/TestPlugin.m @@ -24,9 +24,9 @@ return num * 2; } @end id -init_plugin() +init_plugin(void) { return [[[TestPlugin alloc] init] autorelease]; } Index: utils/objfw-compile ================================================================== --- utils/objfw-compile +++ utils/objfw-compile @@ -84,11 +84,11 @@ exit 1 fi shift - if ! echo "$1" | grep "^[0-9]\+\.[0-9]\+" >/dev/null + if ! echo "$1" | grep "^[0-9]\+\.[0-9]\+$" >/dev/null then echo "$1 is not a valid library version!" exit 1 fi Index: utils/objfw-config.in ================================================================== --- utils/objfw-config.in +++ utils/objfw-config.in @@ -35,11 +35,11 @@ LIBS="-L${libdir} -lobjfw @LIBS@" PLUGIN_CFLAGS="@PLUGIN_CFLAGS@" PLUGIN_LDFLAGS="@PLUGIN_LDFLAGS@" PLUGIN_SUFFIX="@PLUGIN_SUFFIX@" PROG_SUFFIX="@EXEEXT@" -VERSION="0.6-dev" +VERSION="@PACKAGE_VERSION@" show_help() { cat <<__EOF__ objfw-config: Available arguments are: