PageRenderTime 45ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/TCL/src/base/TclList.cs

https://bitbucket.org/eumario/csharp-sqlite
C# | 449 lines | 214 code | 40 blank | 195 comment | 24 complexity | 8fb9675f740c0c4b256f800c574df0fc MD5 | raw file
  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. *
  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. using System.Text;
  18. namespace tcl.lang
  19. {
  20. /// <summary> This class implements the list object type in Tcl.</summary>
  21. public class TclList : InternalRep
  22. {
  23. /// <summary> Internal representation of a list value.</summary>
  24. private ArrayList vector;
  25. /// <summary> Create a new empty Tcl List.</summary>
  26. private TclList()
  27. {
  28. vector = new ArrayList( 10 );
  29. }
  30. /// <summary> Create a new empty Tcl List, with the vector pre-allocated to
  31. /// the given size.
  32. ///
  33. /// </summary>
  34. /// <param name="size">the number of slots pre-allocated in the vector.
  35. /// </param>
  36. private TclList( int size )
  37. {
  38. vector = new ArrayList( size );
  39. }
  40. /// <summary> Called to free any storage for the type's internal rep.</summary>
  41. /// <param name="obj">the TclObject that contains this internalRep.
  42. /// </param>
  43. public void dispose()
  44. {
  45. int size = vector.Count;
  46. for ( int i = 0; i < size; i++ )
  47. {
  48. ( (TclObject)vector[i] ).release();
  49. }
  50. }
  51. /// <summary> DupListInternalRep -> duplicate
  52. ///
  53. /// Returns a dupilcate of the current object.
  54. ///
  55. /// </summary>
  56. /// <param name="obj">the TclObject that contains this internalRep.
  57. /// </param>
  58. public InternalRep duplicate()
  59. {
  60. int size = vector.Count;
  61. TclList newList = new TclList( size );
  62. for ( int i = 0; i < size; i++ )
  63. {
  64. TclObject tobj = (TclObject)vector[i];
  65. tobj.preserve();
  66. newList.vector.Add( tobj );
  67. }
  68. return newList;
  69. }
  70. /// <summary> Called to query the string representation of the Tcl object. This
  71. /// method is called only by TclObject.toString() when
  72. /// TclObject.stringRep is null.
  73. ///
  74. /// </summary>
  75. /// <returns> the string representation of the Tcl object.
  76. /// </returns>
  77. public override string ToString()
  78. {
  79. StringBuilder sbuf = new StringBuilder();
  80. int size = vector.Count;
  81. try
  82. {
  83. for ( int i = 0; i < size; i++ )
  84. {
  85. Object elm = vector[i];
  86. if ( elm != null )
  87. {
  88. Util.appendElement( null, sbuf, elm.ToString() );
  89. }
  90. else
  91. {
  92. Util.appendElement( null, sbuf, "" );
  93. }
  94. }
  95. }
  96. catch ( TclException e )
  97. {
  98. throw new TclRuntimeError( "unexpected TclException: " + e.Message, e );
  99. }
  100. return sbuf.ToString();
  101. }
  102. /// <summary> Creates a new instance of a TclObject with a TclList internal
  103. /// rep.
  104. ///
  105. /// </summary>
  106. /// <returns> the TclObject with the given list value.
  107. /// </returns>
  108. public static TclObject newInstance()
  109. {
  110. return new TclObject( new TclList() );
  111. }
  112. /// <summary> Called to convert the other object's internal rep to list.
  113. ///
  114. /// </summary>
  115. /// <param name="interp">current interpreter.
  116. /// </param>
  117. /// <param name="tobj">the TclObject to convert to use the List internal rep.
  118. /// </param>
  119. /// <exception cref=""> TclException if the object doesn't contain a valid list.
  120. /// </exception>
  121. internal static void setListFromAny( Interp interp, TclObject tobj )
  122. {
  123. InternalRep rep = tobj.InternalRep;
  124. if ( !( rep is TclList ) )
  125. {
  126. TclList tlist = new TclList();
  127. splitList( interp, tlist.vector, tobj.ToString() );
  128. tobj.InternalRep = tlist;
  129. }
  130. }
  131. /// <summary> Splits a list (in string rep) up into its constituent fields.
  132. ///
  133. /// </summary>
  134. /// <param name="interp">current interpreter.
  135. /// </param>
  136. /// <param name="v">store the list elements in this vector.
  137. /// </param>
  138. /// <param name="s">the string to convert into a list.
  139. /// </param>
  140. /// <exception cref=""> TclException if the object doesn't contain a valid list.
  141. /// </exception>
  142. private static void splitList( Interp interp, ArrayList v, string s )
  143. {
  144. int len = s.Length;
  145. int i = 0;
  146. while ( i < len )
  147. {
  148. FindElemResult res = Util.findElement( interp, s, i, len );
  149. if ( res == null )
  150. {
  151. break;
  152. }
  153. else
  154. {
  155. TclObject tobj = TclString.newInstance( res.elem );
  156. tobj.preserve();
  157. v.Add( tobj );
  158. }
  159. i = res.elemEnd;
  160. }
  161. }
  162. /// <summary> Tcl_ListObjAppendElement -> TclList.append()
  163. ///
  164. /// Appends a TclObject element to a list object.
  165. ///
  166. /// </summary>
  167. /// <param name="interp">current interpreter.
  168. /// </param>
  169. /// <param name="tobj">the TclObject to append an element to.
  170. /// </param>
  171. /// <param name="elemObj">the element to append to the object.
  172. /// </param>
  173. /// <exception cref=""> TclException if tobj cannot be converted into a list.
  174. /// </exception>
  175. public static void append( Interp interp, TclObject tobj, TclObject elemObj )
  176. {
  177. if ( tobj.Shared )
  178. {
  179. throw new TclRuntimeError( "TclList.append() called with shared object" );
  180. }
  181. setListFromAny( interp, tobj );
  182. tobj.invalidateStringRep();
  183. TclList tlist = (TclList)tobj.InternalRep;
  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
  405. tlist.vector.RemoveAt( newsize );
  406. }
  407. }
  408. }
  409. }