ObjFW  Check-in [3e1b6bccbc]

Overview
Comment:Properly handle UTF-8 in Win32 console

The previous way was to set the codepage to UTF-8, however, this does
not work properly on some versions of Windows.

Instead, this catches reads / writes on of_std* on the lowlevel,
interprets it as UTF-8, converts it to / from UTF-16 and then uses
ReadConsoleW() / WriteConsoleW().

Surrogates being cut in the middle is not properly handled yet, this
will be implemented in a follow up commit.

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 3e1b6bccbc1d88214cc6967bdc8403b983278783857e2ee2480b5adba19852c5
User & Date: js on 2016-03-12 20:28:31
Other Links: manifest | tags
Context
2016-03-12
21:19
Work around Doxygen shortcomings check-in: 2425966b66 user: js tags: trunk
20:28
Properly handle UTF-8 in Win32 console check-in: 3e1b6bccbc user: js tags: trunk
18:54
ObjFW.xcodeproj: Increase LastUpgradeCheck check-in: ec43a5bda4 user: js tags: trunk
Changes

Modified ObjFW.xcodeproj/project.pbxproj from [dbc183526e] to [0c3df7c8ba].

433
434
435
436
437
438
439

440
441
442
443
444
445
446
		4BE52D2217B990B4005958D1 /* OFZIPArchive.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BE52D2017B990B4005958D1 /* OFZIPArchive.m */; };
		4BE52D2517B990DA005958D1 /* OFChecksumFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BE52D2317B990DA005958D1 /* OFChecksumFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; };
		4BE52D2617B990DA005958D1 /* OFChecksumFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BE52D2417B990DA005958D1 /* OFChecksumFailedException.m */; };
		4BEAF52D19A811DA00B61868 /* module.map in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4BEAF52519A8107500B61868 /* module.map */; };
		4BEC83B919B7CB7100E4BB08 /* OFRIPEMD160Hash.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BEC83B719B7CB7100E4BB08 /* OFRIPEMD160Hash.h */; settings = {ATTRIBUTES = (Public, ); }; };
		4BEC83BA19B7CB7100E4BB08 /* OFRIPEMD160Hash.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BEC83B819B7CB7100E4BB08 /* OFRIPEMD160Hash.m */; };
		4BEC83BC19B7CBDE00E4BB08 /* OFRIPEMD160HashTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BEC83BB19B7CBDE00E4BB08 /* OFRIPEMD160HashTests.m */; };

		4BF33AFB133807590059CEF7 /* ObjFW.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B3D23761337FBC800DD29B8 /* ObjFW.framework */; };
		4BF33AFC133807A20059CEF7 /* OFArrayTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B6EF66E1235358D0076B512 /* OFArrayTests.m */; };
		4BF33AFD133807A20059CEF7 /* OFBlockTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BE5F0E412DF4259005C7A0C /* OFBlockTests.m */; };
		4BF33AFE133807A20059CEF7 /* OFDataArrayTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B6EF66F1235358D0076B512 /* OFDataArrayTests.m */; };
		4BF33AFF133807A20059CEF7 /* OFDateTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BE5F0E512DF4259005C7A0C /* OFDateTests.m */; };
		4BF33B00133807A20059CEF7 /* OFDictionaryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B6EF6701235358D0076B512 /* OFDictionaryTests.m */; };
		4BF33B03133807A20059CEF7 /* OFListTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B6EF6721235358D0076B512 /* OFListTests.m */; };







>







