/TCL/src/base/TclList.cs
C# | 449 lines | 214 code | 40 blank | 195 comment | 24 complexity | 8fb9675f740c0c4b256f800c574df0fc MD5 | raw file
- /*
- * TclList.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: TclList.java,v 1.5 2003/01/09 02:15:39 mdejong Exp $
- *
- */
- using System;
- using System.Collections;
- using System.Text;
- namespace tcl.lang
- {
- /// <summary> This class implements the list object type in Tcl.</summary>
- public class TclList : InternalRep
- {
- /// <summary> Internal representation of a list value.</summary>
- private ArrayList vector;
- /// <summary> Create a new empty Tcl List.</summary>
- private TclList()
- {
- vector = new ArrayList( 10 );
- }
- /// <summary> Create a new empty Tcl List, with the vector pre-allocated to
- /// the given size.
- ///
- /// </summary>
- /// <param name="size">the number of slots pre-allocated in the vector.
- /// </param>
- private TclList( int size )
- {
- vector = new ArrayList( size );
- }
- /// <summary> Called to free any storage for the type's internal rep.</summary>
- /// <param name="obj">the TclObject that contains this internalRep.
- /// </param>
- public void dispose()
- {
- int size = vector.Count;
- for ( int i = 0; i < size; i++ )
- {
- ( (TclObject)vector[i] ).release();
- }
- }
- /// <summary> DupListInternalRep -> duplicate
- ///
- /// Returns a dupilcate of the current object.
- ///
- /// </summary>
- /// <param name="obj">the TclObject that contains this internalRep.
- /// </param>
- public InternalRep duplicate()
- {
- int size = vector.Count;
- TclList newList = new TclList( size );
- for ( int i = 0; i < size; i++ )
- {
- TclObject tobj = (TclObject)vector[i];
- tobj.preserve();
- newList.vector.Add( tobj );
- }
- return newList;
- }
- /// <summary> Called to query the string representation of the Tcl object. This
- /// method is called only by TclObject.toString() when
- /// TclObject.stringRep is null.
- ///
- /// </summary>
- /// <returns> the string representation of the Tcl object.
- /// </returns>
- public override string ToString()
- {
- StringBuilder sbuf = new StringBuilder();
- int size = vector.Count;
- try
- {
- for ( int i = 0; i < size; i++ )
- {
- Object elm = vector[i];
- if ( elm != null )
- {
- Util.appendElement( null, sbuf, elm.ToString() );
- }
- else
- {
- Util.appendElement( null, sbuf, "" );
- }
- }
- }
- catch ( TclException e )
- {
- throw new TclRuntimeError( "unexpected TclException: " + e.Message, e );
- }
- return sbuf.ToString();
- }
- /// <summary> Creates a new instance of a TclObject with a TclList internal
- /// rep.
- ///
- /// </summary>
- /// <returns> the TclObject with the given list value.
- /// </returns>
- public static TclObject newInstance()
- {
- return new TclObject( new TclList() );
- }
- /// <summary> Called to convert the other object's internal rep to list.
- ///
- /// </summary>
- /// <param name="interp">current interpreter.
- /// </param>
- /// <param name="tobj">the TclObject to convert to use the List internal rep.
- /// </param>
- /// <exception cref=""> TclException if the object doesn't contain a valid list.
- /// </exception>
- internal static void setListFromAny( Interp interp, TclObject tobj )
- {
- InternalRep rep = tobj.InternalRep;
- if ( !( rep is TclList ) )
- {
- TclList tlist = new TclList();
- splitList( interp, tlist.vector, tobj.ToString() );
- tobj.InternalRep = tlist;
- }
- }
- /// <summary> Splits a list (in string rep) up into its constituent fields.
- ///
- /// </summary>
- /// <param name="interp">current interpreter.
- /// </param>
- /// <param name="v">store the list elements in this vector.
- /// </param>
- /// <param name="s">the string to convert into a list.
- /// </param>
- /// <exception cref=""> TclException if the object doesn't contain a valid list.
- /// </exception>
- private static void splitList( Interp interp, ArrayList v, string s )
- {
- int len = s.Length;
- int i = 0;
- while ( i < len )
- {
- FindElemResult res = Util.findElement( interp, s, i, len );
- if ( res == null )
- {
- break;
- }
- else
- {
- TclObject tobj = TclString.newInstance( res.elem );
- tobj.preserve();
- v.Add( tobj );
- }
- i = res.elemEnd;
- }
- }
- /// <summary> Tcl_ListObjAppendElement -> TclList.append()
- ///
- /// Appends a TclObject element to a list object.
- ///
- /// </summary>
- /// <param name="interp">current interpreter.
- /// </param>
- /// <param name="tobj">the TclObject to append an element to.
- /// </param>
- /// <param name="elemObj">the element to append to the object.
- /// </param>
- /// <exception cref=""> TclException if tobj cannot be converted into a list.
- /// </exception>
- public static void append( Interp interp, TclObject tobj, TclObject elemObj )
- {
- if ( tobj.Shared )
- {
- throw new TclRuntimeError( "TclList.append() called with shared object" );
- }
- setListFromAny( interp, tobj );
- tobj.invalidateStringRep();
- TclList tlist = (TclList)tobj.InternalRep;
- elemObj.preserve();
- tlist.vector.Add( elemObj );
- }
- /// <summary> Queries the length of the list. If tobj is not a list object,
- /// an attempt will be made to convert it to a list.
- ///
- /// </summary>
- /// <param name="interp">current interpreter.
- /// </param>
- /// <param name="tobj">the TclObject to use as a list.
- /// </param>
- /// <returns> the length of the list.
- /// </returns>
- /// <exception cref=""> TclException if tobj is not a valid list.
- /// </exception>
- public static int getLength( Interp interp, TclObject tobj )
- {
- setListFromAny( interp, tobj );
- TclList tlist = (TclList)tobj.InternalRep;
- return tlist.vector.Count;
- }
- /// <summary> Returns a TclObject array of the elements in a list object. If
- /// tobj is not a list object, an attempt will be made to convert
- /// it to a list. <p>
- ///
- /// The objects referenced by the returned array should be treated
- /// as readonly and their ref counts are _not_ incremented; the
- /// caller must do that if it holds on to a reference.
- ///
- /// </summary>
- /// <param name="interp">the current interpreter.
- /// </param>
- /// <param name="tobj">the list to sort.
- /// </param>
- /// <returns> a TclObject array of the elements in a list object.
- /// </returns>
- /// <exception cref=""> TclException if tobj is not a valid list.
- /// </exception>
- public static TclObject[] getElements( Interp interp, TclObject tobj )
- {
- setListFromAny( interp, tobj );
- TclList tlist = (TclList)tobj.InternalRep;
- int size = tlist.vector.Count;
- TclObject[] objArray = new TclObject[size];
- for ( int i = 0; i < size; i++ )
- {
- objArray[i] = (TclObject)tlist.vector[i];
- }
- return objArray;
- }
- /// <summary> This procedure returns a pointer to the index'th object from
- /// the list referenced by tobj. The first element has index
- /// 0. If index is negative or greater than or equal to the number
- /// of elements in the list, a null is returned. If tobj is not a
- /// list object, an attempt will be made to convert it to a list.
- ///
- /// </summary>
- /// <param name="interp">current interpreter.
- /// </param>
- /// <param name="tobj">the TclObject to use as a list.
- /// </param>
- /// <param name="index">the index of the requested element.
- /// </param>
- /// <returns> the the requested element.
- /// </returns>
- /// <exception cref=""> TclException if tobj is not a valid list.
- /// </exception>
- public static TclObject index( Interp interp, TclObject tobj, int index )
- {
- setListFromAny( interp, tobj );
- TclList tlist = (TclList)tobj.InternalRep;
- if ( index < 0 || index >= tlist.vector.Count )
- {
- return null;
- }
- else
- {
- return (TclObject)tlist.vector[index];
- }
- }
- /// <summary> This procedure inserts the elements in elements[] into the list at
- /// the given index. If tobj is not a list object, an attempt will
- /// be made to convert it to a list.
- ///
- /// </summary>
- /// <param name="interp">current interpreter.
- /// </param>
- /// <param name="tobj">the TclObject to use as a list.
- /// </param>
- /// <param name="index">the starting index of the insertion operation. <=0 means
- /// the beginning of the list. >= TclList.getLength(tobj) means
- /// the end of the list.
- /// </param>
- /// <param name="elements">the element(s) to insert.
- /// </param>
- /// <param name="from">insert elements starting from elements[from] (inclusive)
- /// </param>
- /// <param name="to">insert elements up to elements[to] (inclusive)
- /// </param>
- /// <exception cref=""> TclException if tobj is not a valid list.
- /// </exception>
- internal static void insert( Interp interp, TclObject tobj, int index, TclObject[] elements, int from, int to )
- {
- if ( tobj.Shared )
- {
- throw new TclRuntimeError( "TclList.insert() called with shared object" );
- }
- replace( interp, tobj, index, 0, elements, from, to );
- }
- /// <summary> This procedure replaces zero or more elements of the list
- /// referenced by tobj with the objects from an TclObject array.
- /// If tobj is not a list object, an attempt will be made to
- /// convert it to a list.
- ///
- /// </summary>
- /// <param name="interp">current interpreter.
- /// </param>
- /// <param name="tobj">the TclObject to use as a list.
- /// </param>
- /// <param name="index">the starting index of the replace operation. <=0 means
- /// the beginning of the list. >= TclList.getLength(tobj) means
- /// the end of the list.
- /// </param>
- /// <param name="count">the number of elements to delete from the list. <=0 means
- /// no elements should be deleted and the operation is equivalent to
- /// an insertion operation.
- /// </param>
- /// <param name="elements">the element(s) to insert.
- /// </param>
- /// <param name="from">insert elements starting from elements[from] (inclusive)
- /// </param>
- /// <param name="to">insert elements up to elements[to] (inclusive)
- /// </param>
- /// <exception cref=""> TclException if tobj is not a valid list.
- /// </exception>
- public static void replace( Interp interp, TclObject tobj, int index, int count, TclObject[] elements, int from, int to )
- {
- if ( tobj.Shared )
- {
- throw new TclRuntimeError( "TclList.replace() called with shared object" );
- }
- setListFromAny( interp, tobj );
- tobj.invalidateStringRep();
- TclList tlist = (TclList)tobj.InternalRep;
- int size = tlist.vector.Count;
- int i;
- if ( index >= size )
- {
- // Append to the end of the list. There is no need for deleting
- // elements.
- index = size;
- }
- else
- {
- if ( index < 0 )
- {
- index = 0;
- }
- if ( count > size - index )
- {
- count = size - index;
- }
- for ( i = 0; i < count; i++ )
- {
- TclObject obj = (TclObject)tlist.vector[index];
- obj.release();
- tlist.vector.RemoveAt( index );
- }
- }
- for ( i = from; i <= to; i++ )
- {
- elements[i].preserve();
- tlist.vector.Insert( index++, elements[i] );
- }
- }
- /// <summary> Sorts the list according to the sort mode and (optional) sort command.
- /// The resulting list will contain no duplicates, if argument unique is
- /// specifed as true.
- /// If tobj is not a list object, an attempt will be made to
- /// convert it to a list.
- ///
- /// </summary>
- /// <param name="interp">the current interpreter.
- /// </param>
- /// <param name="tobj">the list to sort.
- /// </param>
- /// <param name="sortMode">the sorting mode.
- /// </param>
- /// <param name="sortIncreasing">true if to sort the elements in increasing order.
- /// </param>
- /// <param name="command">the command to compute the order of two elements.
- /// </param>
- /// <param name="unique">true if the result should contain no duplicates.
- /// </param>
- /// <exception cref=""> TclException if tobj is not a valid list.
- /// </exception>
- internal static void sort( Interp interp, TclObject tobj, int sortMode, int sortIndex, bool sortIncreasing, string command, bool unique )
- {
- setListFromAny( interp, tobj );
- tobj.invalidateStringRep();
- TclList tlist = (TclList)tobj.InternalRep;
- int size = tlist.vector.Count;
- if ( size <= 1 )
- {
- return;
- }
- TclObject[] objArray = new TclObject[size];
- for ( int i = 0; i < size; i++ )
- {
- objArray[i] = (TclObject)tlist.vector[i];
- }
- QSort s = new QSort();
- int newsize = s.sort( interp, objArray, sortMode, sortIndex, sortIncreasing, command, unique );
- for ( int i = 0; i < size; i++ )
- {
- if ( i < newsize )
- {
- tlist.vector[i] = objArray[i];
- objArray[i] = null;
- }
- else
- tlist.vector.RemoveAt( newsize );
- }
- }
- }
- }