summaryrefslogtreecommitdiffstats
path: root/generic/tclIO.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclIO.c')
-rw-r--r--generic/tclIO.c44
1 files changed, 34 insertions, 10 deletions
diff --git a/generic/tclIO.c b/generic/tclIO.c
index dcde8d1..9283bf5 100644
--- a/generic/tclIO.c
+++ b/generic/tclIO.c
@@ -3894,7 +3894,10 @@ Tcl_Write(
if (srcLen < 0) {
srcLen = strlen(src);
}
- return WriteBytes(chanPtr, src, srcLen);
+ if (WriteBytes(chanPtr, src, srcLen) < 0) {
+ return -1;
+ }
+ return srcLen;
}
/*
@@ -6046,12 +6049,11 @@ ReadChars(
/*
* We read more chars than allowed. Reset limits to
* prevent that and try again. Don't forget the extra
- * padding of TCL_UTF_MAX - 1 bytes demanded by the
+ * padding of TCL_UTF_MAX bytes demanded by the
* Tcl_ExternalToUtf() call!
*/
- dstLimit = Tcl_UtfAtIndex(dst, charsToRead + 1)
- + TCL_UTF_MAX - 1 - dst;
+ dstLimit = Tcl_UtfAtIndex(dst, charsToRead) + TCL_UTF_MAX - dst;
statePtr->flags = savedFlags;
statePtr->inputEncodingFlags = savedIEFlags;
statePtr->inputEncodingState = savedState;
@@ -9021,7 +9023,7 @@ MBRead(
}
code = GetInput(inStatePtr->topChanPtr);
- if (code == 0) {
+ if (code == 0 || GotFlag(inStatePtr, CHANNEL_BLOCKED)) {
return TCL_OK;
} else {
MBError(csPtr, TCL_READABLE, code);
@@ -9271,6 +9273,10 @@ CopyData(
csPtr);
}
if (size == 0) {
+ if (!GotFlag(inStatePtr, CHANNEL_NONBLOCKING)) {
+ /* We allowed a short read. Keep trying. */
+ continue;
+ }
if (bufObj != NULL) {
TclDecrRefCount(bufObj);
bufObj = NULL;
@@ -9503,21 +9509,39 @@ DoRead(
}
/*
- * If there is not enough data in the buffers to possibly
- * complete the read, then go get more.
+ * Don't read more data if we have what we need.
*/
- if (bufPtr == NULL || BytesLeft(bufPtr) < bytesToRead) {
+ while (!bufPtr || /* We got no buffer! OR */
+ (!IsBufferFull(bufPtr) && /* Our buffer has room AND */
+ (BytesLeft(bufPtr) < bytesToRead) ) ) {
+ /* Not enough bytes in it
+ * yet to fill the dst */
+ int code;
+
moreData:
- if (GetInput(chanPtr)) {
+ code = GetInput(chanPtr);
+ bufPtr = statePtr->inQueueHead;
+
+ assert (bufPtr != NULL);
+
+ if (GotFlag(statePtr, CHANNEL_EOF|CHANNEL_BLOCKED)) {
+ /* Further reads cannot do any more */
+ break;
+ }
+
+ if (code) {
/* Read error */
UpdateInterest(chanPtr);
TclChannelRelease((Tcl_Channel)chanPtr);
return -1;
}
- bufPtr = statePtr->inQueueHead;
+
+ assert (IsBufferFull(bufPtr));
}
+ assert (bufPtr != NULL);
+
bytesRead = BytesLeft(bufPtr);
bytesWritten = bytesToRead;