433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
		4BE52D2217B990B4005958D1 /* OFZIPArchive.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BE52D2017B990B4005958D1 /* OFZIPArchive.m */; };
		4BE52D2517B990DA005958D1 /* OFChecksumFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BE52D2317B990DA005958D1 /* OFChecksumFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; };
		4BE52D2617B990DA005958D1 /* OFChecksumFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BE52D2417B990DA005958D1 /* OFChecksumFailedException.m */; };
		4BEAF52D19A811DA00B61868 /* module.map in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4BEAF52519A8107500B61868 /* module.map */; };
		4BEC83B919B7CB7100E4BB08 /* OFRIPEMD160Hash.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BEC83B719B7CB7100E4BB08 /* OFRIPEMD160Hash.h */; settings = {ATTRIBUTES = (Public, ); }; };
		4BEC83BA19B7CB7100E4BB08 /* OFRIPEMD160Hash.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BEC83B819B7CB7100E4BB08 /* OFRIPEMD160Hash.m */; };
		4BEC83BC19B7CBDE00E4BB08 /* OFRIPEMD160HashTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BEC83BB19B7CBDE00E4BB08 /* OFRIPEMD160HashTests.m */; };
		4BF171B21C949A3300F5B47B /* OFStdIOStream+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BF171B11C9499F300F5B47B /* OFStdIOStream+Private.h */; };
		4BF33AFB133807590059CEF7 /* ObjFW.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B3D23761337FBC800DD29B8 /* ObjFW.framework */; };
		4BF33AFC133807A20059CEF7 /* OFArrayTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B6EF66E1235358D0076B512 /* OFArrayTests.m */; };
		4BF33AFD133807A20059CEF7 /* OFBlockTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BE5F0E412DF4259005C7A0C /* OFBlockTests.m */; };
		4BF33AFE133807A20059CEF7 /* OFDataArrayTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B6EF66F1235358D0076B512 /* OFDataArrayTests.m */; };
		4BF33AFF133807A20059CEF7 /* OFDateTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BE5F0E512DF4259005C7A0C /* OFDateTests.m */; };
		4BF33B00133807A20059CEF7 /* OFDictionaryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B6EF6701235358D0076B512 /* OFDictionaryTests.m */; };
		4BF33B03133807A20059CEF7 /* OFListTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B6EF6721235358D0076B512 /* OFListTests.m */; };
961
962
963
964
965
966
967

