Just in time processing on a character stream

From Rosetta Code
Revision as of 13:27, 15 December 2013 by rosettacode>Dkf (→‎Tcl: Added implementation)
Just in time processing on a character stream is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Given a stream of characters, presumably (simulated) from a keyboard, that contain the separators "formfeed", "linefeed", "tab" and "space" characters. Print out the ith character of the ith tab-field of the ith line of the ith page to reveal a secret password.

Stop processing immediately upon encountering a "!" found uniquely in this i,i,i,i position (least the system self destruct). The "!" may be found/permitted else where however, in which case it should be ignored.

Ideally this can be generalise as follows:

  • The separators (formfeed, linefeed, tab, space) provided from a user supplied array and can include additional/alternative separators, e.g. (formfeed, linefeed, ".", "," ," ",...).
  • These selection criterial is generalised ith,ith,ith,ith to a boolean function of f(page,line,field,word,...) or f(ith,jth,kth,lth,mth,etc...)

Provide a reasonably interesting message to be decoded, e.g. Silence-Dogood. Your choice.

This task was inspired by the movie "National Treasure" with refers to a "book cipher".

Tcl

Works with: Tcl version 8.6

<lang tcl>package require Tcl 8.6

oo::class create JustInTimeStreamExtract {

   variable map counter counters last
   constructor {{pageSeparator "\f"} {lineSeparator "\n"} {fieldSeparator "\t"}} {

dict set map $pageSeparator NextPage dict set map $lineSeparator NextLine dict set map $fieldSeparator NextField set counter 1 array set counters {page 0 line 0 field 0 char 0} set last ""

   }
   method emit {char} {

puts -nonewline $char set last $char

   }
   method finished {} {

if {$last ne "\n"} { puts "" }

   }
   method stream {{channel stdin} {length 1}} {

try { while 1 { set str [read $channel $length] if {[eof $channel]} break foreach c [split $str ""] { if {[dict exists $map $c]} { my [dict get $map $c] } else { my NextChar $c } } } } trap STOP {} { # Do nothing } my finished

   }
   method NextPage {} {

incr counters(page) array set counters {line 0 field 0 char 0}

   }
   method NextLine {} {

incr counters(line) array set counters {field 0 char 0}

   }
   method NextField {} {

incr counters(field) set counters(char) 0

   }
   method NextChar {char} {

incr counters(char) if {[my PrintThisOne?]} { if {$char eq "!"} { throw STOP "stop character found" } incr counter my emit $char array set counters {page 0 line 0 field 0 char 0} }

   }
   method PrintThisOne? {} {

tcl::mathop::== $counter $counters(page) $counters(line) $counters(field) $counters(char)

   }

}</lang> Demonstration of use: <lang tcl>[JustInTimeStreamExtract new] stream [open "sample.txt"]</lang>