diff options
Diffstat (limited to 'doc/chan.n')
| -rw-r--r-- | doc/chan.n | 390 |
1 files changed, 328 insertions, 62 deletions
@@ -33,17 +33,14 @@ otherwise. .TP \fBchan close \fIchannelName\fR ?\fIdirection\fR? . -Closes and destroys the named channel, deleting any existing event handlers -established for the channel, and returns the empty string. If \fIdirection\fR is -given, it is -.QW\fBread\fR -or -.QW\fBwrite\fR -or any unique abbreviation of those words, and only that side of the channel is -closed. I.e. a read-write channel may become read-only or write-only. -Closing a read-only channel for reading, or closing a write-only channel for -writing is the same as simply closing the channel. It is an error to close a -read-only channel for writing or to close a write-only channel for reading. +Closes and destroys the named channel deleting any existing event handlers +established for the channel. The command returns the empty string. If +\fIdirection\fR is given, it is \fBread\fR, or \fBwrite\fR, or any unique +abbreviation of those words, and only that side of the channel is closed. I.e. a +read-write channel may become read-only or write-only. Closing a read-only +channel for reading, or closing a write-only channel for writing is the same as +simply closing the channel. It is an error to close a read-only channel for +writing or to close a write-only channel for reading. .RS .PP When a channel is closed for writing, any buffered output on the channel is @@ -90,7 +87,7 @@ restores the previous behavior. .TP \fBchan configure \fIchannelName\fR ?\fIoptionName\fR? ?\fIvalue\fR? ?\fIoptionName value\fR?... . -Configures or reports the configuration of \fIchannelName\fR. +Configures or retrieves the configuration of the channel \fIchannelName\fR. .RS .PP If no \fIoptionName\fR or \fIvalue\fR arguments are given, @@ -109,11 +106,11 @@ relevant documentation. For example, additional options are documented for .TP \fB\-blocking\fI boolean\fR . -If \fB\-blocking\fR is set to \fBtrue\fR, which is the default, reading from or -writing to the channel may cause the process to block indefinitely. Otherwise, +If \fB\-blocking\fR is set to \fBtrue\fR (default), reading the channel +or writing to it may cause the process to block indefinitely. Otherwise, operations such as \fBchan gets\fR, \fBchan read\fR, \fBchan puts\fR, \fBchan flush\fR, and \fBchan close\fR take care not to block. Non-blocking mode in -generally requires that the event loop is entered, e.g. by calling +general requires that the event loop is entered, e.g. by calling \fBTcl_DoOneEvent\fR or \fBvwait\fR or by using Tk, to give Tcl a chance to process events on the channel. .\" OPTION: -buffering @@ -135,9 +132,9 @@ connect to terminal-like devices, the default value is \fBline\fR. For any input or output buffers subsequently allocated for this channel. .\" OPTION: -encoding .TP -\fB\-encoding\fR ?\fIname\fR? +\fB\-encoding\fR \fIname\fR . -Sets the encoding of the channel. \fIname\fR is either one of the names +Sets the encoding of the channel to \fIname\fR which should be one of the names returned by \fBencoding names\fR, or .QW \fBbinary\fR \&. Input is converted from the encoding into Unicode, and output is converted @@ -194,7 +191,7 @@ end-of-line character. .RS .PP Returns the input translation for a read-only channel, the output translation -for a write-only channel, and both the input translation and the the output +for a write-only channel, and both the input translation and the output translation for a read-write channel. When two translations are given, they are the input and output translation, respectively. When only one translation is given for a read-write channel, it is the translation for both input and @@ -343,7 +340,7 @@ handler, the handler is deleted if \fIscript\fR returns an error so that it is not evaluated again. .PP Without an event handler, \fBchan gets\fR or \fBchan read\fR on a channel in -blocking mode may block until data becomes available, become during which the +blocking mode may block until data becomes available, during which the thread is unable to perform other work or respond to events on other channels. This could cause the application to appear to .QW "freeze up" @@ -353,19 +350,24 @@ so that the reader or writer can continue to perform other processing while waiting for a channel to become available and then handle channel operations when the channel is ready for the operation. .PP -A -.QW readable -event occurs when there is data that can be read from the channel and also when -there is an error on the channel. The handler must check for these conditions -and handle them appropriately. For example, a handler that does not check -whether the end of the data has been reached may be repeatedly evaluated in a -busy loop until the channel is closed. +A channel is considered to be readable if there is unread data +available on the underlying device. A channel is also considered to +be readable if there is unread data in an input buffer, except in the +special case where the most recent attempt to read from the channel +was a \fBchan gets\fR call that could not find a complete line in the +input buffer. This feature allows a file to be read a line at a time +in non-blocking mode using events. A channel is also considered to be +readable if an end of file or error condition is present on the +underlying file or device. It is important for \fIscript\fR to check +for these conditions and handle them appropriately; for example, if +there is no special check for end of file, an infinite loop may occur +where \fIscript\fR reads no data, returns, and is immediately invoked +again. .PP -A -.QW writable -event occurs when at least one byte of data can be written, or if there is an -error on the channel. A client socket opened in non-blocking mode becomes -writable when it becomes connected or if the connection fails. +A channel is considered to be writable if at least one byte of data can be +written to the underlying file or device without blocking, or if an error +condition is present. Note that client sockets opened in asynchronous mode +become writable when they become connected or if the connection fails. .PP Event-driven channel handling works best for channels in non-blocking mode. A channel in blocking mode blocks when \fBchan puts\fR writes more data than the @@ -386,23 +388,47 @@ while all buffered output is flushed in the background as soon as possible. .TP \fBchan gets \fIchannelName\fR ?\fIvarName\fR? . -Returns the next line from the channel, removing the trailing line feed, or if -\fIvarName\fR is given, assigns the line to that variable and returns the -number of characters read. -the line that was read, removing the trailing line feed, or returns the -empty string if there is no data to return and the end of the file has been -reached, or in non-blocking mode, if no complete line is currently available. -If \fIvarName\fR is given, assigns the line that was read to variable named -\fIvarName\fR and returns the number of characters that were read, or -1 if -there no data available and the end of the channel was reached or the channel -is in non-blocking mode. +Reads a line from the channel consisting of all characters up to the next +end-of-line sequence or until end of file is seen. The line feed character +corresponding to end-of-line sequence is not included as part of the line. +If the \fIvarName\fR argument is specified, the line is stored in the variable +of that name and the command returns the length of the line. If \fIvarName\fR +is not specified, the command returns the line itself as the result of the command. .RS .PP -If the end of the channel is reached the data read so far is returned or -assigned to \fIvarName\fR. When \fIvarName\fR is not given, \fBchan eof\fR may -indicate that the empty string means that the end of the data has been reached, -and \fBchan blocked\fR may indicate that that the empty string means there -isn't currently enough data do return the next line. +If a complete line is not available and the channel is not at EOF, the command +will block in the case of a blocking channel. For non-blocking channels, the +command will return the empty string as the result in the case of \fIvarName\fR +not specified and -1 if it is. +.RE +.RS +.PP +If a blocking channel is already at EOF, the command returns an empty string if +\fIvarName\fR is not specified. Note an empty string result can also be returned +when a blank line (no characters before the next end of line sequence). The two +cases can be distinguished by calling the \fBchan eof\fR command to check for +end of file. If \fIvarName\fR is specified, the command returns -1 on end of file. +There is no ambiguity in this case because blank lines result in 0 being returned. +.RE +.RS +.PP +If a non-blocking channel is already at EOF, the command returns an empty line +if \fIvarName\fR is not specified. This can be distinguished from an empty line +being returned by either a blank line being read or a full line not being available +through the use of the \fBchan eof\fR and \fBchan blocked\fR commands. If +\fBchan eof\fR returns true, the channel is at EOF. If \fBchan blocked\fR returns +true, a full line was not available. If both commands return false, an empty +line was read. If \fIvarName\fR was specified for a non-bocking channel at EOF, +the command returns -1. This can be distinguished from full line not being +available either by \fBchan eof\fR or \fBchan blocked\fR as above. Note that +when \fIvarName\fR is specified, there is no need to distinguish between eof +and blank lines as the latter will result in the command returning 0. +.PP +If the encoding profile \fBstrict\fR is in effect for the channel, the command +will raise an exception with the POSIX error code \fBEILSEQ\fR if any encoding +errors are encountered in the channel input data. The file pointer remains +unchanged and it is possible to introspect, and in some cases recover, by +changing the encoding in use. See \fBENCODING ERROR EXAMPLES\fR later. .RE .\" METHOD: names .TP @@ -509,8 +535,8 @@ given, the trailing line feed is not written. The default channel is \fBstdout\fR. .RS .PP -Each line feed in the output is translated according to the configuration of -\fB\-translation\fR. +Each line feed in the output is translated to the appropriate end of line +sequence as per the \fB\-translation\fR configuration setting of the channel. .PP Because Tcl internally buffers output, characters written to a channel may not immediately be available at the destination. Tcl normally delays output until @@ -518,17 +544,21 @@ the buffer is full or the channel is closed. \fBchan flush\fR forces output in the direction of the destination. .PP When the output for a channel in blocking mode fills up, \fBchan puts\fR blocks -until space in the buffer is available again, but for a channel in non-blocking -mode, it returns immediately and the data is written in the background as fast -possible, constrained by the speed at which as the destination accepts it. -Output to a channel in non-blocking mode only works properly when the -application enters the event loop, giving Tcl a chance to find out that the -destination is ready to accept more data. When a channel is in non-blocking -mode, Tcl's internal buffers can hold an arbitrary amount of data, possibly -consuming a large amount of memory. To avoid wasting memory, channels in -non-blocking mode should normally be handled using \fBchan event\fR, where the -application only invokes \fBchan puts\fR after being recently notified through -a file event handler that the channel is ready for more output data. +until space in the buffer is available again. On the other hand for a channel in +non-blocking mode, it returns immediately and the data is written in the +background as fast possible, constrained by the speed at which as the +destination accepts it. Output to a channel in non-blocking mode only works +properly when the application enters the event loop. When a channel is in +non-blocking mode, Tcl's internal buffers can hold an arbitrary amount of data, +possibly consuming a large amount of memory. To avoid wasting memory, channels +in non-blocking mode should normally be handled using \fBchan event\fR, where +the application only invokes \fBchan puts\fR after being notified through a file +event handler that the channel is ready for more output data. +.PP +The command will raise an error exception with POSIX error code \fBEILSEQ\fR if +the encoding profile \fBstrict\fR is in effect for the channel and the output +data cannot be encoded in the encoding configured for the channel. Data +may be partially written to the channel in this case. .RE .\" METHOD: read .TP @@ -541,7 +571,7 @@ Reads and returns the next \fInumChars\fR characters from the channel. If are read, or if the channel is in non-blocking mode, all currently-available characters are read. If there is an error on the channel, reading ceases and an error is returned. If \fInumChars\fR is not given, \fB\-nonewline\fR -may be given, causing any any trailing line feed to be trimmed. +may be given, causing any trailing line feed to be trimmed. .RS .PP If the channel is in non-blocking mode, fewer characters than requested may be @@ -560,6 +590,21 @@ handler since most serial ports are comparatively slow. It is entirely possible to get a \fBreadable\fR event for each individual character. In blocking mode, \fBchan read\fR blocks forever when reading to the end of the data if there is no \fBchan configure -eofchar\fR configured for the channel. +.PP +If the encoding profile \fBstrict\fR is in effect for the channel, the command +will raise an exception with the POSIX error code \fBEILSEQ\fR if any encoding +errors are encountered in the channel input data. If the channel is in blocking +mode, the error is thrown after advancing the file pointer to the beginning of +the invalid data. The successfully decoded leading portion of the data prior to +the error location is returned as the value of the \fB\-data\fR key of the error +option dictionary. If the channel is in non-blocking mode, the successfully +decoded portion of data is returned by the command without an error +exception being raised. A subsequent read will start at the invalid data +and immediately raise a \fBEILSEQ\fR POSIX error exception. Unlike the +blocking channel case, the \fB\-data\fR key is not present in the +error option dictionary. In the case of exception thrown due to encoding +errors, it is possible to introspect, and in some cases recover, by +changing the encoding in use. See \fBENCODING ERROR EXAMPLES\fR later. .RE .\" METHOD: seek .TP @@ -602,6 +647,13 @@ bytes, or to the current position in bytes if \fIlength\fR is omitted. .SH EXAMPLES .SS "SIMPLE CHANNEL OPERATION EXAMPLES" .PP +Instruct Tcl to always send output to \fBstdout\fR immediately, +whether or not it is to a terminal: +.PP +.CS +\fBfconfigure\fR stdout -buffering none +.CE +.PP In the following example a file is opened using the encoding CP1252, which is common on Windows, searches for a string, rewrites that part, and truncates the file two lines later. @@ -635,6 +687,67 @@ while {[\fBchan gets\fR $f line] >= 0} { \fBchan close\fR $f .CE .PP +This example illustrates flushing of a channel. The user is +prompted for some information. Because the standard input channel +is line buffered, it must be flushed for the user to see the prompt. +.PP +.CS +chan puts -nonewline "Please type your name: " +\fBchan flush\fR stdout +chan gets stdin name +chan puts "Hello there, $name!" +.CE +.PP +This example reads a file one line at a time and prints it out with +the current line number attached to the start of each line. +.PP +.CS +set chan [open "some.file.txt"] +set lineNumber 0 +while {[\fBchan gets\fR $chan line] >= 0} { + chan puts "[incr lineNumber]: $line" +} +chan close $chan +.CE +.PP +In this example illustrating event driven reads, +\fBGetData\fR will be called with the channel as an +argument whenever $chan becomes readable. The \fBread\fR call will +read whatever binary data is currently available without blocking. +Here the channel has the fileevent removed when an end of file +occurs to avoid being continually called (see above). Alternatively +the channel may be closed on this condition. +.PP +.CS +proc GetData {chan} { + set data [chan read $chan] + chan puts "[string length $data] $data" + if {[chan eof $chan]} { + chan event $chan readable {} + } +} + +chan configure $chan -blocking 0 -encoding binary +\fBchan event\fR $chan readable [list GetData $chan] +.CE +.PP +The next example is similar but uses \fBchan gets\fR to read +line-oriented data. +.PP +.CS +proc GetData {chan} { + if {[chan gets $chan line] >= 0} { + chan puts $line + } + if {[chan eof $chan]} { + chan close $chan + } +} + +chan configure $chan -blocking 0 -buffering line -translation crlf +\fBchan event\fR $chan readable [list GetData $chan] +.CE +.PP A network server that echoes its input line-by-line without preventing servicing of other connections at the same time: .PP @@ -671,6 +784,157 @@ proc echoLine {chan clientName} { socket -server connect 12345 vwait forever .CE +.PP +The following example reads a PPM-format image from a file +combining ASCII and binary content. +.PP +.CS +# Open the file and put it into Unix ASCII mode +set f [open teapot.ppm] +\fBchan configure\fR $f -encoding ascii -translation lf + +# Get the header +if {[chan gets $f] ne "P6"} { + error "not a raw\-bits PPM" +} + +# Read lines until we have got non-comment lines +# that supply us with three decimal values. +set words {} +while {[llength $words] < 3} { + chan gets $f line + if {[string match "#*" $line]} continue + lappend words {*}[join [scan $line %d%d%d]] +} + +# Those words supply the size of the image and its +# overall depth per channel. Assign to variables. +lassign $words xSize ySize depth + +# Now switch to binary mode to pull in the data, +# one byte per channel (red,green,blue) per pixel. +\fBchan configure\fR $f -translation binary +set numDataBytes [expr {3 * $xSize * $ySize}] +set data [chan read $f $numDataBytes] + +close $f +.CE +.SS "FILE SEEK EXAMPLES" +.PP +Read a file twice: +.PP +.CS +set f [open file.txt] +set data1 [chan read $f] +\fBchan seek\fR $f 0 +set data2 [chan read $f] +chan close $f +# $data1 eq $data2 if the file wasn't updated +.CE +.PP +Read the last 10 bytes from a file: +.PP +.CS +set f [open file.data] +# This is guaranteed to work with binary data but +# may fail with other encodings... +chan configure $f -translation binary +\fBchan seek\fR $f -10 end +set data [chan read $f 10] +chan close $f +.CE +.PP +Read a line from a file channel only if it starts with \fBfoobar\fR: +.PP +.CS +# Save the offset in case we need to undo the read... +set offset [\fBtell\fR $chan] +if {[read $chan 6] eq "foobar"} { + gets $chan line +} else { + set line {} + # Undo the read... + seek $chan $offset +} +.CE +.SS "ENCODING ERROR EXAMPLES" +.PP +The example below illustrates handling of an encoding error encountered +during channel input. First, creation of a test file containing +the invalid UTF-8 sequence (\fBA \\xC3 B\fR): +.PP +.CS +% set f [open test_A_195_B.txt wb]; chan puts -nonewline $f A\\xC3B; chan close $f +.CE +.PP +An attempt to read the file will result in an encoding error which is +then introspected by switching the channel to binary mode. Note in the +example that when the error is reported the file position remains +unchanged so that the \fBchan gets\fR during recovery returns the +full line. +.PP +.CS +% set f [open test_A_195_B.txt r] +file384b6a8 +% chan configure $f -encoding utf-8 -profile strict +% catch {chan gets $f} e d +1 +% set d +-code 1 -level 0 +-errorstack {INNER {invokeStk1 gets file384b6a8}} +-errorcode {POSIX EILSEQ {invalid or incomplete multibyte or wide character}} +-errorinfo {...} -errorline 1 +% chan tell $f +0 +% chan configure $f -encoding binary -profile strict +% chan gets $f +AÃB +.CE +.PP +The following example is similar to the above but demonstrates recovery after a +blocking read. The successfully decoded data "A" is returned in the error options +dictionary key \fB\-data\fR. The file position is advanced on the encoding error +position 1. The data at the error position is thus recovered by the next +\fBchan read\fR command. +.PP +.CS +% set f [open test_A_195_B.txt r] +file35a65a0 +% chan configure $f -encoding utf-8 -profile strict -blocking 1 +% catch {chan read $f} e d +1 +% set d +-data A -code 1 -level 0 +-errorstack {INNER {invokeStk1 read file35a65a0}} +-errorcode {POSIX EILSEQ {invalid or incomplete multibyte or wide character}} +-errorinfo {...} -errorline 1 +% chan tell $f +1 +% chan configure $f -encoding binary -profile strict +% chan read $f +ÃB +% chan close $f +.CE +.PP +Finally the same example, but this time with a non-blocking channel. +.PP +.CS +% set f [open test_A_195_B.txt r] +file35a65a0 +% chan configure $f -encoding utf-8 -profile strict -blocking 0 +% chan read $f +A +% chan tell $f +1 +% catch {chan read $f} e d +1 +% set d +-code 1 -level 0 +-errorstack {INNER {invokeStk1 read file384b228}} +-errorcode {POSIX EILSEQ {invalid or incomplete multibyte or wide character}} +-errorinfo {...} -errorline 1 +.CE + .SS "CHANNEL COPY EXAMPLES" .PP The first example transfers the contents of one channel exactly to @@ -758,9 +1022,11 @@ vwait done .SH "SEE ALSO" close(n), eof(n), fblocked(n), fconfigure(n), fcopy(n), file(n), fileevent(n), flush(n), gets(n), open(n), puts(n), read(n), seek(n), -socket(n), tell(n), refchan(n), transchan(n) +socket(n), tell(n), refchan(n), transchan(n), +Tcl_StandardChannels(3) .SH KEYWORDS -channel, input, output, events, offset +blocking, channel, end of file, events, input, non-blocking, +offset, output, readable, seek, stdio, tell, writable '\" Local Variables: '\" mode: nroff '\" End: |