968
969
970
971
972
973
974
		4BE5F0E412DF4259005C7A0C /* OFBlockTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFBlockTests.m; path = tests/OFBlockTests.m; sourceTree = SOURCE_ROOT; };
		4BE5F0E512DF4259005C7A0C /* OFDateTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFDateTests.m; path = tests/OFDateTests.m; sourceTree = SOURCE_ROOT; };
		4BEAF52519A8107500B61868 /* module.map */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; name = module.map; path = misc/module.map; sourceTree = SOURCE_ROOT; };
		4BEC83B719B7CB7100E4BB08 /* OFRIPEMD160Hash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFRIPEMD160Hash.h; path = src/OFRIPEMD160Hash.h; sourceTree = "<group>"; };
		4BEC83B819B7CB7100E4BB08 /* OFRIPEMD160Hash.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFRIPEMD160Hash.m; path = src/OFRIPEMD160Hash.m; sourceTree = "<group>"; };
		4BEC83BB19B7CBDE00E4BB08 /* OFRIPEMD160HashTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFRIPEMD160HashTests.m; path = tests/OFRIPEMD160HashTests.m; sourceTree = "<group>"; };
		4BF0749512DFAFCA00A4ADD1 /* OFURLTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFURLTests.m; path = tests/OFURLTests.m; sourceTree = SOURCE_ROOT; };

		4BF1BCBF11C9663F0025511F /* objfw-defs.h.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "objfw-defs.h.in"; path = "src/objfw-defs.h.in"; sourceTree = "<group>"; };
		4BF1BCC011C9663F0025511F /* OFHash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFHash.h; path = src/OFHash.h; sourceTree = "<group>"; };
		4BF1BCC211C9663F0025511F /* OFMD5Hash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFMD5Hash.h; path = src/OFMD5Hash.h; sourceTree = "<group>"; };
		4BF1BCC311C9663F0025511F /* OFMD5Hash.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFMD5Hash.m; path = src/OFMD5Hash.m; sourceTree = "<group>"; };
		4BF1BCC411C9663F0025511F /* OFSHA1Hash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFSHA1Hash.h; path = src/OFSHA1Hash.h; sourceTree = "<group>"; };
		4BF1BCC511C9663F0025511F /* OFSHA1Hash.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFSHA1Hash.m; path = src/OFSHA1Hash.m; sourceTree = "<group>"; };
		4BF1BCC611C9663F0025511F /* OFString+Hashing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "OFString+Hashing.h"; path = "src/OFString+Hashing.h"; sourceTree = "<group>"; };







>







962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
		4BE5F0E412DF4259005C7A0C /* OFBlockTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFBlockTests.m; path = tests/OFBlockTests.m; sourceTree = SOURCE_ROOT; };
		4BE5F0E512DF4259005C7A0C /* OFDateTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFDateTests.m; path = tests/OFDateTests.m; sourceTree = SOURCE_ROOT; };
		4BEAF52519A8107500B61868 /* module.map */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; name = module.map; path = misc/module.map; sourceTree = SOURCE_ROOT; };
		4BEC83B719B7CB7100E4BB08 /* OFRIPEMD160Hash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFRIPEMD160Hash.h; path = src/OFRIPEMD160Hash.h; sourceTree = "<group>"; };
		4BEC83B819B7CB7100E4BB08 /* OFRIPEMD160Hash.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFRIPEMD160Hash.m; path = src/OFRIPEMD160Hash.m; sourceTree = "<group>"; };
		4BEC83BB19B7CBDE00E4BB08 /* OFRIPEMD160HashTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFRIPEMD160HashTests.m; path = tests/OFRIPEMD160HashTests.m; sourceTree = "<group>"; };
		4BF0749512DFAFCA00A4ADD1 /* OFURLTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFURLTests.m; path = tests/OFURLTests.m; sourceTree = SOURCE_ROOT; };
		4BF171B11C9499F300F5B47B /* OFStdIOStream+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "OFStdIOStream+Private.h"; path = "src/OFStdIOStream+Private.h"; sourceTree = "<group>"; };
		4BF1BCBF11C9663F0025511F /* objfw-defs.h.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "objfw-defs.h.in"; path = "src/objfw-defs.h.in"; sourceTree = "<group>"; };
		4BF1BCC011C9663F0025511F /* OFHash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFHash.h; path = src/OFHash.h; sourceTree = "<group>"; };
		4BF1BCC211C9663F0025511F /* OFMD5Hash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFMD5Hash.h; path = src/OFMD5Hash.h; sourceTree = "<group>"; };
		4BF1BCC311C9663F0025511F /* OFMD5Hash.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFMD5Hash.m; path = src/OFMD5Hash.m; sourceTree = "<group>"; };
		4BF1BCC411C9663F0025511F /* OFSHA1Hash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFSHA1Hash.h; path = src/OFSHA1Hash.h; sourceTree = "<group>"; };
		4BF1BCC511C9663F0025511F /* OFSHA1Hash.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFSHA1Hash.m; path = src/OFSHA1Hash.m; sourceTree = "<group>"; };
		4BF1BCC611C9663F0025511F /* OFString+Hashing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "OFString+Hashing.h"; path = "src/OFString+Hashing.h"; sourceTree = "<group>"; };
1412
1413
1414
1415
1416
1417
1418

1419
1420
1421
1422
1423
1424
1425
				4B60259C19B76A5C00694BCC /* OFSHA384Or512Hash.m */,
				4B60259D19B76A5C00694BCC /* OFSHA512Hash.h */,
				4B60259E19B76A5C00694BCC /* OFSHA512Hash.m */,
				4B141BA215FCDF74000C21A8 /* OFSortedList.h */,
				4B141BA315FCDF74000C21A8 /* OFSortedList.m */,
				4B0256E2172B60400062B5F1 /* OFStdIOStream.h */,
				4B0256E3172B60400062B5F1 /* OFStdIOStream.m */,

				4B67997D1099E7C50041064A /* OFStream.h */,
				4B67997E1099E7C50041064A /* OFStream.m */,
				4B6C8AD217BD5C2E00B194F2 /* OFStream+Private.h */,
				4BAF5F49123460C900F4E111 /* OFStreamSocket.h */,
				4BAF5F4A123460C900F4E111 /* OFStreamSocket.m */,
				4B67997F1099E7C50041064A /* OFString.h */,
				4B6799801099E7C50041064A /* OFString.m */,







>







