wasCSharpSQLite – Blame information for rev
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* |
2 | * TclObject.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: TclObject.java,v 1.9 2003/01/09 02:15:40 mdejong Exp $ |
||
13 | * |
||
14 | */ |
||
15 | using System; |
||
16 | using System.Text; |
||
17 | |||
18 | namespace tcl.lang |
||
19 | { |
||
20 | |||
21 | /// <summary> This class implements the basic notion of an "object" in Tcl. The |
||
22 | /// fundamental representation of an object is its string value. However, |
||
23 | /// an object can also have an internal representation, which is a "cached" |
||
24 | /// reprsentation of this object in another form. The type of the internal |
||
25 | /// rep of Tcl objects can mutate. This class provides the storage of the |
||
26 | /// string rep and the internal rep, as well as the facilities for mutating |
||
27 | /// the internal rep. |
||
28 | /// </summary> |
||
29 | |||
30 | public class TclObject |
||
31 | { |
||
32 | /// <summary> Returns the handle to the current internal rep. This method should be |
||
33 | /// called only by an InternalRep implementation. |
||
34 | /// the handle to the current internal rep. |
||
35 | /// Change the internal rep of the object. The old internal rep |
||
36 | /// will be deallocated as a result. This method should be |
||
37 | /// called only by an InternalRep implementation. |
||
38 | /// </summary> |
||
39 | /// <param name="rep">the new internal rep. |
||
40 | /// </param> |
||
41 | public InternalRep InternalRep |
||
42 | { |
||
43 | get |
||
44 | { |
||
45 | disposedCheck(); |
||
46 | return internalRep; |
||
47 | } |
||
48 | |||
49 | set |
||
50 | { |
||
51 | disposedCheck(); |
||
52 | if ( value == null ) |
||
53 | { |
||
54 | throw new TclRuntimeError( "null InternalRep" ); |
||
55 | } |
||
56 | if ( value == internalRep ) |
||
57 | { |
||
58 | return; |
||
59 | } |
||
60 | |||
61 | // In the special case where the internal representation is a CObject, |
||
62 | // we want to call the special interface to convert the underlying |
||
63 | // native object into a reference to the Java TclObject. Note that |
||
64 | // this test will always fail if we are not using the native |
||
65 | // implementation. Also note that the makeReference method |
||
66 | // will do nothing in the case where the Tcl_Obj inside the |
||
67 | // CObject was originally allocated in Java. When converting |
||
68 | // to a CObject we need to break the link made earlier. |
||
69 | |||
70 | if ( ( internalRep is CObject ) && !( value is CObject ) ) |
||
71 | { |
||
72 | // We must ensure that the string rep is copied into Java |
||
73 | // before we lose the reference to the underlying CObject. |
||
74 | // Otherwise we will lose the original string information |
||
75 | // when the backpointer is lost. |
||
76 | |||
77 | if ( (System.Object)stringRep == null ) |
||
78 | { |
||
79 | stringRep = internalRep.ToString(); |
||
80 | } |
||
81 | ( (CObject)internalRep ).makeReference( this ); |
||
82 | } |
||
83 | |||
84 | //System.out.println("TclObject setInternalRep for \"" + stringRep + "\""); |
||
85 | //System.out.println("from \"" + internalRep.getClass().getName() + |
||
86 | // "\" to \"" + rep.getClass().getName() + "\""); |
||
87 | internalRep.dispose(); |
||
88 | internalRep = value; |
||
89 | } |
||
90 | |||
91 | } |
||
92 | /// <summary> Returns true if the TclObject is shared, false otherwise.</summary> |
||
93 | /// <returns> true if the TclObject is shared, false otherwise. |
||
94 | /// </returns> |
||
95 | public bool Shared |
||
96 | { |
||
97 | get |
||
98 | { |
||
99 | disposedCheck(); |
||
100 | return ( refCount > 1 ); |
||
101 | } |
||
102 | |||
103 | } |
||
104 | /// <summary> Returns the refCount of this object. |
||
105 | /// |
||
106 | /// </summary> |
||
107 | /// <returns> refCount. |
||
108 | /// </returns> |
||
109 | public int RefCount |
||
110 | { |
||
111 | get |
||
112 | { |
||
113 | return refCount; |
||
114 | } |
||
115 | |||
116 | } |
||
117 | /// <summary> Returns the Tcl_Obj* objPtr member for a CObject or TclList. |
||
118 | /// This method is only called from Tcl Blend. |
||
119 | /// </summary> |
||
120 | internal long CObjectPtr |
||
121 | { |
||
122 | |||
123 | |||
124 | get |
||
125 | { |
||
126 | if ( internalRep is CObject ) |
||
127 | { |
||
128 | return ( (CObject)internalRep ).CObjectPtr; |
||
129 | } |
||
130 | else |
||
131 | { |
||
132 | return 0; |
||
133 | } |
||
134 | } |
||
135 | |||
136 | } |
||
137 | /// <summary> Returns 2 if the internal rep is a TclList. |
||
138 | /// Returns 1 if the internal rep is a CObject. |
||
139 | /// Otherwise returns 0. |
||
140 | /// This method provides an optimization over |
||
141 | /// invoking getInternalRep() and two instanceof |
||
142 | /// checks via JNI. It is only used by Tcl Blend. |
||
143 | /// </summary> |
||
144 | internal int CObjectInst |
||
145 | { |
||
146 | |||
147 | |||
148 | get |
||
149 | { |
||
150 | if ( internalRep is CObject ) |
||
151 | { |
||
152 | if ( internalRep is TclList ) |
||
153 | return 2; |
||
154 | else |
||
155 | return 1; |
||
156 | } |
||
157 | else |
||
158 | { |
||
159 | return 0; |
||
160 | } |
||
161 | } |
||
162 | |||
163 | } |
||
164 | |||
165 | // Internal representation of the object. |
||
166 | |||
167 | protected internal InternalRep internalRep; |
||
168 | |||
169 | // Reference count of this object. When 0 the object will be deallocated. |
||
170 | |||
171 | protected internal int refCount; |
||
172 | |||
173 | // String representation of the object. |
||
174 | |||
175 | protected internal string stringRep; |
||
176 | |||
177 | // Return true if the TclObject contains a TclList. |
||
178 | |||
179 | public bool isListType() { |
||
180 | return (internalRep.GetType().ToString().Contains("TclList")); |
||
181 | } |
||
182 | |||
183 | /// <summary> Creates a TclObject with the given InternalRep. This method should be |
||
184 | /// called only by an InternalRep implementation. |
||
185 | /// |
||
186 | /// </summary> |
||
187 | /// <param name="rep">the initial InternalRep for this object. |
||
188 | /// </param> |
||
189 | public TclObject( InternalRep rep ) |
||
190 | { |
||
191 | if ( rep == null ) |
||
192 | { |
||
193 | throw new TclRuntimeError( "null InternalRep" ); |
||
194 | } |
||
195 | internalRep = rep; |
||
196 | stringRep = null; |
||
197 | refCount = 0; |
||
198 | } |
||
199 | |||
200 | /// <summary> Creates a TclObject with the given InternalRep and stringRep. |
||
201 | /// This constructor is used by the TclString class only. No other place |
||
202 | /// should call this constructor. |
||
203 | /// |
||
204 | /// </summary> |
||
205 | /// <param name="rep">the initial InternalRep for this object. |
||
206 | /// </param> |
||
207 | /// <param name="s">the initial string rep for this object. |
||
208 | /// </param> |
||
209 | protected internal TclObject( TclString rep, string s ) |
||
210 | { |
||
211 | if ( rep == null ) |
||
212 | { |
||
213 | throw new TclRuntimeError( "null InternalRep" ); |
||
214 | } |
||
215 | internalRep = rep; |
||
216 | stringRep = s; |
||
217 | refCount = 0; |
||
218 | } |
||
219 | |||
220 | /// <summary> Returns the string representation of the object. |
||
221 | /// |
||
222 | /// </summary> |
||
223 | /// <returns> the string representation of the object. |
||
224 | /// </returns> |
||
225 | public override string ToString() |
||
226 | { |
||
227 | disposedCheck(); |
||
228 | if ( (System.Object)stringRep == null ) |
||
229 | { |
||
230 | stringRep = internalRep.ToString().Replace( "Infinity", "inf" ); |
||
231 | } |
||
232 | return stringRep; |
||
233 | } |
||
234 | |||
235 | /// <summary> Returns the UTF8 byte representation of the object. |
||
236 | /// |
||
237 | /// </summary> |
||
238 | /// <returns> the string representation of the object. |
||
239 | /// </returns> |
||
240 | public byte[] ToBytes() |
||
241 | { |
||
242 | disposedCheck(); |
||
243 | if ( (System.Object)stringRep == null ) |
||
244 | { |
||
245 | stringRep = internalRep.ToString(); |
||
246 | } |
||
247 | return Encoding.UTF8.GetBytes( stringRep ); |
||
248 | } |
||
249 | /// <summary> Sets the string representation of the object to null. Next |
||
250 | /// time when toString() is called, getInternalRep().toString() will |
||
251 | /// be called. This method should be called ONLY when an InternalRep |
||
252 | /// is about to modify the value of a TclObject. |
||
253 | /// |
||
254 | /// </summary> |
||
255 | /// <exception cref=""> TclRuntimeError if object is not exclusively owned. |
||
256 | /// </exception> |
||
257 | public void invalidateStringRep() |
||
258 | { |
||
259 | disposedCheck(); |
||
260 | if ( refCount > 1 ) |
||
261 | { |
||
262 | throw new TclRuntimeError( "string representation of object \"" + ToString() + "\" cannot be invalidated: refCount = " + refCount ); |
||
263 | } |
||
264 | stringRep = null; |
||
265 | } |
||
266 | |||
267 | /// <summary> Tcl_DuplicateObj -> duplicate |
||
268 | /// |
||
269 | /// Duplicate a TclObject, this method provides the preferred |
||
270 | /// means to deal with modification of a shared TclObject. |
||
271 | /// It should be invoked in conjunction with isShared instead |
||
272 | /// of using the deprecated takeExclusive method. |
||
273 | /// |
||
274 | /// Example: |
||
275 | /// |
||
276 | /// if (tobj.isShared()) { |
||
277 | /// tobj = tobj.duplicate(); |
||
278 | /// } |
||
279 | /// TclString.append(tobj, "hello"); |
||
280 | /// |
||
281 | /// </summary> |
||
282 | /// <returns> an TclObject with a refCount of 0. |
||
283 | /// </returns> |
||
284 | |||
285 | public TclObject duplicate() |
||
286 | { |
||
287 | disposedCheck(); |
||
288 | if ( internalRep is TclString ) |
||
289 | { |
||
290 | if ( (System.Object)stringRep == null ) |
||
291 | { |
||
292 | stringRep = internalRep.ToString(); |
||
293 | } |
||
294 | } |
||
295 | TclObject newObj = new TclObject( internalRep.duplicate() ); |
||
296 | newObj.stringRep = this.stringRep; |
||
297 | newObj.refCount = 0; |
||
298 | return newObj; |
||
299 | } |
||
300 | |||
301 | /// <deprecated> The takeExclusive method has been deprecated |
||
302 | /// in favor of the new duplicate() method. The takeExclusive |
||
303 | /// method would modify the ref count of the original object |
||
304 | /// and return an object with a ref count of 1 instead of 0. |
||
305 | /// These two behaviors lead to lots of useless duplication |
||
306 | /// of objects that could be modified directly. |
||
307 | /// </deprecated> |
||
308 | |||
309 | public TclObject takeExclusive() |
||
310 | { |
||
311 | disposedCheck(); |
||
312 | if ( refCount == 1 ) |
||
313 | { |
||
314 | return this; |
||
315 | } |
||
316 | else if ( refCount > 1 ) |
||
317 | { |
||
318 | if ( internalRep is TclString ) |
||
319 | { |
||
320 | if ( (System.Object)stringRep == null ) |
||
321 | { |
||
322 | stringRep = internalRep.ToString(); |
||
323 | } |
||
324 | } |
||
325 | TclObject newObj = new TclObject( internalRep.duplicate() ); |
||
326 | newObj.stringRep = this.stringRep; |
||
327 | newObj.refCount = 1; |
||
328 | refCount--; |
||
329 | return newObj; |
||
330 | } |
||
331 | else |
||
332 | { |
||
333 | throw new TclRuntimeError( "takeExclusive() called on object \"" + ToString() + "\" with: refCount = 0" ); |
||
334 | } |
||
335 | } |
||
336 | |||
337 | /// <summary> Tcl_IncrRefCount -> preserve |
||
338 | /// |
||
339 | /// Increments the refCount to indicate the caller's intent to |
||
340 | /// preserve the value of this object. Each preserve() call must be matched |
||
341 | /// by a corresponding release() call. |
||
342 | /// |
||
343 | /// </summary> |
||
344 | /// <exception cref=""> TclRuntimeError if the object has already been deallocated. |
||
345 | /// </exception> |
||
346 | public void preserve() |
||
347 | { |
||
348 | disposedCheck(); |
||
349 | if ( internalRep is CObject ) |
||
350 | { |
||
351 | ( (CObject)internalRep ).incrRefCount(); |
||
352 | } |
||
353 | _preserve(); |
||
354 | } |
||
355 | |||
356 | /// <summary> _preserve |
||
357 | /// |
||
358 | /// Private implementation of preserve() method. |
||
359 | /// This method will be invoked from Native code |
||
360 | /// to change the TclObject's ref count without |
||
361 | /// effecting the ref count of a CObject. |
||
362 | /// </summary> |
||
363 | private void _preserve() |
||
364 | { |
||
365 | refCount++; |
||
366 | } |
||
367 | |||
368 | /// <summary> Tcl_DecrRefCount -> release |
||
369 | /// |
||
370 | /// Decrements the refCount to indicate that the caller is no longer |
||
371 | /// interested in the value of this object. If the refCount reaches 0, |
||
372 | /// the obejct will be deallocated. |
||
373 | /// </summary> |
||
374 | public void release() |
||
375 | { |
||
376 | disposedCheck(); |
||
377 | if ( internalRep is CObject ) |
||
378 | { |
||
379 | ( (CObject)internalRep ).decrRefCount(); |
||
380 | } |
||
381 | _release(); |
||
382 | } |
||
383 | |||
384 | /// <summary> _release |
||
385 | /// |
||
386 | /// Private implementation of preserve() method. |
||
387 | /// This method will be invoked from Native code |
||
388 | /// to change the TclObject's ref count without |
||
389 | /// effecting the ref count of a CObject. |
||
390 | /// </summary> |
||
391 | private void _release() |
||
392 | { |
||
393 | refCount--; |
||
394 | if ( refCount <= 0 ) |
||
395 | { |
||
396 | internalRep.dispose(); |
||
397 | |||
398 | // Setting these to null will ensure that any attempt to use |
||
399 | // this object will result in a Java NullPointerException. |
||
400 | |||
401 | internalRep = null; |
||
402 | stringRep = null; |
||
403 | } |
||
404 | } |
||
405 | |||
406 | /// <summary> Raise a TclRuntimeError if this TclObject has been |
||
407 | /// disposed of before the last ref was released. |
||
408 | /// </summary> |
||
409 | |||
410 | private void disposedCheck() |
||
411 | { |
||
412 | if ( internalRep == null ) |
||
413 | { |
||
414 | throw new TclRuntimeError( "TclObject has been deallocated" ); |
||
415 | } |
||
416 | } |
||
417 | |||
418 | /// <summary> Return string describing type.</summary> |
||
419 | public string typePtr |
||
420 | { |
||
421 | get |
||
422 | { |
||
423 | if ( this.internalRep == null ) |
||
424 | return "null"; |
||
425 | string sType = this.internalRep.GetType().ToString().Replace( "tcl.lang.Tcl", "" ).ToLower(); |
||
426 | if ( sType == "integer" ) |
||
427 | return "int"; |
||
428 | if ( sType == "long" ) |
||
429 | return "int"; |
||
430 | return sType; |
||
431 | } |
||
432 | } |
||
433 | |||
434 | } |
||
435 | } |