/*
* ReadCmd.java --
*
* Copyright (c) 1997 Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and
* redistribution of this file, and for a DISCLAIMER OF ALL
* WARRANTIES.
*
* Included in SQLite3 port to C# for use in testharness only; 2008 Noah B Hart
*
* RCS @(#) $Id: ReadCmd.java,v 1.8 2003/03/08 03:42:44 mdejong Exp $
*
*/
using System.Text;
using System.IO;
namespace tcl.lang
{
/// This class implements the built-in "read" command in Tcl.
class ReadCmd : Command
{
/// This procedure is invoked to process the "read" Tcl command.
/// See the user documentation for details on what it does.
///
///
/// the current interpreter.
///
/// command arguments.
///
public TCL.CompletionCode cmdProc( Interp interp, TclObject[] argv )
{
Channel chan; // The channel being operated on this
// method
int i = 1; // Index to the next arg in argv
int toRead = 0; // Number of bytes or chars to read from channel
int charactersRead; // Number of bytes or chars read from channel
bool readAll = true; // If true read-all else toRead
bool noNewline = false; // If true, strip the newline if there
TclObject result;
if ( ( argv.Length != 2 ) && ( argv.Length != 3 ) )
{
errorWrongNumArgs( interp, argv[0].ToString() );
}
if ( argv[i].ToString().Equals( "-nonewline" ) )
{
noNewline = true;
i++;
}
if ( i == argv.Length )
{
errorWrongNumArgs( interp, argv[0].ToString() );
}
chan = TclIO.getChannel( interp, argv[i].ToString() );
if ( chan == null )
{
throw new TclException( interp, "can not find channel named \"" + argv[i].ToString() + "\"" );
}
// Consumed channel name.
i++;
// Compute how many bytes or chars to read, and see whether the final
// noNewline should be dropped.
if ( i < argv.Length )
{
string arg = argv[i].ToString();
if ( System.Char.IsDigit( arg[0] ) )
{
toRead = TclInteger.get( interp, argv[i] );
readAll = false;
}
else if ( arg.Equals( "nonewline" ) )
{
noNewline = true;
}
else
{
throw new TclException( interp, "bad argument \"" + arg + "\": should be \"nonewline\"" );
}
}
try
{
if ( (System.Object)chan.Encoding == null )
{
result = TclByteArray.newInstance();
}
else
{
result = TclString.newInstance( new StringBuilder( 64 ) );
}
if ( readAll )
{
charactersRead = chan.read( interp, result, TclIO.READ_ALL, 0 );
// If -nonewline was specified, and we have not hit EOF
// and the last char is a "\n", then remove it and return.
if ( noNewline )
{
string inStr = result.ToString();
if ( ( charactersRead > 0 ) && ( inStr[charactersRead - 1] == '\n' ) )
{
interp.setResult( inStr.Substring( 0, ( ( charactersRead - 1 ) ) - ( 0 ) ) );
return TCL.CompletionCode.RETURN;
}
}
}
else
{
// FIXME: Bug here, the -nonewline flag must be respected
// when reading a set number of bytes
charactersRead = chan.read( interp, result, TclIO.READ_N_BYTES, toRead );
}
/*
// FIXME: Port this -nonewline logic from the C code.
if (charactersRead < 0) {
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, "error reading \"", name, "\": ",
Tcl_PosixError(interp), (char *) NULL);
Tcl_DecrRefCount(resultPtr);
return TCL_ERROR;
}
// If requested, remove the last newline in the channel if at EOF.
if ((charactersRead > 0) && (newline != 0)) {
char *result;
int length;
result = Tcl_GetStringFromObj(resultPtr, length);
if (result[length - 1] == '\n') {
Tcl_SetObjLength(resultPtr, length - 1);
}
}
*/
interp.setResult( result );
}
catch ( IOException e )
{
throw new TclRuntimeError( "ReadCmd.cmdProc() Error: IOException when reading " + chan.ChanName );
}
return TCL.CompletionCode.RETURN;
}
/// A unique error msg is printed for read, therefore dont call this
/// instead of the standard TclNumArgsException().
///
///
/// the current interpreter.
///
/// the name of the command (extracted form argv[0] of cmdProc)
///
private void errorWrongNumArgs( Interp interp, string cmd )
{
throw new TclException( interp, "wrong # args: should be \"" + "read channelId ?numChars?\" " + "or \"read ?-nonewline? channelId\"" );
}
}
}