1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
				4B60259C19B76A5C00694BCC /* OFSHA384Or512Hash.m */,
				4B60259D19B76A5C00694BCC /* OFSHA512Hash.h */,
				4B60259E19B76A5C00694BCC /* OFSHA512Hash.m */,
				4B141BA215FCDF74000C21A8 /* OFSortedList.h */,
				4B141BA315FCDF74000C21A8 /* OFSortedList.m */,
				4B0256E2172B60400062B5F1 /* OFStdIOStream.h */,
				4B0256E3172B60400062B5F1 /* OFStdIOStream.m */,
				4BF171B11C9499F300F5B47B /* OFStdIOStream+Private.h */,
				4B67997D1099E7C50041064A /* OFStream.h */,
				4B67997E1099E7C50041064A /* OFStream.m */,
				4B6C8AD217BD5C2E00B194F2 /* OFStream+Private.h */,
				4BAF5F49123460C900F4E111 /* OFStreamSocket.h */,
				4BAF5F4A123460C900F4E111 /* OFStreamSocket.m */,
				4B67997F1099E7C50041064A /* OFString.h */,
				4B6799801099E7C50041064A /* OFString.m */,
1810
1811
1812
1813
1814
1815
1816

1817
1818
1819
1820
1821
1822
1823
				4B2B3E81140D430500EC2F7C /* OFMutableArray_adjacent.h in Headers */,
				4B2B3E83140D430500EC2F7C /* OFMutableDictionary_hashtable.h in Headers */,
				4BA85BCC140ECCE800E91D51 /* OFMutableSet_hashtable.h in Headers */,
				4B552552147AA5DB0003BF47 /* OFMutableString_UTF8.h in Headers */,
				4B6C8AD817BD5C2E00B194F2 /* OFRunLoop+Private.h in Headers */,
				4BA85BCE140ECCE800E91D51 /* OFSet_hashtable.h in Headers */,
				4B8385161951BF9500D5358A /* OFSettings_INIFile.h in Headers */,

				4B6C8AD917BD5C2E00B194F2 /* OFStream+Private.h in Headers */,
				4B552554147AA5DB0003BF47 /* OFString_UTF8.h in Headers */,
				4B6C8ADB17BD5C2E00B194F2 /* OFString_UTF8+Private.h in Headers */,
				4BD653C5143B8489006182F0 /* OFTCPSocket+SOCKS5.h in Headers */,
				4B6C8ADC17BD5C2E00B194F2 /* OFThread+Private.h in Headers */,
				4B6C8ADD17BD5C2E00B194F2 /* OFTimer+Private.h in Headers */,
				4B6C8ADE17BD5C2E00B194F2 /* OFZIPArchiveEntry+Private.h in Headers */,







>







1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
				4B2B3E81140D430500EC2F7C /* OFMutableArray_adjacent.h in Headers */,
				4B2B3E83140D430500EC2F7C /* OFMutableDictionary_hashtable.h in Headers */,
				4BA85BCC140ECCE800E91D51 /* OFMutableSet_hashtable.h in Headers */,
				4B552552147AA5DB0003BF47 /* OFMutableString_UTF8.h in Headers */,
				4B6C8AD817BD5C2E00B194F2 /* OFRunLoop+Private.h in Headers */,
				4BA85BCE140ECCE800E91D51 /* OFSet_hashtable.h in Headers */,
				4B8385161951BF9500D5358A /* OFSettings_INIFile.h in Headers */,
				4BF171B21C949A3300F5B47B /* OFStdIOStream+Private.h in Headers */,
				4B6C8AD917BD5C2E00B194F2 /* OFStream+Private.h in Headers */,
				4B552554147AA5DB0003BF47 /* OFString_UTF8.h in Headers */,
				4B6C8ADB17BD5C2E00B194F2 /* OFString_UTF8+Private.h in Headers */,
				4BD653C5143B8489006182F0 /* OFTCPSocket+SOCKS5.h in Headers */,
				4B6C8ADC17BD5C2E00B194F2 /* OFThread+Private.h in Headers */,
				4B6C8ADD17BD5C2E00B194F2 /* OFTimer+Private.h in Headers */,
				4B6C8ADE17BD5C2E00B194F2 /* OFZIPArchiveEntry+Private.h in Headers */,

Modified configure.ac from [7f36bd5e2a] to [7ffad8963b].

557
558
559
560
561
562
563






