tcl::chan::join 1.0 Reflected/virtual channel support
Concatenation channel
package require Tcl 8.5
package require TclOO
package require tcl::chan::empty ?1?
package require tcl::chan::join ?1.0?
The tcl::chan::join package provides a command creating a read-only concatenation channel much like the tcl::chan::cat command. Unlike tcl::chan::cat, a channel created with tcl::chan::join supports random.access, i.e. the seek and tell commands. Note that if any of the sub-channels does not support random-access (seeking) the join-channel won't support seeking too, and it will be usable only as a sequential, read-only channel. The created channel takes ownership of the sub-channels they were constructed with. Closing the join-channel will close all its sub-channels. For the above rule, a join-channel may be built using the same subchannel more times,
set subch [open "fileA.txt" rb] set jch [tcl::chan::join $subch $subch $subch] ;# join $subch 3 times
but sharing the same sub-channel among two join-channels may produce unexpected results when one of the join-channels is closed, leaving the other join-channel with a closed subchannel.
package require tcl::chan::string set subch [tcl::chan::string "0123456789"] ;# or open a true file ... set jch1 [tcl::chan::join $subch] ;# jch1 'owns' subch set jch2 [tcl::chan::join $subch] ;# jch2 is going to use a subchannel owned by another channel; ;# this is not an error, but the beginning of chaos ... set res1 [read $jch1 4] ;# expected "0123" --> "0123" set res1 [read $jch1 4] ;# expected "3567" --> "3567" set res2 [read $jch2 4] ;# expected "0123" --> "" ???? first unexpected result .. close $jch2 ;# by closing jch2, all its subchannels will be closed. (!including the shared subchannel!) set res1 [read $jch1 4] ;# expected "89" --> error : cannot find channel named xxx (the subchannel name)"
Premise: Altough not indispensable per-se, the presence of the official tcl::chan::* commands of the official Tcllib suite, such as tcl::chan:string, is strongly recommended for composing channels like shown in the following examples.
WARNING : Many Tcl distributions still provide Tcllib 1.18. You need Tcllib 1.19, and in particular tcl::chan::string 1.0.3 (version 1.0.2 has a serious bug about the size of 'string' channels)
package require tcl::chan::string set subch1 [tcl::chan::string "0123456789"] set subch2 [tcl::chan::string "ABCDEFGHIJ"] set jch [tcl::chan::join $subch1 $subch2] chan seek $jch 0 end set nBytes [chan tell $jch] ;# --> 20
# be fd1, fd2, fd3 three channelID set chSep [tcl::chan::string "-----separator------"] set jch [tcl::chan::join $fd1 $chSep $fd2 $chSep $fd3]
set jch [tcl::chan::join] ;# !no subchannels ! if { [eof $jch] } { puts "EOF reached"} ;# --> .. nothing set contents [read $jch] puts "contents: \"$contents\"" ;# --> contents: "" if { [eof $jch] } { puts "EOF reached"} ;# --> "EOF reached"
set subch1 [tcl::chan::string "0123456789"] set subch2 "fakeChannel set subch3 [tcl::chan::string "ABCDEFGHIJ"] set jch [tcl::chan::join $subch1 $subch2 $subch2] ;# --> error: can not find channel named "fakeChannel" ... # .... $subch1 and $subch2 are still open valid channelID
concatenation channel, reflected channel, tip 219, virtual channel
Channels
Copyright (c) 2019 Aldo Buratti <[email protected]> based on tcl::chan::cat by Andreas Kupries