/*
* TclByteArray.java
*
* This class contains the implementation of the Jacl binary data object.
*
* Copyright (c) 1999 Christian Krone.
* 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: TclByteArray.java,v 1.4 2003/03/08 02:05:06 mdejong Exp $
*
*/
using System;
namespace tcl.lang
{
/// This class implements the binary data object type in Tcl.
public class TclByteArray : InternalRep
{
/// The number of bytes used in the byte array.
/// The following structure is the internal rep for a ByteArray object.
/// Keeps track of how much memory has been used. This can be different from
/// how much has been allocated for the byte array to enable growing and
/// shrinking of the ByteArray object with fewer allocations.
///
private int used;
/// Internal representation of the binary data.
private byte[] bytes;
/// Create a new empty Tcl binary data.
private TclByteArray()
{
used = 0;
bytes = new byte[0];
}
/// Create a new Tcl binary data.
private TclByteArray( byte[] b )
{
used = b.Length;
bytes = new byte[used];
Array.Copy( b, 0, bytes, 0, used );
}
/// Create a new Tcl binary data.
private TclByteArray( byte[] b, int position, int length )
{
used = length;
bytes = new byte[used];
Array.Copy( b, position, bytes, 0, used );
}
/// Create a new Tcl binary data.
private TclByteArray( char[] c )
{
used = c.Length;
bytes = new byte[used];
for ( int ix = 0; ix < used; ix++ )
{
bytes[ix] = (byte)c[ix];
}
}
/// Returns a duplicate of the current object.
///
///
/// the TclObject that contains this internalRep.
///
public InternalRep duplicate()
{
return new TclByteArray( bytes, 0, used );
}
/// Implement this no-op for the InternalRep interface.
public void dispose()
{
}
/// Called to query the string representation of the Tcl object. This
/// method is called only by TclObject.toString() when
/// TclObject.stringRep is null.
///
///
/// the string representation of the Tcl object.
///
public override string ToString()
{
char[] c = new char[used];
for ( int ix = 0; ix < used; ix++ )
{
c[ix] = (char)( bytes[ix] & 0xff );
}
return new string( c );
}
/// Creates a new instance of a TclObject with a TclByteArray internal
/// rep.
///
///
/// the TclObject with the given byte array value.
///
public static TclObject newInstance( byte[] b, int position, int length )
{
return new TclObject( new TclByteArray( b, position, length ) );
}
/// Creates a new instance of a TclObject with a TclByteArray internal
/// rep.
///
///
/// the TclObject with the given byte array value.
///
public static TclObject newInstance( byte[] b )
{
return new TclObject( new TclByteArray( b ) );
}
/// Creates a new instance of a TclObject with an empty TclByteArray
/// internal rep.
///
///
/// the TclObject with the empty byte array value.
///
public static TclObject newInstance()
{
return new TclObject( new TclByteArray() );
}
/// Called to convert the other object's internal rep to a ByteArray.
///
///
/// current interpreter.
///
/// the TclObject to convert to use the ByteArray internal rep.
///
/// TclException if the object doesn't contain a valid ByteArray.
///
internal static void setByteArrayFromAny( Interp interp, TclObject tobj )
{
InternalRep rep = tobj.InternalRep;
if ( !( rep is TclByteArray ) )
{
char[] c = tobj.ToString().ToCharArray();
tobj.InternalRep = new TclByteArray( c );
}
}
///
/// This method changes the length of the byte array for this
/// object. Once the caller has set the length of the array, it
/// is acceptable to directly modify the bytes in the array up until
/// Tcl_GetStringFromObj() has been called on this object.
///
/// Results:
/// The new byte array of the specified length.
///
/// Side effects:
/// Allocates enough memory for an array of bytes of the requested
/// size. When growing the array, the old array is copied to the
/// new array; new bytes are undefined. When shrinking, the
/// old array is truncated to the specified length.
///
public static byte[] setLength( Interp interp, TclObject tobj, int length )
{
if ( tobj.Shared )
{
throw new TclRuntimeError( "TclByteArray.setLength() called with shared object" );
}
setByteArrayFromAny( interp, tobj );
TclByteArray tbyteArray = (TclByteArray)tobj.InternalRep;
if ( length > tbyteArray.bytes.Length )
{
byte[] newBytes = new byte[length];
Array.Copy( tbyteArray.bytes, 0, newBytes, 0, tbyteArray.used );
tbyteArray.bytes = newBytes;
}
tobj.invalidateStringRep();
tbyteArray.used = length;
return tbyteArray.bytes;
}
/// Queries the length of the byte array. If tobj is not a byte array
/// object, an attempt will be made to convert it to a byte array.
///
///
/// current interpreter.
///
/// the TclObject to use as a byte array.
///
/// the length of the byte array.
///
/// TclException if tobj is not a valid byte array.
///
public static int getLength( Interp interp, TclObject tobj )
{
setByteArrayFromAny( interp, tobj );
TclByteArray tbyteArray = (TclByteArray)tobj.InternalRep;
return tbyteArray.used;
}
/// Returns the bytes of a ByteArray object. If tobj is not a ByteArray
/// object, an attempt will be made to convert it to a ByteArray.
///
///
/// the current interpreter.
///
/// the byte array object.
///
/// a byte array.
///
/// TclException if tobj is not a valid ByteArray.
///
public static byte[] getBytes( Interp interp, TclObject tobj )
{
setByteArrayFromAny( interp, tobj );
TclByteArray tbyteArray = (TclByteArray)tobj.InternalRep;
return tbyteArray.bytes;
}
}
}