summaryrefslogtreecommitdiffstats
path: root/generic/tclIO.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclIO.c')
-rw-r--r--generic/tclIO.c64
1 files changed, 33 insertions, 31 deletions
diff --git a/generic/tclIO.c b/generic/tclIO.c
index b0d0e32..03aac32 100644
--- a/generic/tclIO.c
+++ b/generic/tclIO.c
@@ -5244,7 +5244,11 @@ ReadChars(
* is larger than the number of characters
* available in the first buffer, only the
* characters from the first buffer are
- * returned. */
+ * returned. The execption is when there is
+ * not any complete character in the first
+ * buffer. In that case, a recursive call
+ * effectively obtains chars from the
+ * second buffer. */
int *factorPtr) /* On input, contains a guess of how many
* bytes need to be allocated to hold the
* result of converting N source bytes to
@@ -5259,6 +5263,15 @@ ReadChars(
int savedFlags = statePtr->flags;
char *dst, *src = RemovePoint(bufPtr);
int dstLimit, numBytes, srcLen = BytesLeft(bufPtr);
+
+ /*
+ * One src byte can yield at most one character. So when the
+ * number of src bytes we plan to read is less than the limit on
+ * character count to be read, clearly we will remain within that
+ * limit, and we can use the value of "srcLen" as a tighter limit
+ * for sizing receiving buffers.
+ */
+
int toRead = ((unsigned) charsToRead > srcLen) ? srcLen : charsToRead;
/*
@@ -5569,43 +5582,32 @@ TranslateInputEOL(
* characters. */
const char *srcStart, /* Source characters. */
int *dstLenPtr, /* On entry, the maximum length of output
- * buffer in bytes; must be <= *srcLenPtr. On
- * exit, the number of bytes actually used in
- * output buffer. */
+ * buffer in bytes. On exit, the number of
+ * bytes actually used in output buffer. */
int *srcLenPtr) /* On entry, the length of source buffer. On
* exit, the number of bytes read from the
* source buffer. */
{
- int dstLen, srcLen, inEofChar;
- const char *eof;
+ const char *eof = NULL;
+ int dstLen = *dstLenPtr;
+ int srcLen = *srcLenPtr;
+ int inEofChar = statePtr->inEofChar;
- dstLen = *dstLenPtr;
-
- eof = NULL;
- inEofChar = statePtr->inEofChar;
if (inEofChar != '\0') {
/*
- * Find EOF in translated buffer then compress out the EOL. The source
- * buffer may be much longer than the destination buffer - we only
- * want to return EOF if the EOF has been copied to the destination
- * buffer.
+ * Make sure we do not read past any logical end of channel input
+ * created by the presence of the input eof char.
*/
- const char *src, *srcMax;
-
- srcMax = srcStart + *srcLenPtr;
- for (src = srcStart; src < srcMax; src++) {
- if (*src == inEofChar) {
- eof = src;
- srcLen = src - srcStart;
- if (srcLen < dstLen) {
- dstLen = srcLen;
- }
- *srcLenPtr = srcLen;
- break;
- }
+ if ((eof = memchr(srcStart, inEofChar, srcLen))) {
+ srcLen = eof - srcStart;
}
}
+
+ if (dstLen > srcLen) {
+ dstLen = srcLen;
+ }
+
switch (statePtr->inputTranslation) {
case TCL_TRANSLATE_LF:
if (dstStart != srcStart) {
@@ -5635,7 +5637,7 @@ TranslateInputEOL(
dst = dstStart;
src = srcStart;
srcEnd = srcStart + dstLen;
- srcMax = srcStart + *srcLenPtr;
+ srcMax = srcStart + srcLen;
for ( ; src < srcEnd; ) {
if (*src == '\r') {
@@ -5663,7 +5665,7 @@ TranslateInputEOL(
dst = dstStart;
src = srcStart;
srcEnd = srcStart + dstLen;
- srcMax = srcStart + *srcLenPtr;
+ srcMax = srcStart + srcLen;
if ((statePtr->flags & INPUT_SAW_CR) && (src < srcMax)) {
if (*src == '\n') {
@@ -5692,9 +5694,10 @@ TranslateInputEOL(
break;
}
default:
- return 0;
+ Tcl_Panic("unknown input translation %d", statePtr->inputTranslation);
}
*dstLenPtr = dstLen;
+ *srcLenPtr = srcLen;
if ((eof != NULL) && (srcStart + srcLen >= eof)) {
/*
@@ -5709,7 +5712,6 @@ TranslateInputEOL(
return 1;
}
- *srcLenPtr = srcLen;
return 0;
}