Compare commits

...
Author SHA1 Message Date
dgp 9befca04cc Make simplificiations possible when we know just bytes are getting copied
without complications of encodings
2014-08-21 04:13:35 +00:00
dgp d8f1034a21 Copy Write() to WriteBytes() to create an arena for performance hacking. 2014-08-20 21:44:31 +00:00
andreask ce04ed5ad3 Fix reviewed and accepted. 2014-08-20 18:59:31 +00:00
dgp eda831ff7e Make test io-36.1.1 more portable. 2014-08-20 18:40:07 +00:00
2 changed files with 130 additions and 3 deletions
+126 -2
View File
@@ -228,8 +228,8 @@ static int WillRead(Channel *chanPtr);
#define WriteChars(chanPtr, src, srcLen) \
Write(chanPtr, src, srcLen, chanPtr->state->encoding)
#define WriteBytes(chanPtr, src, srcLen) \
Write(chanPtr, src, srcLen, tclIdentityEncoding)
static int WriteBytes(Channel *chanPtr, const char *src,
int srcLen);
/*
* Simplifying helper macros. All may use their argument(s) multiple times.
@@ -3888,6 +3888,130 @@ Write(
return total;
}
static int
WriteBytes(
Channel *chanPtr, /* The channel to buffer output for. */
const char *src, /* UTF-8 string to write. */
int srcLen) /* Length of UTF-8 string in bytes. */
{
ChannelState *statePtr = chanPtr->state;
/* State info for channel */
char *nextNewLine = NULL;
int saved = 0, total = 0, flushed = 0, needNlFlush = 0;
if (srcLen) {
WillWrite(chanPtr);
}
if (GotFlag(statePtr, CHANNEL_LINEBUFFERED)
|| (statePtr->outputTranslation != TCL_TRANSLATE_LF)) {
nextNewLine = memchr(src, '\n', srcLen);
}
while (srcLen + saved > 0) {
ChannelBuffer *bufPtr;
char *dst;
int dstLen, srcLimit = srcLen;
if (nextNewLine) {
srcLimit = nextNewLine - src;
}
/* Get space to write into */
bufPtr = statePtr->curOutPtr;
if (bufPtr == NULL) {
bufPtr = AllocChannelBuffer(statePtr->bufSize);
statePtr->curOutPtr = bufPtr;
}
if (saved) {
/* Start new buffer with \n straddled over from last one */
InsertPoint(bufPtr)[0] = '\n';
bufPtr->nextAdded++;
saved = 0;
needNlFlush = 1;
}
PreserveChannelBuffer(bufPtr);
dst = InsertPoint(bufPtr);
dstLen = SpaceLeft(bufPtr);
if (srcLimit < 0) {
srcLimit = strlen(src);
}
if (srcLimit > dstLen) {
srcLimit = dstLen;
}
memcpy(dst, src, (size_t) srcLimit);
bufPtr->nextAdded += srcLimit;
src += srcLimit;
srcLen -= srcLimit;
total += srcLimit;
dst += srcLimit;
dstLen -= srcLimit;
if (src == nextNewLine && dstLen > 0) {
static char crln[3] = "\r\n";
char *nl = NULL;
int nlLen = 0;
switch (statePtr->outputTranslation) {
case TCL_TRANSLATE_LF:
nl = crln + 1;
nlLen = 1;
break;
case TCL_TRANSLATE_CR:
nl = crln;
nlLen = 1;
break;
case TCL_TRANSLATE_CRLF:
nl = crln;
nlLen = 2;
break;
default:
Tcl_Panic("unknown output translation requested");
break;
}
memcpy(dst, nl, (size_t) nlLen);
bufPtr->nextAdded += nlLen;
src++;
srcLen--;
total += nlLen;
dst += nlLen;
dstLen -= nlLen;
nextNewLine = memchr(src, '\n', srcLen);
needNlFlush = 1;
}
if (IsBufferOverflowing(bufPtr)) {
/* Can only happend when \r\n straddles buffers */
saved = 1;
bufPtr->nextAdded = bufPtr->bufLength;
}
if (IsBufferFull(bufPtr)) {
if (FlushChannel(NULL, chanPtr, 0) != 0) {
ReleaseChannelBuffer(bufPtr);
return -1;
}
/* TODO: ought to add bytes actually flushed */
flushed += statePtr->bufSize;
needNlFlush = 0;
}
ReleaseChannelBuffer(bufPtr);
}
if ((flushed < total) && (GotFlag(statePtr, CHANNEL_UNBUFFERED) ||
(needNlFlush && GotFlag(statePtr, CHANNEL_LINEBUFFERED)))) {
if (FlushChannel(NULL, chanPtr, 0) != 0) {
return -1;
}
}
return total;
}
/*
*---------------------------------------------------------------------------
+4 -1
View File
@@ -4924,7 +4924,10 @@ test io-36.1 {Tcl_InputBlocked on nonblocking pipe} {stdio openpipe} {
test io-36.1.1 {Tcl_InputBlocked on nonblocking binary pipe} {stdio openpipe} {
set f1 [open "|[list [interpreter]]" r+]
chan configure $f1 -encoding binary -translation lf -eofchar {}
puts $f1 {puts hello_from_pipe}
puts $f1 {
chan configure stdout -encoding binary -translation lf -eofchar {}
puts hello_from_pipe
}
flush $f1
gets $f1
fconfigure $f1 -blocking off -buffering full