564
565
566
567
568
569
570
			ac_cv_snprintf_useful_ret="no"
		])
	])
	AC_MSG_RESULT($ac_cv_snprintf_useful_ret)
])
test x"$have_asprintf" != x"yes" -a x"$ac_cv_snprintf_useful_ret" != x"yes" && \
	AC_MSG_ERROR(No asprintf and no snprintf returning required space!)







AC_CHECK_FUNCS(sigaction)

AC_CHECK_FUNCS([arc4random random], break)

AC_CHECK_LIB(dl, dlopen, LIBS="$LIBS -ldl")
AC_CHECK_HEADERS_ONCE(dlfcn.h)







>
>
>
>
>
>







557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
			ac_cv_snprintf_useful_ret="no"
		])
	])
	AC_MSG_RESULT($ac_cv_snprintf_useful_ret)
])
test x"$have_asprintf" != x"yes" -a x"$ac_cv_snprintf_useful_ret" != x"yes" && \
	AC_MSG_ERROR(No asprintf and no snprintf returning required space!)

case "$host_os" in
mingw*)
	AC_SUBST(OFSTDIOSTREAM_WIN32CONSOLE_M, "OFStdIOStream_Win32Console.m")
	;;
esac

AC_CHECK_FUNCS(sigaction)

AC_CHECK_FUNCS([arc4random random], break)

AC_CHECK_LIB(dl, dlopen, LIBS="$LIBS -ldl")
AC_CHECK_HEADERS_ONCE(dlfcn.h)

Modified extra.mk.in from [e68111f1bd] to [0a73f0c691].

34
35
36
37
38
39
40

41
42
43
44
45
46
47
OFHTTP = @OFHTTP@
OFHTTPCLIENTTESTS_M = @OFHTTPCLIENTTESTS_M@
OFPROCESS_M = @OFPROCESS_M@
OFKERNELEVENTOBSERVER_EPOLL_M = @OFKERNELEVENTOBSERVER_EPOLL_M@
OFKERNELEVENTOBSERVER_KQUEUE_M = @OFKERNELEVENTOBSERVER_KQUEUE_M@
OFKERNELEVENTOBSERVER_POLL_M = @OFKERNELEVENTOBSERVER_POLL_M@
OFKERNELEVENTOBSERVER_SELECT_M = @OFKERNELEVENTOBSERVER_SELECT_M@

OFZIP = @OFZIP@
PROPERTIESTESTS_M = @PROPERTIESTESTS_M@
REEXPORT_LIBOBJC = @REEXPORT_LIBOBJC@
RUNTIME = @RUNTIME@
RUNTIME_A = @RUNTIME_A@
RUNTIME_RUNTIME_A = @RUNTIME_RUNTIME_A@
RUNTIME_RUNTIME_LIB_A = @RUNTIME_RUNTIME_LIB_A@







>







34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
OFHTTP = @OFHTTP@
OFHTTPCLIENTTESTS_M = @OFHTTPCLIENTTESTS_M@
OFPROCESS_M = @OFPROCESS_M@
OFKERNELEVENTOBSERVER_EPOLL_M = @OFKERNELEVENTOBSERVER_EPOLL_M@
OFKERNELEVENTOBSERVER_KQUEUE_M = @OFKERNELEVENTOBSERVER_KQUEUE_M@
OFKERNELEVENTOBSERVER_POLL_M = @OFKERNELEVENTOBSERVER_POLL_M@
OFKERNELEVENTOBSERVER_SELECT_M = @OFKERNELEVENTOBSERVER_SELECT_M@
OFSTDIOSTREAM_WIN32CONSOLE_M = @OFSTDIOSTREAM_WIN32CONSOLE_M@
OFZIP = @OFZIP@
PROPERTIESTESTS_M = @PROPERTIESTESTS_M@
REEXPORT_LIBOBJC = @REEXPORT_LIBOBJC@
RUNTIME = @RUNTIME@
RUNTIME_A = @RUNTIME_A@
RUNTIME_RUNTIME_A = @RUNTIME_RUNTIME_A@
RUNTIME_RUNTIME_LIB_A = @RUNTIME_RUNTIME_LIB_A@

Modified src/Makefile from [d07ba32ec9] to [2bb467052c].

