wasCSharpSQLite – Blame information for rev 1

Subversion Repositories:
Rev:
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 }