ObjFW  Check-in [69749b6a5b]

Overview
Comment:Do not conform to OFReadyFor*Observing by default

Instead of letting OFStream conform to it, which itself does not really
conform to it, let all the subclasses that actually do conform to it.

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 69749b6a5ba999100f63c5cece5649b1221ff4b899314acfadb01999914644da
User & Date: js on 2017-11-19 11:04:22
Other Links: manifest | tags
Context
2017-11-19
12:05
Fix warnings introduced by OFComparing change check-in: 11f24addd7 user: js tags: trunk
11:04
Do not conform to OFReadyFor*Observing by default check-in: 69749b6a5b user: js tags: trunk
2017-11-18
19:14
Fix the last Doxygen warnings check-in: bb281804a3 user: js tags: trunk
Changes

Modified configure.ac from [49cf0ecee8] to [1919a82c3d].

902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
AC_MSG_RESULT($atomic_ops)

AC_ARG_ENABLE(files,
	AS_HELP_STRING([--disable-files], [disable file support]))
AS_IF([test x"$enable_files" != x"no"], [
	AC_DEFINE(OF_HAVE_FILES, 1, [Whether we have files])
	AC_SUBST(USE_SRCS_FILES, '${SRCS_FILES}')
	AC_SUBST(USE_SRCS_FILES_NOINCLUDE, '${SRCS_FILES_NOINCLUDE}')
	AC_SUBST(OFHASH, "ofhash")
	AC_SUBST(OFZIP, "ofzip")

	case "$host_os" in
		msdosdjgpp*)
			dnl DJGPP has the type, but it's not really usable.
			;;







<







902
903
904
905
906
907
908

909
910
911
912
913
914
915
AC_MSG_RESULT($atomic_ops)

AC_ARG_ENABLE(files,
	AS_HELP_STRING([--disable-files], [disable file support]))
AS_IF([test x"$enable_files" != x"no"], [
	AC_DEFINE(OF_HAVE_FILES, 1, [Whether we have files])
	AC_SUBST(USE_SRCS_FILES, '${SRCS_FILES}')

	AC_SUBST(OFHASH, "ofhash")
	AC_SUBST(OFZIP, "ofzip")

	case "$host_os" in
		msdosdjgpp*)
			dnl DJGPP has the type, but it's not really usable.
			;;

Modified extra.mk.in from [153d2e2b77] to [901b193c8a].

62
63
64
65
66
67
68
69
70
71
72
73
74
RUN_TESTS = @RUN_TESTS@
TESTPLUGIN = @TESTPLUGIN@
TESTS_LIBS = @TESTS_LIBS@
TESTS_OBJCFLAGS = @TESTS_OBJCFLAGS@
UNICODE_M = @UNICODE_M@
USE_INCLUDES_ATOMIC = @USE_INCLUDES_ATOMIC@
USE_SRCS_FILES = @USE_SRCS_FILES@
USE_SRCS_FILES_NOINCLUDE = @USE_SRCS_FILES_NOINCLUDE@
USE_SRCS_PLUGINS = @USE_SRCS_PLUGINS@
USE_SRCS_SOCKETS = @USE_SRCS_SOCKETS@
USE_SRCS_THREADS = @USE_SRCS_THREADS@
WEAK_NSFOUNDATIONVERSIONNUMBER = @WEAK_NSFOUNDATIONVERSIONNUMBER@
WRAPPER = @WRAPPER@







<





62
63
64
65
66
67
68

69
70
71
72
73
RUN_TESTS = @RUN_TESTS@
TESTPLUGIN = @TESTPLUGIN@
TESTS_LIBS = @TESTS_LIBS@
TESTS_OBJCFLAGS = @TESTS_OBJCFLAGS@
UNICODE_M = @UNICODE_M@
USE_INCLUDES_ATOMIC = @USE_INCLUDES_ATOMIC@
USE_SRCS_FILES = @USE_SRCS_FILES@

USE_SRCS_PLUGINS = @USE_SRCS_PLUGINS@
USE_SRCS_SOCKETS = @USE_SRCS_SOCKETS@
USE_SRCS_THREADS = @USE_SRCS_THREADS@
WEAK_NSFOUNDATIONVERSIONNUMBER = @WEAK_NSFOUNDATIONVERSIONNUMBER@
WRAPPER = @WRAPPER@

Modified src/Makefile from [8aff73e1a1] to [340ccc4065].

112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
       ${USE_SRCS_SOCKETS}		\
       ${USE_SRCS_THREADS}
SRCS_FILES = OFFile.m			\
	     OFFileManager.m		\
	     OFINICategory.m		\
	     OFINIFile.m		\
	     OFSettings.m
SRCS_FILES_NOINCLUDE = OFURLHandler_file.m
SRCS_PLUGINS = OFPlugin.m
SRCS_SOCKETS = OFHTTPClient.m			\
	       OFHTTPServer.m			\
	       OFKernelEventObserver.m		\
	       OFStreamSocket.m			\
	       OFTCPSocket.m			\
	       OFUDPSocket.m			\
	       resolver.m			\
	       socket.m
SRCS_THREADS = OFCondition.m		\
	       OFMutex.m		\







<



<







112
113
114
115
116
117
118

119
120
121

122
123
124
125
126
127
128
       ${USE_SRCS_SOCKETS}		\
       ${USE_SRCS_THREADS}
SRCS_FILES = OFFile.m			\
	     OFFileManager.m		\
	     OFINICategory.m		\
	     OFINIFile.m		\
	     OFSettings.m

SRCS_PLUGINS = OFPlugin.m
SRCS_SOCKETS = OFHTTPClient.m			\
	       OFHTTPServer.m			\

	       OFStreamSocket.m			\
	       OFTCPSocket.m			\
	       OFUDPSocket.m			\
	       resolver.m			\
	       socket.m
SRCS_THREADS = OFCondition.m		\
	       OFMutex.m		\
139
140
141
142
143
144
145

146
147
148
149
150
151
152
		  atomic_powerpc.h		\
		  atomic_sync_builtins.h	\
		  atomic_x86.h
INCLUDES := ${SRCS:.m=.h}			\
	    OFCollection.h			\
	    OFCryptoHash.h			\
	    OFJSONRepresentation.h		\

	    OFKeyValueCoding.h			\
	    OFLocking.h				\
	    OFMessagePackRepresentation.h	\
	    OFSerialization.h			\
	    OFTLSSocket.h			\
	    ObjFW.h				\
	    autorelease.h			\







>







137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
		  atomic_powerpc.h		\
		  atomic_sync_builtins.h	\
		  atomic_x86.h
INCLUDES := ${SRCS:.m=.h}			\
	    OFCollection.h			\
	    OFCryptoHash.h			\
	    OFJSONRepresentation.h		\
	    OFKernelEventObserver.h		\
	    OFKeyValueCoding.h			\
	    OFLocking.h				\
	    OFMessagePackRepresentation.h	\
	    OFSerialization.h			\
	    OFTLSSocket.h			\
	    ObjFW.h				\
	    autorelease.h			\
169
170
171
172
173
174
175
176
177
178


179
180
181
182
183
184
185
186
	OFMutableDictionary_hashtable.m	\
	OFMutableSet_hashtable.m	\
	OFMutableString_UTF8.m		\
	OFSet_hashtable.m		\
	OFString_UTF8.m			\
	${AUTORELEASE_M}		\
	${FOUNDATION_COMPAT_M}		\
	${INSTANCE_M}			\
	${USE_SRCS_FILES_NOINCLUDE}
SRCS_FILES += OFSettings_INIFile.m


SRCS_SOCKETS += ${OFKERNELEVENTOBSERVER_EPOLL_M}	\
		${OFKERNELEVENTOBSERVER_KQUEUE_M}	\
		${OFKERNELEVENTOBSERVER_POLL_M}		\
		${OFKERNELEVENTOBSERVER_SELECT_M}	\
		OFTCPSocket+SOCKS5.m

OBJS_EXTRA = ${RUNTIME_RUNTIME_A}	\
	     ${EXCEPTIONS_EXCEPTIONS_A} \







|
<
|
>
>
|







168
169
170
171
172
173
174
175

176
177
178
179
180
181
182
183
184
185
186
	OFMutableDictionary_hashtable.m	\
	OFMutableSet_hashtable.m	\
	OFMutableString_UTF8.m		\
	OFSet_hashtable.m		\
	OFString_UTF8.m			\
	${AUTORELEASE_M}		\
	${FOUNDATION_COMPAT_M}		\
	${INSTANCE_M}

SRCS_FILES += OFSettings_INIFile.m	\
	      OFURLHandler_file.m
SRCS_SOCKETS += OFKernelEventObserver.m			\
		${OFKERNELEVENTOBSERVER_EPOLL_M}	\
		${OFKERNELEVENTOBSERVER_KQUEUE_M}	\
		${OFKERNELEVENTOBSERVER_POLL_M}		\
		${OFKERNELEVENTOBSERVER_SELECT_M}	\
		OFTCPSocket+SOCKS5.m

OBJS_EXTRA = ${RUNTIME_RUNTIME_A}	\
	     ${EXCEPTIONS_EXCEPTIONS_A} \

Modified src/OFFile.h from [92705fc93e] to [557607a4f8].

11
12
13
14
15
16
17

18
19
20
21
22
23
24
 * 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 "OFSeekableStream.h"


#ifndef OF_MORPHOS
# define OF_FILE_HANDLE_IS_FD
# define OF_INVALID_FILE_HANDLE (-1)
typedef int of_file_handle_t;
#else
# define BOOL EXEC_BOOL







>







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFSeekableStream.h"
#import "OFKernelEventObserver.h"

#ifndef OF_MORPHOS
# define OF_FILE_HANDLE_IS_FD
# define OF_INVALID_FILE_HANDLE (-1)
typedef int of_file_handle_t;
#else
# define BOOL EXEC_BOOL
34
35
36
37
38
39
40



41
42
43
44
45
46
47

/*!
 * @class OFFile OFFile.h ObjFW/OFFile.h
 *
 * @brief A class which provides methods to read and write files.
 */
@interface OFFile: OFSeekableStream



{
	of_file_handle_t _handle;
	bool _atEndOfStream;
}

/*!
 * @brief Creates a new OFFile with the specified path and mode.







>
>
>







35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

/*!
 * @class OFFile OFFile.h ObjFW/OFFile.h
 *
 * @brief A class which provides methods to read and write files.
 */
@interface OFFile: OFSeekableStream
#ifdef OF_FILE_HANDLE_IS_FD
    <OFReadyForReadingObserving, OFReadyForWritingObserving>
#endif
{
	of_file_handle_t _handle;
	bool _atEndOfStream;
}

/*!
 * @brief Creates a new OFFile with the specified path and mode.

Modified src/OFHTTPClient.m from [69a4197ea4] to [a6980a9e89].

22
23
24
25
26
27
28

29
30
31
32
33
34
35
#include <string.h>

#import "OFHTTPClient.h"
#import "OFData.h"
#import "OFDictionary.h"
#import "OFHTTPRequest.h"
#import "OFHTTPResponse.h"

#import "OFNumber.h"
#import "OFString.h"
#import "OFTCPSocket.h"
#import "OFURL.h"

#import "OFAlreadyConnectedException.h"
#import "OFHTTPRequestFailedException.h"







>







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <string.h>

#import "OFHTTPClient.h"
#import "OFData.h"
#import "OFDictionary.h"
#import "OFHTTPRequest.h"
#import "OFHTTPResponse.h"
#import "OFKernelEventObserver.h"
#import "OFNumber.h"
#import "OFString.h"
#import "OFTCPSocket.h"
#import "OFURL.h"

#import "OFAlreadyConnectedException.h"
#import "OFHTTPRequestFailedException.h"
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
		       request: (OFHTTPRequest *)request
		     redirects: (unsigned int)redirects
		       context: (id)context;
- (void)start;
- (void)closeAndReconnect;
@end

@interface OFHTTPClientResponse: OFHTTPResponse
{
	OFTCPSocket *_socket;
	bool _hasContentLength, _chunked, _keepAlive, _atEndOfStream;
	size_t _toRead;
}

@property (nonatomic, setter=of_setKeepAlive:) bool of_keepAlive;







|







62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
		       request: (OFHTTPRequest *)request
		     redirects: (unsigned int)redirects
		       context: (id)context;
- (void)start;
- (void)closeAndReconnect;
@end

@interface OFHTTPClientResponse: OFHTTPResponse <OFReadyForReadingObserving>
{
	OFTCPSocket *_socket;
	bool _hasContentLength, _chunked, _keepAlive, _atEndOfStream;
	size_t _toRead;
}

@property (nonatomic, setter=of_setKeepAlive:) bool of_keepAlive;

Modified src/OFHTTPServer.m from [3bc806eac7] to [1522d55623].

169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
		tmp++;
	}

	return [OFString stringWithUTF8StringNoCopy: cString
				       freeWhenDone: true];
}

@interface OFHTTPServerResponse: OFHTTPResponse
{
	OFTCPSocket *_socket;
	OFHTTPServer *_server;
	OFHTTPRequest *_request;
	bool _chunked, _headersSent;
}








|







169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
		tmp++;
	}

	return [OFString stringWithUTF8StringNoCopy: cString
				       freeWhenDone: true];
}

@interface OFHTTPServerResponse: OFHTTPResponse <OFReadyForWritingObserving>
{
	OFTCPSocket *_socket;
	OFHTTPServer *_server;
	OFHTTPRequest *_request;
	bool _chunked, _headersSent;
}

Modified src/OFInflateStream.h from [e064c26fb9] to [a58b9e9e07].

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


OF_ASSUME_NONNULL_BEGIN

#define OF_INFLATE_STREAM_BUFFER_SIZE 4096

/*!
 * @class OFInflateStream OFInflateStream.h ObjFW/OFInflateStream.h



 *
 * @brief A class that handles Deflate decompression transparently for an
 *	  underlying stream.
 */
@interface OFInflateStream: OFStream
{
#ifdef OF_INFLATE_STREAM_M
@public
#endif
	OFStream *_stream;
	uint8_t _buffer[OF_INFLATE_STREAM_BUFFER_SIZE];
	uint16_t _bufferIndex, _bufferLength;
	uint8_t _byte;
	uint8_t _bitIndex, _savedBitsLength;
	uint16_t _savedBits;
	uint8_t *_Nullable _slidingWindow;
	uint16_t _slidingWindowIndex, _slidingWindowMask;







>







>
>
>




|




|







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
 * 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 "OFStream.h"
#import "OFKernelEventObserver.h"

OF_ASSUME_NONNULL_BEGIN

#define OF_INFLATE_STREAM_BUFFER_SIZE 4096

/*!
 * @class OFInflateStream OFInflateStream.h ObjFW/OFInflateStream.h
 *
 * @note This class only conforms to OFReadyForReadingObserving if the
 *	 underlying stream does so, too.
 *
 * @brief A class that handles Deflate decompression transparently for an
 *	  underlying stream.
 */
@interface OFInflateStream: OFStream <OFReadyForReadingObserving>
{
#ifdef OF_INFLATE_STREAM_M
@public
#endif
	OF_KINDOF(OFStream *) _stream;
	uint8_t _buffer[OF_INFLATE_STREAM_BUFFER_SIZE];
	uint16_t _bufferIndex, _bufferLength;
	uint8_t _byte;
	uint8_t _bitIndex, _savedBitsLength;
	uint16_t _savedBits;
	uint8_t *_Nullable _slidingWindow;
	uint16_t _slidingWindowIndex, _slidingWindowMask;

Modified src/OFKernelEventObserver.h from [cad56e81b9] to [ee35836078].

12
13
14
15
16
17
18

19

20
21
22
23
24
25
26
 * 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 "socket.h"


OF_ASSUME_NONNULL_BEGIN

@class OFMutableArray OF_GENERIC(ObjectType);
@class OFDate;
#ifdef OF_HAVE_THREADS
@class OFMutex;







>
|
>







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFObject.h"

#ifdef OF_HAVE_SOCKETS
# import "socket.h"
#endif

OF_ASSUME_NONNULL_BEGIN

@class OFMutableArray OF_GENERIC(ObjectType);
@class OFDate;
#ifdef OF_HAVE_THREADS
@class OFMutex;
86
87
88
89
90
91
92

93
94
95
96
97
98
99
/*!
 * @brief The file descriptor for writing that should be checked by the
 *	  OFKernelEventObserver.
 */
@property (readonly, nonatomic) int fileDescriptorForWriting;
@end


/*!
 * @class OFKernelEventObserver
 *	  OFKernelEventObserver.h ObjFW/OFKernelEventObserver.h
 *
 * @brief A class that can observe multiple kernel events (e.g. streams being
 *	  ready to read) at once.
 *







>







88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/*!
 * @brief The file descriptor for writing that should be checked by the
 *	  OFKernelEventObserver.
 */
@property (readonly, nonatomic) int fileDescriptorForWriting;
@end

#ifdef OF_HAVE_SOCKETS
/*!
 * @class OFKernelEventObserver
 *	  OFKernelEventObserver.h ObjFW/OFKernelEventObserver.h
 *
 * @brief A class that can observe multiple kernel events (e.g. streams being
 *	  ready to read) at once.
 *
201
202
203
204
205
206
207

208
209
 *
 * This is automatically done when a new object is added or removed by another
 * thread, but in some circumstances, it might be desirable for a thread to
 * manually stop the observe running in another thread.
 */
- (void)cancel;
@end


OF_ASSUME_NONNULL_END







>


204
205
206
207
208
209
210
211
212
213
 *
 * This is automatically done when a new object is added or removed by another
 * thread, but in some circumstances, it might be desirable for a thread to
 * manually stop the observe running in another thread.
 */
- (void)cancel;
@end
#endif

OF_ASSUME_NONNULL_END

Modified src/OFProcess.h from [b0f7aa5681] to [b5fba3c334].

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
#include "objfw-defs.h"

#ifdef OF_HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif

#import "OFStream.h"

#import "OFString.h"

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

OF_ASSUME_NONNULL_BEGIN

@class OFArray OF_GENERIC(ObjectType);
@class OFDictionary OF_GENERIC(KeyType, ObjectType);

/*!
 * @class OFProcess OFProcess.h ObjFW/OFProcess.h
 *
 * @brief A class for stream-like communication with a newly created process.
 */
@interface OFProcess: OFStream



{
#ifndef OF_WINDOWS
	pid_t _pid;
	int _readPipe[2], _writePipe[2];
#else
	HANDLE _process, _readPipe[2], _writePipe[2];
#endif







>

















>
>
>







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
#include "objfw-defs.h"

#ifdef OF_HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif

#import "OFStream.h"
#import "OFKernelEventObserver.h"
#import "OFString.h"

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

OF_ASSUME_NONNULL_BEGIN

@class OFArray OF_GENERIC(ObjectType);
@class OFDictionary OF_GENERIC(KeyType, ObjectType);

/*!
 * @class OFProcess OFProcess.h ObjFW/OFProcess.h
 *
 * @brief A class for stream-like communication with a newly created process.
 */
@interface OFProcess: OFStream
#ifndef OF_WINDOWS
    <OFReadyForReadingObserving, OFReadyForWritingObserving>
#endif
{
#ifndef OF_WINDOWS
	pid_t _pid;
	int _readPipe[2], _writePipe[2];
#else
	HANDLE _process, _readPipe[2], _writePipe[2];
#endif

Modified src/OFProcess.m from [47e26e30a9] to [b38c51b4de].

523
524
525
526
527
528
529

530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546

547
548
549
550
551
552
553
							     errNo: errNo];
	}
#endif

	return (size_t)bytesWritten;
}


- (int)fileDescriptorForReading
{
#ifndef OF_WINDOWS
	return _readPipe[0];
#else
	OF_UNRECOGNIZED_SELECTOR
#endif
}

- (int)fileDescriptorForWriting
{
#ifndef OF_WINDOWS
	return _writePipe[1];
#else
	OF_UNRECOGNIZED_SELECTOR
#endif
}


- (void)closeForWriting
{
#ifndef OF_WINDOWS
	if (_writePipe[1] != -1)
		close(_writePipe[1]);








>


<

<
<
<




<

<
<
<

>







523
524
525
526
527
528
529
530
531
532

533



534
535
536
537

538



539
540
541
542
543
544
545
546
547
							     errNo: errNo];
	}
#endif

	return (size_t)bytesWritten;
}

#ifndef OF_WINDOWS
- (int)fileDescriptorForReading
{

	return _readPipe[0];



}

- (int)fileDescriptorForWriting
{

	return _writePipe[1];



}
#endif

- (void)closeForWriting
{
#ifndef OF_WINDOWS
	if (_writePipe[1] != -1)
		close(_writePipe[1]);

Modified src/OFRunLoop+Private.h from [f6fcbe1db8] to [ea09023939].

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

OF_ASSUME_NONNULL_BEGIN

@interface OFRunLoop ()
+ (void)of_setMainRunLoop: (OFRunLoop *)runLoop;
#ifdef OF_HAVE_SOCKETS
+ (void)of_addAsyncReadForStream: (OFStream *)stream

			  buffer: (void *)buffer
			  length: (size_t)length
			  target: (id)target
			selector: (SEL)selector
			 context: (nullable id)context;
+ (void)of_addAsyncReadForStream: (OFStream *)stream

			  buffer: (void *)buffer
		     exactLength: (size_t)length
			  target: (id)target
			selector: (SEL)selector
			 context: (nullable id)context;
+ (void)of_addAsyncReadLineForStream: (OFStream *)stream

			    encoding: (of_string_encoding_t)encoding
			      target: (id)target
			    selector: (SEL)selector
			     context: (nullable id)context;
+ (void)of_addAsyncWriteForStream: (OFStream *)stream

			   buffer: (const void *)buffer
			   length: (size_t)length
			   target: (id)target
			 selector: (SEL)selector
			  context: (nullable id)context;
+ (void)of_addAsyncAcceptForTCPSocket: (OFTCPSocket *)socket
			       target: (id)target







|
>





|
>





|
>




|
>







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

OF_ASSUME_NONNULL_BEGIN

@interface OFRunLoop ()
+ (void)of_setMainRunLoop: (OFRunLoop *)runLoop;
#ifdef OF_HAVE_SOCKETS
+ (void)of_addAsyncReadForStream: (OFStream <OFReadyForReadingObserving> *)
				      stream
			  buffer: (void *)buffer
			  length: (size_t)length
			  target: (id)target
			selector: (SEL)selector
			 context: (nullable id)context;
+ (void)of_addAsyncReadForStream: (OFStream <OFReadyForReadingObserving> *)
				      stream
			  buffer: (void *)buffer
		     exactLength: (size_t)length
			  target: (id)target
			selector: (SEL)selector
			 context: (nullable id)context;
+ (void)of_addAsyncReadLineForStream: (OFStream <OFReadyForReadingObserving> *)
					  stream
			    encoding: (of_string_encoding_t)encoding
			      target: (id)target
			    selector: (SEL)selector
			     context: (nullable id)context;
+ (void)of_addAsyncWriteForStream: (OFStream <OFReadyForWritingObserving> *)
				       stream
			   buffer: (const void *)buffer
			   length: (size_t)length
			   target: (id)target
			 selector: (SEL)selector
			  context: (nullable id)context;
+ (void)of_addAsyncAcceptForTCPSocket: (OFTCPSocket *)socket
			       target: (id)target
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
			     buffer: (const void *)buffer
			     length: (size_t)length
			   receiver: (of_udp_socket_address_t)receiver
			     target: (id)target
			   selector: (SEL)selector
			    context: (nullable id)context;
# ifdef OF_HAVE_BLOCKS
+ (void)of_addAsyncReadForStream: (OFStream *)stream

			  buffer: (void *)buffer
			  length: (size_t)length
			   block: (of_stream_async_read_block_t)block;
+ (void)of_addAsyncReadForStream: (OFStream *)stream

			  buffer: (void *)buffer
		     exactLength: (size_t)length
			   block: (of_stream_async_read_block_t)block;
+ (void)of_addAsyncReadLineForStream: (OFStream *)stream

			    encoding: (of_string_encoding_t)encoding
			       block: (of_stream_async_read_line_block_t)block;
+ (void)of_addAsyncWriteForStream: (OFStream *)stream

			   buffer: (const void *)buffer
			   length: (size_t)length
			    block: (of_stream_async_write_block_t)block;
+ (void)of_addAsyncAcceptForTCPSocket: (OFTCPSocket *)socket
				block: (of_tcp_socket_async_accept_block_t)
					   block;
+ (void)of_addAsyncReceiveForUDPSocket: (OFUDPSocket *)socket







|
>



|
>



|
>


|
>







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
			     buffer: (const void *)buffer
			     length: (size_t)length
			   receiver: (of_udp_socket_address_t)receiver
			     target: (id)target
			   selector: (SEL)selector
			    context: (nullable id)context;
# ifdef OF_HAVE_BLOCKS
+ (void)of_addAsyncReadForStream: (OFStream <OFReadyForReadingObserving> *)
				      stream
			  buffer: (void *)buffer
			  length: (size_t)length
			   block: (of_stream_async_read_block_t)block;
+ (void)of_addAsyncReadForStream: (OFStream <OFReadyForReadingObserving> *)
				      stream
			  buffer: (void *)buffer
		     exactLength: (size_t)length
			   block: (of_stream_async_read_block_t)block;
+ (void)of_addAsyncReadLineForStream: (OFStream <OFReadyForReadingObserving> *)
					  stream
			    encoding: (of_string_encoding_t)encoding
			       block: (of_stream_async_read_line_block_t)block;
+ (void)of_addAsyncWriteForStream: (OFStream <OFReadyForWritingObserving> *)
				       stream
			   buffer: (const void *)buffer
			   length: (size_t)length
			    block: (of_stream_async_write_block_t)block;
+ (void)of_addAsyncAcceptForTCPSocket: (OFTCPSocket *)socket
				block: (of_tcp_socket_async_accept_block_t)
					   block;
+ (void)of_addAsyncReceiveForUDPSocket: (OFUDPSocket *)socket

Modified src/OFRunLoop.m from [2a10d90f42] to [5ad7583705].

525
526
527
528
529
530
531
532

533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548

549
550
551
552
553
554
555
556
557
558
559
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
									\
	queueItem = [[[type alloc] init] autorelease];			\
	code								\
	[queue appendObject: queueItem];				\
									\
	objc_autoreleasePoolPop(pool);

+ (void)of_addAsyncReadForStream: (OFStream *)stream

			  buffer: (void *)buffer
			  length: (size_t)length
			  target: (id)target
			selector: (SEL)selector
			 context: (id)context
{
	ADD_READ(OFRunLoop_ReadQueueItem, stream, {
		queueItem->_target = [target retain];
		queueItem->_selector = selector;
		queueItem->_context = [context retain];
		queueItem->_buffer = buffer;
		queueItem->_length = length;
	})
}

+ (void)of_addAsyncReadForStream: (OFStream *)stream

			  buffer: (void *)buffer
		     exactLength: (size_t)exactLength
			  target: (id)target
			selector: (SEL)selector
			 context: (id)context
{
	ADD_READ(OFRunLoop_ExactReadQueueItem, stream, {
		queueItem->_target = [target retain];
		queueItem->_selector = selector;
		queueItem->_context = [context retain];
		queueItem->_buffer = buffer;
		queueItem->_exactLength = exactLength;
	})
}

+ (void)of_addAsyncReadLineForStream: (OFStream *)stream

			    encoding: (of_string_encoding_t)encoding
			      target: (id)target
			    selector: (SEL)selector
			     context: (id)context
{
	ADD_READ(OFRunLoop_ReadLineQueueItem, stream, {
		queueItem->_target = [target retain];
		queueItem->_selector = selector;
		queueItem->_context = [context retain];
		queueItem->_encoding = encoding;
	})
}

+ (void)of_addAsyncWriteForStream: (OFStream *)stream

			   buffer: (const void *)buffer
			   length: (size_t)length
			   target: (id)target
			 selector: (SEL)selector
			  context: (id)context
{
	ADD_WRITE(OFRunLoop_WriteQueueItem, stream, {







|
>















|
>















|
>













|
>







525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
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
									\
	queueItem = [[[type alloc] init] autorelease];			\
	code								\
	[queue appendObject: queueItem];				\
									\
	objc_autoreleasePoolPop(pool);

+ (void)of_addAsyncReadForStream: (OFStream <OFReadyForReadingObserving> *)
				      stream
			  buffer: (void *)buffer
			  length: (size_t)length
			  target: (id)target
			selector: (SEL)selector
			 context: (id)context
{
	ADD_READ(OFRunLoop_ReadQueueItem, stream, {
		queueItem->_target = [target retain];
		queueItem->_selector = selector;
		queueItem->_context = [context retain];
		queueItem->_buffer = buffer;
		queueItem->_length = length;
	})
}

+ (void)of_addAsyncReadForStream: (OFStream <OFReadyForReadingObserving> *)
				      stream
			  buffer: (void *)buffer
		     exactLength: (size_t)exactLength
			  target: (id)target
			selector: (SEL)selector
			 context: (id)context
{
	ADD_READ(OFRunLoop_ExactReadQueueItem, stream, {
		queueItem->_target = [target retain];
		queueItem->_selector = selector;
		queueItem->_context = [context retain];
		queueItem->_buffer = buffer;
		queueItem->_exactLength = exactLength;
	})
}

+ (void)of_addAsyncReadLineForStream: (OFStream <OFReadyForReadingObserving> *)
					  stream
			    encoding: (of_string_encoding_t)encoding
			      target: (id)target
			    selector: (SEL)selector
			     context: (id)context
{
	ADD_READ(OFRunLoop_ReadLineQueueItem, stream, {
		queueItem->_target = [target retain];
		queueItem->_selector = selector;
		queueItem->_context = [context retain];
		queueItem->_encoding = encoding;
	})
}

+ (void)of_addAsyncWriteForStream: (OFStream <OFReadyForWritingObserving> *)
				       stream
			   buffer: (const void *)buffer
			   length: (size_t)length
			   target: (id)target
			 selector: (SEL)selector
			  context: (id)context
{
	ADD_WRITE(OFRunLoop_WriteQueueItem, stream, {
634
635
636
637
638
639
640
641

642
643
644
645
646
647
648
649
650
651
652
653

654
655
656
657
658
659
660
661
662
663
664
665

666
667
668
669
670
671
672
673
674
675

676
677
678
679
680
681
682
		queueItem->_buffer = buffer;
		queueItem->_length = length;
		queueItem->_receiver = receiver;
	})
}

# ifdef OF_HAVE_BLOCKS
+ (void)of_addAsyncReadForStream: (OFStream *)stream

			  buffer: (void *)buffer
			  length: (size_t)length
			   block: (of_stream_async_read_block_t)block
{
	ADD_READ(OFRunLoop_ReadQueueItem, stream, {
		queueItem->_block = [block copy];
		queueItem->_buffer = buffer;
		queueItem->_length = length;
	})
}

+ (void)of_addAsyncReadForStream: (OFStream *)stream

			  buffer: (void *)buffer
		     exactLength: (size_t)exactLength
			   block: (of_stream_async_read_block_t)block
{
	ADD_READ(OFRunLoop_ExactReadQueueItem, stream, {
		queueItem->_block = [block copy];
		queueItem->_buffer = buffer;
		queueItem->_exactLength = exactLength;
	})
}

+ (void)of_addAsyncReadLineForStream: (OFStream *)stream

			    encoding: (of_string_encoding_t)encoding
			       block: (of_stream_async_read_line_block_t)block
{
	ADD_READ(OFRunLoop_ReadLineQueueItem, stream, {
		queueItem->_block = [block copy];
		queueItem->_encoding = encoding;
	})
}

+ (void)of_addAsyncWriteForStream: (OFStream *)stream

			   buffer: (const void *)buffer
			   length: (size_t)length
			    block: (of_stream_async_write_block_t)block
{
	ADD_WRITE(OFRunLoop_WriteQueueItem, stream, {
		queueItem->_block = [block copy];
		queueItem->_buffer = buffer;







|
>











|
>











|
>









|
>







638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
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
		queueItem->_buffer = buffer;
		queueItem->_length = length;
		queueItem->_receiver = receiver;
	})
}

# ifdef OF_HAVE_BLOCKS
+ (void)of_addAsyncReadForStream: (OFStream <OFReadyForReadingObserving> *)
				      stream
			  buffer: (void *)buffer
			  length: (size_t)length
			   block: (of_stream_async_read_block_t)block
{
	ADD_READ(OFRunLoop_ReadQueueItem, stream, {
		queueItem->_block = [block copy];
		queueItem->_buffer = buffer;
		queueItem->_length = length;
	})
}

+ (void)of_addAsyncReadForStream: (OFStream <OFReadyForReadingObserving> *)
				      stream
			  buffer: (void *)buffer
		     exactLength: (size_t)exactLength
			   block: (of_stream_async_read_block_t)block
{
	ADD_READ(OFRunLoop_ExactReadQueueItem, stream, {
		queueItem->_block = [block copy];
		queueItem->_buffer = buffer;
		queueItem->_exactLength = exactLength;
	})
}

+ (void)of_addAsyncReadLineForStream: (OFStream <OFReadyForReadingObserving> *)
					  stream
			    encoding: (of_string_encoding_t)encoding
			       block: (of_stream_async_read_line_block_t)block
{
	ADD_READ(OFRunLoop_ReadLineQueueItem, stream, {
		queueItem->_block = [block copy];
		queueItem->_encoding = encoding;
	})
}

+ (void)of_addAsyncWriteForStream: (OFStream <OFReadyForWritingObserving> *)
				       stream
			   buffer: (const void *)buffer
			   length: (size_t)length
			    block: (of_stream_async_write_block_t)block
{
	ADD_WRITE(OFRunLoop_WriteQueueItem, stream, {
		queueItem->_block = [block copy];
		queueItem->_buffer = buffer;

Modified src/OFStdIOStream.h from [0ce400e3cf] to [9c739b6c2b].

11
12
13
14
15
16
17

18
19
20
21
22
23
24
 * 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 "OFStream.h"


#ifdef OF_MORPHOS
# define BOOL EXEC_BOOL
# include <proto/dos.h>
# undef BOOL
#endif








>







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFStream.h"
#import "OFKernelEventObserver.h"

#ifdef OF_MORPHOS
# define BOOL EXEC_BOOL
# include <proto/dos.h>
# undef BOOL
#endif

32
33
34
35
36
37
38



39
40
41
42
43
44
45
 * 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



{
#ifndef OF_MORPHOS
	int _fd;
#else
	BPTR _handle;
	bool _closable;
#endif







>
>
>







33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
 * 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
#if !defined(OF_WINDOWS) && !defined(OF_MORPHOS)
    <OFReadyForReadingObserving, OFReadyForWritingObserving>
#endif
{
#ifndef OF_MORPHOS
	int _fd;
#else
	BPTR _handle;
	bool _closable;
#endif

Modified src/OFStream.h from [9a95fdcb49] to [cfa0bd1248].

100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
 *	 @ref lowlevelReadIntoBuffer:length:, @ref lowlevelWriteBuffer:length:
 *	 and @ref lowlevelIsAtEndOfStream, but nothing else, as those are are
 *	 the methods that do the actual work. OFStream uses those for all other
 *	 methods and does all the caching and other stuff for you. If you
 *	 override these methods without the `lowlevel` prefix, you *will* break
 *	 caching and get broken results!
 */
@interface OFStream: OFObject <
#ifdef OF_HAVE_SOCKETS
    OFReadyForReadingObserving, OFReadyForWritingObserving,
#endif
    OFCopying>
{
#if !defined(OF_SEEKABLE_STREAM_M) && !defined(OF_TCP_SOCKET_M)
@private
#endif
	char *_Nullable _readBuffer, *_Nullable _readBufferMemory;
	char *_Nullable _writeBuffer;
	size_t _readBufferLength, _writeBufferLength;







|
<
<
<
<







100
101
102
103
104
105
106
107




108
109
110
111
112
113
114
 *	 @ref lowlevelReadIntoBuffer:length:, @ref lowlevelWriteBuffer:length:
 *	 and @ref lowlevelIsAtEndOfStream, but nothing else, as those are are
 *	 the methods that do the actual work. OFStream uses those for all other
 *	 methods and does all the caching and other stuff for you. If you
 *	 override these methods without the `lowlevel` prefix, you *will* break
 *	 caching and get broken results!
 */
@interface OFStream: OFObject <OFCopying>




{
#if !defined(OF_SEEKABLE_STREAM_M) && !defined(OF_TCP_SOCKET_M)
@private
#endif
	char *_Nullable _readBuffer, *_Nullable _readBufferMemory;
	char *_Nullable _writeBuffer;
	size_t _readBufferLength, _writeBufferLength;
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
 * @brief Whether the stream is in blocking mode.
 *
 * By default, a stream is in blocking mode.
 * On Win32, setting this currently only works for sockets!
 */
@property (readonly, nonatomic, getter=isBlocking) bool blocking;

/*!
 * @brief The file descriptor for the read end of the stream.
 */
@property (readonly, nonatomic) int fileDescriptorForReading;

/*!
 * @brief The file descriptor for the write end of the stream.
 */
@property (readonly, nonatomic) int fileDescriptorForWriting;

/*!
 * @brief Reads *at most* size bytes from the stream into a buffer.
 *
 * On network streams, this might read less than the specified number of bytes.
 * If you want to read exactly the specified number of bytes, use
 * @ref readIntoBuffer:exactLength:. Note that a read can even return 0 bytes -
 * this does not necessarily mean that the stream ended, so you still need to







<
<
<
<
<
<
<
<
<
<







136
137
138
139
140
141
142










143
144
145
146
147
148
149
 * @brief Whether the stream is in blocking mode.
 *
 * By default, a stream is in blocking mode.
 * On Win32, setting this currently only works for sockets!
 */
@property (readonly, nonatomic, getter=isBlocking) bool blocking;











/*!
 * @brief Reads *at most* size bytes from the stream into a buffer.
 *
 * On network streams, this might read less than the specified number of bytes.
 * If you want to read exactly the specified number of bytes, use
 * @ref readIntoBuffer:exactLength:. Note that a read can even return 0 bytes -
 * this does not necessarily mean that the stream ended, so you still need to
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
 *
 * On network streams, this might read less than the specified number of bytes.
 * If you want to read exactly the specified number of bytes, use
 * @ref asyncReadIntoBuffer:exactLength:target:selector:context:. Note that a
 * read can even return 0 bytes - this does not necessarily mean that the
 * stream ended, so you still need to check @ref atEndOfStream.
 *
 * @note The stream must implement @ref fileDescriptorForReading and return a
 *	 valid file descriptor in order for this to work!
 *
 * @param buffer The buffer into which the data is read.
 *		 The buffer must not be freed before the async read completed!
 * @param length The length of the data that should be read at most.
 *		 The buffer *must* be *at least* this big!
 * @param target The target on which the selector should be called when the
 *		 data has been received. If the method returns true, it will be







|
|







182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
 *
 * On network streams, this might read less than the specified number of bytes.
 * If you want to read exactly the specified number of bytes, use
 * @ref asyncReadIntoBuffer:exactLength:target:selector:context:. Note that a
 * read can even return 0 bytes - this does not necessarily mean that the
 * stream ended, so you still need to check @ref atEndOfStream.
 *
 * @note The stream must conform to @ref OFReadyForReadingObserving in order
 *	 for this to work!
 *
 * @param buffer The buffer into which the data is read.
 *		 The buffer must not be freed before the async read completed!
 * @param length The length of the data that should be read at most.
 *		 The buffer *must* be *at least* this big!
 * @param target The target on which the selector should be called when the
 *		 data has been received. If the method returns true, it will be
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
 *	  stream into a buffer.
 *
 * Unlike @ref asyncReadIntoBuffer:length:target:selector:context:, this method
 * does not call the method when less than the specified length has been read -
 * instead, it waits until it got exactly the specified length, the stream has
 * ended or an exception occurred.
 *
 * @note The stream must implement @ref fileDescriptorForReading and return a
 *	 valid file descriptor in order for this to work!
 *
 * @param buffer The buffer into which the data is read
 * @param length The length of the data that should be read.
 *		 The buffer *must* be *at least* this big!
 * @param target The target on which the selector should be called when the
 *		 data has been received. If the method returns true, it will be
 *		 called again with the same buffer and exact length when more







|
|







215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
 *	  stream into a buffer.
 *
 * Unlike @ref asyncReadIntoBuffer:length:target:selector:context:, this method
 * does not call the method when less than the specified length has been read -
 * instead, it waits until it got exactly the specified length, the stream has
 * ended or an exception occurred.
 *
 * @note The stream must conform to @ref OFReadyForReadingObserving in order
 *	 for this to work!
 *
 * @param buffer The buffer into which the data is read
 * @param length The length of the data that should be read.
 *		 The buffer *must* be *at least* this big!
 * @param target The target on which the selector should be called when the
 *		 data has been received. If the method returns true, it will be
 *		 called again with the same buffer and exact length when more
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
 *
 * On network streams, this might read less than the specified number of bytes.
 * If you want to read exactly the specified number of bytes, use
 * @ref asyncReadIntoBuffer:exactLength:block:. Note that a read can even
 * return 0 bytes - this does not necessarily mean that the stream ended, so
 * you still need to check @ref atEndOfStream.
 *
 * @note The stream must implement @ref fileDescriptorForReading and return a
 *	 valid file descriptor in order for this to work!
 *
 * @param buffer The buffer into which the data is read.
 *		 The buffer must not be freed before the async read completed!
 * @param length The length of the data that should be read at most.
 *		 The buffer *must* be *at least* this big!
 * @param block The block to call when the data has been received.
 *		If the block returns true, it will be called again with the same







|
|







249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
 *
 * On network streams, this might read less than the specified number of bytes.
 * If you want to read exactly the specified number of bytes, use
 * @ref asyncReadIntoBuffer:exactLength:block:. Note that a read can even
 * return 0 bytes - this does not necessarily mean that the stream ended, so
 * you still need to check @ref atEndOfStream.
 *
 * @note The stream must conform to @ref OFReadyForReadingObserving in order
 *	 for this to work!
 *
 * @param buffer The buffer into which the data is read.
 *		 The buffer must not be freed before the async read completed!
 * @param length The length of the data that should be read at most.
 *		 The buffer *must* be *at least* this big!
 * @param block The block to call when the data has been received.
 *		If the block returns true, it will be called again with the same
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
 *	  stream into a buffer.
 *
 * Unlike @ref asyncReadIntoBuffer:length:block:, this method does not invoke
 * the block when less than the specified length has been read - instead, it
 * waits until it got exactly the specified length, the stream has ended or an
 * exception occurred.
 *
 * @note The stream must implement @ref fileDescriptorForReading and return a
 *	 valid file descriptor in order for this to work!
 *
 * @param buffer The buffer into which the data is read
 * @param length The length of the data that should be read.
 *		 The buffer *must* be *at least* this big!
 * @param block The block to call when the data has been received.
 *		If the block returns true, it will be called again with the same
 *		buffer and exact length when more data has been received. If







|
|







275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
 *	  stream into a buffer.
 *
 * Unlike @ref asyncReadIntoBuffer:length:block:, this method does not invoke
 * the block when less than the specified length has been read - instead, it
 * waits until it got exactly the specified length, the stream has ended or an
 * exception occurred.
 *
 * @note The stream must conform to @ref OFReadyForReadingObserving in order
 *	 for this to work!
 *
 * @param buffer The buffer into which the data is read
 * @param length The length of the data that should be read.
 *		 The buffer *must* be *at least* this big!
 * @param block The block to call when the data has been received.
 *		If the block returns true, it will be called again with the same
 *		buffer and exact length when more data has been received. If
658
659
660
661
662
663
664
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
694
- (nullable OFString *)readLineWithEncoding: (of_string_encoding_t)encoding;

#ifdef OF_HAVE_SOCKETS
/*!
 * @brief Asynchronously reads until a newline, `\0`, end of stream or an
 *	  exception occurs.
 *
 * @note The stream must implement @ref fileDescriptorForReading and return a
 *	 valid file descriptor in order for this to work!
 *
 * @param target The target on which to call the selector when the data has
 *		 been received. If the method returns true, it will be called
 *		 again when the next line has been received. If you want the
 *		 next method in the queue to handle the next line, you need to
 *		 return false from the method
 * @param selector The selector to call on the target. The signature must be
 *		   `bool (OFStream *stream, OFString *line, id context,
 *		   id exception)`.
 * @param context A context object to pass along to the target
 */
- (void)asyncReadLineWithTarget: (id)target
		       selector: (SEL)selector
			context: (nullable id)context;

/*!
 * @brief Asynchronously reads with the specified encoding until a newline,
 *	  `\0`, end of stream or an exception occurs.
 *
 * @note The stream must implement @ref fileDescriptorForReading and return a
 *	 valid file descriptor in order for this to work!
 *
 * @param encoding The encoding used by the stream
 * @param target The target on which to call the selector when the data has
 *		 been received. If the method returns true, it will be called
 *		 again when the next line has been received. If you want the
 *		 next method in the queue to handle the next line, you need to
 *		 return false from the method







|
|



















|
|







644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
- (nullable OFString *)readLineWithEncoding: (of_string_encoding_t)encoding;

#ifdef OF_HAVE_SOCKETS
/*!
 * @brief Asynchronously reads until a newline, `\0`, end of stream or an
 *	  exception occurs.
 *
 * @note The stream must conform to @ref OFReadyForReadingObserving in order
 *	 for this to work!
 *
 * @param target The target on which to call the selector when the data has
 *		 been received. If the method returns true, it will be called
 *		 again when the next line has been received. If you want the
 *		 next method in the queue to handle the next line, you need to
 *		 return false from the method
 * @param selector The selector to call on the target. The signature must be
 *		   `bool (OFStream *stream, OFString *line, id context,
 *		   id exception)`.
 * @param context A context object to pass along to the target
 */
- (void)asyncReadLineWithTarget: (id)target
		       selector: (SEL)selector
			context: (nullable id)context;

/*!
 * @brief Asynchronously reads with the specified encoding until a newline,
 *	  `\0`, end of stream or an exception occurs.
 *
 * @note The stream must conform to @ref OFReadyForReadingObserving in order
 *	 for this to work!
 *
 * @param encoding The encoding used by the stream
 * @param target The target on which to call the selector when the data has
 *		 been received. If the method returns true, it will be called
 *		 again when the next line has been received. If you want the
 *		 next method in the queue to handle the next line, you need to
 *		 return false from the method
703
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
			  context: (nullable id)context;

# ifdef OF_HAVE_BLOCKS
/*!
 * @brief Asynchronously reads until a newline, `\0`, end of stream or an
 *	  exception occurs.
 *
 * @note The stream must implement @ref fileDescriptorForReading and return a
 *	 valid file descriptor in order for this to work!
 *
 * @param block The block to call when the data has been received.
 *		If the block returns true, it will be called again when the next
 *		line has been received. If you want the next block in the queue
 *		to handle the next line, you need to return false from the
 *		block.
 */
- (void)asyncReadLineWithBlock: (of_stream_async_read_line_block_t)block;

/*!
 * @brief Asynchronously reads with the specified encoding until a newline,
 *	  `\0`, end of stream or an exception occurs.
 *
 * @note The stream must implement @ref fileDescriptorForReading and return a
 *	 valid file descriptor in order for this to work!
 *
 * @param encoding The encoding used by the stream
 * @param block The block to call when the data has been received.
 *		If the block returns true, it will be called again when the next
 *		line has been received. If you want the next block in the queue
 *		to handle the next line, you need to return false from the
 *		block.







|
|













|
|







689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
			  context: (nullable id)context;

# ifdef OF_HAVE_BLOCKS
/*!
 * @brief Asynchronously reads until a newline, `\0`, end of stream or an
 *	  exception occurs.
 *
 * @note The stream must conform to @ref OFReadyForReadingObserving in order
 *	 for this to work!
 *
 * @param block The block to call when the data has been received.
 *		If the block returns true, it will be called again when the next
 *		line has been received. If you want the next block in the queue
 *		to handle the next line, you need to return false from the
 *		block.
 */
- (void)asyncReadLineWithBlock: (of_stream_async_read_line_block_t)block;

/*!
 * @brief Asynchronously reads with the specified encoding until a newline,
 *	  `\0`, end of stream or an exception occurs.
 *
 * @note The stream must conform to @ref OFReadyForReadingObserving in order
 *	 for this to work!
 *
 * @param encoding The encoding used by the stream
 * @param block The block to call when the data has been received.
 *		If the block returns true, it will be called again when the next
 *		line has been received. If you want the next block in the queue
 *		to handle the next line, you need to return false from the
 *		block.
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
- (size_t)writeBuffer: (const void *)buffer
	       length: (size_t)length;

#ifdef OF_HAVE_SOCKETS
/*!
 * @brief Asynchronously writes a buffer into the stream.
 *
 * @note The stream must implement @ref fileDescriptorForWriting and return a
 *	 valid file descriptor in order for this to work!
 *
 * @param buffer The buffer from which the data is written into the stream. The
 *		 buffer needs to be valid until the write request is completed!
 * @param length The length of the data that should be written
 * @param target The target on which the selector should be called when the
 *		 data has been written. The method should return the length for
 *		 the next write with the same callback or 0 if it should not







|
|







805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
- (size_t)writeBuffer: (const void *)buffer
	       length: (size_t)length;

#ifdef OF_HAVE_SOCKETS
/*!
 * @brief Asynchronously writes a buffer into the stream.
 *
 * @note The stream must conform to @ref OFReadyForWritingObserving in order
 *	 for this to work!
 *
 * @param buffer The buffer from which the data is written into the stream. The
 *		 buffer needs to be valid until the write request is completed!
 * @param length The length of the data that should be written
 * @param target The target on which the selector should be called when the
 *		 data has been written. The method should return the length for
 *		 the next write with the same callback or 0 if it should not
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
		selector: (SEL)selector
		 context: (nullable id)context;

# ifdef OF_HAVE_BLOCKS
/*!
 * @brief Asynchronously writes a buffer into the stream.
 *
 * @note The stream must implement @ref fileDescriptorForWriting and return a
 *	 valid file descriptor in order for this to work!
 *
 * @param buffer The buffer from which the data is written into the stream. The
 *		 buffer needs to be valid until the write request is completed!
 * @param length The length of the data that should be written
 * @param block The block to call when the data has been written. It should
 *		return the length for the next write with the same callback or
 *		0 if it should not repeat. The buffer may be changed, so that







|
|







832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
		selector: (SEL)selector
		 context: (nullable id)context;

# ifdef OF_HAVE_BLOCKS
/*!
 * @brief Asynchronously writes a buffer into the stream.
 *
 * @note The stream must conform to @ref OFReadyForWritingObserving in order
 *	 for this to work!
 *
 * @param buffer The buffer from which the data is written into the stream. The
 *		 buffer needs to be valid until the write request is completed!
 * @param length The length of the data that should be written
 * @param block The block to call when the data has been written. It should
 *		return the length for the next write with the same callback or
 *		0 if it should not repeat. The buffer may be changed, so that

Modified src/OFStream.m from [3125ef69c3] to [e841a9f1c7].

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
#ifdef OF_HAVE_SOCKETS
- (void)asyncReadIntoBuffer: (void *)buffer
		     length: (size_t)length
		     target: (id)target
		   selector: (SEL)selector
		    context: (id)context
{



	[OFRunLoop of_addAsyncReadForStream: self
				     buffer: buffer
				     length: length
				     target: target
				   selector: selector
				    context: context];
}

- (void)asyncReadIntoBuffer: (void *)buffer
		exactLength: (size_t)length
		     target: (id)target
		   selector: (SEL)selector
		    context: (id)context
{



	[OFRunLoop of_addAsyncReadForStream: self
				     buffer: buffer
				exactLength: length
				     target: target
				   selector: selector
				    context: context];
}

# ifdef OF_HAVE_BLOCKS
- (void)asyncReadIntoBuffer: (void *)buffer
		     length: (size_t)length
		      block: (of_stream_async_read_block_t)block
{



	[OFRunLoop of_addAsyncReadForStream: self
				     buffer: buffer
				     length: length
				      block: block];
}

- (void)asyncReadIntoBuffer: (void *)buffer
		exactLength: (size_t)length
		      block: (of_stream_async_read_block_t)block
{



	[OFRunLoop of_addAsyncReadForStream: self
				     buffer: buffer
				exactLength: length
				      block: block];
}
# endif
#endif








>
>
>
|













>
>
>
|












>
>
>
|









>
>
>
|







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
244
245
246
247
248
249
250
251
252
253
254
#ifdef OF_HAVE_SOCKETS
- (void)asyncReadIntoBuffer: (void *)buffer
		     length: (size_t)length
		     target: (id)target
		   selector: (SEL)selector
		    context: (id)context
{
	OFStream <OFReadyForReadingObserving> *stream =
	    (OFStream <OFReadyForReadingObserving> *)self;

	[OFRunLoop of_addAsyncReadForStream: stream
				     buffer: buffer
				     length: length
				     target: target
				   selector: selector
				    context: context];
}

- (void)asyncReadIntoBuffer: (void *)buffer
		exactLength: (size_t)length
		     target: (id)target
		   selector: (SEL)selector
		    context: (id)context
{
	OFStream <OFReadyForReadingObserving> *stream =
	    (OFStream <OFReadyForReadingObserving> *)self;

	[OFRunLoop of_addAsyncReadForStream: stream
				     buffer: buffer
				exactLength: length
				     target: target
				   selector: selector
				    context: context];
}

# ifdef OF_HAVE_BLOCKS
- (void)asyncReadIntoBuffer: (void *)buffer
		     length: (size_t)length
		      block: (of_stream_async_read_block_t)block
{
	OFStream <OFReadyForReadingObserving> *stream =
	    (OFStream <OFReadyForReadingObserving> *)self;

	[OFRunLoop of_addAsyncReadForStream: stream
				     buffer: buffer
				     length: length
				      block: block];
}

- (void)asyncReadIntoBuffer: (void *)buffer
		exactLength: (size_t)length
		      block: (of_stream_async_read_block_t)block
{
	OFStream <OFReadyForReadingObserving> *stream =
	    (OFStream <OFReadyForReadingObserving> *)self;

	[OFRunLoop of_addAsyncReadForStream: stream
				     buffer: buffer
				exactLength: length
				      block: block];
}
# endif
#endif

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
}

- (void)asyncReadLineWithEncoding: (of_string_encoding_t)encoding
			   target: (id)target
			 selector: (SEL)selector
			  context: (id)context
{



	[OFRunLoop of_addAsyncReadLineForStream: self
				       encoding: encoding
					 target: target
				       selector: selector
					context: context];
}

# ifdef OF_HAVE_BLOCKS
- (void)asyncReadLineWithBlock: (of_stream_async_read_line_block_t)block
{
	[self asyncReadLineWithEncoding: OF_STRING_ENCODING_UTF_8
				  block: block];
}

- (void)asyncReadLineWithEncoding: (of_string_encoding_t)encoding
			    block: (of_stream_async_read_line_block_t)block
{



	[OFRunLoop of_addAsyncReadLineForStream: self
				       encoding: encoding
					  block: block];
}
# endif
#endif

- (OFString *)tryReadLine







>
>
>
|
















>
>
>
|







838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
}

- (void)asyncReadLineWithEncoding: (of_string_encoding_t)encoding
			   target: (id)target
			 selector: (SEL)selector
			  context: (id)context
{
	OFStream <OFReadyForReadingObserving> *stream =
	    (OFStream <OFReadyForReadingObserving> *)self;

	[OFRunLoop of_addAsyncReadLineForStream: stream
				       encoding: encoding
					 target: target
				       selector: selector
					context: context];
}

# ifdef OF_HAVE_BLOCKS
- (void)asyncReadLineWithBlock: (of_stream_async_read_line_block_t)block
{
	[self asyncReadLineWithEncoding: OF_STRING_ENCODING_UTF_8
				  block: block];
}

- (void)asyncReadLineWithEncoding: (of_string_encoding_t)encoding
			    block: (of_stream_async_read_line_block_t)block
{
	OFStream <OFReadyForReadingObserving> *stream =
	    (OFStream <OFReadyForReadingObserving> *)self;

	[OFRunLoop of_addAsyncReadLineForStream: stream
				       encoding: encoding
					  block: block];
}
# endif
#endif

- (OFString *)tryReadLine
1075
1076
1077
1078
1079
1080
1081



1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094



1095
1096
1097
1098
1099
1100
1101
1102
#ifdef OF_HAVE_SOCKETS
- (void)asyncWriteBuffer: (const void *)buffer
		  length: (size_t)length
		  target: (id)target
		selector: (SEL)selector
		 context: (id)context
{



	[OFRunLoop of_addAsyncWriteForStream: self
				      buffer: buffer
				      length: length
				      target: target
				    selector: selector
				     context: context];
}

# ifdef OF_HAVE_BLOCKS
- (void)asyncWriteBuffer: (const void *)buffer
		  length: (size_t)length
		   block: (of_stream_async_write_block_t)block
{



	[OFRunLoop of_addAsyncWriteForStream: self
				      buffer: buffer
				      length: length
				       block: block];
}
# endif
#endif








>
>
>
|












>
>
>
|







1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
#ifdef OF_HAVE_SOCKETS
- (void)asyncWriteBuffer: (const void *)buffer
		  length: (size_t)length
		  target: (id)target
		selector: (SEL)selector
		 context: (id)context
{
	OFStream <OFReadyForWritingObserving> *stream =
	    (OFStream <OFReadyForWritingObserving> *)self;

	[OFRunLoop of_addAsyncWriteForStream: stream
				      buffer: buffer
				      length: length
				      target: target
				    selector: selector
				     context: context];
}

# ifdef OF_HAVE_BLOCKS
- (void)asyncWriteBuffer: (const void *)buffer
		  length: (size_t)length
		   block: (of_stream_async_write_block_t)block
{
	OFStream <OFReadyForWritingObserving> *stream =
	    (OFStream <OFReadyForWritingObserving> *)self;

	[OFRunLoop of_addAsyncWriteForStream: stream
				      buffer: buffer
				      length: length
				       block: block];
}
# endif
#endif

Modified src/OFStreamSocket.h from [860d3abaef] to [b23fa26dc0].

21
22
23
24
25
26
27
28

29
30
31
32
33
34
35
OF_ASSUME_NONNULL_BEGIN

/*!
 * @class OFStreamSocket OFStreamSocket.h ObjFW/OFStreamSocket.h
 *
 * @brief A class which provides methods to create and use stream sockets.
 */
@interface OFStreamSocket: OFStream

{
	of_socket_t _socket;
	bool _atEndOfStream;
}

/*!
 * @brief Returns a new, autoreleased OFTCPSocket.







|
>







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

/*!
 * @class OFStreamSocket OFStreamSocket.h ObjFW/OFStreamSocket.h
 *
 * @brief A class which provides methods to create and use stream sockets.
 */
@interface OFStreamSocket: OFStream <OFReadyForReadingObserving,
    OFReadyForWritingObserving>
{
	of_socket_t _socket;
	bool _atEndOfStream;
}

/*!
 * @brief Returns a new, autoreleased OFTCPSocket.

Modified src/OFTarArchive.h from [155fb2c98a] to [5395b52e6f].

11
12
13
14
15
16
17

18
19
20
21
22
23
24
 * 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 "OFTarArchiveEntry.h"

OF_ASSUME_NONNULL_BEGIN

@class OFString;
@class OFStream;








>







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFObject.h"
#import "OFKernelEventObserver.h"
#import "OFTarArchiveEntry.h"

OF_ASSUME_NONNULL_BEGIN

@class OFString;
@class OFStream;

38
39
40
41
42
43
44



45
46

47
48
49
50
51
52
53
	OF_KINDOF(OFStream *) _Nullable _lastReturnedStream;
}

/*!
 * @brief A stream for reading the current entry
 *
 * @note This is only available in read mode.



 */
@property (readonly, nonatomic) OFStream *streamForReadingCurrentEntry;


/*!
 * @brief Creates a new OFTarArchive object with the specified stream.
 *
 * @param stream A stream from which the tar archive will be read.
 *		 For append mode, this needs to be an OFSeekableStream.
 * @param mode The mode for the tar file. Valid modes are "r" for reading,







>
>
>

|
>







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
	OF_KINDOF(OFStream *) _Nullable _lastReturnedStream;
}

/*!
 * @brief A stream for reading the current entry
 *
 * @note This is only available in read mode.
 *
 * @note The returned stream only conforms to @ref OFReadyForReadingObserving if
 *	 the underlying stream does so, too.
 */
@property (readonly, nonatomic)
    OFStream <OFReadyForReadingObserving> *streamForReadingCurrentEntry;

/*!
 * @brief Creates a new OFTarArchive object with the specified stream.
 *
 * @param stream A stream from which the tar archive will be read.
 *		 For append mode, this needs to be an OFSeekableStream.
 * @param mode The mode for the tar file. Valid modes are "r" for reading,
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
 */
- (nullable OFTarArchiveEntry *)nextEntry;

/*!
 * @brief Returns a stream for writing the specified entry.
 *
 * @note This is only available in write and append mode.



 *
 * @warning Calling @ref nextEntry will invalidate all streams returned by
 *	    @ref streamForReadingCurrentEntry or
 *	    @ref streamForWritingEntry:! Reading from or writing to an
 *	    invalidated stream will throw an @ref OFReadFailedException or
 *	    @ref OFWriteFailedException!
 *
 * @param entry The entry for which a stream for writing should be returned
 * @return A stream for writing the specified entry
 */

- (OFStream *)streamForWritingEntry: (OFTarArchiveEntry *)entry;

/*!
 * @brief Closes the OFTarArchive.
 */
- (void)close;
@end

OF_ASSUME_NONNULL_END







>
>
>










>
|








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
 */
- (nullable OFTarArchiveEntry *)nextEntry;

/*!
 * @brief Returns a stream for writing the specified entry.
 *
 * @note This is only available in write and append mode.
 *
 * @note The returned stream only conforms to @ref OFReadyForWritingObserving if
 *	 the underlying stream does so, too.
 *
 * @warning Calling @ref nextEntry will invalidate all streams returned by
 *	    @ref streamForReadingCurrentEntry or
 *	    @ref streamForWritingEntry:! Reading from or writing to an
 *	    invalidated stream will throw an @ref OFReadFailedException or
 *	    @ref OFWriteFailedException!
 *
 * @param entry The entry for which a stream for writing should be returned
 * @return A stream for writing the specified entry
 */
- (OFStream <OFReadyForWritingObserving> *)
    streamForWritingEntry: (OFTarArchiveEntry *)entry;

/*!
 * @brief Closes the OFTarArchive.
 */
- (void)close;
@end

OF_ASSUME_NONNULL_END

Modified src/OFTarArchive.m from [72c8a07e42] to [247f54af17].

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
#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFNotOpenException.h"
#import "OFOutOfRangeException.h"
#import "OFTruncatedDataException.h"
#import "OFWriteFailedException.h"

@interface OFTarArchive_FileReadStream: OFStream
{
	OFTarArchiveEntry *_entry;
	OF_KINDOF(OFStream *) _stream;
	uint64_t _toRead;
	bool _atEndOfStream;
}

- (instancetype)initWithStream: (OFStream *)stream
			 entry: (OFTarArchiveEntry *)entry;
- (void)of_skip;
@end

@interface OFTarArchive_FileWriteStream: OFStream
{
	OFTarArchiveEntry *_entry;
	OFStream *_stream;
	uint64_t _toWrite;
}

- (instancetype)initWithStream: (OFStream *)stream
			 entry: (OFTarArchiveEntry *)entry;
@end








|












|


|







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
#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFNotOpenException.h"
#import "OFOutOfRangeException.h"
#import "OFTruncatedDataException.h"
#import "OFWriteFailedException.h"

@interface OFTarArchive_FileReadStream: OFStream <OFReadyForReadingObserving>
{
	OFTarArchiveEntry *_entry;
	OF_KINDOF(OFStream *) _stream;
	uint64_t _toRead;
	bool _atEndOfStream;
}

- (instancetype)initWithStream: (OFStream *)stream
			 entry: (OFTarArchiveEntry *)entry;
- (void)of_skip;
@end

@interface OFTarArchive_FileWriteStream: OFStream <OFReadyForWritingObserving>
{
	OFTarArchiveEntry *_entry;
	OF_KINDOF(OFStream *) _stream;
	uint64_t _toWrite;
}

- (instancetype)initWithStream: (OFStream *)stream
			 entry: (OFTarArchiveEntry *)entry;
@end

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
	_lastReturnedStream = [[OFTarArchive_FileReadStream alloc]
	    initWithStream: _stream
		     entry: entry];

	return entry;
}

- (OFStream *)streamForReadingCurrentEntry
{
	if (_mode != OF_TAR_ARCHIVE_MODE_READ)
		@throw [OFInvalidArgumentException exception];

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

	return [[_lastReturnedStream retain] autorelease];
}


- (OFStream *)streamForWritingEntry: (OFTarArchiveEntry *)entry
{
	void *pool;

	if (_mode != OF_TAR_ARCHIVE_MODE_WRITE &&
	    _mode != OF_TAR_ARCHIVE_MODE_APPEND)
		@throw [OFInvalidArgumentException exception];








|










>
|







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
	_lastReturnedStream = [[OFTarArchive_FileReadStream alloc]
	    initWithStream: _stream
		     entry: entry];

	return entry;
}

- (OFStream <OFReadyForReadingObserving> *)streamForReadingCurrentEntry
{
	if (_mode != OF_TAR_ARCHIVE_MODE_READ)
		@throw [OFInvalidArgumentException exception];

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

	return [[_lastReturnedStream retain] autorelease];
}

- (OFStream <OFReadyForWritingObserving> *)
    streamForWritingEntry: (OFTarArchiveEntry *)entry
{
	void *pool;

	if (_mode != OF_TAR_ARCHIVE_MODE_WRITE &&
	    _mode != OF_TAR_ARCHIVE_MODE_APPEND)
		@throw [OFInvalidArgumentException exception];