49
50
51
52
53
54
55

56
57
58
59
60
61
62
       OFSHA224Or256Hash.m		\
       OFSHA256Hash.m			\
       OFSHA384Hash.m			\
       OFSHA384Or512Hash.m		\
       OFSHA512Hash.m			\
       OFSortedList.m			\
       OFStdIOStream.m			\

       OFStream.m			\
       OFString.m			\
       OFString+Hashing.m		\
       OFString+JSONValue.m		\
       OFString+Serialization.m		\
       OFString+URLEncoding.m		\
       OFString+XMLEscaping.m		\







>







49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
       OFSHA224Or256Hash.m		\
       OFSHA256Hash.m			\
       OFSHA384Hash.m			\
       OFSHA384Or512Hash.m		\
       OFSHA512Hash.m			\
       OFSortedList.m			\
       OFStdIOStream.m			\
       ${OFSTDIOSTREAM_WIN32CONSOLE_M}	\
       OFStream.m			\
       OFString.m			\
       OFString+Hashing.m		\
       OFString+JSONValue.m		\
       OFString+Serialization.m		\
       OFString+URLEncoding.m		\
       OFString+XMLEscaping.m		\

Added src/OFStdIOStream+Private.h version [f20eb9937a].



















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * 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 "OFStdIOStream.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFStdIOStream ()
- (instancetype)OF_initWithFileDescriptor: (int)fd;
@end

OF_ASSUME_NONNULL_END

Modified src/OFStdIOStream.h from [f1e2e1ce28] to [70525b9be4].

22
23
24
25
26
27
28

29

30
31
32
33
34
35
36
 * @class OFStdIOStream OFStdIOStream.h ObjFW/OFStdIOStream.h
 *
 * @brief A class for providing standard input, output and error as OFStream.
 *
 * The global variables @ref of_stdin, @ref of_stdout and @ref of_stderr are
 * instances of this class and need no initialization.
 */

OF_SUBCLASSING_RESTRICTED

@interface OFStdIOStream: OFStream
{
	int  _fd;
	bool _atEndOfStream;
}
@end








>

>







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 * @class OFStdIOStream OFStdIOStream.h ObjFW/OFStdIOStream.h
 *
 * @brief A class for providing standard input, output and error as OFStream.
 *
 * The global variables @ref of_stdin, @ref of_stdout and @ref of_stderr are
 * instances of this class and need no initialization.
 */
#ifdef OF_STDIO_STREAM_WIN32_CONSOLE_H
OF_SUBCLASSING_RESTRICTED
#endif
@interface OFStdIOStream: OFStream
{
	int  _fd;
	bool _atEndOfStream;
}
@end

Modified src/OFStdIOStream.m from [b1b921ad96] to [e2adf5fa8a].

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
# undef __USE_XOPEN
#endif

#include <errno.h>
#include <unistd.h>

#import "OFStdIOStream.h"

#import "OFDate.h"
#import "OFApplication.h"

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

#ifdef OF_WINDOWS
# include <windows.h>
#endif

OFStdIOStream *of_stdin = nil;
OFStdIOStream *of_stdout = nil;
OFStdIOStream *of_stderr = nil;

#ifdef OF_WINDOWS
UINT originalConsoleCP;
UINT originalConsoleOutputCP;

static void
restoreCodepage(void)
{
	SetConsoleCP(originalConsoleCP);
	SetConsoleOutputCP(originalConsoleOutputCP);
}
#endif

@interface OFStdIOStream ()
- (instancetype)OF_initWithFileDescriptor: (int)fd;
@end

