ObjFW  Check-in [06bcb21fc7]

Overview
Comment:Add OFLocalization

This singleton gives access to all things locale, including the ability
to get localized strings.

This also adds the OF_LOCALIZED() macro. Its first argument is an ID for
the string to be localized and its second argument is the fallback
string to be used if it cannot retrieve the localized string. Following
that are variable name / value pairs to be replaced in the localized
string.

Getting translated strings is not implemented yet: Instead, it always
uses the fallback string.

This also switches ofhttp to localized strings.

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 06bcb21fc76b4915588681cef8a6e5f455f78562f938bc3532e34fca30a00cbc
User & Date: js on 2017-01-09 06:26:04
Other Links: manifest | tags
Context
2017-01-09
17:36
Update copyright check-in: 44f45c2e35 user: js tags: trunk
06:26
Add OFLocalization check-in: 06bcb21fc7 user: js tags: trunk
2017-01-08
20:14
Clean up the dllexport mess a little check-in: f57765b5c6 user: js tags: trunk
Changes

Modified ObjFW.xcodeproj/project.pbxproj from [33b1d62e30] to [368861be8c].

675
676
677
678
679
680
681




682
683
684
685
686
687
688
		4B3ED7C31AF62C30004C8FF1 /* OFGetOptionFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B3ED7C11AF62C30004C8FF1 /* OFGetOptionFailedException.m */; };
		4B40EC1B189FE2650031E19E /* socket.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B40EC1A189FE2650031E19E /* socket.m */; };
		4B44836D1D0497DE005D12A7 /* OFUndefinedKeyException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B44836B1D0497DE005D12A7 /* OFUndefinedKeyException.h */; settings = {ATTRIBUTES = (Public, ); }; };
		4B44836E1D0497DE005D12A7 /* OFUndefinedKeyException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B44836C1D0497DE005D12A7 /* OFUndefinedKeyException.m */; };
		4B4483711D04989C005D12A7 /* RuntimeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B44836F1D049887005D12A7 /* RuntimeTests.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 */; 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, ); }; };
		4B49EA70143B3A090005BBC6 /* OFXMLCharacters.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B49EA6A143B3A090005BBC6 /* OFXMLCharacters.m */; };







>
>
>
>







675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
		4B3ED7C31AF62C30004C8FF1 /* OFGetOptionFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B3ED7C11AF62C30004C8FF1 /* OFGetOptionFailedException.m */; };
		4B40EC1B189FE2650031E19E /* socket.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B40EC1A189FE2650031E19E /* socket.m */; };
		4B44836D1D0497DE005D12A7 /* OFUndefinedKeyException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B44836B1D0497DE005D12A7 /* OFUndefinedKeyException.h */; settings = {ATTRIBUTES = (Public, ); }; };
		4B44836E1D0497DE005D12A7 /* OFUndefinedKeyException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B44836C1D0497DE005D12A7 /* OFUndefinedKeyException.m */; };
		4B4483711D04989C005D12A7 /* RuntimeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B44836F1D049887005D12A7 /* RuntimeTests.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 */; };
		4B46E2211E235EA700121ED6 /* OFLocalization.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B46E21F1E235EA700121ED6 /* OFLocalization.h */; settings = {ATTRIBUTES = (Public, ); }; };
		4B46E2221E235EA700121ED6 /* OFLocalization.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B46E21F1E235EA700121ED6 /* OFLocalization.h */; settings = {ATTRIBUTES = (Public, ); }; };
		4B46E2231E235EA700121ED6 /* OFLocalization.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B46E2201E235EA700121ED6 /* OFLocalization.m */; };
		4B46E2241E235EA700121ED6 /* OFLocalization.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B46E2201E235EA700121ED6 /* OFLocalization.m */; };
		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, ); }; };
		4B49EA70143B3A090005BBC6 /* OFXMLCharacters.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B49EA6A143B3A090005BBC6 /* OFXMLCharacters.m */; };
1248
1249
1250
1251
1252
1253
1254


1255
1256
1257
1258
1259
1260
1261
		4B3ED7C11AF62C30004C8FF1 /* OFGetOptionFailedException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFGetOptionFailedException.m; path = src/exceptions/OFGetOptionFailedException.m; sourceTree = "<group>"; };
		4B40EC1A189FE2650031E19E /* socket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = socket.m; path = src/socket.m; sourceTree = "<group>"; };
		4B44836B1D0497DE005D12A7 /* OFUndefinedKeyException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFUndefinedKeyException.h; path = src/exceptions/OFUndefinedKeyException.h; sourceTree = "<group>"; };
		4B44836C1D0497DE005D12A7 /* OFUndefinedKeyException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFUndefinedKeyException.m; path = src/exceptions/OFUndefinedKeyException.m; sourceTree = "<group>"; };
		4B44836F1D049887005D12A7 /* RuntimeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RuntimeTests.m; path = tests/RuntimeTests.m; sourceTree = "<group>"; };
		4B45355113DCFE1E0037AB4D /* OFCountedSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFCountedSet.h; path = src/OFCountedSet.h; sourceTree = "<group>"; };
		4B45355213DCFE1E0037AB4D /* OFCountedSet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFCountedSet.m; path = src/OFCountedSet.m; sourceTree = "<group>"; };


		4B48B95214DC23B100546D39 /* OFXMLProcessingInstructions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFXMLProcessingInstructions.h; path = src/OFXMLProcessingInstructions.h; sourceTree = "<group>"; };
		4B48B95314DC23B100546D39 /* OFXMLProcessingInstructions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFXMLProcessingInstructions.m; path = src/OFXMLProcessingInstructions.m; sourceTree = "<group>"; };
		4B49EA65143B39CE0005BBC6 /* OFXMLNodeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFXMLNodeTests.m; path = tests/OFXMLNodeTests.m; sourceTree = "<group>"; };
		4B49EA67143B3A090005BBC6 /* OFXMLCDATA.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFXMLCDATA.h; path = src/OFXMLCDATA.h; sourceTree = "<group>"; };
		4B49EA68143B3A090005BBC6 /* OFXMLCDATA.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFXMLCDATA.m; path = src/OFXMLCDATA.m; sourceTree = "<group>"; };
		4B49EA69143B3A090005BBC6 /* OFXMLCharacters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFXMLCharacters.h; path = src/OFXMLCharacters.h; sourceTree = "<group>"; };
		4B49EA6A143B3A090005BBC6 /* OFXMLCharacters.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFXMLCharacters.m; path = src/OFXMLCharacters.m; sourceTree = "<group>"; };







>
>







1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
		4B3ED7C11AF62C30004C8FF1 /* OFGetOptionFailedException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFGetOptionFailedException.m; path = src/exceptions/OFGetOptionFailedException.m; sourceTree = "<group>"; };
		4B40EC1A189FE2650031E19E /* socket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = socket.m; path = src/socket.m; sourceTree = "<group>"; };
		4B44836B1D0497DE005D12A7 /* OFUndefinedKeyException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFUndefinedKeyException.h; path = src/exceptions/OFUndefinedKeyException.h; sourceTree = "<group>"; };
		4B44836C1D0497DE005D12A7 /* OFUndefinedKeyException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFUndefinedKeyException.m; path = src/exceptions/OFUndefinedKeyException.m; sourceTree = "<group>"; };
		4B44836F1D049887005D12A7 /* RuntimeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RuntimeTests.m; path = tests/RuntimeTests.m; sourceTree = "<group>"; };
		4B45355113DCFE1E0037AB4D /* OFCountedSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFCountedSet.h; path = src/OFCountedSet.h; sourceTree = "<group>"; };
		4B45355213DCFE1E0037AB4D /* OFCountedSet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFCountedSet.m; path = src/OFCountedSet.m; sourceTree = "<group>"; };
		4B46E21F1E235EA700121ED6 /* OFLocalization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFLocalization.h; path = src/OFLocalization.h; sourceTree = "<group>"; };
		4B46E2201E235EA700121ED6 /* OFLocalization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFLocalization.m; path = src/OFLocalization.m; sourceTree = "<group>"; };
		4B48B95214DC23B100546D39 /* OFXMLProcessingInstructions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFXMLProcessingInstructions.h; path = src/OFXMLProcessingInstructions.h; sourceTree = "<group>"; };
		4B48B95314DC23B100546D39 /* OFXMLProcessingInstructions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFXMLProcessingInstructions.m; path = src/OFXMLProcessingInstructions.m; sourceTree = "<group>"; };
		4B49EA65143B39CE0005BBC6 /* OFXMLNodeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFXMLNodeTests.m; path = tests/OFXMLNodeTests.m; sourceTree = "<group>"; };
		4B49EA67143B3A090005BBC6 /* OFXMLCDATA.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFXMLCDATA.h; path = src/OFXMLCDATA.h; sourceTree = "<group>"; };
		4B49EA68143B3A090005BBC6 /* OFXMLCDATA.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFXMLCDATA.m; path = src/OFXMLCDATA.m; sourceTree = "<group>"; };
		4B49EA69143B3A090005BBC6 /* OFXMLCharacters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFXMLCharacters.h; path = src/OFXMLCharacters.h; sourceTree = "<group>"; };
		4B49EA6A143B3A090005BBC6 /* OFXMLCharacters.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFXMLCharacters.m; path = src/OFXMLCharacters.m; sourceTree = "<group>"; };
1971
1972
1973
1974
1975
1976
1977


1978
1979
1980
1981
1982
1983
1984
				4B0EA9161898690E00F573A4 /* OFKernelEventObserver_select.h */,
				4B0EA9171898690E00F573A4 /* OFKernelEventObserver_select.m */,
				4BC176231D04963000C32718 /* OFKeyValueCoding.h */,
				4BC176241D04963000C32718 /* OFObject+KeyValueCoding.h */,
				4BC176251D04963000C32718 /* OFObject+KeyValueCoding.m */,
				4B67996C1099E7C50041064A /* OFList.h */,
				4B67996D1099E7C50041064A /* OFList.m */,


				4B6743F9163C395900EB1E59 /* OFLocking.h */,
				4B3B0796166978780044E634 /* OFMapTable.h */,
				4B3B0797166978780044E634 /* OFMapTable.m */,
				4BC1C3EA184B5EB200BBF50F /* OFMapTable+Private.h */,
				4BF1BCC211C9663F0025511F /* OFMD5Hash.h */,
				4BF1BCC311C9663F0025511F /* OFMD5Hash.m */,
				4BCAA9AD1772432E003EF859 /* OFMessagePackExtension.h */,







>
>







1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
				4B0EA9161898690E00F573A4 /* OFKernelEventObserver_select.h */,
				4B0EA9171898690E00F573A4 /* OFKernelEventObserver_select.m */,
				4BC176231D04963000C32718 /* OFKeyValueCoding.h */,
				4BC176241D04963000C32718 /* OFObject+KeyValueCoding.h */,
				4BC176251D04963000C32718 /* OFObject+KeyValueCoding.m */,
				4B67996C1099E7C50041064A /* OFList.h */,
				4B67996D1099E7C50041064A /* OFList.m */,
				4B46E21F1E235EA700121ED6 /* OFLocalization.h */,
				4B46E2201E235EA700121ED6 /* OFLocalization.m */,
				4B6743F9163C395900EB1E59 /* OFLocking.h */,
				4B3B0796166978780044E634 /* OFMapTable.h */,
				4B3B0797166978780044E634 /* OFMapTable.m */,
				4BC1C3EA184B5EB200BBF50F /* OFMapTable+Private.h */,
				4BF1BCC211C9663F0025511F /* OFMD5Hash.h */,
				4BF1BCC311C9663F0025511F /* OFMD5Hash.m */,
				4BCAA9AD1772432E003EF859 /* OFMessagePackExtension.h */,
2341
2342
2343
2344
2345
2346
2347

2348
2349
2350
2351
2352
2353
2354
				4B2C21F41DA292BE00735907 /* OFINICategory.h in Headers */,
				4B2C21F51DA292BE00735907 /* OFINIFile.h in Headers */,
				4B2C21F61DA292BE00735907 /* OFIntrospection.h in Headers */,
				4B2C21F71DA292BE00735907 /* OFJSONRepresentation.h in Headers */,
				4B2C21F81DA292BE00735907 /* OFKernelEventObserver.h in Headers */,
				4B2C21F91DA292BE00735907 /* OFKeyValueCoding.h in Headers */,
				4B2C21FA1DA292BE00735907 /* OFList.h in Headers */,

				4B2C21FB1DA292BE00735907 /* OFLocking.h in Headers */,
				4B2C21FC1DA292BE00735907 /* OFMapTable.h in Headers */,
				4B2C21FD1DA292BE00735907 /* OFMD5Hash.h in Headers */,
				4B2C21FE1DA292BE00735907 /* OFMessagePackExtension.h in Headers */,
				4B2C21FF1DA292BE00735907 /* OFMessagePackRepresentation.h in Headers */,
				4B2C22001DA292BE00735907 /* OFMutableArray.h in Headers */,
				4B2C22011DA292BE00735907 /* OFMutableDictionary.h in Headers */,







>







2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
				4B2C21F41DA292BE00735907 /* OFINICategory.h in Headers */,
				4B2C21F51DA292BE00735907 /* OFINIFile.h in Headers */,
				4B2C21F61DA292BE00735907 /* OFIntrospection.h in Headers */,
				4B2C21F71DA292BE00735907 /* OFJSONRepresentation.h in Headers */,
				4B2C21F81DA292BE00735907 /* OFKernelEventObserver.h in Headers */,
				4B2C21F91DA292BE00735907 /* OFKeyValueCoding.h in Headers */,
				4B2C21FA1DA292BE00735907 /* OFList.h in Headers */,
				4B46E2221E235EA700121ED6 /* OFLocalization.h in Headers */,
				4B2C21FB1DA292BE00735907 /* OFLocking.h in Headers */,
				4B2C21FC1DA292BE00735907 /* OFMapTable.h in Headers */,
				4B2C21FD1DA292BE00735907 /* OFMD5Hash.h in Headers */,
				4B2C21FE1DA292BE00735907 /* OFMessagePackExtension.h in Headers */,
				4B2C21FF1DA292BE00735907 /* OFMessagePackRepresentation.h in Headers */,
				4B2C22001DA292BE00735907 /* OFMutableArray.h in Headers */,
				4B2C22011DA292BE00735907 /* OFMutableDictionary.h in Headers */,
2558
2559
2560
2561
2562
2563
2564

2565
2566
2567
2568
2569
2570
2571
				4B06855318B2AD3800FC731A /* OFINICategory.h in Headers */,
				4B5B02BE18B288A400CE6AE4 /* OFINIFile.h in Headers */,
				4BA49D9013DB113B00381CDB /* OFIntrospection.h in Headers */,
				4BA02BA115041F5900002F84 /* OFJSONRepresentation.h in Headers */,
				4B0EA9211898690E00F573A4 /* OFKernelEventObserver.h in Headers */,
				4BC1762F1D04963000C32718 /* OFKeyValueCoding.h in Headers */,
				4B3D23CB1337FCB000DD29B8 /* OFList.h in Headers */,

				4B674402163C395900EB1E59 /* OFLocking.h in Headers */,
				4B3B0798166978780044E634 /* OFMapTable.h in Headers */,
				4B3D23CC1337FCB000DD29B8 /* OFMD5Hash.h in Headers */,
				4BCAA9AF1772432F003EF859 /* OFMessagePackExtension.h in Headers */,
				4B879A8E177231F000EBCEA4 /* OFMessagePackRepresentation.h in Headers */,
				4B3D23CD1337FCB000DD29B8 /* OFMutableArray.h in Headers */,
				4B3D23CE1337FCB000DD29B8 /* OFMutableDictionary.h in Headers */,







