wasCSharpSQLite – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /*
2 * ArrayCmd.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: ArrayCmd.java,v 1.4 2003/01/10 01:57:57 mdejong Exp $
13 *
14 */
15 using System;
16 using System.Collections;
17  
18 namespace tcl.lang
19 {
20  
21 /// <summary> This class implements the built-in "array" command in Tcl.</summary>
22  
23 class ArrayCmd : Command
24 {
25 internal static Type procClass = null;
26  
27 private static readonly string[] validCmds = new string[] { "anymore", "donesearch", "exists", "get", "names", "nextelement", "set", "size", "startsearch", "unset" };
28  
29 internal const int OPT_ANYMORE = 0;
30 internal const int OPT_DONESEARCH = 1;
31 internal const int OPT_EXISTS = 2;
32 internal const int OPT_GET = 3;
33 internal const int OPT_NAMES = 4;
34 internal const int OPT_NEXTELEMENT = 5;
35 internal const int OPT_SET = 6;
36 internal const int OPT_SIZE = 7;
37 internal const int OPT_STARTSEARCH = 8;
38 internal const int OPT_UNSET = 9;
39  
40 /// <summary> This procedure is invoked to process the "array" Tcl command.
41 /// See the user documentation for details on what it does.
42 /// </summary>
43  
44 public TCL.CompletionCode cmdProc( Interp interp, TclObject[] objv )
45 {
46 Var var = null, array = null;
47 bool notArray = false;
48 string varName, msg;
49 int index;//, result;
50  
51 if ( objv.Length < 3 )
52 {
53 throw new TclNumArgsException( interp, 1, objv, "option arrayName ?arg ...?" );
54 }
55  
56 index = TclIndex.get( interp, objv[1], validCmds, "option", 0 );
57  
58 // Locate the array variable (and it better be an array).
59  
60  
61 varName = objv[2].ToString();
62 Var[] retArray = Var.lookupVar( interp, varName, null, 0, null, false, false );
63  
64 // Assign the values returned in the array
65 if ( retArray != null )
66 {
67 var = retArray[0];
68 array = retArray[1];
69 }
70  
71 if ( ( var == null ) || !var.isVarArray() || var.isVarUndefined() )
72 {
73 notArray = true;
74 }
75  
76 // Special array trace used to keep the env array in sync for
77 // array names, array get, etc.
78  
79 if ( var != null && var.traces != null )
80 {
81 msg = Var.callTraces( interp, array, var, varName, null, ( TCL.VarFlag.LEAVE_ERR_MSG | TCL.VarFlag.NAMESPACE_ONLY | TCL.VarFlag.GLOBAL_ONLY | TCL.VarFlag.TRACE_ARRAY ) );
82 if ( (System.Object)msg != null )
83 {
84 throw new TclVarException( interp, varName, null, "trace array", msg );
85 }
86 }
87  
88 switch ( index )
89 {
90  
91 case OPT_ANYMORE:
92 {
93 if ( objv.Length != 4 )
94 {
95 throw new TclNumArgsException( interp, 2, objv, "arrayName searchId" );
96 }
97 if ( notArray )
98 {
99  
100 errorNotArray( interp, objv[2].ToString() );
101 }
102  
103 if ( var.sidVec == null )
104 {
105  
106 errorIllegalSearchId( interp, objv[2].ToString(), objv[3].ToString() );
107 }
108  
109  
110 SearchId e = var.getSearch( objv[3].ToString() );
111 if ( e == null )
112 {
113  
114 errorIllegalSearchId( interp, objv[2].ToString(), objv[3].ToString() );
115 }
116  
117 if ( e.HasMore )
118 {
119 interp.setResult( "1" );
120 }
121 else
122 {
123 interp.setResult( "0" );
124 }
125 break;
126 }
127  
128 case OPT_DONESEARCH:
129 {
130  
131 if ( objv.Length != 4 )
132 {
133 throw new TclNumArgsException( interp, 2, objv, "arrayName searchId" );
134 }
135 if ( notArray )
136 {
137  
138 errorNotArray( interp, objv[2].ToString() );
139 }
140  
141 bool rmOK = true;
142 if ( var.sidVec != null )
143 {
144  
145 rmOK = ( var.removeSearch( objv[3].ToString() ) );
146 }
147 if ( ( var.sidVec == null ) || !rmOK )
148 {
149  
150 errorIllegalSearchId( interp, objv[2].ToString(), objv[3].ToString() );
151 }
152 break;
153 }
154  
155 case OPT_EXISTS:
156 {
157  
158 if ( objv.Length != 3 )
159 {
160 throw new TclNumArgsException( interp, 2, objv, "arrayName" );
161 }
162 interp.setResult( !notArray );
163 break;
164 }
165  
166 case OPT_GET:
167 {
168 // Due to the differences in the hashtable implementation
169 // from the Tcl core and Java, the output will be rearranged.
170 // This is not a negative side effect, however, test results
171 // will differ.
172  
173 if ( ( objv.Length != 3 ) && ( objv.Length != 4 ) )
174 {
175 throw new TclNumArgsException( interp, 2, objv, "arrayName ?pattern?" );
176 }
177 if ( notArray )
178 {
179 return TCL.CompletionCode.RETURN;
180 }
181  
182 string pattern = null;
183 if ( objv.Length == 4 )
184 {
185  
186 pattern = objv[3].ToString();
187 }
188  
189 Hashtable table = (Hashtable)var.value;
190 TclObject tobj = TclList.newInstance();
191  
192 string arrayName = objv[2].ToString();
193 string key, strValue;
194 Var var2;
195  
196 // Go through each key in the hash table. If there is a
197 // pattern, test for a match. Each valid key and its value
198 // is written into sbuf, which is returned.
199  
200 // FIXME : do we need to port over the 8.1 code for this loop?
201  
202 for ( IDictionaryEnumerator e = table.GetEnumerator(); e.MoveNext(); )
203 {
204 key = ( (string)e.Key );
205 var2 = (Var)e.Value;
206 if ( var2.isVarUndefined() )
207 {
208 continue;
209 }
210  
211 if ( (System.Object)pattern != null && !Util.stringMatch( key, pattern ) )
212 {
213 continue;
214 }
215  
216  
217 strValue = interp.getVar( arrayName, key, 0 ).ToString();
218  
219 TclList.append( interp, tobj, TclString.newInstance( key ) );
220 TclList.append( interp, tobj, TclString.newInstance( strValue ) );
221 }
222 interp.setResult( tobj );
223 break;
224 }
225  
226 case OPT_NAMES:
227 {
228  
229 if ( ( objv.Length != 3 ) && ( objv.Length != 4 ) )
230 {
231 throw new TclNumArgsException( interp, 2, objv, "arrayName ?pattern?" );
232 }
233 if ( notArray )
234 {
235 return TCL.CompletionCode.RETURN;
236 }
237  
238 string pattern = null;
239 if ( objv.Length == 4 )
240 {
241  
242 pattern = objv[3].ToString();
243 }
244  
245 Hashtable table = (Hashtable)var.value;
246 TclObject tobj = TclList.newInstance();
247 string key;
248  
249 // Go through each key in the hash table. If there is a
250 // pattern, test for a match. Each valid key and its value
251 // is written into sbuf, which is returned.
252  
253 for ( IDictionaryEnumerator e = table.GetEnumerator(); e.MoveNext(); )
254 {
255 key = (string)e.Key;
256 Var elem = (Var)e.Value;
257 if ( !elem.isVarUndefined() )
258 {
259 if ( (System.Object)pattern != null )
260 {
261 if ( !Util.stringMatch( key, pattern ) )
262 {
263 continue;
264 }
265 }
266 TclList.append( interp, tobj, TclString.newInstance( key ) );
267 }
268 }
269 interp.setResult( tobj );
270 break;
271 }
272  
273 case OPT_NEXTELEMENT:
274 {
275  
276 if ( objv.Length != 4 )
277 {
278 throw new TclNumArgsException( interp, 2, objv, "arrayName searchId" );
279 }
280 if ( notArray )
281 {
282  
283 errorNotArray( interp, objv[2].ToString() );
284 }
285  
286 if ( var.sidVec == null )
287 {
288  
289 errorIllegalSearchId( interp, objv[2].ToString(), objv[3].ToString() );
290 }
291  
292  
293 SearchId e = var.getSearch( objv[3].ToString() );
294 if ( e == null )
295 {
296  
297 errorIllegalSearchId( interp, objv[2].ToString(), objv[3].ToString() );
298 }
299 if ( e.HasMore )
300 {
301 Hashtable table = (Hashtable)var.value;
302 DictionaryEntry entry = e.nextEntry();
303 string key = (string)entry.Key;
304 Var elem = (Var)entry.Value;
305 if ( ( elem.flags & VarFlags.UNDEFINED ) == 0 )
306 {
307 interp.setResult( key );
308 }
309 else
310 {
311 interp.setResult( "" );
312 }
313 }
314 break;
315 }
316  
317 case OPT_SET:
318 {
319  
320 if ( objv.Length != 4 )
321 {
322 throw new TclNumArgsException( interp, 2, objv, "arrayName list" );
323 }
324 int size = TclList.getLength( interp, objv[3] );
325 if ( size % 2 != 0 )
326 {
327 throw new TclException( interp, "list must have an even number of elements" );
328 }
329  
330 int i;
331  
332 string name1 = objv[2].ToString();
333 string name2, strValue;
334  
335 // Set each of the array variable names in the interp
336  
337 for ( i = 0; i < size; i++ )
338 {
339  
340 name2 = TclList.index( interp, objv[3], i++ ).ToString();
341  
342 strValue = TclList.index( interp, objv[3], i ).ToString();
343 interp.setVar( name1, name2, TclString.newInstance( strValue ), 0 );
344 }
345 break;
346 }
347  
348 case OPT_SIZE:
349 {
350  
351 if ( objv.Length != 3 )
352 {
353 throw new TclNumArgsException( interp, 2, objv, "arrayName" );
354 }
355 if ( notArray )
356 {
357 interp.setResult( 0 );
358 }
359 else
360 {
361 Hashtable table = (Hashtable)var.value;
362 int size = 0;
363 for ( IDictionaryEnumerator e = table.GetEnumerator(); e.MoveNext(); )
364 {
365 Var elem = (Var)e.Value;
366 if ( ( elem.flags & VarFlags.UNDEFINED ) == 0 )
367 {
368 size++;
369 }
370 }
371 interp.setResult( size );
372 }
373 break;
374 }
375  
376 case OPT_STARTSEARCH:
377 {
378  
379 if ( objv.Length != 3 )
380 {
381 throw new TclNumArgsException( interp, 2, objv, "arrayName" );
382 }
383 if ( notArray )
384 {
385  
386 errorNotArray( interp, objv[2].ToString() );
387 }
388  
389 if ( var.sidVec == null )
390 {
391 var.sidVec = new ArrayList( 10 );
392 }
393  
394 // Create a SearchId Object:
395 // To create a new SearchId object, a unique string
396 // identifier needs to be composed and we need to
397 // create an Enumeration of the array keys. The
398 // unique string identifier is created from three
399 // strings:
400 //
401 // "s-" is the default prefix
402 // "i" is a unique number that is 1+ the greatest
403 // SearchId index currently on the ArrayVar.
404 // "name" is the name of the array
405 //
406 // Once the SearchId string is created we construct a
407 // new SearchId object using the string and the
408 // Enumeration. From now on the string is used to
409 // uniquely identify the SearchId object.
410  
411 int i = var.NextIndex;
412  
413 string s = "s-" + i + "-" + objv[2].ToString();
414 IDictionaryEnumerator e = ( (Hashtable)var.value ).GetEnumerator();
415 var.sidVec.Add( new SearchId( e, s, i ) );
416 interp.setResult( s );
417 break;
418 }
419  
420 case OPT_UNSET:
421 {
422 string pattern;
423 string name;
424  
425 if ( ( objv.Length != 3 ) && ( objv.Length != 4 ) )
426 {
427 throw new TclNumArgsException( interp, 2, objv, "arrayName ?pattern?" );
428 }
429 if ( notArray )
430 {
431  
432 //Ignot this error -- errorNotArray(interp, objv[2].ToString());
433 break;
434 }
435 if ( objv.Length == 3 )
436 {
437 // When no pattern is given, just unset the whole array
438  
439 interp.unsetVar( objv[2], 0 );
440 }
441 else
442 {
443  
444 pattern = objv[3].ToString();
445 Hashtable table = (Hashtable)( ( (Hashtable)var.value ).Clone() );
446 for ( IDictionaryEnumerator e = table.GetEnumerator(); e.MoveNext(); )
447 {
448 name = (string)e.Key;
449 Var elem = (Var)e.Value;
450 if ( var.isVarUndefined() )
451 {
452 continue;
453 }
454 if ( Util.stringMatch( name, pattern ) )
455 {
456 interp.unsetVar( varName, name, 0 );
457 }
458 }
459 }
460 break;
461 }
462 }
463 return TCL.CompletionCode.RETURN;
464 }
465  
466 /// <summary> Error meassage thrown when an invalid identifier is used
467 /// to access an array.
468 ///
469 /// </summary>
470 /// <param name="interp">currrent interpreter.
471 /// </param>
472 /// <param name="String">var is the string representation of the
473 /// variable that was passed in.
474 /// </param>
475  
476 private static void errorNotArray( Interp interp, string var )
477 {
478 throw new TclException( interp, "\"" + var + "\" isn't an array" );
479 }
480  
481  
482 /// <summary> Error message thrown when an invalid SearchId is used. The
483 /// string used to reference the SearchId is parced to determine
484 /// the reason for the failure.
485 ///
486 /// </summary>
487 /// <param name="interp">currrent interpreter.
488 /// </param>
489 /// <param name="String">sid is the string represenation of the
490 /// SearchId that was passed in.
491 /// </param>
492  
493 internal static void errorIllegalSearchId( Interp interp, string varName, string sid )
494 {
495  
496 int val = validSearchId( sid.ToCharArray(), varName );
497  
498 if ( val == 1 )
499 {
500 throw new TclException( interp, "couldn't find search \"" + sid + "\"" );
501 }
502 else if ( val == 0 )
503 {
504 throw new TclException( interp, "illegal search identifier \"" + sid + "\"" );
505 }
506 else
507 {
508 throw new TclException( interp, "search identifier \"" + sid + "\" isn't for variable \"" + varName + "\"" );
509 }
510 }
511  
512 /// <summary> A valid SearchId is represented by the format s-#-arrayName. If
513 /// the SearchId string does not match this format than it is illegal,
514 /// else we cannot find it. This method is used by the
515 /// ErrorIllegalSearchId method to determine the type of error message.
516 ///
517 /// </summary>
518 /// <param name="char">pattern[] is the string use dto identify the SearchId
519 /// </param>
520 /// <returns> 1 if its a valid searchID; 0 if it is not a valid searchId,
521 /// but it is for the array, -1 if it is not a valid searchId and NOT
522 /// for the array.
523 /// </returns>
524  
525 private static int validSearchId( char[] pattern, string varName )
526 {
527 int i;
528  
529 if ( ( pattern[0] != 's' ) || ( pattern[1] != '-' ) || ( pattern[2] < '0' ) || ( pattern[2] > '9' ) )
530 {
531 return 0;
532 }
533 for ( i = 3; ( i < pattern.Length && pattern[i] != '-' ); i++ )
534 {
535 if ( pattern[i] < '0' || pattern[i] > '9' )
536 {
537 return 0;
538 }
539 }
540 if ( ++i >= pattern.Length )
541 {
542 return 0;
543 }
544 if ( varName.Equals( new string( pattern, i, ( pattern.Length - i ) ) ) )
545 {
546 return 1;
547 }
548 else
549 {
550 return -1;
551 }
552 }
553 }
554 }