void
of_log(OFConstantString *format, ...)
{
	void *pool = objc_autoreleasePoolPush();
	OFDate *date;
	OFString *dateString, *me, *msg;
	va_list arguments;







>







<
<
<
<




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







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
# undef __USE_XOPEN
#endif

#include <errno.h>
#include <unistd.h>

#import "OFStdIOStream.h"
#import "OFStdIOStream+Private.h"
#import "OFDate.h"
#import "OFApplication.h"

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





OFStdIOStream *of_stdin = nil;
OFStdIOStream *of_stdout = nil;
OFStdIOStream *of_stderr = nil;

















void
of_log(OFConstantString *format, ...)
{
	void *pool = objc_autoreleasePoolPush();
	OFDate *date;
	OFString *dateString, *me, *msg;
	va_list arguments;
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
	[of_stderr writeFormat: @"[%@.%03d %@(%d)] %@\n", dateString,
				[date microsecond] / 1000, me, getpid(), msg];

	objc_autoreleasePoolPop(pool);
}

@implementation OFStdIOStream

+ (void)load
{
	of_stdin = [[OFStdIOStream alloc] OF_initWithFileDescriptor: 0];
	of_stdout = [[OFStdIOStream alloc] OF_initWithFileDescriptor: 1];
	of_stderr = [[OFStdIOStream alloc] OF_initWithFileDescriptor: 2];
}

#ifdef OF_WINDOWS
+ (void)initialize
{
	originalConsoleCP = GetConsoleCP();
	originalConsoleOutputCP = GetConsoleOutputCP();
	atexit(restoreCodepage);

	SetConsoleCP(CP_UTF8);
	SetConsoleOutputCP(CP_UTF8);
}
#endif

- init
{
	OF_INVALID_INIT_METHOD
}








>






<
<
<
<
<
<
<
<
<
<
<







58
59
60
61
62
63
64
65
66
67
68
69
70
71











72
73
74
75
76
77
78
	[of_stderr writeFormat: @"[%@.%03d %@(%d)] %@\n", dateString,
				[date microsecond] / 1000, me, getpid(), msg];

	objc_autoreleasePoolPop(pool);
}

@implementation OFStdIOStream
#ifndef OF_WINDOWS
+ (void)load
{
	of_stdin = [[OFStdIOStream alloc] OF_initWithFileDescriptor: 0];
	of_stdout = [[OFStdIOStream alloc] OF_initWithFileDescriptor: 1];
	of_stderr = [[OFStdIOStream alloc] OF_initWithFileDescriptor: 2];
}











#endif

- init
{
	OF_INVALID_INIT_METHOD
}

Added src/OFStdIOStream_Win32Console.h version [5329f7273d].



























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * 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.
 */

#define OF_STDIO_STREAM_WIN32CONSOLE_H

#import "OFStdIOStream.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFStdIOStream_Win32Console: OFStdIOStream
{
	HANDLE _handle;
}
@end

OF_ASSUME_NONNULL_END

Added src/OFStdIOStream_Win32Console.m version [7d8639b924].



















































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * 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.
 */

/*
 * This file tries to make writing UTF-8 strings to the console "just work" on
 * Windows.
 *
 * Windows does provide a way to change the codepage of the console to UTF-8,
 * but unfortunately, different Windows versions handle that differently. For
 * example on Windows XP when using Windows XP's console, changing the codepage
 * to UTF-8 mostly breaks write() and completely breaks read(): write()
 * suddenly returns the number of characters - instead of bytes - written and
 * read() just returns 0 as soon as a Unicode character is being read.
 *
 * So instead of just using the UTF-8 codepage, this captures all reads and
 * writes to of_std{in,err,out} on the lowlevel, interprets the buffer as UTF-8
 * and converts to / from UTF-16 to use ReadConsoleW() and WriteConsoleW(), as
 * reading or writing binary from / to the console would not make any sense
 * anyway and thus it's safe to assume it's text.
 *
 * In order to not do this when redirecting input / output to a file, it checks
 * that the handle is indeed a console.
 *
 * TODO: Properly handle surrogates being cut in the middle
 */

#define OF_STDIO_STREAM_WIN32_CONSOLE_M

#include "config.h"

#import "OFStdIOStream_Win32Console.h"
#import "OFStdIOStream+Private.h"
#import "OFDataArray.h"

#import "OFInvalidArgumentException.h"
#import "OFInvalidEncodingException.h"
#import "OFOutOfRangeException.h"
#import "OFReadFailedException.h"
#import "OFWriteFailedException.h"

#include <windows.h>

@implementation OFStdIOStream_Win32Console
+ (void)load
{
	of_stdin = [[OFStdIOStream_Win32Console alloc]
	    OF_initWithFileDescriptor: 0];
	of_stdout = [[OFStdIOStream_Win32Console alloc]
	    OF_initWithFileDescriptor: 1];
	of_stderr = [[OFStdIOStream_Win32Console alloc]
	    OF_initWithFileDescriptor: 2];
}

