PageRenderTime 47ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/trunk/managed/csharp-sqlite/TCL/src/base/TclList.cs

https://bitbucket.org/KyanhaLLC/opensim-libs
C# | 449 lines | 213 code | 41 blank | 195 comment | 28 complexity | 8f67117aeaa8639e3feb0d9a659208ef MD5 | raw file
Possible License(s): Apache-2.0, BSD-2-Clause, MIT, LGPL-2.1, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, GPL-3.0, BSD-3-Clause
  1. /*
  2. * TclList.java
  3. *
  4. * Copyright (c) 1997 Sun Microsystems, Inc.
  5. *
  6. * See the file "license.terms" for information on usage and
  7. * redistribution of this file, and for a DISCLAIMER OF ALL
  8. * WARRANTIES.
  9. *
  10. * Included in SQLite3 port to C# for use in testharness only; 2008 Noah B Hart
  11. * $Header$
  12. * RCS @(#) $Id: TclList.java,v 1.5 2003/01/09 02:15:39 mdejong Exp $
  13. *
  14. */
  15. using System;
  16. using System.Collections;
  17. namespace tcl.lang
  18. {
  19. /// <summary> This class implements the list object type in Tcl.</summary>
  20. public class TclList : InternalRep
  21. {
  22. /// <summary> Internal representation of a list value.</summary>
  23. private ArrayList vector;
  24. /// <summary> Create a new empty Tcl List.</summary>
  25. private TclList()
  26. {
  27. vector = new ArrayList( 10 );
  28. }
  29. /// <summary> Create a new empty Tcl List, with the vector pre-allocated to
  30. /// the given size.
  31. ///
  32. /// </summary>
  33. /// <param name="size">the number of slots pre-allocated in the vector.
  34. /// </param>
  35. private TclList( int size )
  36. {
  37. vector = new ArrayList( size );
  38. }
  39. /// <summary> Called to free any storage for the type's internal rep.</summary>
  40. /// <param name="obj">the TclObject that contains this internalRep.
  41. /// </param>
  42. public void dispose()
  43. {
  44. int size = vector.Count;
  45. for ( int i = 0 ; i < size ; i++ )
  46. {
  47. ( (TclObject)vector[i] ).release();
  48. }
  49. }
  50. /// <summary> DupListInternalRep -> duplicate
  51. ///
  52. /// Returns a dupilcate of the current object.
  53. ///
  54. /// </summary>
  55. /// <param name="obj">the TclObject that contains this internalRep.
  56. /// </param>
  57. public InternalRep duplicate()
  58. {
  59. int size = vector.Count;
  60. TclList newList = new TclList( size );
  61. for ( int i = 0 ; i < size ; i++ )
  62. {
  63. TclObject tobj = (TclObject)vector[i];
  64. tobj.preserve();
  65. newList.vector.Add( tobj );
  66. }
  67. return newList;
  68. }
  69. /// <summary> Called to query the string representation of the Tcl object. This
  70. /// method is called only by TclObject.toString() when
  71. /// TclObject.stringRep is null.
  72. ///
  73. /// </summary>
  74. /// <returns> the string representation of the Tcl object.
  75. /// </returns>
  76. public override string ToString()
  77. {
  78. System.Text.StringBuilder sbuf = new System.Text.StringBuilder();
  79. int size = vector.Count;
  80. try
  81. {
  82. for ( int i = 0 ; i < size ; i++ )
  83. {
  84. Object elm = vector[i];
  85. if ( elm != null )
  86. {
  87. Util.appendElement( null, sbuf, elm.ToString() );
  88. }
  89. else
  90. {
  91. Util.appendElement( null, sbuf, "" );
  92. }
  93. }
  94. }
  95. catch ( TclException e )
  96. {
  97. throw new TclRuntimeError( "unexpected TclException: " + e.Message, e );
  98. }
  99. return sbuf.ToString();
  100. }
  101. /// <summary> Creates a new instance of a TclObject with a TclList internal
  102. /// rep.
  103. ///
  104. /// </summary>
  105. /// <returns> the TclObject with the given list value.
  106. /// </returns>
  107. public static TclObject newInstance()
  108. {
  109. return new TclObject( new TclList() );
  110. }
  111. /// <summary> Called to convert the other object's internal rep to list.
  112. ///
  113. /// </summary>
  114. /// <param name="interp">current interpreter.
  115. /// </param>
  116. /// <param name="tobj">the TclObject to convert to use the List internal rep.
  117. /// </param>
  118. /// <exception cref=""> TclException if the object doesn't contain a valid list.
  119. /// </exception>
  120. internal static void setListFromAny( Interp interp, TclObject tobj )
  121. {
  122. InternalRep rep = tobj.InternalRep;
  123. if ( !( rep is TclList ) )
  124. {
  125. TclList tlist = new TclList();
  126. splitList( interp, tlist.vector, tobj.ToString() );
  127. tobj.InternalRep = tlist;
  128. }
  129. }
  130. /// <summary> Splits a list (in string rep) up into its constituent fields.
  131. ///
  132. /// </summary>
  133. /// <param name="interp">current interpreter.
  134. /// </param>
  135. /// <param name="v">store the list elements in this vector.
  136. /// </param>
  137. /// <param name="s">the string to convert into a list.
  138. /// </param>
  139. /// <exception cref=""> TclException if the object doesn't contain a valid list.
  140. /// </exception>
  141. private static void splitList( Interp interp, ArrayList v, string s )
  142. {
  143. int len = s.Length;
  144. int i = 0;
  145. while ( i < len )
  146. {
  147. FindElemResult res = Util.findElement( interp, s, i, len );
  148. if ( res == null )
  149. {
  150. break;
  151. }
  152. else
  153. {
  154. TclObject tobj = TclString.newInstance( res.elem );
  155. tobj.preserve();
  156. v.Add( tobj );
  157. }
  158. i = res.elemEnd;
  159. }
  160. }
  161. /// <summary> Tcl_ListObjAppendElement -> TclList.append()
  162. ///
  163. /// Appends a TclObject element to a list object.
  164. ///
  165. /// </summary>
  166. /// <param name="interp">current interpreter.
  167. /// </param>
  168. /// <param name="tobj">the TclObject to append an element to.
  169. /// </param>
  170. /// <param name="elemObj">the element to append to the object.
  171. /// </param>
  172. /// <exception cref=""> TclException if tobj cannot be converted into a list.
  173. /// </exception>
  174. public static void append( Interp interp, TclObject tobj, TclObject elemObj )
  175. {
  176. if ( tobj.Shared )
  177. {
  178. throw new TclRuntimeError( "TclList.append() called with shared object" );
  179. }
  180. setListFromAny( interp, tobj );
  181. tobj.invalidateStringRep();
  182. TclList tlist = (TclList)tobj.InternalRep;
  183. if ( !String.IsNullOrEmpty( elemObj.stringRep ) && elemObj.stringRep[0] == '{' ) elemObj = TclString.newInstance( elemObj.stringRep.Substring( 1, elemObj.stringRep.Length - 2 ) );
  184. elemObj.preserve();
  185. tlist.vector.Add( elemObj );
  186. }
  187. /// <summary> Queries the length of the list. If tobj is not a list object,
  188. /// an attempt will be made to convert it to a list.
  189. ///
  190. /// </summary>
  191. /// <param name="interp">current interpreter.
  192. /// </param>
  193. /// <param name="tobj">the TclObject to use as a list.
  194. /// </param>
  195. /// <returns> the length of the list.
  196. /// </returns>
  197. /// <exception cref=""> TclException if tobj is not a valid list.
  198. /// </exception>
  199. public static int getLength( Interp interp, TclObject tobj )
  200. {
  201. setListFromAny( interp, tobj );
  202. TclList tlist = (TclList)tobj.InternalRep;
  203. return tlist.vector.Count;
  204. }
  205. /// <summary> Returns a TclObject array of the elements in a list object. If
  206. /// tobj is not a list object, an attempt will be made to convert
  207. /// it to a list. <p>
  208. ///
  209. /// The objects referenced by the returned array should be treated
  210. /// as readonly and their ref counts are _not_ incremented; the
  211. /// caller must do that if it holds on to a reference.
  212. ///
  213. /// </summary>
  214. /// <param name="interp">the current interpreter.
  215. /// </param>
  216. /// <param name="tobj">the list to sort.
  217. /// </param>
  218. /// <returns> a TclObject array of the elements in a list object.
  219. /// </returns>
  220. /// <exception cref=""> TclException if tobj is not a valid list.
  221. /// </exception>
  222. public static TclObject[] getElements( Interp interp, TclObject tobj )
  223. {
  224. setListFromAny( interp, tobj );
  225. TclList tlist = (TclList)tobj.InternalRep;
  226. int size = tlist.vector.Count;
  227. TclObject[] objArray = new TclObject[size];
  228. for ( int i = 0 ; i < size ; i++ )
  229. {
  230. objArray[i] = (TclObject)tlist.vector[i];
  231. }
  232. return objArray;
  233. }
  234. /// <summary> This procedure returns a pointer to the index'th object from
  235. /// the list referenced by tobj. The first element has index
  236. /// 0. If index is negative or greater than or equal to the number
  237. /// of elements in the list, a null is returned. If tobj is not a
  238. /// list object, an attempt will be made to convert it to a list.
  239. ///
  240. /// </summary>
  241. /// <param name="interp">current interpreter.
  242. /// </param>
  243. /// <param name="tobj">the TclObject to use as a list.
  244. /// </param>
  245. /// <param name="index">the index of the requested element.
  246. /// </param>
  247. /// <returns> the the requested element.
  248. /// </returns>
  249. /// <exception cref=""> TclException if tobj is not a valid list.
  250. /// </exception>
  251. public static TclObject index( Interp interp, TclObject tobj, int index )
  252. {
  253. setListFromAny( interp, tobj );
  254. TclList tlist = (TclList)tobj.InternalRep;
  255. if ( index < 0 || index >= tlist.vector.Count )
  256. {
  257. return null;
  258. }
  259. else
  260. {
  261. return (TclObject)tlist.vector[index];
  262. }
  263. }
  264. /// <summary> This procedure inserts the elements in elements[] into the list at
  265. /// the given index. If tobj is not a list object, an attempt will
  266. /// be made to convert it to a list.
  267. ///
  268. /// </summary>
  269. /// <param name="interp">current interpreter.
  270. /// </param>
  271. /// <param name="tobj">the TclObject to use as a list.
  272. /// </param>
  273. /// <param name="index">the starting index of the insertion operation. <=0 means
  274. /// the beginning of the list. >= TclList.getLength(tobj) means
  275. /// the end of the list.
  276. /// </param>
  277. /// <param name="elements">the element(s) to insert.
  278. /// </param>
  279. /// <param name="from">insert elements starting from elements[from] (inclusive)
  280. /// </param>
  281. /// <param name="to">insert elements up to elements[to] (inclusive)
  282. /// </param>
  283. /// <exception cref=""> TclException if tobj is not a valid list.
  284. /// </exception>
  285. internal static void insert( Interp interp, TclObject tobj, int index, TclObject[] elements, int from, int to )
  286. {
  287. if ( tobj.Shared )
  288. {
  289. throw new TclRuntimeError( "TclList.insert() called with shared object" );
  290. }
  291. replace( interp, tobj, index, 0, elements, from, to );
  292. }
  293. /// <summary> This procedure replaces zero or more elements of the list
  294. /// referenced by tobj with the objects from an TclObject array.
  295. /// If tobj is not a list object, an attempt will be made to
  296. /// convert it to a list.
  297. ///
  298. /// </summary>
  299. /// <param name="interp">current interpreter.
  300. /// </param>
  301. /// <param name="tobj">the TclObject to use as a list.
  302. /// </param>
  303. /// <param name="index">the starting index of the replace operation. <=0 means
  304. /// the beginning of the list. >= TclList.getLength(tobj) means
  305. /// the end of the list.
  306. /// </param>
  307. /// <param name="count">the number of elements to delete from the list. <=0 means
  308. /// no elements should be deleted and the operation is equivalent to
  309. /// an insertion operation.
  310. /// </param>
  311. /// <param name="elements">the element(s) to insert.
  312. /// </param>
  313. /// <param name="from">insert elements starting from elements[from] (inclusive)
  314. /// </param>
  315. /// <param name="to">insert elements up to elements[to] (inclusive)
  316. /// </param>
  317. /// <exception cref=""> TclException if tobj is not a valid list.
  318. /// </exception>
  319. public static void replace( Interp interp, TclObject tobj, int index, int count, TclObject[] elements, int from, int to )
  320. {
  321. if ( tobj.Shared )
  322. {
  323. throw new TclRuntimeError( "TclList.replace() called with shared object" );
  324. }
  325. setListFromAny( interp, tobj );
  326. tobj.invalidateStringRep();
  327. TclList tlist = (TclList)tobj.InternalRep;
  328. int size = tlist.vector.Count;
  329. int i;
  330. if ( index >= size )
  331. {
  332. // Append to the end of the list. There is no need for deleting
  333. // elements.
  334. index = size;
  335. }
  336. else
  337. {
  338. if ( index < 0 )
  339. {
  340. index = 0;
  341. }
  342. if ( count > size - index )
  343. {
  344. count = size - index;
  345. }
  346. for ( i = 0 ; i < count ; i++ )
  347. {
  348. TclObject obj = (TclObject)tlist.vector[index];
  349. obj.release();
  350. tlist.vector.RemoveAt( index );
  351. }
  352. }
  353. for ( i = from ; i <= to ; i++ )
  354. {
  355. elements[i].preserve();
  356. tlist.vector.Insert( index++, elements[i] );
  357. }
  358. }
  359. /// <summary> Sorts the list according to the sort mode and (optional) sort command.
  360. /// The resulting list will contain no duplicates, if argument unique is
  361. /// specifed as true.
  362. /// If tobj is not a list object, an attempt will be made to
  363. /// convert it to a list.
  364. ///
  365. /// </summary>
  366. /// <param name="interp">the current interpreter.
  367. /// </param>
  368. /// <param name="tobj">the list to sort.
  369. /// </param>
  370. /// <param name="sortMode">the sorting mode.
  371. /// </param>
  372. /// <param name="sortIncreasing">true if to sort the elements in increasing order.
  373. /// </param>
  374. /// <param name="command">the command to compute the order of two elements.
  375. /// </param>
  376. /// <param name="unique">true if the result should contain no duplicates.
  377. /// </param>
  378. /// <exception cref=""> TclException if tobj is not a valid list.
  379. /// </exception>
  380. internal static void sort( Interp interp, TclObject tobj, int sortMode, int sortIndex, bool sortIncreasing, string command, bool unique )
  381. {
  382. setListFromAny( interp, tobj );
  383. tobj.invalidateStringRep();
  384. TclList tlist = (TclList)tobj.InternalRep;
  385. int size = tlist.vector.Count;
  386. if ( size <= 1 )
  387. {
  388. return;
  389. }
  390. TclObject[] objArray = new TclObject[size];
  391. for ( int i = 0 ; i < size ; i++ )
  392. {
  393. objArray[i] = (TclObject)tlist.vector[i];
  394. }
  395. QSort s = new QSort();
  396. int newsize = s.sort( interp, objArray, sortMode, sortIndex, sortIncreasing, command, unique );
  397. for ( int i = 0 ; i < size ; i++ )
  398. {
  399. if ( i < newsize )
  400. {
  401. tlist.vector[i] = objArray[i];
  402. objArray[i] = null;
  403. }
  404. else tlist.vector.RemoveAt( newsize );
  405. }
  406. }
  407. }
  408. }