/* * 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\"" ); } } }