Tcl Source Code

Artifact [8d7386b6bf]
Login

Artifact 8d7386b6bf454930436567ea28dc90a6c7911647:

Attachment "escape2times.patch" to ticket [1516109fff] added by mdejong 2006-07-03 09:57:15.
2006-07-02  Mo DeJong  <[email protected]>

	* generic/tclEncoding.c (EscapeFromUtfProc):
        Clear the TCL_ENCODING_END flag when end
        bytes are written. This fix keep this method
        from writing escape bytes for an encoding
        like iso2022-jp multiple times when the
        escape byte overlap with the end of the
        IO buffer.
	* tests/io.test: Add test case for escape
        byte overlap case.

Index: generic/tclEncoding.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclEncoding.c,v
retrieving revision 1.42
diff -u -r1.42 tclEncoding.c
--- generic/tclEncoding.c	5 Apr 2006 00:18:50 -0000	1.42
+++ generic/tclEncoding.c	3 Jul 2006 02:36:07 -0000
@@ -2973,7 +2973,7 @@
 
     if (flags & TCL_ENCODING_START) {
 	state = 0;
-	if (dst + dataPtr->initLen > dstEnd) {
+	if ((dst + dataPtr->initLen) > dstEnd) {
 	    *srcReadPtr = 0;
 	    *dstWrotePtr = 0;
 	    return TCL_CONVERT_NOSPACE;
@@ -3081,7 +3081,17 @@
 
     if ((result == TCL_OK) && (flags & TCL_ENCODING_END)) {
 	unsigned int len = dataPtr->subTables[0].sequenceLen;
-	if (dst + dataPtr->finalLen + (state?len:0) > dstEnd) {
+	/*
+	 * Certain encodings like iso2022-jp need to write
+	 * an escape sequence after all characters have
+	 * been converted. This logic checks that enough
+	 * room is available in the buffer for the escape bytes.
+	 * The TCL_ENCODING_END flag is cleared after a final
+	 * escape sequence has been added to the buffer so
+	 * that another call to this method does not attempt
+	 * to append escape bytes a second time.
+	 */
+	if ((dst + dataPtr->finalLen + (state?len:0)) > dstEnd) {
 	    result = TCL_CONVERT_NOSPACE;
 	} else {
 	    if (state) {
@@ -3092,6 +3102,7 @@
 	    memcpy((VOID *) dst, (VOID *) dataPtr->final,
 		    (size_t) dataPtr->finalLen);
 	    dst += dataPtr->finalLen;
+	    state &= ~TCL_ENCODING_END;
 	}
     }
 
Index: tests/io.test
===================================================================
RCS file: /cvsroot/tcl/tcl/tests/io.test,v
retrieving revision 1.71
diff -u -r1.71 io.test
--- tests/io.test	21 Mar 2006 11:12:29 -0000	1.71
+++ tests/io.test	3 Jul 2006 02:36:31 -0000
@@ -117,6 +117,66 @@
     contents $path(test2)
 } "    \x1b\$B\$O\x1b(B"
 
+test io-1.9 {Tcl_WriteChars: WriteChars} {
+    # When closing a channel with an encoding that appends
+    # escape bytes, check for the case where the escape
+    # bytes overflow the current IO buffer. The bytes
+    # should be moved into a new buffer.
+
+    set data "1234567890 [format %c 12399]"
+
+    set sizes [list]
+
+    # With default buffer size
+    set f [open $path(test2) w]
+    fconfigure      $f -encoding iso2022-jp
+    puts -nonewline $f $data
+    close           $f
+    lappend sizes [file size $path(test2)]
+
+    # With buffer size equal to the length
+    # of the data, the escape bytes would
+    # go into the next buffer.
+
+    set f [open $path(test2) w]
+    fconfigure      $f -encoding iso2022-jp -buffersize 16
+    puts -nonewline $f $data
+    close           $f
+    lappend sizes [file size $path(test2)]
+
+    # With buffer size that is large enough
+    # to hold 1 byte of escaped data, but
+    # not all 3. This should not write
+    # the escape bytes to the first buffer
+    # and then again to the second buffer.
+
+    set f [open $path(test2) w]
+    fconfigure      $f -encoding iso2022-jp -buffersize 17
+    puts -nonewline $f $data
+    close           $f
+    lappend sizes [file size $path(test2)]
+
+    # With buffer size that can hold 2 out of
+    # 3 bytes of escaped data.
+
+    set f [open $path(test2) w]
+    fconfigure      $f -encoding iso2022-jp -buffersize 18
+    puts -nonewline $f $data
+    close           $f
+    lappend sizes [file size $path(test2)]
+
+    # With buffer size that can hold all the
+    # data and escape bytes.
+
+    set f [open $path(test2) w]
+    fconfigure      $f -encoding iso2022-jp -buffersize 19
+    puts -nonewline $f $data
+    close           $f
+    lappend sizes [file size $path(test2)]
+
+    set sizes
+} {19 19 19 19 19}
+
 test io-2.1 {WriteBytes} {
     # loop until all bytes are written