
###########################################################################
# Copyright (c) 1998, Jeffrey Glen Rennie
# All rights reserved.
###########################################################################
###############################################################################
# buffer data structure
# pretty straight forward.

proc bufCreate { } {
    list
}

proc bufAppendLine { varBuffer args } {
    upvar $varBuffer buffer
    eval "lappend buffer $args"
}

proc bufPopLastLine {varBuffer } {
    upvar $varBuffer buffer
    set nLine [llength $buffer]
    incr nLine -1
    set lineResult [lindex $buffer $nLine]
    incr nLine -1
    set buffer [lrange $buffer 0 $nLine]
    set lineResult
}

proc bufLineCount { buffer } {
    llength $buffer
}

proc bufInsertLine { varBuffer nLine line } {
    upvar $varBuffer buf
    set buf [linsert $buf $nLine $line]
}

proc bufGetLine { buffer nLine } {
    lindex $buffer $nLine
}

proc bufReplaceLine { varBuffer nLine line } {
    upvar $varBuffer buf
    lremove buf $nLine
    set buf [linsert $buf $nLine $line]
}

proc bufRemoveLine { varBuffer nLine } {
    upvar $varBuffer buf
    lremove buf $nLine
}

proc bufContents { buffer } {
    set contents ""
    foreach line $buffer {
	append contents $line "\n"
    }
    set contents
}

proc lremove { lstVar index } {
    upvar $lstVar lst
    set lst [concat [lrange $lst 0 [expr "$index - 1"]] \
	    [lrange $lst [expr "$index + 1"] end]]
}

proc bufRawContents { buffer } {
    set contents ""
    foreach line $buffer {
	append contents $line
    }
    set contents
}

proc bufWriteContents { buffer file } {
    foreach line $buffer {
	puts $file $line
    }
    flush $file
}

proc bufReadContents { file args } {
    set isBinary [llength $args]
    set oldState [fconfigure $file]
    #get rid of socket-specific config info in oldState
    regsub -- "-peername.*" $oldState "" oldState
    set bufResult [bufCreate]
    if { $isBinary } {
	fconfigure $file -blocking 0 -buffering full -translation binary
	bufAppendLine $bufResult [read -nonewline $file]
    } else { #it's a text file
	fconfigure $file -blocking 0 -buffering line -translation crlf
	set nLineLength 1
	while { ! [fblocked $file] } {
	    set strLine [gets $file]
	    set nLineLength [string length $strLine]
	    if { $nLineLength > 0 } {
		bufAppendLine $bufResult $strLine
	    }
	}
    }
    eval "fconfigure $file $oldState"
    return $bufResult
}

proc bufReadHTTPLine { file bufResult nMessageSection strOldSocketState \
	callbackWhenDone } {
    set strLine [gets $file]
    if { [string length [ string trim strLine]] == 0 } {
	incr nMessageSection
    }
    bufAppendLine $bufResult $strLine
    if { $nMessageSection < 2 } {
	fileevent $file readable [list bufReadHTTPLine $file $bufResult \
		$nMessageSection $strOldSocketState $callbackWhenDone]
    } else {
	fileevent $file readable ""
	eval "fconfigure $strOldSocketState"
	eval "$callbackWhenDone $bufResult"
    }
}

proc bufReadHTTP { file callbackWhenDone} {
    set strOldState [fconfigure $file]
    #get rid of socket-specific config info in oldState
    regsub -- "-peername.*" $strOldState "" strOldState

    fconfigure $file -blocking 0 -buffering line -translation auto
    fileevent $file readable [list bufReadHTTPLine $file [bufCreate] \
	    0 $strOldState $callbackWhenDone]
}





###########################################################################
# Copyright (c) 1998, Jeffrey Glen Rennie
# All rights reserved.
###########################################################################
