Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix for [fa3d9fd818fa0072], [fcopy $chan1 $chan2 -size $size] is not [puts -nonewline $chan2 [read $chan1 -size $size]. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk | main |
Files: | files | file ages | folders |
SHA3-256: |
51d813943bcaf835b9fc29a42afdcb3e |
User & Date: | pooryorick 2023-04-03 21:20:28.848 |
References
2023-04-04
| ||
21:54 | Starting with [51d813943bcaf835], chan-io-52.10 and io-52.10 are failing on the Windows (with Visua... check-in: 05e4362604 user: jan.nijtmans tags: core-8-branch | |
2023-04-03
| ||
21:28 | • Pending ticket [fa3d9fd818]: fcopy $chan1 $chan2 -size $size is not puts -nonewline $chan2 [read $chan1 -size $size plus 6 other changes artifact: 3a99a85328 user: pooryorick | |
Context
2023-04-04
| ||
21:49 | TIP #628 addendum (various fixes to improve handling of 8.7 <-> 9.0 header differences) check-in: d29e69a635 user: jan.nijtmans tags: trunk, main | |
18:56 | Merge trunk. check-in: 2510ec2a15 user: pooryorick tags: unchained | |
2023-04-03
| ||
21:20 | Fix for [fa3d9fd818fa0072], [fcopy $chan1 $chan2 -size $size] is not [puts -nonewline $chan2 [read $... check-in: 51d813943b user: pooryorick tags: trunk, main | |
20:58 | Fix for [fa3d9fd818fa0072], [fcopy $chan1 $chan2 -size $size] is not [puts -nonewline $chan2 [read $... check-in: 704a7e8389 user: pooryorick tags: bug-fa3d9fd818fa0072 | |
19:58 | Fix typo in test io-53.12.1. check-in: b154e3fedf user: pooryorick tags: trunk, main | |
Changes
Changes to doc/chan.n.
︙ | ︙ | |||
222 223 224 225 226 227 228 | translations occur during either input or output. This translation is typically used on UNIX platforms, .RE .RE .TP \fBchan copy \fIinputChan outputChan\fR ?\fB\-size \fIsize\fR? ?\fB\-command \fIcallback\fR? . | | > > | | < < < | < < | | | | | | | | > | > > > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > < < > | > | < > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | < < < < < < < < < > > > | 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 | translations occur during either input or output. This translation is typically used on UNIX platforms, .RE .RE .TP \fBchan copy \fIinputChan outputChan\fR ?\fB\-size \fIsize\fR? ?\fB\-command \fIcallback\fR? . Reads characters from \fIinputChan\fR and writes them to \fIoutputChan\fR until all characters are copied, blocking until the copy is complete and returning the number of characters copied. Leverages internal buffers to avoid extra copies and to avoid buffering too much data in main memory when copying large files to slow destinations like network sockets. .RS .PP \fB\-size\fR limits the number of characters copied. .PP If \fB\-command\fR is gviven, \fBchan copy\fR returns immediately, works in the background, and calls \fIcallback\fR when the copy completes, providing as an additional argument the number of characters written to \fIoutputChan\fR. If an error occurres during the background copy, another argument provides message for the error. \fIinputChan\fR and \fIoutputChan\fR are automatically configured for non-blocking mode if needed. Background copying only works correctly if events are being processed, e.g. via \fBvwait\fR or Tk. .PP During a background copy no other read operation may be performed on \fIinputChan\fR, and no write operation may be performed on \fIoutputChan\fR. However, write operations may by performed on \fIinputChan\fR and read operations may be performed on \fIoutputChan\fR, as exhibited by the bidirectional copy example below. .PP If either \fIinputChan\fR or \fIoutputChan\fR is closed while the copy is in progress, copying ceases and \fBno\fR callback is made. If \fIinputChan\fR is closed all data already queued is written to \fIoutputChan\fR. .PP There should be no event handler established for \fIinputChan\fR because it may become readable during a background copy. An attempt to read or write from within an event handler results result in the error, "channel busy". Any wrong-sided I/O attempted (by a \fBfileevent\fR handler or otherwise) results in a .QW "channel busy" error. .PP .PP .IP \fBEXAMPLES\fR .PP The first example transfers the contents of one channel exactly to another. Note that when copying one file to another, it is better to use \fBfile copy\fR which also copies file metadata (e.g. the file access permissions) where possible. .PP .CS fconfigure $in -translation binary fconfigure $out -translation binary \fBfcopy\fR $in $out .CE .PP This second example shows how the callback gets passed the number of bytes transferred. It also uses vwait to put the application into the event loop. Of course, this simplified example could be done without the command callback. .PP .CS proc Cleanup {in out bytes {error {}}} { global total set total $bytes close $in close $out if {[string length $error] != 0} { # error occurred during the copy } } set in [open $file1] set out [socket $server $port] \fBfcopy\fR $in $out -command [list Cleanup $in $out] vwait total .CE .PP The third example copies in chunks and tests for end of file in the command callback. .PP .CS proc CopyMore {in out chunk bytes {error {}}} { global total done incr total $bytes if {([string length $error] != 0) || [eof $in]} { set done $total close $in close $out } else { \fBfcopy\fR $in $out -size $chunk \e -command [list CopyMore $in $out $chunk] } } set in [open $file1] set out [socket $server $port] set chunk 1024 set total 0 \fBfcopy\fR $in $out -size $chunk \e -command [list CopyMore $in $out $chunk] vwait done .CE .PP The fourth example starts an asynchronous, bidirectional fcopy between two sockets. Those could also be pipes from two [open "|hal 9000" r+] (though their conversation would remain secret to the script, since all four fileevent slots are busy). .PP .CS set flows 2 proc Done {dir args} { global flows done puts "$dir is over." incr flows -1 if {$flows<=0} {set done 1} } \fBfcopy\fR $sok1 $sok2 -command [list Done UP] \fBfcopy\fR $sok2 $sok1 -command [list Done DOWN] vwait done .CE .RE .TP \fBchan create \fImode cmdPrefix\fR . Creates a new channel, called a \fBreflected\fR channel, with \fIcmdPrefix\fR as its handler, and returns the name of the channel. \fBcmdPrefix\fR is the first words of a command that provides the interface for a \fBrefchan\fR. |
︙ | ︙ |
Changes to doc/fcopy.n.
︙ | ︙ | |||
8 9 10 11 12 13 14 | .TH fcopy n 8.0 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME fcopy \- Copy data from one channel to another .SH SYNOPSIS | | | > | | | < < < < < < | < < < < < | < | < < | | | | < < < | < | < > > > | < | | < | > | < < > | > < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | .TH fcopy n 8.0 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME fcopy \- Copy data from one channel to another .SH SYNOPSIS \fBfcopy \fIinputChan\fR \fIoutputChan\fR ?\fB\-size \fIsize\fR? ?\fB\-command \fIcallback\fR? .BE .SH DESCRIPTION .PP Reads characters from \fIinputChan\fR and writes them to \fIoutputChan\fR until all characters are copied, blocking until the copy is complete and returning the number of characters copied. Leverages internal buffers to avoid extra copies and to avoid buffering too much data in main memory when copying large files to slow destinations like network sockets. .PP \fB\-size\fR limits the number of characters copied. .PP \fB\-command\fR makes \fBfcopy\fR return immediately, work in the background, and call \fIcallback\fR when the copy completes, providing as an additional argument the number of characters written to \fIoutputChan\fR. If an error occurres during the background copy, another argument provides the message for the error. \fIinputChan\fR and \fIoutputChan\fR are automatically configured for non-blocking mode if needed. Background copying only works correctly if events are being processed e.g. via \fBvwait\fR or Tk. .PP During a background copy no other read operation may be performed on \fIinputChan\fR, and no other write operation may be performed on \fIoutputChan\fR. However, write operations may by performed on \fIinputChan\fR and read operations may be performed on \fIoutputChan\fR, as exhibited by the bidirectional copy example below. .PP If either \fIinputChan\fR or \fIoutputChan\fR is closed while the copy is in progress, copying ceases and \fBno\fR callback is made. If \fIinputChan\fR is closed all data already queued is written to \fIoutputChan\fR. .PP There should be no event handler established for \fIinputChan\fR because it may become readable during a background copy. An attempt to read or write from within an event handler results result in the error, "channel busy". Any wrong-sided I/O attempted (by a \fBfileevent\fR handler or otherwise) results in a .QW "channel busy" error. .SH EXAMPLES .PP The first example transfers the contents of one channel exactly to another. Note that when copying one file to another, it is better to use \fBfile copy\fR which also copies file metadata (e.g. the file access permissions) where possible. .PP |
︙ | ︙ | |||
140 141 142 143 144 145 146 | incr total $bytes if {([string length $error] != 0) || [eof $in]} { set done $total close $in close $out } else { \fBfcopy\fR $in $out -size $chunk \e | | | | 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | incr total $bytes if {([string length $error] != 0) || [eof $in]} { set done $total close $in close $out } else { \fBfcopy\fR $in $out -size $chunk \e -command [list CopyMore $in $out $chunk] } } set in [open $file1] set out [socket $server $port] set chunk 1024 set total 0 \fBfcopy\fR $in $out -size $chunk \e -command [list CopyMore $in $out $chunk] vwait done .CE .PP The fourth example starts an asynchronous, bidirectional fcopy between two sockets. Those could also be pipes from two [open "|hal 9000" r+] (though their conversation would remain secret to the script, since all four fileevent slots are busy). |
︙ | ︙ |
Changes to generic/tclEncoding.c.
︙ | ︙ | |||
2566 2567 2568 2569 2570 2571 2572 | } else { /* PROFILE_STRICT */ result = TCL_CONVERT_SYNTAX; break; } } else { /* | | < | 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 | } else { /* PROFILE_STRICT */ result = TCL_CONVERT_SYNTAX; break; } } else { /* * For output convert 0xC080 to a real null. */ *dst++ = 0; src += 2; } } else if (!Tcl_UtfCharComplete(src, srcEnd - src)) { /* |
︙ | ︙ |
Changes to generic/tclIO.c.
︙ | ︙ | |||
170 171 172 173 174 175 176 177 178 179 180 181 182 183 | int errorCode); static int CloseChannelPart(Tcl_Interp *interp, Channel *chanPtr, int errorCode, int flags); static int CloseWrite(Tcl_Interp *interp, Channel *chanPtr); static void CommonGetsCleanup(Channel *chanPtr); static int CopyData(CopyState *csPtr, int mask); static void DeleteTimerHandler(ChannelState *statePtr); static int MoveBytes(CopyState *csPtr); static void MBCallback(CopyState *csPtr, Tcl_Obj *errObj); static void MBError(CopyState *csPtr, int mask, int errorCode); static int MBRead(CopyState *csPtr); static int MBWrite(CopyState *csPtr); static void MBEvent(void *clientData, int mask); | > > | 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | int errorCode); static int CloseChannelPart(Tcl_Interp *interp, Channel *chanPtr, int errorCode, int flags); static int CloseWrite(Tcl_Interp *interp, Channel *chanPtr); static void CommonGetsCleanup(Channel *chanPtr); static int CopyData(CopyState *csPtr, int mask); static void DeleteTimerHandler(ChannelState *statePtr); int Lossless(ChannelState *inStatePtr, ChannelState *outStatePtr, long long toRead); static int MoveBytes(CopyState *csPtr); static void MBCallback(CopyState *csPtr, Tcl_Obj *errObj); static void MBError(CopyState *csPtr, int mask, int errorCode); static int MBRead(CopyState *csPtr); static int MBWrite(CopyState *csPtr); static void MBEvent(void *clientData, int mask); |
︙ | ︙ | |||
334 335 336 337 338 339 340 341 342 343 344 345 346 347 | FreeChannelInternalRep, /* freeIntRepProc */ DupChannelInternalRep, /* dupIntRepProc */ NULL, /* updateStringProc */ NULL, /* setFromAnyProc */ TCL_OBJTYPE_V0 }; #define ChanSetInternalRep(objPtr, resPtr) \ do { \ Tcl_ObjInternalRep ir; \ (resPtr)->refCount++; \ ir.twoPtrValue.ptr1 = (resPtr); \ ir.twoPtrValue.ptr2 = NULL; \ Tcl_StoreInternalRep((objPtr), &chanObjType, &ir); \ | > > > | 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 | FreeChannelInternalRep, /* freeIntRepProc */ DupChannelInternalRep, /* dupIntRepProc */ NULL, /* updateStringProc */ NULL, /* setFromAnyProc */ TCL_OBJTYPE_V0 }; #define GetIso88591() \ (binaryEncoding ? Tcl_GetEncoding(NULL, "iso8859-1") : binaryEncoding) #define ChanSetInternalRep(objPtr, resPtr) \ do { \ Tcl_ObjInternalRep ir; \ (resPtr)->refCount++; \ ir.twoPtrValue.ptr1 = (resPtr); \ ir.twoPtrValue.ptr2 = NULL; \ Tcl_StoreInternalRep((objPtr), &chanObjType, &ir); \ |
︙ | ︙ | |||
9360 9361 9362 9363 9364 9365 9366 | /* * Make sure the output side is unbuffered. */ ResetFlag(outStatePtr, CHANNEL_LINEBUFFERED); SetFlag(outStatePtr, CHANNEL_UNBUFFERED); | < < < < < | < < < < < < | 9365 9366 9367 9368 9369 9370 9371 9372 9373 9374 9375 9376 9377 9378 9379 | /* * Make sure the output side is unbuffered. */ ResetFlag(outStatePtr, CHANNEL_LINEBUFFERED); SetFlag(outStatePtr, CHANNEL_UNBUFFERED); moveBytes = Lossless(inStatePtr, outStatePtr, toRead); /* * Allocate a new CopyState to maintain info about the current copy in * progress. This structure will be deallocated when the copy is * completed. */ |
︙ | ︙ | |||
9678 9679 9680 9681 9682 9683 9684 | Tcl_Channel inChan, outChan; ChannelState *inStatePtr, *outStatePtr; int result = TCL_OK; Tcl_Size sizeb; Tcl_WideInt total; Tcl_WideInt size; /* TODO - be careful if total and size are made unsigned */ const char *buffer; | | < | < < < < | | 9672 9673 9674 9675 9676 9677 9678 9679 9680 9681 9682 9683 9684 9685 9686 9687 9688 9689 9690 9691 9692 9693 9694 9695 9696 9697 9698 9699 9700 9701 9702 9703 9704 9705 9706 | Tcl_Channel inChan, outChan; ChannelState *inStatePtr, *outStatePtr; int result = TCL_OK; Tcl_Size sizeb; Tcl_WideInt total; Tcl_WideInt size; /* TODO - be careful if total and size are made unsigned */ const char *buffer; int moveBytes; int underflow; /* Input underflow */ inChan = (Tcl_Channel) csPtr->readPtr; outChan = (Tcl_Channel) csPtr->writePtr; inStatePtr = csPtr->readPtr->state; outStatePtr = csPtr->writePtr->state; interp = csPtr->interp; cmdPtr = csPtr->cmdPtr; /* * Copy the data the slow way, using the translation mechanism. * * Note: We have make sure that we use the topmost channel in a stack for * the copying. The caller uses Tcl_GetChannel to access it, and thus gets * the bottom of the stack. */ moveBytes = Lossless(inStatePtr, outStatePtr, csPtr->toRead); if (!moveBytes) { TclNewObj(bufObj); Tcl_IncrRefCount(bufObj); } while (csPtr->toRead != (Tcl_WideInt) 0) { /* * Check for unreported background errors. |
︙ | ︙ | |||
9744 9745 9746 9747 9748 9749 9750 | * underflow instead to prime the readable fileevent. */ size = 0; underflow = 1; } else { /* | | | | 9733 9734 9735 9736 9737 9738 9739 9740 9741 9742 9743 9744 9745 9746 9747 9748 9749 9750 9751 9752 9753 9754 9755 9756 9757 | * underflow instead to prime the readable fileevent. */ size = 0; underflow = 1; } else { /* * Read up to bufSize characters. */ if ((csPtr->toRead == (Tcl_WideInt) -1) || (csPtr->toRead > (Tcl_WideInt) csPtr->bufSize)) { sizeb = csPtr->bufSize; } else { sizeb = csPtr->toRead; } if (moveBytes) { size = DoRead(inStatePtr->topChanPtr, csPtr->buffer, sizeb, !GotFlag(inStatePtr, CHANNEL_NONBLOCKING)); } else { size = DoReadChars(inStatePtr->topChanPtr, bufObj, sizeb, !GotFlag(inStatePtr, CHANNEL_NONBLOCKING) ,0 /* No append */); } |
︙ | ︙ | |||
9821 9822 9823 9824 9825 9826 9827 | } } /* * Now write the buffer out. */ | | | < < < < < | | | 9810 9811 9812 9813 9814 9815 9816 9817 9818 9819 9820 9821 9822 9823 9824 9825 9826 9827 9828 9829 9830 9831 9832 9833 9834 9835 9836 9837 | } } /* * Now write the buffer out. */ if (moveBytes) { buffer = csPtr->buffer; sizeb = WriteBytes(outStatePtr->topChanPtr, buffer, size); } else { buffer = Tcl_GetStringFromObj(bufObj, &sizeb); sizeb = WriteChars(outStatePtr->topChanPtr, buffer, sizeb); } /* * [Bug 2895565]. At this point 'size' still contains the number of * characters which have been read. We keep this to later to * update the totals and toRead information, see marker (UP) below. We * must not overwrite it with 'sizeb', which is the number of written * characters, and both EOL translation and encoding * conversion may have changed this number unpredictably in relation * to 'size' (It can be smaller or larger, in the latter case able to * drive toRead below -1, causing infinite looping). Completely * unsuitable for updating totals and toRead. */ if (sizeb == TCL_INDEX_NONE) { |
︙ | ︙ | |||
9866 9867 9868 9869 9870 9871 9872 | if (msg != NULL) { Tcl_DecrRefCount(msg); } break; } /* | | | | 9850 9851 9852 9853 9854 9855 9856 9857 9858 9859 9860 9861 9862 9863 9864 9865 9866 9867 | if (msg != NULL) { Tcl_DecrRefCount(msg); } break; } /* * Update the current character count. Do it now so the count is valid * before a return or break takes us out of the loop. The invariant at * the top of the loop should be that csPtr->toRead holds the number * of characters left to copy. */ if (csPtr->toRead != -1) { csPtr->toRead -= size; } csPtr->total += size; |
︙ | ︙ | |||
9936 9937 9938 9939 9940 9941 9942 | if (bufObj != NULL) { TclDecrRefCount(bufObj); bufObj = NULL; } /* | | | | 9920 9921 9922 9923 9924 9925 9926 9927 9928 9929 9930 9931 9932 9933 9934 9935 | if (bufObj != NULL) { TclDecrRefCount(bufObj); bufObj = NULL; } /* * Make the callback or return the number of characters transferred. The * local total is used because StopCopy frees csPtr. */ total = csPtr->total; if (cmdPtr && interp) { int code; /* |
︙ | ︙ | |||
10256 10257 10258 10259 10260 10261 10262 10263 10264 10265 10266 10267 10268 10269 | static void CopyEventProc( void *clientData, int mask) { (void) CopyData((CopyState *)clientData, mask); } /* *---------------------------------------------------------------------- * * StopCopy -- * * This routine halts a copy that is in progress. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 10240 10241 10242 10243 10244 10245 10246 10247 10248 10249 10250 10251 10252 10253 10254 10255 10256 10257 10258 10259 10260 10261 10262 10263 10264 10265 10266 10267 10268 10269 10270 10271 10272 10273 10274 10275 10276 10277 10278 10279 10280 10281 10282 10283 10284 10285 10286 10287 10288 10289 10290 10291 10292 10293 10294 10295 10296 10297 | static void CopyEventProc( void *clientData, int mask) { (void) CopyData((CopyState *)clientData, mask); } /* *---------------------------------------------------------------------- * * Lossless -- * * Determines whether copying characters between two channel states would * be lossless, i.e. whether one byte corresponds to one character, every * character appears in the Unicode character set, there are no * translations to be performed, and no inline signals to respond to. * * Result: * True if copying would be lossless. * *---------------------------------------------------------------------- */ int Lossless( ChannelState *inStatePtr, ChannelState *outStatePtr, long long toRead) { return inStatePtr->inEofChar == '\0' /* No eofChar to stop input */ && inStatePtr->inputTranslation == TCL_TRANSLATE_LF && outStatePtr->outputTranslation == TCL_TRANSLATE_LF && ( ( (inStatePtr->encoding == NULL || inStatePtr->encoding == GetBinaryEncoding() ) && (outStatePtr->encoding == NULL || outStatePtr->encoding == GetBinaryEncoding() ) ) || ( toRead == -1 && inStatePtr->encoding == outStatePtr->encoding && CHANNEL_PROFILE_GET(inStatePtr->inputEncodingFlags) == TCL_ENCODING_PROFILE_TCL8 && CHANNEL_PROFILE_GET(outStatePtr->inputEncodingFlags) == TCL_ENCODING_PROFILE_TCL8 ) ); } /* *---------------------------------------------------------------------- * * StopCopy -- * * This routine halts a copy that is in progress. |
︙ | ︙ |
Changes to tests/chanio.test.
︙ | ︙ | |||
6882 6883 6884 6885 6886 6887 6888 | } 5 test chan-io-52.11 {TclCopyChannel & encodings} -setup { set f [open $path(utf8-fcopy.txt) w] fconfigure $f -encoding utf-8 -translation lf puts $f АА close $f } -constraints {fcopy} -body { | < < | | > > > | > > | < > | > > | 6882 6883 6884 6885 6886 6887 6888 6889 6890 6891 6892 6893 6894 6895 6896 6897 6898 6899 6900 6901 6902 6903 6904 6905 6906 6907 6908 6909 6910 6911 6912 | } 5 test chan-io-52.11 {TclCopyChannel & encodings} -setup { set f [open $path(utf8-fcopy.txt) w] fconfigure $f -encoding utf-8 -translation lf puts $f АА close $f } -constraints {fcopy} -body { set in [open $path(utf8-fcopy.txt) r] set out [open $path(kyrillic.txt) w] # -translation binary is also -encoding binary chan configure $in -translation binary chan configure $out -encoding koi8-r -translation lf -profile strict catch {chan copy $in $out} cres copts return $cres } -cleanup { if {$in in [chan names]} { close $in } if {$out in [chan names]} { close $out } catch {unset cres} } -match glob -result {error writing "*": invalid or incomplete\ multibyte or wide character} test chan-io-53.1 {CopyData} -setup { file delete $path(test1) } -constraints {fcopy} -body { set f1 [open $thisScript] set f2 [open $path(test1) w] chan configure $f1 -translation lf -blocking 0 |
︙ | ︙ |
Changes to tests/io.test.
︙ | ︙ | |||
7515 7516 7517 7518 7519 7520 7521 | close $in close $out file size $path(utf8-fcopy.txt) } 5 test io-52.11 {TclCopyChannel & encodings} -setup { set out [open $path(utf8-fcopy.txt) w] | | | < < < < | < | > > > | > > | | | | > | 7515 7516 7517 7518 7519 7520 7521 7522 7523 7524 7525 7526 7527 7528 7529 7530 7531 7532 7533 7534 7535 7536 7537 7538 7539 7540 7541 7542 7543 7544 7545 7546 7547 7548 7549 | close $in close $out file size $path(utf8-fcopy.txt) } 5 test io-52.11 {TclCopyChannel & encodings} -setup { set out [open $path(utf8-fcopy.txt) w] fconfigure $out -encoding utf-8 -translation lf -profile strict puts $out АА close $out } -constraints {fcopy} -body { set in [open $path(utf8-fcopy.txt) r] set out [open $path(kyrillic.txt) w] # -translation binary is also -encoding binary fconfigure $in -translation binary fconfigure $out -encoding koi8-r -translation lf -profile strict catch {fcopy $in $out} cres copts return $cres } -cleanup { if {$in in [chan names]} { close $in } if {$out in [chan names]} { close $out } catch {unset cres} } -match glob -result {error writing "*": invalid or incomplete\ multibyte or wide character} test io-52.12 {coverage of -translation auto} { file delete $path(test1) $path(test2) set out [open $path(test1) wb] chan configure $out -translation lf puts -nonewline $out abcdefg\rhijklmn\nopqrstu\r\nvwxyz close $out |
︙ | ︙ | |||
7775 7776 7777 7778 7779 7780 7781 7782 7783 7784 7785 7786 7787 7788 | vwait ::s0 set ::s0 } -cleanup { close $in close $out unset ::s0 } -match glob -result {0 {error writing "file*": invalid or incomplete multibyte or wide character}} test io-53.1 {CopyData} {fcopy} { file delete $path(test1) set f1 [open $thisScript] set f2 [open $path(test1) w] fconfigure $f1 -translation lf -blocking 0 | > > > > > > > > > > > > > > > > > > > > > > > | 7776 7777 7778 7779 7780 7781 7782 7783 7784 7785 7786 7787 7788 7789 7790 7791 7792 7793 7794 7795 7796 7797 7798 7799 7800 7801 7802 7803 7804 7805 7806 7807 7808 7809 7810 7811 7812 | vwait ::s0 set ::s0 } -cleanup { close $in close $out unset ::s0 } -match glob -result {0 {error writing "file*": invalid or incomplete multibyte or wide character}} test io-52.24 {fcopy -size should always be characters} -setup { set out [open utf8-fcopy-52.24.txt w] fconfigure $out -encoding utf-8 -translation lf puts $out "Á" close $out } -constraints {fcopy} -body { set in [open utf8-fcopy-52.24.txt r] set out [open utf8-fcopy-52.24.out.txt w+] fconfigure $in -encoding utf-8 -profile tcl8 fconfigure $out -encoding utf-8 -profile tcl8 fcopy $in $out -size 1 seek $out 0 # a result of \xc3 means that only the first byte of the utf-8 encoding of # Á made it into to the output file. read $out } -cleanup { close $in close $out catch {file delete utf8-fcopy-52.24.txt} catch {file delete utf8-fcopy-52.24.out.txt} } -result Á test io-53.1 {CopyData} {fcopy} { file delete $path(test1) set f1 [open $thisScript] set f2 [open $path(test1) w] fconfigure $f1 -translation lf -blocking 0 |
︙ | ︙ |