>







2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
				4B06855318B2AD3800FC731A /* OFINICategory.h in Headers */,
				4B5B02BE18B288A400CE6AE4 /* OFINIFile.h in Headers */,
				4BA49D9013DB113B00381CDB /* OFIntrospection.h in Headers */,
				4BA02BA115041F5900002F84 /* OFJSONRepresentation.h in Headers */,
				4B0EA9211898690E00F573A4 /* OFKernelEventObserver.h in Headers */,
				4BC1762F1D04963000C32718 /* OFKeyValueCoding.h in Headers */,
				4B3D23CB1337FCB000DD29B8 /* OFList.h in Headers */,
				4B46E2211E235EA700121ED6 /* OFLocalization.h in Headers */,
				4B674402163C395900EB1E59 /* OFLocking.h in Headers */,
				4B3B0798166978780044E634 /* OFMapTable.h in Headers */,
				4B3D23CC1337FCB000DD29B8 /* OFMD5Hash.h in Headers */,
				4BCAA9AF1772432F003EF859 /* OFMessagePackExtension.h in Headers */,
				4B879A8E177231F000EBCEA4 /* OFMessagePackRepresentation.h in Headers */,
				4B3D23CD1337FCB000DD29B8 /* OFMutableArray.h in Headers */,
				4B3D23CE1337FCB000DD29B8 /* OFMutableDictionary.h in Headers */,
3095
3096
3097
3098
3099
3100
3101

3102
3103
3104
3105
3106
3107
3108
				4B2C213E1DA292BE00735907 /* OFIntrospection.m in Sources */,
				4B2C213F1DA292BE00735907 /* OFGZIPStream.m in Sources */,
				4B2C21401DA292BE00735907 /* OFKernelEventObserver.m in Sources */,
				4B2C21411DA292BE00735907 /* OFKernelEventObserver_kqueue.m in Sources */,
				4B2C21421DA292BE00735907 /* OFKernelEventObserver_poll.m in Sources */,
				4B2C21431DA292BE00735907 /* OFKernelEventObserver_select.m in Sources */,
				4B2C21441DA292BE00735907 /* OFList.m in Sources */,

				4B2C21451DA292BE00735907 /* OFMapTable.m in Sources */,
				4B2C21461DA292BE00735907 /* OFMD5Hash.m in Sources */,
				4B2C21471DA292BE00735907 /* OFMessagePackExtension.m in Sources */,
				4B2C21481DA292BE00735907 /* OFMutableArray.m in Sources */,
				4B2C21491DA292BE00735907 /* OFMutableArray_adjacent.m in Sources */,
				4B2C214A1DA292BE00735907 /* OFMutableDictionary.m in Sources */,
				4B2C214B1DA292BE00735907 /* OFMutableDictionary_hashtable.m in Sources */,







>







3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
				4B2C213E1DA292BE00735907 /* OFIntrospection.m in Sources */,
				4B2C213F1DA292BE00735907 /* OFGZIPStream.m in Sources */,
				4B2C21401DA292BE00735907 /* OFKernelEventObserver.m in Sources */,
				4B2C21411DA292BE00735907 /* OFKernelEventObserver_kqueue.m in Sources */,
				4B2C21421DA292BE00735907 /* OFKernelEventObserver_poll.m in Sources */,
				4B2C21431DA292BE00735907 /* OFKernelEventObserver_select.m in Sources */,
				4B2C21441DA292BE00735907 /* OFList.m in Sources */,
				4B46E2241E235EA700121ED6 /* OFLocalization.m in Sources */,
				4B2C21451DA292BE00735907 /* OFMapTable.m in Sources */,
				4B2C21461DA292BE00735907 /* OFMD5Hash.m in Sources */,
				4B2C21471DA292BE00735907 /* OFMessagePackExtension.m in Sources */,
				4B2C21481DA292BE00735907 /* OFMutableArray.m in Sources */,
				4B2C21491DA292BE00735907 /* OFMutableArray_adjacent.m in Sources */,
				4B2C214A1DA292BE00735907 /* OFMutableDictionary.m in Sources */,
				4B2C214B1DA292BE00735907 /* OFMutableDictionary_hashtable.m in Sources */,
3282
3283
3284
3285
3286
3287
3288

3289
3290
3291
3292
3293
3294
3295
				4BA49D9113DB113B00381CDB /* OFIntrospection.m in Sources */,
				4BD112611CCB73A60076FDB9 /* OFGZIPStream.m in Sources */,
				4B0EA9221898690E00F573A4 /* OFKernelEventObserver.m in Sources */,
				4B0EA91C1898690E00F573A4 /* OFKernelEventObserver_kqueue.m in Sources */,
				4B0EA91E1898690E00F573A4 /* OFKernelEventObserver_poll.m in Sources */,
				4B0EA9201898690E00F573A4 /* OFKernelEventObserver_select.m in Sources */,
				4B3D23991337FC0D00DD29B8 /* OFList.m in Sources */,

				4B3B0799166978780044E634 /* OFMapTable.m in Sources */,
				4B3D239A1337FC0D00DD29B8 /* OFMD5Hash.m in Sources */,
				4BCAA9B01772432F003EF859 /* OFMessagePackExtension.m in Sources */,
				4B3D239B1337FC0D00DD29B8 /* OFMutableArray.m in Sources */,
				4B2B3E82140D430500EC2F7C /* OFMutableArray_adjacent.m in Sources */,
				4B3D239C1337FC0D00DD29B8 /* OFMutableDictionary.m in Sources */,
				4B2B3E84140D430500EC2F7C /* OFMutableDictionary_hashtable.m in Sources */,







>







3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
				4BA49D9113DB113B00381CDB /* OFIntrospection.m in Sources */,
				4BD112611CCB73A60076FDB9 /* OFGZIPStream.m in Sources */,
				4B0EA9221898690E00F573A4 /* OFKernelEventObserver.m in Sources */,
				4B0EA91C1898690E00F573A4 /* OFKernelEventObserver_kqueue.m in Sources */,
				4B0EA91E1898690E00F573A4 /* OFKernelEventObserver_poll.m in Sources */,
				4B0EA9201898690E00F573A4 /* OFKernelEventObserver_select.m in Sources */,
				4B3D23991337FC0D00DD29B8 /* OFList.m in Sources */,
				4B46E2231E235EA700121ED6 /* OFLocalization.m in Sources */,
				4B3B0799166978780044E634 /* OFMapTable.m in Sources */,
				4B3D239A1337FC0D00DD29B8 /* OFMD5Hash.m in Sources */,
				4BCAA9B01772432F003EF859 /* OFMessagePackExtension.m in Sources */,
				4B3D239B1337FC0D00DD29B8 /* OFMutableArray.m in Sources */,
				4B2B3E82140D430500EC2F7C /* OFMutableArray_adjacent.m in Sources */,
				4B3D239C1337FC0D00DD29B8 /* OFMutableDictionary.m in Sources */,
				4B2B3E84140D430500EC2F7C /* OFMutableDictionary_hashtable.m in Sources */,

Modified src/Makefile from [dc8c07a997] to [143a1e3a3b].

24
25
26
27
28
29
30

31
32
33
34
35
36
37
       OFDeflate64Stream.m		\
       OFDictionary.m			\
       OFEnumerator.m			\
       OFGZIPStream.m			\
       OFHMAC.m				\
       OFIntrospection.m		\
       OFList.m				\

       OFMapTable.m			\
       OFMD5Hash.m			\
       OFMessagePackExtension.m		\
       OFMutableArray.m			\
       OFMutableDictionary.m		\
       OFMutableSet.m			\
       OFMutableString.m		\







>







24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
       OFDeflate64Stream.m		\
       OFDictionary.m			\
       OFEnumerator.m			\
       OFGZIPStream.m			\
       OFHMAC.m				\
       OFIntrospection.m		\
       OFList.m				\
       OFLocalization.m			\
       OFMapTable.m			\
       OFMD5Hash.m			\
       OFMessagePackExtension.m		\
       OFMutableArray.m			\
       OFMutableDictionary.m		\
       OFMutableSet.m			\
       OFMutableString.m		\

Modified src/OFApplication.m from [4b696ca492] to [514600c380].

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

#include "config.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef HAVE_LANGINFO_H
# include <langinfo.h>
#endif
#include <locale.h>
#include <signal.h>

#import "OFApplication.h"
#import "OFString.h"
#import "OFArray.h"
#import "OFDictionary.h"
#import "OFSystemInfo.h"
#import "OFRunLoop.h"
#import "OFRunLoop+Private.h"
#import "OFThread.h"
#import "OFThread+Private.h"

#import "OFOutOfMemoryException.h"
#import "OFOutOfRangeException.h"







<
<
<







|







16
17
18
19
20
21
22



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

#include "config.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>




#include <locale.h>
#include <signal.h>

#import "OFApplication.h"
#import "OFString.h"
#import "OFArray.h"
#import "OFDictionary.h"
#import "OFLocalization.h"
#import "OFRunLoop.h"
#import "OFRunLoop+Private.h"
#import "OFThread.h"
#import "OFThread+Private.h"

#import "OFOutOfMemoryException.h"
#import "OFOutOfRangeException.h"
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
- (void)OF_setArgumentCount: (int)argc
      andWideArgumentValues: (wchar_t*[])argv;
#endif
- (void)OF_run;
@end

static OFApplication *app = nil;
extern void of_system_info_parse_locale(char*);

