Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Headers/CoreFoundation/CFStreamPriv.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ struct __CFReadStream
CFRuntimeBase parent;
struct CFReadStreamImpl impl;

Boolean open, closed, failed;
Boolean open, closed, failed, atEnd;
CFErrorRef error;

/* callbacks when used with a runloop */
Expand Down
15 changes: 13 additions & 2 deletions Source/CFStream.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
# include <unistd.h>
# include <errno.h>
#endif
#include <errno.h>
#include <stdlib.h>

CONST_STRING_DECL(kCFStreamPropertyDataWritten, "kCFStreamPropertyDataWritten");
Expand Down Expand Up @@ -557,7 +558,7 @@ CFStreamGetError (CFErrorRef inError)
{
if (!inError)
{
CFStreamError error = { kCFStreamErrorDomainPOSIX, 0 };
CFStreamError error = { 0, 0 };
return error;
}
else
Expand Down Expand Up @@ -856,7 +857,11 @@ CFWriteStreamBufferWrite (CFWriteStreamRef s, const UInt8 *buffer,
stream->bufferCapacity = cap;
}
else
bufferLength = bufSpace;
{
CFWriteStreamSetError(s, ENOMEM);
s->failed = true;
return -1;
}
}

GSMemoryCopy(stream->buffer + stream->position, buffer, bufferLength);
Expand Down Expand Up @@ -1027,6 +1032,7 @@ CFReadStreamBufferGetBuffer (CFReadStreamRef s, CFIndex maxBytesToRead,

retval = stream->buffer + stream->position;
stream->position += *numBytesRead;
s->atEnd = (stream->position >= stream->bufferCapacity);

return retval;
}
Expand Down Expand Up @@ -1068,6 +1074,8 @@ CFReadStreamGetStatus (CFReadStreamRef stream)
return kCFStreamStatusClosed;
else if (stream->failed)
return kCFStreamStatusError;
else if (stream->atEnd)
return kCFStreamStatusAtEnd;
else if (stream->open)
return kCFStreamStatusOpen;
else
Expand All @@ -1089,6 +1097,8 @@ CFReadStreamHasBytesAvailable (CFReadStreamRef stream)
CF_OBJC_FUNCDISPATCHV(_kCFReadStreamTypeID, Boolean, stream,
"hasBytesAvailable");

if (!stream->open || stream->closed)
return false;
if (stream->impl.hasBytes != NULL)
return stream->impl.hasBytes(stream);
return true;
Expand Down Expand Up @@ -1196,6 +1206,7 @@ CFReadStreamBufferRead (CFReadStreamRef s, UInt8 *buffer, CFIndex bufferLength)

GSMemoryCopy(buffer, stream->buffer + stream->position, bufferLength);
stream->position += bufferLength;
s->atEnd = (stream->position >= stream->bufferCapacity);

return bufferLength;
}
Expand Down
30 changes: 30 additions & 0 deletions Tests/CFStream/no_error.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include <CoreFoundation/CFStream.h>

#include "../CFTesting.h"

int main (void)
{
const char *data = "ABC";
CFReadStreamRef r;
CFWriteStreamRef w;
CFStreamError e;

r = CFReadStreamCreateWithBytesNoCopy (NULL, (const UInt8 *)data, 3,
kCFAllocatorNull);
CFReadStreamOpen (r);
e = CFReadStreamGetError (r);
PASS_CF(e.domain == 0 && e.error == 0,
"A read stream with no error reports domain 0.");
CFReadStreamClose (r);
CFRelease (r);

w = CFWriteStreamCreateWithAllocatedBuffers (NULL, NULL);
CFWriteStreamOpen (w);
e = CFWriteStreamGetError (w);
PASS_CF(e.domain == 0 && e.error == 0,
"A write stream with no error reports domain 0.");
CFWriteStreamClose (w);
CFRelease (w);

return 0;
}
27 changes: 27 additions & 0 deletions Tests/CFStream/read_atend.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include <CoreFoundation/CFStream.h>

#include "../CFTesting.h"

int main (void)
{
const char *data = "ABCDEFGHIJ";
UInt8 buf[64];
CFReadStreamRef r;

r = CFReadStreamCreateWithBytesNoCopy (NULL, (const UInt8 *)data, 10,
kCFAllocatorNull);
CFReadStreamOpen (r);
CFReadStreamRead (r, buf, 10);
PASS_CF(CFReadStreamGetStatus (r) == kCFStreamStatusAtEnd,
"Status is AtEnd once all bytes are consumed.");
PASS_CF(CFReadStreamHasBytesAvailable (r) == false,
"No bytes are available at the end.");
PASS_CF(CFReadStreamRead (r, buf, 64) == 0,
"Reading past the end returns zero.");
PASS_CF(CFReadStreamGetStatus (r) == kCFStreamStatusAtEnd,
"Status remains AtEnd past the end.");
CFReadStreamClose (r);
CFRelease (r);

return 0;
}
19 changes: 19 additions & 0 deletions Tests/CFStream/read_unopened.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include <CoreFoundation/CFStream.h>

#include "../CFTesting.h"

int main (void)
{
const char *data = "ABCDEFGHIJ";
CFReadStreamRef r;

r = CFReadStreamCreateWithBytesNoCopy (NULL, (const UInt8 *)data, 10,
kCFAllocatorNull);
PASS_CF(CFReadStreamGetStatus (r) == kCFStreamStatusNotOpen,
"Status is NotOpen before opening.");
PASS_CF(CFReadStreamHasBytesAvailable (r) == false,
"No bytes are available before the stream is opened.");
CFRelease (r);

return 0;
}
27 changes: 27 additions & 0 deletions Tests/CFStream/write_overflow.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include <CoreFoundation/CFStream.h>

#include "../CFTesting.h"
#include <string.h>
#include <errno.h>

int main (void)
{
UInt8 fb[8];
CFWriteStreamRef w;
CFStreamError e;

w = CFWriteStreamCreateWithBuffer (NULL, fb, 8);
CFWriteStreamOpen (w);
PASS_CF(CFWriteStreamWrite (w, (const UInt8 *)"ABCDEFGH", 8) == 8,
"Filling the fixed buffer exactly succeeds.");
PASS_CF(CFWriteStreamWrite (w, (const UInt8 *)"X", 1) == -1,
"Writing past the fixed buffer returns -1.");
PASS_CF(CFWriteStreamGetStatus (w) == kCFStreamStatusError,
"Status is Error after overflowing the fixed buffer.");
e = CFWriteStreamGetError (w);
PASS_CF(e.domain == kCFStreamErrorDomainPOSIX && e.error == ENOMEM,
"Overflowing the fixed buffer reports POSIX ENOMEM.");
CFRelease (w);

return 0;
}
Loading