wasCSharpSQLite – Blame information for rev
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* |
2 | * LappendCmd.java |
||
3 | * |
||
4 | * Copyright (c) 1997 Cornell University. |
||
5 | * Copyright (c) 1997 Sun Microsystems, Inc. |
||
6 | * Copyright (c) 1998-1999 by Scriptics Corporation. |
||
7 | * Copyright (c) 1999 Mo DeJong. |
||
8 | * |
||
9 | * See the file "license.terms" for information on usage and |
||
10 | * redistribution of this file, and for a DISCLAIMER OF ALL |
||
11 | * WARRANTIES. |
||
12 | * |
||
13 | * Included in SQLite3 port to C# for use in testharness only; 2008 Noah B Hart |
||
14 | * |
||
15 | * RCS @(#) $Id: LappendCmd.java,v 1.3 2003/01/09 02:15:39 mdejong Exp $ |
||
16 | * |
||
17 | */ |
||
18 | using System; |
||
19 | namespace tcl.lang |
||
20 | { |
||
21 | |||
22 | /// <summary> This class implements the built-in "lappend" command in Tcl.</summary> |
||
23 | class LappendCmd : Command |
||
24 | { |
||
25 | /// <summary> |
||
26 | /// Tcl_LappendObjCmd -> LappendCmd.cmdProc |
||
27 | /// |
||
28 | /// This procedure is invoked to process the "lappend" Tcl command. |
||
29 | /// See the user documentation for details on what it does. |
||
30 | /// </summary> |
||
31 | |||
32 | public TCL.CompletionCode cmdProc( Interp interp, TclObject[] objv ) |
||
33 | { |
||
34 | TclObject varValue, newValue = null; |
||
35 | int i;//int numElems, i, j; |
||
36 | bool createdNewObj, createVar; |
||
37 | |||
38 | if ( objv.Length < 2 ) |
||
39 | { |
||
40 | throw new TclNumArgsException( interp, 1, objv, "varName ?value value ...?" ); |
||
41 | } |
||
42 | if ( objv.Length == 2 ) |
||
43 | { |
||
44 | try |
||
45 | { |
||
46 | newValue = interp.getVar( objv[1], 0 ); |
||
47 | } |
||
48 | catch ( TclException e ) |
||
49 | { |
||
50 | // The variable doesn't exist yet. Just create it with an empty |
||
51 | // initial value. |
||
52 | varValue = TclList.newInstance(); |
||
53 | |||
54 | try |
||
55 | { |
||
56 | newValue = interp.setVar( objv[1], varValue, 0 ); |
||
57 | } |
||
58 | finally |
||
59 | { |
||
60 | if ( newValue == null ) |
||
61 | varValue.release(); // free unneeded object |
||
62 | } |
||
63 | |||
64 | interp.resetResult(); |
||
65 | return TCL.CompletionCode.RETURN; |
||
66 | } |
||
67 | } |
||
68 | else |
||
69 | { |
||
70 | // We have arguments to append. We used to call Tcl_SetVar2 to |
||
71 | // append each argument one at a time to ensure that traces were run |
||
72 | // for each append step. We now append the arguments all at once |
||
73 | // because it's faster. Note that a read trace and a write trace for |
||
74 | // the variable will now each only be called once. Also, if the |
||
75 | // variable's old value is unshared we modify it directly, otherwise |
||
76 | // we create a new copy to modify: this is "copy on write". |
||
77 | |||
78 | createdNewObj = false; |
||
79 | createVar = true; |
||
80 | |||
81 | try |
||
82 | { |
||
83 | varValue = interp.getVar( objv[1], 0 ); |
||
84 | } |
||
85 | catch ( TclException e ) |
||
86 | { |
||
87 | // We couldn't read the old value: either the var doesn't yet |
||
88 | // exist or it's an array element. If it's new, we will try to |
||
89 | // create it with Tcl_ObjSetVar2 below. |
||
90 | |||
91 | // FIXME : not sure we even need this parse for anything! |
||
92 | // If we do not need to parse could we at least speed it up a bit |
||
93 | |||
94 | string varName; |
||
95 | int nameBytes; |
||
96 | |||
97 | |||
98 | varName = objv[1].ToString(); |
||
99 | nameBytes = varName.Length; // Number of Unicode chars in string |
||
100 | |||
101 | for ( i = 0; i < nameBytes; i++ ) |
||
102 | { |
||
103 | if ( varName[i] == '(' ) |
||
104 | { |
||
105 | i = nameBytes - 1; |
||
106 | if ( varName[i] == ')' ) |
||
107 | { |
||
108 | // last char is ')' => array ref |
||
109 | createVar = false; |
||
110 | } |
||
111 | break; |
||
112 | } |
||
113 | } |
||
114 | varValue = TclList.newInstance(); |
||
115 | createdNewObj = true; |
||
116 | } |
||
117 | |||
118 | // We only take this branch when the catch branch was not run |
||
119 | if ( createdNewObj == false && varValue.Shared ) |
||
120 | { |
||
121 | varValue = varValue.duplicate(); |
||
122 | createdNewObj = true; |
||
123 | } |
||
124 | |||
125 | // Insert the new elements at the end of the list. |
||
126 | |||
127 | for ( i = 2; i < objv.Length; i++ ) |
||
128 | TclList.append( interp, varValue, objv[i] ); |
||
129 | |||
130 | // No need to call varValue.invalidateStringRep() since it |
||
131 | // is called during the TclList.append operation. |
||
132 | |||
133 | // Now store the list object back into the variable. If there is an |
||
134 | // error setting the new value, decrement its ref count if it |
||
135 | // was new and we didn't create the variable. |
||
136 | |||
137 | try |
||
138 | { |
||
139 | |||
140 | newValue = interp.setVar( objv[1].ToString(), varValue, 0 ); |
||
141 | } |
||
142 | catch ( TclException e ) |
||
143 | { |
||
144 | if ( createdNewObj && !createVar ) |
||
145 | { |
||
146 | varValue.release(); // free unneeded obj |
||
147 | } |
||
148 | throw; |
||
149 | } |
||
150 | } |
||
151 | |||
152 | // Set the interpreter's object result to refer to the variable's value |
||
153 | // object. |
||
154 | |||
155 | interp.setResult( newValue ); |
||
156 | return TCL.CompletionCode.RETURN; |
||
157 | } |
||
158 | } |
||
159 | } |