- (instancetype)OF_initWithFileDescriptor: (int)fd
{
	self = [super OF_initWithFileDescriptor: fd];

	@try {
		DWORD mode;

		switch (fd) {
		case 0:
			_handle = GetStdHandle(STD_INPUT_HANDLE);
			break;
		case 1:
			_handle = GetStdHandle(STD_OUTPUT_HANDLE);
			break;
		case 2:
			_handle = GetStdHandle(STD_ERROR_HANDLE);
			break;
		default:
			@throw [OFInvalidArgumentException exception];
		}

		/* Not a console: Treat it as a regular OFStdIOStream */
		if (!GetConsoleMode(_handle, &mode))
			object_setClass(self, [OFStdIOStream class]);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (size_t)lowlevelReadIntoBuffer: (void*)buffer_
			  length: (size_t)length
{
	void *pool = objc_autoreleasePoolPush();
	char *buffer = buffer_;
	of_char16_t *UTF16;
	size_t j = 0;
	OFDataArray *rest = nil;

	UTF16 = [self allocMemoryWithSize: sizeof(of_char16_t)
				    count: length];
	@try {
		DWORD UTF16Len;

		if (!ReadConsoleW(_handle, UTF16, length, &UTF16Len, NULL))
			@throw [OFReadFailedException
			    exceptionWithObject: self
				requestedLength: length];

		for (size_t i = 0; i < UTF16Len; i++) {
			of_unichar_t c = UTF16[i];
			char UTF8[4];
			size_t UTF8Len;

			/* Missing high surrogate */
			if ((c & 0xFC00) == 0xDC00)
				@throw [OFInvalidEncodingException exception];

			if ((c & 0xFC00) == 0xD800) {
				of_char16_t next;

				if (UTF16Len <= i + 1)
					@throw [OFInvalidEncodingException
					    exception];

				next = UTF16[i + 1];

				if ((next & 0xFC00) != 0xDC00)
					@throw [OFInvalidEncodingException
					    exception];

				c = (((c & 0x3FF) << 10) | (next & 0x3FF)) +
				    0x10000;

				i++;
			}

			if ((UTF8Len = of_string_utf8_encode(c, UTF8)) == 0)
				@throw [OFInvalidEncodingException exception];

			if (j + UTF8Len <= length) {
				memcpy(buffer + j, UTF8, UTF8Len);
				j += UTF8Len;
			} else {
				if (rest == nil)
					rest = [OFDataArray dataArray];

				[rest addItems: UTF8
					 count: UTF8Len];
			}
		}

		if (rest != nil)
			[self unreadFromBuffer: [rest items]
					length: [rest count]];
	} @finally {
		[self freeMemory: UTF16];
	}

	objc_autoreleasePoolPop(pool);

	return j;
}

- (void)lowlevelWriteBuffer: (const void*)buffer_
		     length: (size_t)length
{
	const char *buffer = buffer_;
	of_char16_t *tmp;

	if (length > SIZE_MAX / 2)
		@throw [OFOutOfRangeException exception];

	tmp = [self allocMemoryWithSize: sizeof(of_char16_t)
				  count: length * 2];
	@try {
		size_t i = 0, j = 0;
		DWORD written;

		while (i < length) {
			of_unichar_t c;
			size_t cLen;

			cLen = of_string_utf8_decode(buffer + i, length - i,
			    &c);

			if (cLen == 0 || c > 0x10FFFF)
				@throw [OFInvalidEncodingException exception];

			if (c > 0xFFFF) {
				c -= 0x10000;
				tmp[j++] = 0xD800 | (c >> 10);
				tmp[j++] = 0xDC00 | (c & 0x3FF);
			} else
				tmp[j++] = c;

			i += cLen;
		}

		if (!WriteConsoleW(_handle, tmp, j, &written, NULL) ||
		    written != j)
			@throw [OFWriteFailedException
			    exceptionWithObject: self
				requestedLength: j];
	} @finally {
		[self freeMemory: tmp];
	}
}
@end