static void
atexitHandler(void)
{
	id <OFApplicationDelegate> delegate = [app delegate];

	if ([delegate respondsToSelector: @selector(applicationWillTerminate)])







<







65
66
67
68
69
70
71

72
73
74
75
76
77
78
- (void)OF_setArgumentCount: (int)argc
      andWideArgumentValues: (wchar_t*[])argv;
#endif
- (void)OF_run;
@end

static OFApplication *app = nil;


static void
atexitHandler(void)
{
	id <OFApplicationDelegate> delegate = [app delegate];

	if ([delegate respondsToSelector: @selector(applicationWillTerminate)])
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
{
	id <OFApplicationDelegate> delegate;
#ifdef OF_WINDOWS
	wchar_t **wargv, **wenvp;
	int wargc, si = 0;
#endif

	of_system_info_parse_locale(setlocale(LC_ALL, ""));

	if ([cls isSubclassOfClass: [OFApplication class]]) {
		fprintf(stderr, "FATAL ERROR:\n  Class %s is a subclass of "
		    "class OFApplication, but class\n  %s was specified as "
		    "application delegate!\n  Most likely, you wanted to "
		    "subclass OFObject instead or specified\n  the wrong class "
		    "with OF_APPLICATION_DELEGATE().\n",







|







101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
{
	id <OFApplicationDelegate> delegate;
#ifdef OF_WINDOWS
	wchar_t **wargv, **wenvp;
	int wargc, si = 0;
#endif

	[[OFLocalization alloc] initWithLocale: setlocale(LC_ALL, "")];

	if ([cls isSubclassOfClass: [OFApplication class]]) {
		fprintf(stderr, "FATAL ERROR:\n  Class %s is a subclass of "
		    "class OFApplication, but class\n  %s was specified as "
		    "application delegate!\n  Most likely, you wanted to "
		    "subclass OFObject instead or specified\n  the wrong class "
		    "with OF_APPLICATION_DELEGATE().\n",
244
245
246
247
248
249
250



251
252
253
254
255
256
257
258
259
260
261
262

			objc_autoreleasePoolPop(pool);
		}

		FreeEnvironmentStringsW(env0);
#elif !defined(OF_IOS)
		if (env != NULL) {



			for (; *env != NULL; env++) {
				OFString *key, *value;
				char *sep;
				const of_string_encoding_t encoding =
				    [OFSystemInfo native8BitEncoding];

				pool = objc_autoreleasePoolPush();

				if ((sep = strchr(*env, '=')) == NULL) {
					fprintf(stderr, "Warning: Invalid "
					    "environment variable: %s\n", *env);
					continue;







>
>
>



<
<







240
241
242
243
244
245
246
247
248
249
250
251
252


253
254
255
256
257
258
259

			objc_autoreleasePoolPop(pool);
		}

		FreeEnvironmentStringsW(env0);
#elif !defined(OF_IOS)
		if (env != NULL) {
			const of_string_encoding_t encoding =
			    [OFLocalization encoding];

			for (; *env != NULL; env++) {
				OFString *key, *value;
				char *sep;



				pool = objc_autoreleasePoolPush();

				if ((sep = strchr(*env, '=')) == NULL) {
					fprintf(stderr, "Warning: Invalid "
					    "environment variable: %s\n", *env);
					continue;
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
	void *pool = objc_autoreleasePoolPush();
	OFMutableArray *arguments;
	of_string_encoding_t encoding;

	_argc = argc;
	_argv = argv;

	encoding = [OFSystemInfo native8BitEncoding];

# ifndef OF_NINTENDO_DS
	if (*argc > 0) {
# else
	if (__system_argv->argvMagic == ARGV_MAGIC &&
	    __system_argv->argc > 0) {
# endif







|







346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
	void *pool = objc_autoreleasePoolPush();
	OFMutableArray *arguments;
	of_string_encoding_t encoding;

	_argc = argc;
	_argv = argv;

	encoding = [OFLocalization encoding];

# ifndef OF_NINTENDO_DS
	if (*argc > 0) {
# else
	if (__system_argv->argvMagic == ARGV_MAGIC &&
	    __system_argv->argc > 0) {
# endif

Modified src/OFFile.m from [70abf75d98] to [6d0086e491].

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#ifdef OF_NINTENDO_DS
# include <stdbool.h>
# include <filesystem.h>
#endif

#import "OFFile.h"
#import "OFString.h"
#import "OFSystemInfo.h"

#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFOpenItemFailedException.h"
#import "OFOutOfRangeException.h"
#import "OFReadFailedException.h"
#import "OFSeekFailedException.h"







|







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#ifdef OF_NINTENDO_DS
# include <stdbool.h>
# include <filesystem.h>
#endif

#import "OFFile.h"
#import "OFString.h"
#import "OFLocalization.h"

#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFOpenItemFailedException.h"
#import "OFOutOfRangeException.h"
#import "OFReadFailedException.h"
#import "OFSeekFailedException.h"
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180

		flags |= O_CLOEXEC;

#if defined(OF_WINDOWS)
		if ((_fd = _wopen([path UTF16String], flags,
		    DEFAULT_MODE)) == -1)
#elif defined(OF_HAVE_OFF64_T)
		if ((_fd = open64([path cStringWithEncoding: [OFSystemInfo
		    native8BitEncoding]], flags, DEFAULT_MODE)) == -1)
#else
		if ((_fd = open([path cStringWithEncoding: [OFSystemInfo
		    native8BitEncoding]], flags, DEFAULT_MODE)) == -1)
#endif
			@throw [OFOpenItemFailedException
			    exceptionWithPath: path
					 mode: mode
					errNo: errno];
	} @catch (id e) {
		[self release];







|
|

|
|







162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180

		flags |= O_CLOEXEC;

#if defined(OF_WINDOWS)
		if ((_fd = _wopen([path UTF16String], flags,
		    DEFAULT_MODE)) == -1)
#elif defined(OF_HAVE_OFF64_T)
		if ((_fd = open64([path cStringWithEncoding:
		    [OFLocalization encoding]], flags, DEFAULT_MODE)) == -1)
#else
		if ((_fd = open([path cStringWithEncoding:
		    [OFLocalization encoding]], flags, DEFAULT_MODE)) == -1)
#endif
			@throw [OFOpenItemFailedException
			    exceptionWithPath: path
					 mode: mode
					errNo: errno];
	} @catch (id e) {
		[self release];

Modified src/OFFileManager.m from [bdb65f91bc] to [c2a222bc22].

30
31
32
33
34
35
36

37
38
39
40
41
42
43

#import "OFFileManager.h"
#import "OFFile.h"
#import "OFString.h"
#import "OFArray.h"
#import "OFDate.h"
#import "OFSystemInfo.h"


#ifdef OF_HAVE_THREADS
# import "OFMutex.h"
#endif

#import "OFChangeCurrentDirectoryPathFailedException.h"
#import "OFChangeOwnerFailedException.h"







>







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

#import "OFFileManager.h"
#import "OFFile.h"
#import "OFString.h"
#import "OFArray.h"
#import "OFDate.h"
#import "OFSystemInfo.h"
#import "OFLocalization.h"

#ifdef OF_HAVE_THREADS
# import "OFMutex.h"
#endif

#import "OFChangeCurrentDirectoryPathFailedException.h"
#import "OFChangeOwnerFailedException.h"
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136

int
of_stat(OFString *path, of_stat_t *buffer)
{
#if defined(OF_WINDOWS)
	return _wstat64([path UTF16String], buffer);
#elif defined(OF_HAVE_OFF64_T)
	return stat64([path cStringWithEncoding:
	    [OFSystemInfo native8BitEncoding]], buffer);
#else
	return stat([path cStringWithEncoding:
	    [OFSystemInfo native8BitEncoding]], buffer);
#endif
}

int
of_lstat(OFString *path, of_stat_t *buffer)
{
#if defined(OF_WINDOWS)
	return _wstat64([path UTF16String], buffer);
#elif defined(HAVE_LSTAT)
# ifdef OF_HAVE_OFF64_T
	return lstat64([path cStringWithEncoding:
	    [OFSystemInfo native8BitEncoding]], buffer);
# else
	return lstat([path cStringWithEncoding:
	    [OFSystemInfo native8BitEncoding]], buffer);
# endif
#else
# ifdef OF_HAVE_OFF64_T
	return stat64([path cStringWithEncoding:
	    [OFSystemInfo native8BitEncoding]], buffer);
# else
	return stat([path cStringWithEncoding:
	    [OFSystemInfo native8BitEncoding]], buffer);
# endif
#endif
}

@implementation OFFileManager
+ (void)initialize
{







|
|

|
|










|
|

|
|



|
|

|
|







96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137

int
of_stat(OFString *path, of_stat_t *buffer)
{
#if defined(OF_WINDOWS)
	return _wstat64([path UTF16String], buffer);
#elif defined(OF_HAVE_OFF64_T)
	return stat64([path cStringWithEncoding: [OFLocalization encoding]],
	    buffer);
#else
	return stat([path cStringWithEncoding: [OFLocalization encoding]],
	    buffer);
#endif
}

int
of_lstat(OFString *path, of_stat_t *buffer)
{
#if defined(OF_WINDOWS)
	return _wstat64([path UTF16String], buffer);
#elif defined(HAVE_LSTAT)
# ifdef OF_HAVE_OFF64_T
	return lstat64([path cStringWithEncoding: [OFLocalization encoding]],
	    buffer);
# else
	return lstat([path cStringWithEncoding: [OFLocalization encoding]],
	    buffer);
# endif
#else
# ifdef OF_HAVE_OFF64_T
	return stat64([path cStringWithEncoding: [OFLocalization encoding]],
	    buffer);
# else
	return stat([path cStringWithEncoding: [OFLocalization encoding]],
	    buffer);
# endif
#endif
}

@implementation OFFileManager
+ (void)initialize
{
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
	wchar_t *buffer = _wgetcwd(NULL, 0);
#endif

	@try {
#ifndef OF_WINDOWS
		ret = [OFString
		    stringWithCString: buffer
			     encoding: [OFSystemInfo native8BitEncoding]];
#else
		ret = [OFString stringWithUTF16String: buffer];
#endif
	} @finally {
		free(buffer);
	}








|







179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
	wchar_t *buffer = _wgetcwd(NULL, 0);
#endif

	@try {
#ifndef OF_WINDOWS
		ret = [OFString
		    stringWithCString: buffer
			     encoding: [OFLocalization encoding]];
#else
		ret = [OFString stringWithUTF16String: buffer];
#endif
	} @finally {
		free(buffer);
	}

259
260
261
262
263
264
265
266
267
268
269
270
271
272
273

- (void)createDirectoryAtPath: (OFString*)path
{
	if (path == nil)
		@throw [OFInvalidArgumentException exception];

#ifndef OF_WINDOWS
	if (mkdir([path cStringWithEncoding: [OFSystemInfo native8BitEncoding]],
	    DIR_MODE) != 0)
#else
	if (_wmkdir([path UTF16String]) != 0)
#endif
		@throw [OFCreateDirectoryFailedException
		    exceptionWithPath: path
				errNo: errno];







|







260
261
262
263
264
265
266
267
268
269
270
271
272
273
274

- (void)createDirectoryAtPath: (OFString*)path
{
	if (path == nil)
		@throw [OFInvalidArgumentException exception];

#ifndef OF_WINDOWS
	if (mkdir([path cStringWithEncoding: [OFLocalization encoding]],
	    DIR_MODE) != 0)
#else
	if (_wmkdir([path UTF16String]) != 0)
#endif
		@throw [OFCreateDirectoryFailedException
		    exceptionWithPath: path
				errNo: errno];
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
		@throw [OFInvalidArgumentException exception];

	files = [OFMutableArray array];

#ifndef OF_WINDOWS
	DIR *dir;

	encoding = [OFSystemInfo native8BitEncoding];

	if ((dir = opendir([path cStringWithEncoding: encoding])) == NULL)
		@throw [OFOpenItemFailedException exceptionWithPath: path
							      errNo: errno];

# if !defined(HAVE_READDIR_R) && defined(OF_HAVE_THREADS)
	[readdirMutex lock];







|







319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
		@throw [OFInvalidArgumentException exception];

	files = [OFMutableArray array];

#ifndef OF_WINDOWS
	DIR *dir;

	encoding = [OFLocalization encoding];

	if ((dir = opendir([path cStringWithEncoding: encoding])) == NULL)
		@throw [OFOpenItemFailedException exceptionWithPath: path
							      errNo: errno];

# if !defined(HAVE_READDIR_R) && defined(OF_HAVE_THREADS)
	[readdirMutex lock];
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444

- (void)changeCurrentDirectoryPath: (OFString*)path
{
	if (path == nil)
		@throw [OFInvalidArgumentException exception];

#ifndef OF_WINDOWS
	if (chdir([path cStringWithEncoding:
	    [OFSystemInfo native8BitEncoding]]) != 0)
#else
	if (_wchdir([path UTF16String]) != 0)
#endif
		@throw [OFChangeCurrentDirectoryPathFailedException
		    exceptionWithPath: path
				errNo: errno];
}







|
<







430
431
432
433
434
435
436
437

438
439
440
441
442
443
444

- (void)changeCurrentDirectoryPath: (OFString*)path
{
	if (path == nil)
		@throw [OFInvalidArgumentException exception];

#ifndef OF_WINDOWS
	if (chdir([path cStringWithEncoding: [OFLocalization encoding]]) != 0)

#else
	if (_wchdir([path UTF16String]) != 0)
#endif
		@throw [OFChangeCurrentDirectoryPathFailedException
		    exceptionWithPath: path
				errNo: errno];
}
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
- (void)changePermissionsOfItemAtPath: (OFString*)path
			  permissions: (mode_t)permissions
{
	if (path == nil)
		@throw [OFInvalidArgumentException exception];

# ifndef OF_WINDOWS
	if (chmod([path cStringWithEncoding: [OFSystemInfo native8BitEncoding]],
	    permissions) != 0)
# else
	if (_wchmod([path UTF16String], permissions) != 0)
# endif
		@throw [OFChangePermissionsFailedException
		    exceptionWithPath: path
			  permissions: permissions







|







520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
- (void)changePermissionsOfItemAtPath: (OFString*)path
			  permissions: (mode_t)permissions
{
	if (path == nil)
		@throw [OFInvalidArgumentException exception];

# ifndef OF_WINDOWS
	if (chmod([path cStringWithEncoding: [OFLocalization encoding]],
	    permissions) != 0)
# else
	if (_wchmod([path UTF16String], permissions) != 0)
# endif
		@throw [OFChangePermissionsFailedException
		    exceptionWithPath: path
			  permissions: permissions
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
		@throw [OFStatItemFailedException exceptionWithPath: path
							      errNo: errno];

# ifdef OF_HAVE_THREADS
	[passwdMutex lock];
	@try {
# endif
		of_string_encoding_t encoding =
		    [OFSystemInfo native8BitEncoding];

		if (owner != NULL) {
			struct passwd *passwd = getpwuid(s.st_uid);

			*owner = [OFString stringWithCString: passwd->pw_name
						    encoding: encoding];
		}







|
<







550
551
552
553
554
555
556
557

558
559
560
561
562
563
564
		@throw [OFStatItemFailedException exceptionWithPath: path
							      errNo: errno];

# ifdef OF_HAVE_THREADS
	[passwdMutex lock];
	@try {
# endif
		of_string_encoding_t encoding = [OFLocalization encoding];


		if (owner != NULL) {
			struct passwd *passwd = getpwuid(s.st_uid);

			*owner = [OFString stringWithCString: passwd->pw_name
						    encoding: encoding];
		}
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
	uid_t uid = -1;
	gid_t gid = -1;
	of_string_encoding_t encoding;

	if (path == nil || (owner == nil && group == nil))
		@throw [OFInvalidArgumentException exception];

	encoding = [OFSystemInfo native8BitEncoding];

# ifdef OF_HAVE_THREADS
	[passwdMutex lock];
	@try {
# endif
		if (owner != nil) {
			struct passwd *passwd;







|







583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
	uid_t uid = -1;
	gid_t gid = -1;
	of_string_encoding_t encoding;

	if (path == nil || (owner == nil && group == nil))
		@throw [OFInvalidArgumentException exception];

	encoding = [OFLocalization encoding];

# ifdef OF_HAVE_THREADS
	[passwdMutex lock];
	@try {
# endif
		if (owner != nil) {
			struct passwd *passwd;
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
	if (of_lstat(destination, &s) == 0)
		@throw [OFCopyItemFailedException
		    exceptionWithSourcePath: source
			    destinationPath: destination
				      errNo: EEXIST];

#ifndef OF_WINDOWS
	encoding = [OFSystemInfo native8BitEncoding];

	if (rename([source cStringWithEncoding: encoding],
	    [destination cStringWithEncoding: encoding]) != 0) {
#else
	if (_wrename([source UTF16String], [destination UTF16String]) != 0) {
#endif
		if (errno != EXDEV)







|







795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
	if (of_lstat(destination, &s) == 0)
		@throw [OFCopyItemFailedException
		    exceptionWithSourcePath: source
			    destinationPath: destination
				      errNo: EEXIST];

#ifndef OF_WINDOWS
	encoding = [OFLocalization encoding];

	if (rename([source cStringWithEncoding: encoding],
	    [destination cStringWithEncoding: encoding]) != 0) {
#else
	if (_wrename([source UTF16String], [destination UTF16String]) != 0) {
#endif
		if (errno != EXDEV)
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
			    [path stringByAppendingPathComponent: item]];

			objc_autoreleasePoolPop(pool2);
		}

#ifndef OF_WINDOWS
		if (rmdir([path cStringWithEncoding:
		    [OFSystemInfo native8BitEncoding]]) != 0)
#else
		if (_wrmdir([path UTF16String]) != 0)
#endif
			@throw [OFRemoveItemFailedException
				exceptionWithPath: path
					    errNo: errno];
	} else {
#ifndef OF_WINDOWS
		if (unlink([path cStringWithEncoding:
		    [OFSystemInfo native8BitEncoding]]) != 0)
#else
		if (_wunlink([path UTF16String]) != 0)
#endif
			@throw [OFRemoveItemFailedException
			    exceptionWithPath: path
					errNo: errno];
	}







|









|







879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
			    [path stringByAppendingPathComponent: item]];

			objc_autoreleasePoolPop(pool2);
		}

#ifndef OF_WINDOWS
		if (rmdir([path cStringWithEncoding:
		    [OFLocalization encoding]]) != 0)
#else
		if (_wrmdir([path UTF16String]) != 0)
#endif
			@throw [OFRemoveItemFailedException
				exceptionWithPath: path
					    errNo: errno];
	} else {
#ifndef OF_WINDOWS
		if (unlink([path cStringWithEncoding:
		    [OFLocalization encoding]]) != 0)
#else
		if (_wunlink([path UTF16String]) != 0)
#endif
			@throw [OFRemoveItemFailedException
			    exceptionWithPath: path
					errNo: errno];
	}
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
	void *pool;
	of_string_encoding_t encoding;

	if (source == nil || destination == nil)
		@throw [OFInvalidArgumentException exception];

	pool = objc_autoreleasePoolPush();
	encoding = [OFSystemInfo native8BitEncoding];

	if (link([source cStringWithEncoding: encoding],
	    [destination cStringWithEncoding: encoding]) != 0)
		@throw [OFLinkFailedException
		    exceptionWithSourcePath: source
			    destinationPath: destination
				      errNo: errno];







|







912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
	void *pool;
	of_string_encoding_t encoding;

	if (source == nil || destination == nil)
		@throw [OFInvalidArgumentException exception];

	pool = objc_autoreleasePoolPush();
	encoding = [OFLocalization encoding];

	if (link([source cStringWithEncoding: encoding],
	    [destination cStringWithEncoding: encoding]) != 0)
		@throw [OFLinkFailedException
		    exceptionWithSourcePath: source
			    destinationPath: destination
				      errNo: errno];
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
	void *pool;
	of_string_encoding_t encoding;

	if (source == nil || destination == nil)
		@throw [OFInvalidArgumentException exception];

	pool = objc_autoreleasePoolPush();
	encoding = [OFSystemInfo native8BitEncoding];

	if (symlink([source cStringWithEncoding: encoding],
	    [destination cStringWithEncoding: encoding]) != 0)
		@throw [OFCreateSymbolicLinkFailedException
		    exceptionWithSourcePath: source
			    destinationPath: destination
				      errNo: errno];







|







955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
	void *pool;
	of_string_encoding_t encoding;

	if (source == nil || destination == nil)
		@throw [OFInvalidArgumentException exception];

	pool = objc_autoreleasePoolPush();
	encoding = [OFLocalization encoding];

	if (symlink([source cStringWithEncoding: encoding],
	    [destination cStringWithEncoding: encoding]) != 0)
		@throw [OFCreateSymbolicLinkFailedException
		    exceptionWithSourcePath: source
			    destinationPath: destination
				      errNo: errno];
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
	char destination[PATH_MAX];
	ssize_t length;
	of_string_encoding_t encoding;

	if (path == nil)
		@throw [OFInvalidArgumentException exception];

	encoding = [OFSystemInfo native8BitEncoding];
	length = readlink([path cStringWithEncoding: encoding],
	    destination, PATH_MAX);

	if (length < 0)
		@throw [OFStatItemFailedException exceptionWithPath: path
							      errNo: errno];








|







1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
	char destination[PATH_MAX];
	ssize_t length;
	of_string_encoding_t encoding;

	if (path == nil)
		@throw [OFInvalidArgumentException exception];

	encoding = [OFLocalization encoding];
	length = readlink([path cStringWithEncoding: encoding],
	    destination, PATH_MAX);

	if (length < 0)
		@throw [OFStatItemFailedException exceptionWithPath: path
							      errNo: errno];

Added src/OFLocalization.h version [1add140a90].





































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/*
 * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016
 *   Jonathan Schleifer <js@heap.zone>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFObject.h"
#import "OFString.h"

OF_ASSUME_NONNULL_BEGIN

/*! @file */

#define OF_LOCALIZED(ID, ...)				\
	[[OFLocalization sharedLocalization]		\
	    localizedStringForID: ID			\
			fallback: __VA_ARGS__, nil]

/*!
 * @class OFLocalization OFLocalization.h ObjFW/OFLocalization.h
 *
 * @brief A class for querying the locale and retrieving localized strings.
 */
@interface OFLocalization: OFObject
{
	OFString *_language;
	OFString *_territory;
	of_string_encoding_t _encoding;
	OFString *_decimalPoint;
}

/**
 * The language of the locale.
 *
 * If the language is unknown, it is `nil`.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy) OFString *language;

/*!
 * The territory of the locale.
 *
 * If the territory is unknown, it is `nil`.
 */
@property OF_NULLABLE_PROPERTY (readonly, copy) OFString *territory;

/*!
 * The native 8-bit string encoding for the locale.
 *
 * This is useful to encode strings correctly for passing them to operating
 * system calls.
 *
 * If the native 8-bit encoding is unknown, UTF-8 is assumed.
 */
@property (readonly) of_string_encoding_t encoding;

/*!
 * The decimal point of the system's locale.
 */
@property (readonly, copy) OFString *decimalPoint;

/*!
 * @brief Returns the shared OFLocalization instance.
 *
 * @warning If you don't use @ref OFApplication, this might be `nil`! In this
 *	    case, you need to manually allocate an instance and call
 *	    @ref initWithLocale: once, passing the locale used (as would be
 *	    returned by `setlocale()`).
 *
 * @return The shared OFLocalization instance
 */
+ (instancetype)sharedLocalization;

/**
 * @brief Returns the language of the locale.
 *
 * If the language is unknown, `nil` is returned.
 *
 * @return The language of the locale.
 */
+ (nullable OFString*)language;

/*!
 * @brief Returns the territory of the locale.
 *
 * If the territory is unknown, `nil` is returned.
 *
 * @return The territory of the locale.
 */
+ (nullable OFString*)territory;

/*!
 * @brief Returns the native 8-bit string encoding for the locale.
 *
 * This is useful to encode strings correctly for passing them to operating
 * system calls.
 *
 * If the native 8-bit encoding is unknown, UTF-8 is assumed.
 *
 * @return The native 8-bit string encoding for the locale
 */
+ (of_string_encoding_t)encoding;

/*!
 * @brief Returns the decimal point of the system's locale.
 *
 * @return The decimal point of the system's locale
 */
+ (OFString*)decimalPoint;

/*!
 * @brief Initializes the OFLocalization singleton with the specified locale.
 *
 * @warning You should never call this yourself, except if you do not use
 *	    @ref OFApplication. In this case, you need to allocate exactly one
 *	    instance of OFLocalization, which will be come the singleton, and
 *	    call this method.
 *
 * @param locale The locale used, as returned from `setlocale()`
 */
- initWithLocale: (char*)locale;

/*!
 * @brief Returns the localized string for the specified ID, using the fallback
 *	  string if it cannot be looked up or is missing.
 *
 * @note This takes a variadic argument, terminated by `nil`, that consists of
 *	 pairs of variable names and variable values, which will be replaced
 *	 inside the localized string. For example, you can pass
 *	 `@"name", @"foo", nil`, causing `%[name]` to be replaced with `foo` in
 *	 the localized string.
 *
 * @note Generally, you want to use @ref OF_LOCALIZED instead, which also takes
 *	 care of the `nil` sentinel automatically.
 *
 * @param ID The ID for the localized string
 * @param fallback The fallback to use in case the localized string cannot be
 *		   looked up or is missing
 * @return The localized string
 */
- (OFString*)localizedStringForID: (OFConstantString*)ID
			 fallback: (OFConstantString*)fallback, ... OF_SENTINEL;
/**
 * @brief Returns the localized string for the specified ID, using the fallback
 *	  string if it cannot be looked up or is missing.
 *
 * @note This takes a variadic argument, terminated by `nil` and passed as
 *	 va_list, that consists of pairs of variable names and variable values,
 *	 which will be replaced inside the localized string. For example, you
 *	 can pass `@"name", @"foo", nil`, causing `%[name]` to be replaced with
 *	 `foo` in the localized string.
 *
 * @note Generally, you want to use @ref OF_LOCALIZED instead, which also takes
 *	 care of the `nil` sentinel automatically.
 *
 * @param ID The ID for the localized string
 * @param fallback The fallback to use in case the localized string cannot be
 *		   looked up or is missing
 * @param arguments A va_list of arguments, consisting of pairs of variable
 *		    names and values to replace in the localized string,
 *		    terminated with `nil`
 * @return The localized string
 */
- (OFString*)localizedStringForID: (OFConstantString*)ID
			 fallback: (OFConstantString*)fallback
			arguments: (va_list)arguments;
@end

OF_ASSUME_NONNULL_END

Added src/OFLocalization.m version [fbc5149bde].











































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
/*
 * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016
 *   Jonathan Schleifer <js@heap.zone>
 *
 * 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"

#include <locale.h>

#import "OFLocalization.h"
#import "OFString.h"

#import "OFInvalidArgumentException.h"

static OFLocalization *sharedLocalization = nil;

@implementation OFLocalization
@synthesize language = _language, territory = _territory, encoding = _encoding;
@synthesize decimalPoint = _decimalPoint;

+ (instancetype)sharedLocalization
{
	return sharedLocalization;
}

+ (OFString*)language
{
	return [sharedLocalization language];
}

+ (OFString*)territory
{
	return [sharedLocalization territory];
}

+ (of_string_encoding_t)encoding
{
	return [sharedLocalization encoding];
}

+ (OFString*)decimalPoint
{
	return [sharedLocalization decimalPoint];
}

- initWithLocale: (char*)locale
{
	self = [super init];

	if (locale == NULL) {
		_encoding = OF_STRING_ENCODING_UTF_8;
		_decimalPoint = @".";
		return self;
	}

	locale = of_strdup(locale);

	@try {
		char *tmp;

		/* We don't care for extras behind the @ */
		if ((tmp = strrchr(locale, '@')) != NULL)
			*tmp = '\0';

		/* Encoding */
		if ((tmp = strrchr(locale, '.')) != NULL) {
			size_t tmpLen;

			*tmp++ = '\0';

			tmpLen = strlen(tmp);
			for (size_t i = 0; i < tmpLen; i++)
				tmp[i] = of_ascii_tolower(tmp[i]);

			if (strcmp(tmp, "utf8") == 0 ||
			    strcmp(tmp, "utf-8") == 0)
				_encoding = OF_STRING_ENCODING_UTF_8;
			else if (strcmp(tmp, "ascii") == 0 ||
			    strcmp(tmp, "us-ascii") == 0)
				_encoding = OF_STRING_ENCODING_ASCII;
			else if (strcmp(tmp, "iso8859-1") == 0 ||
			    strcmp(tmp, "iso-8859-1") == 0)
				_encoding = OF_STRING_ENCODING_ISO_8859_1;
			else if (strcmp(tmp, "iso8859-15") == 0 ||
			    strcmp(tmp, "iso-8859-15") == 0)
				_encoding = OF_STRING_ENCODING_ISO_8859_15;
			/* Windows uses a codepage */
			else if (strcmp(tmp, "1252") == 0)
				_encoding = OF_STRING_ENCODING_WINDOWS_1252;
		}

		/* Territory */
		if ((tmp = strrchr(locale, '_')) != NULL) {
			*tmp++ = '\0';
			_territory = [[OFString alloc]
			    initWithCString: tmp
				   encoding: OF_STRING_ENCODING_ASCII];
		}

		_language = [[OFString alloc]
		    initWithCString: locale
			   encoding: OF_STRING_ENCODING_ASCII];

		_decimalPoint = [[OFString alloc]
		    initWithCString: localeconv()->decimal_point
			   encoding: _encoding];
	} @catch (id e) {
		[self release];
		@throw e;
	} @finally {
		free(locale);
	}

	sharedLocalization = self;

	return self;
}

- (OFString*)localizedStringForID: (OFConstantString*)ID
			 fallback: (OFConstantString*)fallback, ...
{
	OFString *ret;
	va_list args;

	va_start(args, fallback);
	ret = [self localizedStringForID: ID
				fallback: fallback
			       arguments: args];
	va_end(args);

	return ret;
}

- (OFString*)localizedStringForID: (OFConstantString*)ID
			 fallback: (OFConstantString*)fallback
			arguments: (va_list)arguments
{
	OFMutableString *ret = [OFMutableString string];
	void *pool = objc_autoreleasePoolPush();
	const char *UTF8String = [fallback UTF8String];
	size_t UTF8StringLength = [fallback UTF8StringLength];
	size_t last = 0;
	int state = 0;

	for (size_t i = 0; i < UTF8StringLength; i++) {
		switch (state) {
		case 0:
			if (UTF8String[i] == '%') {
				[ret appendUTF8String: UTF8String + last
					       length: i - last];

				last = i + 1;
				state = 1;
			}
			break;
		case 1:
			if (UTF8String[i] == '[') {
				last = i + 1;
				state = 2;
			} else {
				[ret appendString: @"%"];
				state = 0;
			}
			break;
		case 2:
			if (UTF8String[i] == ']') {
				va_list argsCopy;
				OFConstantString *name;

				OFString *var = [OFString
				    stringWithUTF8String: UTF8String + last
						  length: i - last];

				/*
				 * We loop, as most of the time, we only have
				 * one or maybe two variables, meaning looping
				 * is faster than constructing a dictionary.
				 */
				va_copy(argsCopy, arguments);
				while ((name = va_arg(argsCopy,
				    OFConstantString*)) != nil) {
					id value = va_arg(argsCopy, id);

					if (value == nil)
						@throw
						    [OFInvalidArgumentException
						    exception];

					if ([name isEqual: var]) {
						[ret appendString:
						    [value description]];
						break;
					}
				}

				last = i + 1;
				state = 0;
			}
			break;
		}
	}
	switch (state) {
	case 1:
		[ret appendString: @"%"];
		/* Explicit fall-through */
	case 0:
		[ret appendUTF8String: UTF8String + last
			       length: UTF8StringLength - last];
		break;
	}

	objc_autoreleasePoolPop(pool);

	[ret makeImmutable];

	return ret;
}
@end

Modified src/OFObject.m from [f0a708441f] to [f695ac4fbd].

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

#include <assert.h>

#include <sys/time.h>

#import "OFObject.h"
#import "OFArray.h"
#import "OFSystemInfo.h"
#import "OFTimer.h"
#import "OFRunLoop.h"
#import "OFThread.h"

#import "OFAllocFailedException.h"
#import "OFEnumerationMutationException.h"
#import "OFInitializationFailedException.h"







|







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

#include <assert.h>

#include <sys/time.h>

#import "OFObject.h"
#import "OFArray.h"
#import "OFLocalization.h"
#import "OFTimer.h"
#import "OFRunLoop.h"
#import "OFThread.h"

#import "OFAllocFailedException.h"
#import "OFEnumerationMutationException.h"
#import "OFInitializationFailedException.h"
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

#if !defined(OF_APPLE_RUNTIME) || defined(__OBJC2__)
static void
uncaughtExceptionHandler(id exception)
{
	OFString *description = [exception description];
	OFArray *backtrace = nil;
	of_string_encoding_t encoding = [OFSystemInfo native8BitEncoding];

	fprintf(stderr, "\nRuntime error: Unhandled exception:\n%s\n",
	    [description cStringWithEncoding: encoding]);

	if ([exception respondsToSelector: @selector(backtrace)])
		backtrace = [exception backtrace];








|







100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

#if !defined(OF_APPLE_RUNTIME) || defined(__OBJC2__)
static void
uncaughtExceptionHandler(id exception)
{
	OFString *description = [exception description];
	OFArray *backtrace = nil;
	of_string_encoding_t encoding = [OFLocalization encoding];

	fprintf(stderr, "\nRuntime error: Unhandled exception:\n%s\n",
	    [description cStringWithEncoding: encoding]);

	if ([exception respondsToSelector: @selector(backtrace)])
		backtrace = [exception backtrace];

196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
	return instance;
}

const char*
_NSPrintForDebugger(id object)
{
	return [[object description]
	    cStringWithEncoding: [OFSystemInfo native8BitEncoding]];
}

/* References for static linking */
void
_references_to_categories_of_OFObject(void)
{
	_OFObject_KeyValueCoding_reference = 1;







|







196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
	return instance;
}

const char*
_NSPrintForDebugger(id object)
{
	return [[object description]
	    cStringWithEncoding: [OFLocalization encoding]];
}

/* References for static linking */
void
_references_to_categories_of_OFObject(void)
{
	_OFObject_KeyValueCoding_reference = 1;

Modified src/OFPlugin.m from [50477690f4] to [58ad217163].

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

#ifdef HAVE_DLFCN_H
# include <dlfcn.h>
#endif

#import "OFPlugin.h"
#import "OFString.h"
#import "OFSystemInfo.h"

#import "OFInitializationFailedException.h"

typedef OFPlugin* (*init_plugin_t)(void);

of_plugin_handle_t
of_dlopen(OFString *path, int flags)
{
#ifndef OF_WINDOWS
	return dlopen([path cStringWithEncoding:
	    [OFSystemInfo native8BitEncoding]], flags);
#else
	if (path == nil)
		return GetModuleHandle(NULL);

	return LoadLibraryW([path UTF16String]);
#endif
}







|









|
|







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

#ifdef HAVE_DLFCN_H
# include <dlfcn.h>
#endif

#import "OFPlugin.h"
#import "OFString.h"
#import "OFLocalization.h"

#import "OFInitializationFailedException.h"

typedef OFPlugin* (*init_plugin_t)(void);

of_plugin_handle_t
of_dlopen(OFString *path, int flags)
{
#ifndef OF_WINDOWS
	return dlopen([path cStringWithEncoding: [OFLocalization encoding]],
	    flags);
#else
	if (path == nil)
		return GetModuleHandle(NULL);

	return LoadLibraryW([path UTF16String]);
#endif
}

Modified src/OFProcess.m from [273ab6b21b] to [b11627a172].

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#endif

#import "OFProcess.h"
#import "OFString.h"
#import "OFArray.h"
#import "OFDictionary.h"
#import "OFDataArray.h"
#import "OFSystemInfo.h"

#import "OFInitializationFailedException.h"
#import "OFOutOfRangeException.h"
#import "OFReadFailedException.h"
#import "OFWriteFailedException.h"

#ifdef OF_WINDOWS







|







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#endif

#import "OFProcess.h"
#import "OFString.h"
#import "OFArray.h"
#import "OFDictionary.h"
#import "OFDataArray.h"
#import "OFLocalization.h"

#import "OFInitializationFailedException.h"
#import "OFOutOfRangeException.h"
#import "OFReadFailedException.h"
#import "OFWriteFailedException.h"

#ifdef OF_WINDOWS
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
		const char *path;
		char **argv;

		if (pipe(_readPipe) != 0 || pipe(_writePipe) != 0)
			@throw [OFInitializationFailedException
			    exceptionWithClass: [self class]];

		path = [program cStringWithEncoding:
		    [OFSystemInfo native8BitEncoding]];
		[self OF_getArgV: &argv
		  forProgramName: programName
		    andArguments: arguments];

		@try {
			char **env = [self
			    OF_environmentForDictionary: environment];







|
<







145
146
147
148
149
150
151
152

153
154
155
156
157
158
159
		const char *path;
		char **argv;

		if (pipe(_readPipe) != 0 || pipe(_writePipe) != 0)
			@throw [OFInitializationFailedException
			    exceptionWithClass: [self class]];

		path = [program cStringWithEncoding: [OFLocalization encoding]];

		[self OF_getArgV: &argv
		  forProgramName: programName
		    andArguments: arguments];

		@try {
			char **env = [self
			    OF_environmentForDictionary: environment];
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
	OFString *const *objects = [arguments objects];
	size_t i, count = [arguments count];
	of_string_encoding_t encoding;

	*argv = [self allocMemoryWithSize: sizeof(char*)
				    count: count + 2];

	encoding = [OFSystemInfo native8BitEncoding];

	(*argv)[0] = (char*)[programName cStringWithEncoding: encoding];

	for (i = 0; i < count; i++)
		(*argv)[i + 1] =
		    (char*)[objects[i] cStringWithEncoding: encoding];

	(*argv)[i + 1] = NULL;
}

- (char**)OF_environmentForDictionary: (OFDictionary*)environment
{
	OFEnumerator *keyEnumerator, *objectEnumerator;
	char **envp;
	size_t i, count;
	of_string_encoding_t encoding;

	if (environment == nil)
		return NULL;

	encoding = [OFSystemInfo native8BitEncoding];

	count = [environment count];
	envp = [self allocMemoryWithSize: sizeof(char*)
				   count: count + 1];

	keyEnumerator = [environment keyEnumerator];
	objectEnumerator = [environment objectEnumerator];







|




















|







345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
	OFString *const *objects = [arguments objects];
	size_t i, count = [arguments count];
	of_string_encoding_t encoding;

	*argv = [self allocMemoryWithSize: sizeof(char*)
				    count: count + 2];

	encoding = [OFLocalization encoding];

	(*argv)[0] = (char*)[programName cStringWithEncoding: encoding];

	for (i = 0; i < count; i++)
		(*argv)[i + 1] =
		    (char*)[objects[i] cStringWithEncoding: encoding];

	(*argv)[i + 1] = NULL;
}

- (char**)OF_environmentForDictionary: (OFDictionary*)environment
{
	OFEnumerator *keyEnumerator, *objectEnumerator;
	char **envp;
	size_t i, count;
	of_string_encoding_t encoding;

	if (environment == nil)
		return NULL;

	encoding = [OFLocalization encoding];

	count = [environment count];
	envp = [self allocMemoryWithSize: sizeof(char*)
				   count: count + 1];

	keyEnumerator = [environment keyEnumerator];
	objectEnumerator = [environment objectEnumerator];

Modified src/OFString.h from [898af43561] to [0fabfb3f71].

44
45
46
47
48
49
50




51
52
53
54
55
56
57
#endif
typedef of_char32_t of_unichar_t;

/*!
 * @brief The encoding of a string.
 */
typedef enum of_string_encoding_t {




	/*! UTF-8 */
	OF_STRING_ENCODING_UTF_8,
	/*! ASCII */
	OF_STRING_ENCODING_ASCII,
	/*! ISO 8859-1 */
	OF_STRING_ENCODING_ISO_8859_1,
	/*! ISO 8859-15 */







>
>
>
>







44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#endif
typedef of_char32_t of_unichar_t;

/*!
 * @brief The encoding of a string.
 */
typedef enum of_string_encoding_t {
	/*
	 * UTF-8 *has* to be 0, so that if the @ref OFLocalization singleton is
	 * `nil`, `[OFLocalization encoding]` returns UTF-8.
	 */
	/*! UTF-8 */
	OF_STRING_ENCODING_UTF_8,
	/*! ASCII */
	OF_STRING_ENCODING_ASCII,
	/*! ISO 8859-1 */
	OF_STRING_ENCODING_ISO_8859_1,
	/*! ISO 8859-15 */

Modified src/OFString.m from [011cdaca0e] to [451da8b217].

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

#import "OFString.h"
#import "OFString_UTF8.h"
#import "OFString_UTF8+Private.h"
#import "OFArray.h"
#import "OFDictionary.h"
#import "OFDataArray.h"
#import "OFSystemInfo.h"
#ifdef OF_HAVE_FILES
# import "OFFile.h"
#endif
#import "OFURL.h"
#ifdef OF_HAVE_SOCKETS
# import "OFHTTPClient.h"
# import "OFHTTPRequest.h"







|







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

#import "OFString.h"
#import "OFString_UTF8.h"
#import "OFString_UTF8+Private.h"
#import "OFArray.h"
#import "OFDictionary.h"
#import "OFDataArray.h"
#import "OFLocalization.h"
#ifdef OF_HAVE_FILES
# import "OFFile.h"
#endif
#import "OFURL.h"
#ifdef OF_HAVE_SOCKETS
# import "OFHTTPClient.h"
# import "OFHTTPRequest.h"
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
#ifdef HAVE_STRTOF_L
	const char *UTF8String = [self UTF8String];
#else
	/*
	 * If we have no strtof_l, we have no other choice but to replace "."
	 * with the locale's decimal point.
	 */
	OFString *decimalPoint = [OFSystemInfo decimalPoint];
	const char *UTF8String = [[self
	    stringByReplacingOccurrencesOfString: @"."
				      withString: decimalPoint] UTF8String];
#endif
	char *endPointer = NULL;
	float value;








|







2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
#ifdef HAVE_STRTOF_L
	const char *UTF8String = [self UTF8String];
#else
	/*
	 * If we have no strtof_l, we have no other choice but to replace "."
	 * with the locale's decimal point.
	 */
	OFString *decimalPoint = [OFLocalization decimalPoint];
	const char *UTF8String = [[self
	    stringByReplacingOccurrencesOfString: @"."
				      withString: decimalPoint] UTF8String];
#endif
	char *endPointer = NULL;
	float value;

2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
#ifdef HAVE_STRTOD_L
	const char *UTF8String = [self UTF8String];
#else
	/*
	 * If we have no strtod_l, we have no other choice but to replace "."
	 * with the locale's decimal point.
	 */
	OFString *decimalPoint = [OFSystemInfo decimalPoint];
	const char *UTF8String = [[self
	    stringByReplacingOccurrencesOfString: @"."
				      withString: decimalPoint] UTF8String];
#endif
	char *endPointer = NULL;
	double value;








|







2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
#ifdef HAVE_STRTOD_L
	const char *UTF8String = [self UTF8String];
#else
	/*
	 * If we have no strtod_l, we have no other choice but to replace "."
	 * with the locale's decimal point.
	 */
	OFString *decimalPoint = [OFLocalization decimalPoint];
	const char *UTF8String = [[self
	    stringByReplacingOccurrencesOfString: @"."
				      withString: decimalPoint] UTF8String];
#endif
	char *endPointer = NULL;
	double value;

Modified src/OFSystemInfo.h from [c797094656] to [cbabc25539].

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
 *
 * A CPU with multiple cores counts as multiple CPUs.
 *
 * @return The number of CPUs installed in the system
 */
+ (size_t)numberOfCPUs;

/*!
 * @brief Returns the native 8-bit string encoding of the operating system.
 *
 * This is useful to encode strings correctly for passing them to operating
 * system calls.
 *
 * If the native 8-bit encoding is unknown, UTF-8 is assumed.
 *
 * @return The native 8-bit string encoding of the operating system
 */
+ (of_string_encoding_t)native8BitEncoding;

/*!
 * @brief Returns the language of the locale.
 *
 * If the language is unknown, nil is returned.
 *
 * @return The language of the locale.
 */
+ (OFString*)language;

/*!
 * @brief Returns the territory of the locale.
 *
 * If the territory is unknown, nil is returned.
 *
 * @return The territory of the locale.
 */
+ (OFString*)territory;

/*!
 * @brief Returns the decimal point in the system's locale.
 *
 * @return The decimal point in the system's locale
 */
+ (OFString*)decimalPoint;

/*!
 * @brief Returns the path where user data for the application can be stored.
 *
 * On Unix systems, this adheres to the XDG Base Directory specification.@n
 * On Mac OS X and iOS, it uses the `NSApplicationSupportDirectory` directory.@n
 * On Windows, it uses the `APPDATA` environment variable.@n
 * On Haiku, it uses the `B_USER_SETTINGS_DIRECTORY` directory.







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







37
38
39
40
41
42
43





































44
45
46
47
48
49
50
 *
 * A CPU with multiple cores counts as multiple CPUs.
 *
 * @return The number of CPUs installed in the system
 */
+ (size_t)numberOfCPUs;






































/*!
 * @brief Returns the path where user data for the application can be stored.
 *
 * On Unix systems, this adheres to the XDG Base Directory specification.@n
 * On Mac OS X and iOS, it uses the `NSApplicationSupportDirectory` directory.@n
 * On Windows, it uses the `APPDATA` environment variable.@n
 * On Haiku, it uses the `B_USER_SETTINGS_DIRECTORY` directory.

Modified src/OFSystemInfo.m from [70cccb5f86] to [f489c81282].

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

/* Work around __block being used by glibc */
#include <stdlib.h>	/* include any libc header to get the libc defines */
#ifdef __GLIBC__
# undef __USE_XOPEN
#endif

#include <locale.h>
#include <unistd.h>

#include "platform.h"

#ifdef OF_MAC_OS_X
# include <sys/sysctl.h>
#endif







<







20
21
22
23
24
25
26

27
28
29
30
31
32
33

/* Work around __block being used by glibc */
#include <stdlib.h>	/* include any libc header to get the libc defines */
#ifdef __GLIBC__
# undef __USE_XOPEN
#endif


#include <unistd.h>

#include "platform.h"

#ifdef OF_MAC_OS_X
# include <sys/sysctl.h>
#endif
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
struct x86_regs {
	uint32_t eax, ebx, ecx, edx;
};
#endif

static size_t pageSize;
static size_t numberOfCPUs;
static of_string_encoding_t native8BitEncoding = OF_STRING_ENCODING_UTF_8;
static OFString *language = nil;
static OFString *territory = nil;
static OFString *decimalPoint = @".";

void
of_system_info_parse_locale(char *locale)
{
	if (locale == NULL)
		return;

	locale = of_strdup(locale);

	@try {
		char *tmp;

		/* We don't care for extras behind the @ */
		if ((tmp = strrchr(locale, '@')) != NULL)
			*tmp = '\0';

		/* Encoding */
		if ((tmp = strrchr(locale, '.')) != NULL) {
			size_t tmpLen;

			*tmp++ = '\0';

			tmpLen = strlen(tmp);
			for (size_t i = 0; i < tmpLen; i++)
				tmp[i] = of_ascii_tolower(tmp[i]);

			if (strcmp(tmp, "utf8") == 0 ||
			    strcmp(tmp, "utf-8") == 0)
				native8BitEncoding = OF_STRING_ENCODING_UTF_8;
			else if (strcmp(tmp, "ascii") == 0 ||
			    strcmp(tmp, "us-ascii") == 0)
				native8BitEncoding = OF_STRING_ENCODING_ASCII;
			else if (strcmp(tmp, "iso8859-1") == 0 ||
			    strcmp(tmp, "iso-8859-1") == 0)
				native8BitEncoding =
				    OF_STRING_ENCODING_ISO_8859_1;
			else if (strcmp(tmp, "iso8859-15") == 0 ||
			    strcmp(tmp, "iso-8859-15") == 0)
				native8BitEncoding =
				    OF_STRING_ENCODING_ISO_8859_15;
			/* Windows uses a codepage */
			else if (strcmp(tmp, "1252") == 0)
				native8BitEncoding =
				    OF_STRING_ENCODING_WINDOWS_1252;
		}

		/* Territory */
		if ((tmp = strrchr(locale, '_')) != NULL) {
			*tmp++ = '\0';
			territory = [[OFString alloc]
			    initWithCString: tmp
				   encoding: OF_STRING_ENCODING_ASCII];
		}

		language = [[OFString alloc]
		    initWithCString: locale
			   encoding: OF_STRING_ENCODING_ASCII];
	} @finally {
		free(locale);
	}

	decimalPoint = [[OFString alloc]
	    initWithCString: localeconv()->decimal_point
		   encoding: native8BitEncoding];
}

#if defined(OF_X86_64) || defined(OF_X86)
static OF_INLINE struct x86_regs OF_CONST_FUNC
x86_cpuid(uint32_t eax, uint32_t ecx)
{
	struct x86_regs regs;








<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







61
62
63
64
65
66
67





































































68
69
70
71
72
73
74
struct x86_regs {
	uint32_t eax, ebx, ecx, edx;
};
#endif

static size_t pageSize;
static size_t numberOfCPUs;






































































#if defined(OF_X86_64) || defined(OF_X86)
static OF_INLINE struct x86_regs OF_CONST_FUNC
x86_cpuid(uint32_t eax, uint32_t ecx)
{
	struct x86_regs regs;

209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
}

+ (size_t)numberOfCPUs
{
	return numberOfCPUs;
}

+ (of_string_encoding_t)native8BitEncoding
{
	return native8BitEncoding;
}

+ (OFString*)language
{
	return language;
}

+ (OFString*)territory
{
	return territory;
}

+ (OFString*)decimalPoint
{
	return decimalPoint;
}

+ (OFString*)userDataPath
{
#if defined(OF_MAC_OS_X) || defined(OF_IOS)
	void *pool = objc_autoreleasePoolPush();
	char pathC[PATH_MAX];
	OFMutableString *path;
	OFString *home;







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







139
140
141
142
143
144
145




















146
147
148
149
150
151
152
}

+ (size_t)numberOfCPUs
{
	return numberOfCPUs;
}





















+ (OFString*)userDataPath
{
#if defined(OF_MAC_OS_X) || defined(OF_IOS)
	void *pool = objc_autoreleasePoolPush();
	char pathC[PATH_MAX];
	OFMutableString *path;
	OFString *home;

Modified src/ObjFW.h from [9d37e8cfea] to [b467e259b3].

96
97
98
99
100
101
102
103
104


105
106
107
108
109
110
111
#import "OFXMLProcessingInstructions.h"
#import "OFXMLParser.h"
#import "OFXMLElementBuilder.h"

#import "OFMessagePackExtension.h"

#import "OFApplication.h"
#import "OFOptionsParser.h"
#import "OFSystemInfo.h"


#import "OFTimer.h"
#import "OFRunLoop.h"

#import "OFAllocFailedException.h"
#import "OFException.h"
#ifdef OF_HAVE_SOCKETS
# import "OFAcceptFailedException.h"







<

>
>







96
97
98
99
100
101
102

103
104
105
106
107
108
109
110
111
112
#import "OFXMLProcessingInstructions.h"
#import "OFXMLParser.h"
#import "OFXMLElementBuilder.h"

#import "OFMessagePackExtension.h"

#import "OFApplication.h"

#import "OFSystemInfo.h"
#import "OFLocalization.h"
#import "OFOptionsParser.h"
#import "OFTimer.h"
#import "OFRunLoop.h"

#import "OFAllocFailedException.h"
#import "OFException.h"
#ifdef OF_HAVE_SOCKETS
# import "OFAcceptFailedException.h"

Modified src/exceptions/OFException.m from [a913b4b6a3] to [9a85916e30].

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#ifdef HAVE_DLFCN_H
# include <dlfcn.h>
#endif

#import "OFException.h"
#import "OFString.h"
#import "OFArray.h"
#import "OFSystemInfo.h"

#import "OFInitializationFailedException.h"
#import "OFLockFailedException.h"
#import "OFUnlockFailedException.h"

#if !defined(HAVE_STRERROR_R) && defined(OF_HAVE_THREADS)
# import "threading.h"







|







24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#ifdef HAVE_DLFCN_H
# include <dlfcn.h>
#endif

#import "OFException.h"
#import "OFString.h"
#import "OFArray.h"
#import "OFLocalization.h"

#import "OFInitializationFailedException.h"
#import "OFLockFailedException.h"
#import "OFUnlockFailedException.h"

#if !defined(HAVE_STRERROR_R) && defined(OF_HAVE_THREADS)
# import "threading.h"
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
#endif

#ifdef HAVE_STRERROR_R
	if (strerror_r(errNo, buffer, 256) != 0)
		return @"Unknown error (strerror_r failed)";

	ret = [OFString stringWithCString: buffer
				 encoding: [OFSystemInfo native8BitEncoding]];
#else
# ifdef OF_HAVE_THREADS
	if (!of_mutex_lock(&mutex))
		@throw [OFLockFailedException exception];

	@try {
# endif
		ret = [OFString
		    stringWithCString: strerror(errNo)
			     encoding: [OFSystemInfo native8BitEncoding]];
# ifdef OF_HAVE_THREADS
	} @finally {
		if (!of_mutex_unlock(&mutex))
			@throw [OFUnlockFailedException exception];
	}
# endif
#endif







|









|







186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
#endif

#ifdef HAVE_STRERROR_R
	if (strerror_r(errNo, buffer, 256) != 0)
		return @"Unknown error (strerror_r failed)";

	ret = [OFString stringWithCString: buffer
				 encoding: [OFLocalization encoding]];
#else
# ifdef OF_HAVE_THREADS
	if (!of_mutex_lock(&mutex))
		@throw [OFLockFailedException exception];

	@try {
# endif
		ret = [OFString
		    stringWithCString: strerror(errNo)
			     encoding: [OFLocalization encoding]];
# ifdef OF_HAVE_THREADS
	} @finally {
		if (!of_mutex_unlock(&mutex))
			@throw [OFUnlockFailedException exception];
	}
# endif
#endif

Modified src/of_asprintf.m from [78991846e2] to [5de6ff2576].

29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#ifdef HAVE_XLOCALE_H
# include <xlocale.h>
#endif

#include <sys/types.h>

#import "OFString.h"
#import "OFSystemInfo.h"

#import "OFInitializationFailedException.h"

#define MAX_SUBFORMAT_LEN 64

#ifndef HAVE_ASPRINTF
/*







|







29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#ifdef HAVE_XLOCALE_H
# include <xlocale.h>
#endif

#include <sys/types.h>

#import "OFString.h"
#import "OFLocalization.h"

#import "OFInitializationFailedException.h"

#define MAX_SUBFORMAT_LEN 64

#ifndef HAVE_ASPRINTF
/*
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
			char *tmp2;

			@try {
				OFMutableString *tmpStr = [OFMutableString
				    stringWithUTF8String: tmp
						  length: tmpLen];
				OFString *decimalPoint =
				    [OFSystemInfo decimalPoint];
				[tmpStr replaceOccurrencesOfString: decimalPoint
							withString: @"."];
				if ([tmpStr UTF8StringLength] > INT_MAX)
					return false;
				tmpLen = (int)[tmpStr UTF8StringLength];
				tmp2 = malloc(tmpLen);
				memcpy(tmp2, [tmpStr UTF8String], tmpLen);







|







558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
			char *tmp2;

			@try {
				OFMutableString *tmpStr = [OFMutableString
				    stringWithUTF8String: tmp
						  length: tmpLen];
				OFString *decimalPoint =
				    [OFLocalization decimalPoint];
				[tmpStr replaceOccurrencesOfString: decimalPoint
							withString: @"."];
				if ([tmpStr UTF8StringLength] > INT_MAX)
					return false;
				tmpLen = (int)[tmpStr UTF8StringLength];
				tmp2 = malloc(tmpLen);
				memcpy(tmp2, [tmpStr UTF8String], tmpLen);

Modified utils/ofhttp/OFHTTP.m from [3ef2bcb62b] to [6d271e2d00].

26
27
28
29
30
31
32

33
34
35
36
37
38
39
#import "OFHTTPRequest.h"
#import "OFHTTPResponse.h"
#import "OFOptionsParser.h"
#import "OFStdIOStream.h"
#import "OFSystemInfo.h"
#import "OFTCPSocket.h"
#import "OFURL.h"


#import "OFAddressTranslationFailedException.h"
#import "OFConnectionFailedException.h"
#import "OFHTTPRequestFailedException.h"
#import "OFInvalidFormatException.h"
#import "OFInvalidServerReplyException.h"
#import "OFOpenItemFailedException.h"







>







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#import "OFHTTPRequest.h"
#import "OFHTTPResponse.h"
#import "OFOptionsParser.h"
#import "OFStdIOStream.h"
#import "OFSystemInfo.h"
#import "OFTCPSocket.h"
#import "OFURL.h"
#import "OFLocalization.h"

#import "OFAddressTranslationFailedException.h"
#import "OFConnectionFailedException.h"
#import "OFHTTPRequestFailedException.h"
#import "OFInvalidFormatException.h"
#import "OFInvalidServerReplyException.h"
#import "OFOpenItemFailedException.h"
68
69
70
71
72
73
74
75

76
77
78
79
80
81
82
83
84
85
86
87
@end

OF_APPLICATION_DELEGATE(OFHTTP)

static void
help(OFStream *stream, bool full, int status)
{
	[of_stderr writeFormat:

	    @"Usage: %@ -[cehHmoOPqv] url1 [url2 ...]\n",
	    [OFApplication programName]];

	if (full)
		[stream writeString:
		    @"\nOptions:\n    "
		    @"-b  --body           "
		    @"  Specify the file to send as body\n    "
		    @"-c  --continue       "
		    @"  Continue download of existing file\n    "
		    @"-f  --force          "
		    @"  Force / overwrite existing file\n    "







|
>
|
|


|







69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
@end

OF_APPLICATION_DELEGATE(OFHTTP)

static void
help(OFStream *stream, bool full, int status)
{
	[of_stderr writeString:
	    OF_LOCALIZED(@"usage",
	    @"Usage: %[prog] -[cehHmoOPqv] url1 [url2 ...]\n",
	    @"prog", [OFApplication programName])];

	if (full)
		[stream writeString: OF_LOCALIZED(@"full_usage",
		    @"\nOptions:\n    "
		    @"-b  --body           "
		    @"  Specify the file to send as body\n    "
		    @"-c  --continue       "
		    @"  Continue download of existing file\n    "
		    @"-f  --force          "
		    @"  Force / overwrite existing file\n    "
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
		    @"-O  --detect-filename"
		    @"  Do a HEAD request to detect the file name\n    "
		    @"-P  --proxy          "
		    @"  Specify SOCKS5 proxy\n    "
		    @"-q  --quiet          "
		    @"  Quiet mode (no output, except errors)\n    "
		    @"-v  --verbose        "
		    @"  Verbose mode (print headers)\n"];

	[OFApplication terminateWithStatus: status];
}

@implementation OFHTTP
- init
{







|







98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
		    @"-O  --detect-filename"
		    @"  Do a HEAD request to detect the file name\n    "
		    @"-P  --proxy          "
		    @"  Specify SOCKS5 proxy\n    "
		    @"-q  --quiet          "
		    @"  Quiet mode (no output, except errors)\n    "
		    @"-v  --verbose        "
		    @"  Verbose mode (print headers)\n")];

	[OFApplication terminateWithStatus: status];
}

@implementation OFHTTP
- init
{
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147

- (void)addHeader: (OFString*)header
{
	size_t pos = [header rangeOfString: @":"].location;
	OFString *name, *value;

	if (pos == OF_NOT_FOUND) {
		[of_stderr writeFormat: @"%@: Headers must to be in format "
					"name:value!\n",
					[OFApplication programName]];
		[OFApplication terminateWithStatus: 1];
	}

	name = [header substringWithRange: of_range(0, pos)];
	name = [name stringByDeletingEnclosingWhitespaces];

	value = [header substringWithRange:







|
|
|







133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149

- (void)addHeader: (OFString*)header
{
	size_t pos = [header rangeOfString: @":"].location;
	OFString *name, *value;

	if (pos == OF_NOT_FOUND) {
		[of_stderr writeString: OF_LOCALIZED(@"invalid_input_header",
		    @"%[prog]: Headers must to be in format name:value!\n",
		    @"prog", [OFApplication programName])];
		[OFApplication terminateWithStatus: 1];
	}

	name = [header substringWithRange: of_range(0, pos)];
	name = [name stringByDeletingEnclosingWhitespaces];

	value = [header substringWithRange:
181
182
183
184
185
186
187

188
189
190
191
192
193
194
195
196
197
	else if ([method isEqual: @"PUT"])
		_method = OF_HTTP_REQUEST_METHOD_PUT;
	else if ([method isEqual: @"DELETE"])
		_method = OF_HTTP_REQUEST_METHOD_DELETE;
	else if ([method isEqual: @"TRACE"])
		_method = OF_HTTP_REQUEST_METHOD_TRACE;
	else {

		[of_stderr writeFormat: @"%@: Invalid request method %@!\n",
					[OFApplication programName],
					method];
		[OFApplication terminateWithStatus: 1];
	}

	objc_autoreleasePoolPop(pool);
}

- (void)setProxy: (OFString*)proxy







>
|
|
|







183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
	else if ([method isEqual: @"PUT"])
		_method = OF_HTTP_REQUEST_METHOD_PUT;
	else if ([method isEqual: @"DELETE"])
		_method = OF_HTTP_REQUEST_METHOD_DELETE;
	else if ([method isEqual: @"TRACE"])
		_method = OF_HTTP_REQUEST_METHOD_TRACE;
	else {
		[of_stderr writeString: OF_LOCALIZED(@"invalid_input_method",
		    @"%[prog]: Invalid request method %[method]!\n",
		    @"prog", [OFApplication programName],
		    @"method", method)];
		[OFApplication terminateWithStatus: 1];
	}

	objc_autoreleasePoolPop(pool);
}

- (void)setProxy: (OFString*)proxy
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228

		if (port > UINT16_MAX)
			@throw [OFOutOfRangeException exception];

		[OFTCPSocket setSOCKS5Host: host];
		[OFTCPSocket setSOCKS5Port: (uint16_t)port];
	} @catch (OFInvalidFormatException *e) {
		[of_stderr writeFormat: @"%@: Proxy must to be in format "
					"host:port!\n",
					[OFApplication programName]];
		[OFApplication terminateWithStatus: 1];
	}
}

- (void)applicationDidFinishLaunching
{
	OFString *outputPath;







|
|
|







215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231

		if (port > UINT16_MAX)
			@throw [OFOutOfRangeException exception];

		[OFTCPSocket setSOCKS5Host: host];
		[OFTCPSocket setSOCKS5Port: (uint16_t)port];
	} @catch (OFInvalidFormatException *e) {
		[of_stderr writeString: OF_LOCALIZED(@"invalid_input_proxy",
		    @"%[prog]: Proxy must to be in format host:port!\n",
		    @"prog", [OFApplication programName])];
		[OFApplication terminateWithStatus: 1];
	}
}

- (void)applicationDidFinishLaunching
{
	OFString *outputPath;
259
260
261
262
263
264
265
266

267

268
269
270



271

272

273
274

275
276
277
278
279
280

281
282
283
284
285
286
287
288

289
290
291
292



293

294
295
296

297
298
299
300
301
302
303
304
305
306
307
308
309

310
311
312
313
314
315
316
317

318
319
320
321
322
323
324
325
326
327
			[self setMethod: [optionsParser argument]];
			break;
		case 'P':
			[self setProxy: [optionsParser argument]];
			break;
		case ':':
			if ([optionsParser lastLongOption] != nil)
				[of_stderr writeFormat:

				    @"%@: Argument for option --%@ missing\n",

				    [OFApplication programName],
				    [optionsParser lastLongOption]];
			else



				[of_stderr writeFormat:

				    @"%@: Argument for option -%C missing\n",

				    [OFApplication programName],
				    [optionsParser lastOption]];


			[OFApplication terminateWithStatus: 1];
			break;
		case '=':
			[of_stderr writeFormat: @"%@: Option --%@ takes no "
						@"argument\n",

						[OFApplication programName],
						[optionsParser lastLongOption]];

			[OFApplication terminateWithStatus: 1];
			break;
		case '?':
			if ([optionsParser lastLongOption] != nil)
				[of_stderr writeFormat:

				    @"%@: Unknown option: --%@\n",
				    [OFApplication programName],
				    [optionsParser lastLongOption]];
			else



				[of_stderr writeFormat:

				    @"%@: Unknown option: -%C\n",
				    [OFApplication programName],
				    [optionsParser lastOption]];


			[OFApplication terminateWithStatus: 1];
			break;
		}
	}

	_outputPath = [outputPath copy];
	_URLs = [[optionsParser remainingArguments] retain];

	if ([_URLs count] < 1)
		help(of_stderr, false, 1);

	if (_quiet && _verbose) {

		[of_stderr writeFormat: @"%@: -q / --quiet and -v / --verbose "
					@"are mutually exclusive!\n",
					[OFApplication programName]];
		[OFApplication terminateWithStatus: 1];
	}

	if (_outputPath != nil && [_URLs count] > 1) {
		[of_stderr writeFormat: @"%@: Cannot use -o / --output when "

					@"more than one URL has been "
					@"specified!\n",
					[OFApplication programName]];
		[OFApplication terminateWithStatus: 1];
	}

	[self performSelector: @selector(downloadNextURL)
		   afterDelay: 0];
}








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




|
|
>
|
|





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













>
|
|
|




|
>
|
|
|







262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
			[self setMethod: [optionsParser argument]];
			break;
		case 'P':
			[self setProxy: [optionsParser argument]];
			break;
		case ':':
			if ([optionsParser lastLongOption] != nil)
				[of_stderr writeString:
				    OF_LOCALIZED(@"long_argument_missing",
				    @"%[prog]: Argument for option --%[opt] "
				    "missing\n"
				    @"prog", [OFApplication programName],
				    @"opt", [optionsParser lastLongOption])];
			else {
				OFString *optStr = [OFString
				    stringWithFormat: @"%c",
				    [optionsParser lastOption]];
				[of_stderr writeString:
				    OF_LOCALIZED(@"argument_missing",
				    @"%[prog]: Argument for option -%[opt] "
				    "missing\n",
				    @"prog", [OFApplication programName],
				    @"opt", optStr)];
			}

			[OFApplication terminateWithStatus: 1];
			break;
		case '=':
			[of_stderr writeString:
			    OF_LOCALIZED(@"takes_no_argument",
			    @"%[prog]: Option --%[opt] takes no argument\n",
			    @"prog", [OFApplication programName],
			    @"opt", [optionsParser lastLongOption])];

			[OFApplication terminateWithStatus: 1];
			break;
		case '?':
			if ([optionsParser lastLongOption] != nil)
				[of_stderr writeString:
				    OF_LOCALIZED(@"unknown_long_option",
				    @"%[prog]: Unknown option: --%[opt]\n",
				    @"prog", [OFApplication programName],
				    @"opt", [optionsParser lastLongOption])];
			else {
				OFString *optStr = [OFString
				    stringWithFormat: @"%c",
				    [optionsParser lastOption]];
				[of_stderr writeString:
				    OF_LOCALIZED(@"unknown_option",
				    @"%[prog]: Unknown option: -%[opt]\n",
				    @"prog", [OFApplication programName],
				    @"opt", optStr)];
			}

			[OFApplication terminateWithStatus: 1];
			break;
		}
	}

	_outputPath = [outputPath copy];
	_URLs = [[optionsParser remainingArguments] retain];

	if ([_URLs count] < 1)
		help(of_stderr, false, 1);

	if (_quiet && _verbose) {
		[of_stderr writeString: OF_LOCALIZED(@"quiet_xor_verbose",
		    @"%[prog]: -q / --quiet and -v / --verbose are mutually "
		    @"exclusive!\n",
		    @"prog", [OFApplication programName])];
		[OFApplication terminateWithStatus: 1];
	}

	if (_outputPath != nil && [_URLs count] > 1) {
		[of_stderr writeString:
		    OF_LOCALIZED(@"output_only_with_one_url",
		    @"%[prog]: Cannot use -o / --output when more than one URL "
		    @"has been specified!\n",
		    @"prog", [OFApplication programName])];
		[OFApplication terminateWithStatus: 1];
	}

	[self performSelector: @selector(downloadNextURL)
		   afterDelay: 0];
}

363
364
365
366
367
368
369
370


371
372
373

374
375
376
377
378


379
380
381

382
383
384
385
386


387
388
389
390
391
392
393

394
395
396
397
398
399


400
401
402
403
404
405


406
407


408
409
410


411
412
413


414
415
416
417
418

419
420
421
422
423
424
425
426
427
428

	@try {
		response = [_HTTPClient performRequest: request];
	} @catch (OFAddressTranslationFailedException *e) {
		if (!_quiet)
			[of_stdout writeString: @"\n"];

		[of_stderr writeFormat: @"%@: Failed to download <%@>!\n"


					@"  Address translation failed: %@\n",
					[OFApplication programName],
					[[request URL] string], e];

	} @catch (OFConnectionFailedException *e) {
		if (!_quiet)
			[of_stdout writeString: @"\n"];

		[of_stderr writeFormat: @"%@: Failed to download <%@>!\n"


					@"  Connection failed: %@\n",
					[OFApplication programName],
					[[request URL] string], e];

	} @catch (OFInvalidServerReplyException *e) {
		if (!_quiet)
			[of_stdout writeString: @"\n"];

		[of_stderr writeFormat: @"%@: Failed to download <%@>!\n"


					@"  Invalid server reply!\n",
					[OFApplication programName],
					[[request URL] string]];
	} @catch (OFUnsupportedProtocolException *e) {
		if (!_quiet)
			[of_stdout writeString: @"\n"];


		[of_stderr writeFormat: @"%@: No SSL library loaded!\n"
					@"  In order to download via https, "
					@"you need to preload an SSL library "
					@"for ObjFW\n  such as ObjOpenSSL!\n",
					[OFApplication programName]];
	} @catch (OFReadOrWriteFailedException *e) {


		OFString *action = @"Read or write";

		if (!_quiet)
			[of_stdout writeString: @"\n"];

		if ([e isKindOfClass: [OFReadFailedException class]])


			action = @"Read";
		else if ([e isKindOfClass: [OFWriteFailedException class]])


			action = @"Write";

		[of_stderr writeFormat: @"%@: Failed to download <%@>!\n"


					@"  %@ failed: %@\n",
					[OFApplication programName],
					[[request URL] string], action, e];


	} @catch (OFHTTPRequestFailedException *e) {
		if (!_quiet)
			[of_stdout writeFormat: @" ➜ %d\n",
						[[e response] statusCode]];


		[of_stderr writeFormat: @"%@: Failed to download <%@>!\n",
					[OFApplication programName],
					[[request URL] string]];
	}

	if (!_quiet && response != nil)
		[of_stdout writeFormat: @" ➜ %d\n", [response statusCode]];

	return response;
}







|
>
>
|
|
|
>




|
>
>
|
|
|
>




|
>
>
|
|
|




>
|
|
|
|
|

>
>
|





>
>
|

>
>
|

|
>
>
|
|
|
>
>





>
|
|
|







383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468

	@try {
		response = [_HTTPClient performRequest: request];
	} @catch (OFAddressTranslationFailedException *e) {
		if (!_quiet)
			[of_stdout writeString: @"\n"];

		[of_stderr writeString:
		    OF_LOCALIZED(@"download_failed_address_translation",
		    @"%[prog]: Failed to download <%[url]>!\n"
		    @"  Address translation failed: %[exception]\n",
		    @"prog", [OFApplication programName],
		    @"url", [[request URL] string],
		    @"exception", e)];
	} @catch (OFConnectionFailedException *e) {
		if (!_quiet)
			[of_stdout writeString: @"\n"];

		[of_stderr writeString:
		    OF_LOCALIZED(@"download_failed_connection_failed",
		    @"%[prog]: Failed to download <%[url]>!\n"
		    @"  Connection failed: %[exception]\n",
		    @"prog", [OFApplication programName],
		    @"url", [[request URL] string],
		    @"exception", e)];
	} @catch (OFInvalidServerReplyException *e) {
		if (!_quiet)
			[of_stdout writeString: @"\n"];

		[of_stderr writeString:
		    OF_LOCALIZED(@"download_failed_invalid_server_reply",
		    @"%[prog]: Failed to download <%[url]>!\n"
		    @"  Invalid server reply!\n",
		    @"prog", [OFApplication programName],
		    @"url", [[request URL] string])];
	} @catch (OFUnsupportedProtocolException *e) {
		if (!_quiet)
			[of_stdout writeString: @"\n"];

		[of_stderr writeString: OF_LOCALIZED(@"no_ssl_library",
		    @"%[prog]: No SSL library loaded!\n"
		    @"  In order to download via https, you need to preload an "
		    @"SSL library for ObjFW\n"
		    "such as ObjOpenSSL!\n",
		    @"prog", [OFApplication programName])];
	} @catch (OFReadOrWriteFailedException *e) {
		OFString *error = OF_LOCALIZED(
		    @"download_failed_read_or_write_failed_any",
		    @"Read or write failed");

		if (!_quiet)
			[of_stdout writeString: @"\n"];

		if ([e isKindOfClass: [OFReadFailedException class]])
			error = OF_LOCALIZED(
			    @"download_failed_read_or_write_failed_read",
			    @"Read failed");
		else if ([e isKindOfClass: [OFWriteFailedException class]])
			error = OF_LOCALIZED(
			    @"download_failed_read_or_write_failed_write",
			    @"Write failed");

		[of_stderr writeString:
		    OF_LOCALIZED(@"download_failed_read_or_write_failed",
		    @"%[prog]: Failed to download <%[url]>!\n"
		    @"  %[error]: %[exception]\n",
		    @"prog", [OFApplication programName],
		    @"url", [[request URL] string],
		    @"error", error,
		    @"exception", e)];
	} @catch (OFHTTPRequestFailedException *e) {
		if (!_quiet)
			[of_stdout writeFormat: @" ➜ %d\n",
						[[e response] statusCode]];

		[of_stderr writeString: OF_LOCALIZED(@"download_failed",
		    @"%[prog]: Failed to download <%[url]>!\n",
		    @"prog", [OFApplication programName],
		    @"url", [[request URL] string])];
	}

	if (!_quiet && response != nil)
		[of_stdout writeFormat: @" ➜ %d\n", [response statusCode]];

	return response;
}
560
561
562
563
564
565
566
567


568


569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589

590
591
592
593
594
595
596
		[_progressBar release];
		_progressBar = nil;

		if (!_quiet)
			[of_stdout writeString: @"\n  Error!\n"];

		URL = [_URLs objectAtIndex: _URLIndex - 1];
		[of_stderr writeFormat: @"%@: Failed to download <%@>: %@\n",


					[OFApplication programName], URL, e];



		_errorCode = 1;
		goto next;
	}

	_received += length;

	[_output writeBuffer: buffer
		      length: length];

	[_progressBar setReceived: _received];

	if ([response isAtEndOfStream] ||
	    (_length >= 0 && _received >= _length)) {
		[_progressBar stop];
		[_progressBar draw];
		[_progressBar release];
		_progressBar = nil;

		if (!_quiet)
			[of_stdout writeString: @"\n  Done!\n"];


		goto next;
	}

	return true;

next:







|
>
>
|
>
>




















|
>







600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
		[_progressBar release];
		_progressBar = nil;

		if (!_quiet)
			[of_stdout writeString: @"\n  Error!\n"];

		URL = [_URLs objectAtIndex: _URLIndex - 1];
		[of_stderr writeString:
		    OF_LOCALIZED(@"download_failed_exception",
		    @"%[prog]: Failed to download <%[url]>: %[exception]\n",
		    @"prog", [OFApplication programName],
		    @"url", URL,
		    @"exception", e)];

		_errorCode = 1;
		goto next;
	}

	_received += length;

	[_output writeBuffer: buffer
		      length: length];

	[_progressBar setReceived: _received];

	if ([response isAtEndOfStream] ||
	    (_length >= 0 && _received >= _length)) {
		[_progressBar stop];
		[_progressBar draw];
		[_progressBar release];
		_progressBar = nil;

		if (!_quiet)
			[of_stdout writeString:
			    OF_LOCALIZED(@"download_done", @"\n  Done!\n")];

		goto next;
	}

	return true;

next:
620
621
622
623
624
625
626

627
628
629
630
631
632
633
634
635
636

637
638
639
640
641
642
643
644
645
646
	if (_URLIndex >= [_URLs count])
		[OFApplication terminateWithStatus: _errorCode];

	@try {
		URLString = [_URLs objectAtIndex: _URLIndex++];
		URL = [OFURL URLWithString: URLString];
	} @catch (OFInvalidFormatException *e) {

		[of_stderr writeFormat: @"%@: Invalid URL: <%@>!\n",
					[OFApplication programName],
					URLString];

		_errorCode = 1;
		goto next;
	}

	if (![[URL scheme] isEqual: @"http"] &&
	    ![[URL scheme] isEqual: @"https"]) {

		[of_stderr writeFormat: @"%@: Invalid scheme: <%@:>!\n",
					[OFApplication programName],
					URLString];

		_errorCode = 1;
		goto next;
	}

	clientHeaders = [[_clientHeaders mutableCopy] autorelease];








>
|
|
|







>
|
|
|







665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
	if (_URLIndex >= [_URLs count])
		[OFApplication terminateWithStatus: _errorCode];

	@try {
		URLString = [_URLs objectAtIndex: _URLIndex++];
		URL = [OFURL URLWithString: URLString];
	} @catch (OFInvalidFormatException *e) {
		[of_stderr writeString: OF_LOCALIZED(@"invalid_url",
		    @"%[prog]: Invalid URL: <%[url]>!\n",
		    @"prog", [OFApplication programName],
		    @"url", URLString)];

		_errorCode = 1;
		goto next;
	}

	if (![[URL scheme] isEqual: @"http"] &&
	    ![[URL scheme] isEqual: @"https"]) {
		[of_stderr writeString: OF_LOCALIZED(@"invalid_scheme",
		    @"%[prog]: Invalid scheme: <%[scheme]:>!\n",
		    @"prog", [OFApplication programName],
		    @"scheme", URLString)];

		_errorCode = 1;
		goto next;
	}

	clientHeaders = [[_clientHeaders mutableCopy] autorelease];

704
705
706
707
708
709
710
711
712
713
714
715
716
717



718
719
720
721



722
723
724
725



726
727
728




729
730
731
732
733
734
735
736
737
738
739
740
741




742
743
744
745
746
747
748
749
750







751
752
753
754
755
756
757
758
759
760

761
762

763
764
765
766
767
768
769
770
771
772
773
774

775

776


777
778
779
780
781
782
783
	type = [headers objectForKey: @"Content-Type"];

	if (lengthString != nil)
		_length = [lengthString decimalValue];

	if (!_quiet) {
		if (type == nil)
			type = @"unknown";

		if (_length >= 0) {
			if (_resumedFrom + _length >= GIBIBYTE)
				lengthString = [OFString stringWithFormat:
				    @"%,.2f GiB",
				    (float)(_resumedFrom + _length) / GIBIBYTE];



			else if (_resumedFrom + _length >= MEBIBYTE)
				lengthString = [OFString stringWithFormat:
				    @"%,.2f MiB",
				    (float)(_resumedFrom + _length) / MEBIBYTE];



			else if (_resumedFrom + _length >= KIBIBYTE)
				lengthString = [OFString stringWithFormat:
				    @"%,.2f KiB",
				    (float)(_resumedFrom + _length) / KIBIBYTE];



			else
				lengthString = [OFString stringWithFormat:
				    @"%jd bytes", _resumedFrom + _length];




		} else
			lengthString = @"unknown";

		[of_stdout writeFormat: @"  Name: %@\n", fileName];

		if (_verbose) {
			void *pool = objc_autoreleasePoolPush();
			OFDictionary OF_GENERIC(OFString*, OFString*) *headers =
			    [response headers];
			OFEnumerator *keyEnumerator = [headers keyEnumerator];
			OFEnumerator *objectEnumerator =
			    [headers objectEnumerator];
			OFString *key, *object;





			while ((key = [keyEnumerator nextObject]) != nil &&
			    (object = [objectEnumerator nextObject]) != nil)
				[of_stdout writeFormat: @"  %@: %@\n",
							key, object];

			objc_autoreleasePoolPop(pool);
		} else {
			[of_stdout writeFormat: @"  Type: %@\n", type];







			[of_stdout writeFormat: @"  Size: %@\n", lengthString];
		}
	}

	if ([_outputPath isEqual: @"-"])
		_output = of_stdout;
	else {
		if (!_continue && !_force &&
		    [fileManager fileExistsAtPath: fileName]) {
			[of_stderr writeFormat:

			    @"%@: File %@ already exists!\n",
			    [OFApplication programName], fileName];


			_errorCode = 1;
			goto next;
		}

		@try {
			OFString *mode =
			    ([response statusCode] == 206 ? @"ab" : @"wb");
			_output = [[OFFile alloc] initWithPath: fileName
							  mode: mode];
		} @catch (OFOpenItemFailedException *e) {
			[of_stderr writeFormat:

			    @"%@: Failed to open file %@!\n",

			    [OFApplication programName], fileName];



			_errorCode = 1;
			goto next;
		}
	}

	if (!_quiet) {







|


|

|

>
>
>
|

|

>
>
>
|

|

>
>
>
|

|
>
>
>
>

|
|
<









>
>
>
>








|
>
>
>
>
>
>
>
|








|
>
|
|
>











|
>
|
>
|
>
>







751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791

792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
	type = [headers objectForKey: @"Content-Type"];

	if (lengthString != nil)
		_length = [lengthString decimalValue];

	if (!_quiet) {
		if (type == nil)
			type = OF_LOCALIZED(@"type_unknown", @"unknown");

		if (_length >= 0) {
			if (_resumedFrom + _length >= GIBIBYTE) {
				lengthString = [OFString stringWithFormat:
				    @"%,.2f",
				    (float)(_resumedFrom + _length) / GIBIBYTE];
				lengthString = OF_LOCALIZED(@"size_gib",
				    @"%[num] GiB",
				    @"num", lengthString);
			} else if (_resumedFrom + _length >= MEBIBYTE) {
				lengthString = [OFString stringWithFormat:
				    @"%,.2f",
				    (float)(_resumedFrom + _length) / MEBIBYTE];
				lengthString = OF_LOCALIZED(@"size_mib",
				    @"%[num] MiB",
				    @"num", lengthString);
			} else if (_resumedFrom + _length >= KIBIBYTE) {
				lengthString = [OFString stringWithFormat:
				    @"%,.2f",
				    (float)(_resumedFrom + _length) / KIBIBYTE];
				lengthString = OF_LOCALIZED(@"size_kib",
				    @"%[num] KiB",
				    @"num", lengthString);
			} else {
				lengthString = [OFString stringWithFormat:
				    @"%jd", _resumedFrom + _length];
				lengthString = OF_LOCALIZED(@"size_bytes",
				    @"%[num] bytes",
				    @"num", lengthString);
			}
		} else
			lengthString =
			    OF_LOCALIZED(@"size_unknown", @"unknown");


		if (_verbose) {
			void *pool = objc_autoreleasePoolPush();
			OFDictionary OF_GENERIC(OFString*, OFString*) *headers =
			    [response headers];
			OFEnumerator *keyEnumerator = [headers keyEnumerator];
			OFEnumerator *objectEnumerator =
			    [headers objectEnumerator];
			OFString *key, *object;

			[of_stdout writeString: OF_LOCALIZED(@"info_name_nopad",
			    @"  Name: %[name]\n",
			    @"name", fileName)];

			while ((key = [keyEnumerator nextObject]) != nil &&
			    (object = [objectEnumerator nextObject]) != nil)
				[of_stdout writeFormat: @"  %@: %@\n",
							key, object];

			objc_autoreleasePoolPop(pool);
		} else {
			[of_stdout writeString: OF_LOCALIZED(@"info_name",
			    @"  Name: %[name]\n",
			    @"name", fileName)];
			[of_stdout writeString: OF_LOCALIZED(@"info_type",
			    @"  Type: %[type]\n",
			    @"type", type)];
			[of_stdout writeString: OF_LOCALIZED(@"info_size",
			    @"  Size: %[size]\n",
			    @"size", lengthString)];
		}
	}

	if ([_outputPath isEqual: @"-"])
		_output = of_stdout;
	else {
		if (!_continue && !_force &&
		    [fileManager fileExistsAtPath: fileName]) {
			[of_stderr writeString:
			    OF_LOCALIZED(@"ouput_already_exists",
			    @"%[prog]: File %[filename] already exists!\n",
			    @"prog", [OFApplication programName],
			    @"filename", fileName)];

			_errorCode = 1;
			goto next;
		}

		@try {
			OFString *mode =
			    ([response statusCode] == 206 ? @"ab" : @"wb");
			_output = [[OFFile alloc] initWithPath: fileName
							  mode: mode];
		} @catch (OFOpenItemFailedException *e) {
			[of_stderr writeString:
			    OF_LOCALIZED(@"failed_to_open_output",
			    @"%[prog]: Failed to open file %[filename]: "
			    @"%[exception]\n",
			    @"prog", [OFApplication programName],
			    @"filename",fileName,
			    @"exception", e)];

			_errorCode = 1;
			goto next;
		}
	}

	if (!_quiet) {

Modified utils/ofhttp/ProgressBar.m from [b2906f802b] to [1f06b0db97].

17
18
19
20
21
22
23

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

#include <math.h>

#import "OFDate.h"
#import "OFStdIOStream.h"
#import "OFTimer.h"


#import "ProgressBar.h"

#define GIBIBYTE (1024 * 1024 * 1024)
#define MEBIBYTE (1024 * 1024)
#define KIBIBYTE (1024)








>







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

#include <math.h>

#import "OFDate.h"
#import "OFStdIOStream.h"
#import "OFTimer.h"
#import "OFLocalization.h"

#import "ProgressBar.h"

#define GIBIBYTE (1024 * 1024 * 1024)
#define MEBIBYTE (1024 * 1024)
#define KIBIBYTE (1024)

134
135
136
137
138
139
140
141

142



143
144
145
146
147
148

149



150

151



152

153



154


155



156
157
158
159
160
161
162
163



164
165
166
167



168
169
170
171



172
173
174




175
176
177
178
179
180

181



182

183



184

185



186


187



188
189
190
191
192
193
194

		_BPS = (float)_received / (float)timeInterval;
		_ETA = timeInterval;
	}

	if (isinf(_ETA))
		[of_stdout writeString: @"--:--:-- "];
	else if (_ETA >= 99 * 3600)

		[of_stdout writeFormat: @"%,4.2f d ", _ETA / (24 * 3600)];



	else
		[of_stdout writeFormat: @"%2u:%02u:%02u ",
		    (uint8_t)(_ETA / 3600), (uint8_t)(_ETA / 60) % 60,
		    (uint8_t)_ETA % 60];

	if (_BPS >= GIBIBYTE)

		[of_stdout writeFormat: @"%,7.2f GiB/s", _BPS / GIBIBYTE];



	else if (_BPS >= MEBIBYTE)

		[of_stdout writeFormat: @"%,7.2f MiB/s", _BPS / MEBIBYTE];



	else if (_BPS >= KIBIBYTE)

		[of_stdout writeFormat: @"%,7.2f KiB/s", _BPS / KIBIBYTE];



	else


		[of_stdout writeFormat: @"%,7.2f B/s  ", _BPS];



}

- (void)_drawReceived
{
	if (_resumedFrom + _received >= GIBIBYTE)
		[of_stdout writeFormat:
		    @"\r  %,7.2f GiB ",
		    (float)(_resumedFrom + _received) / GIBIBYTE];



	else if (_resumedFrom + _received >= MEBIBYTE)
		[of_stdout writeFormat:
		    @"\r  %,7.2f MiB ",
		    (float)(_resumedFrom + _received) / MEBIBYTE];



	else if (_resumedFrom + _received >= KIBIBYTE)
		[of_stdout writeFormat:
		    @"\r  %,7.2f KiB ",
		    (float)(_resumedFrom + _received) / KIBIBYTE];



	else
		[of_stdout writeFormat:
		    @"\r  %jd bytes ", _resumedFrom + _received];





	if (_stopped)
		_BPS = (float)_received /
		    -(float)[_startDate timeIntervalSinceNow];

	if (_BPS >= GIBIBYTE)

		[of_stdout writeFormat: @"%,7.2f GiB/s", _BPS / GIBIBYTE];



	else if (_BPS >= MEBIBYTE)

		[of_stdout writeFormat: @"%,7.2f MiB/s", _BPS / MEBIBYTE];



	else if (_BPS >= KIBIBYTE)

		[of_stdout writeFormat: @"%,7.2f KiB/s", _BPS / KIBIBYTE];



	else


		[of_stdout writeFormat: @"%,7.2f B/s  ", _BPS];



}

- (void)draw
{
	if (_length > 0)
		[self _drawProgress];
	else







|
>
|
>
>
>
|




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




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





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







135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183

184
185
186
187
188
189

190
191
192
193
194
195

196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243

		_BPS = (float)_received / (float)timeInterval;
		_ETA = timeInterval;
	}

	if (isinf(_ETA))
		[of_stdout writeString: @"--:--:-- "];
	else if (_ETA >= 99 * 3600) {
		OFString *num = [OFString stringWithFormat:
		    @"%,4.2f", _ETA / (24 * 3600)];
		[of_stdout writeString: OF_LOCALIZED(@"eta_days",
		    @"%[num] d ",
		    @"num", num)];
	} else
		[of_stdout writeFormat: @"%2u:%02u:%02u ",
		    (uint8_t)(_ETA / 3600), (uint8_t)(_ETA / 60) % 60,
		    (uint8_t)_ETA % 60];

	if (_BPS >= GIBIBYTE) {
		OFString *num = [OFString stringWithFormat:
		    @"%,7.2f", _BPS / GIBIBYTE];
		[of_stdout writeString: OF_LOCALIZED(@"progress_gibs",
		    @"%[num] GiB/s",
		    @"num", num)];
	} else if (_BPS >= MEBIBYTE) {
		OFString *num = [OFString stringWithFormat:
		    @"%,7.2f", _BPS / MEBIBYTE];
		[of_stdout writeString: OF_LOCALIZED(@"progress_mibs",
		    @"%[num] MiB/s",
		    @"num", num)];
	} else if (_BPS >= KIBIBYTE) {
		OFString *num = [OFString stringWithFormat:
		    @"%,7.2f", _BPS / KIBIBYTE];
		[of_stdout writeString: OF_LOCALIZED(@"progress_kibs",
		    @"%[num] KiB/s",
		    @"num", num)];
	} else {
		OFString *num = [OFString stringWithFormat:
		    @"%,7.2f", _BPS];
		[of_stdout writeString: OF_LOCALIZED(@"progress_bps",
		    @"%[num] B/s  ",
		    @"num", num)];
	}
}

- (void)_drawReceived
{
	if (_resumedFrom + _received >= GIBIBYTE) {
		OFString *num = [OFString stringWithFormat:

		    @"%,7.2f", (float)(_resumedFrom + _received) / GIBIBYTE];
		[of_stdout writeString: OF_LOCALIZED(@"progress_gib",
		    @"\r  %[num] GiB ",
		    @"num", num)];
	} else if (_resumedFrom + _received >= MEBIBYTE) {
		OFString *num = [OFString stringWithFormat:

		    @"%,7.2f", (float)(_resumedFrom + _received) / MEBIBYTE];
		[of_stdout writeString: OF_LOCALIZED(@"progress_mib",
		    @"\r  %[num] MiB ",
		    @"num", num)];
	} else if (_resumedFrom + _received >= KIBIBYTE) {
		OFString *num = [OFString stringWithFormat:

		    @"%,7.2f", (float)(_resumedFrom + _received) / KIBIBYTE];
		[of_stdout writeString: OF_LOCALIZED(@"progress_kib",
		    @"\r  %[num] KiB ",
		    @"num", num)];
	} else {
		OFString *num = [OFString stringWithFormat:
		    @"%jd", _resumedFrom + _received];
		[of_stdout writeString: OF_LOCALIZED(@"progress_bytes",
		    @"\r  %[num] bytes ",
		    @"num", num)];
	}

	if (_stopped)
		_BPS = (float)_received /
		    -(float)[_startDate timeIntervalSinceNow];

	if (_BPS >= GIBIBYTE) {
		OFString *num = [OFString stringWithFormat:
		    @"%,7.2f", _BPS / GIBIBYTE];
		[of_stdout writeString: OF_LOCALIZED(@"progress_gibs",
		    @"%[num] GiB/s",
		    @"num", num)];
	} else if (_BPS >= MEBIBYTE) {
		OFString *num = [OFString stringWithFormat:
		    @"%,7.2f", _BPS / MEBIBYTE];
		[of_stdout writeString: OF_LOCALIZED(@"progress_mibs",
		    @"%[num] MiB/s",
		    @"num", num)];
	} else if (_BPS >= KIBIBYTE) {
		OFString *num = [OFString stringWithFormat:
		    @"%,7.2f", _BPS / KIBIBYTE];
		[of_stdout writeString: OF_LOCALIZED(@"progress_kibs",
		    @"%[num] KiB/s",
		    @"num", num)];
	} else {
		OFString *num = [OFString stringWithFormat:
		    @"%,7.2f", _BPS];
		[of_stdout writeString: OF_LOCALIZED(@"progress_bps",
		    @"%[num] B/s  ",
		    @"num", num)];
	}
}

- (void)draw
{
	if (_length > 0)
		[self _drawProgress];
	else