001: /*
002: * TclBoolean.java
003: *
004: * Copyright (c) 1997 Sun Microsystems, Inc.
005: *
006: * See the file "license.terms" for information on usage and
007: * redistribution of this file, and for a DISCLAIMER OF ALL
008: * WARRANTIES.
009: *
010: * RCS: @(#) $Id: TclBoolean.java,v 1.9 2006/06/13 06:52:47 mdejong Exp $
011: *
012: */
013:
014: package tcl.lang;
015:
016: /**
017: * This class implements the boolean object type in Tcl.
018: */
019:
020: public class TclBoolean implements InternalRep {
021: /**
022: * Internal representations for all TclBooleans.
023: */
024:
025: private final static TclBoolean trueRep = new TclBoolean(true);
026: private final static TclBoolean falseRep = new TclBoolean(false);
027:
028: private final boolean value;
029:
030: /**
031: * Construct a TclBoolean representation with the given boolean value.
032: * Note that only two TclBoolean internal rep instances will ever
033: * exist.
034: *
035: * @param b initial boolean value.
036: */
037: private TclBoolean(boolean b) {
038: value = b;
039: }
040:
041: /**
042: * Returns a dupilcate of the current object.
043: */
044: public InternalRep duplicate() {
045: return this ;
046: }
047:
048: /**
049: * Implement this no-op for the InternalRep interface.
050: */
051:
052: public void dispose() {
053: }
054:
055: /**
056: * Called to query the string representation of the Tcl object. This
057: * method is called only by TclObject.toString() when
058: * TclObject.stringRep is null.
059: *
060: * @return the string representation of the Tcl object.
061: */
062: public String toString() {
063: if (value) {
064: return "1";
065: } else {
066: return "0";
067: }
068: }
069:
070: /**
071: * Creates a new instance of a TclObject with a TclBoolean internal
072: * representation.
073: *
074: * @param b initial value of the boolean object.
075: * @return the TclObject with the given boolean value.
076: */
077:
078: public static TclObject newInstance(boolean b) {
079: return new TclObject(b ? trueRep : falseRep);
080: }
081:
082: /**
083: * SetBooleanFromAny -> setBooleanFromAny
084: *
085: * Called to convert the other object's internal rep to boolean.
086: *
087: * @param interp current interpreter.
088: * @param tobj the TclObject to convert to use the
089: * representation provided by this class.
090: */
091: private static void setBooleanFromAny(Interp interp, TclObject tobj)
092: throws TclException {
093: // Get the string representation. Make it up-to-date if necessary.
094: String string = tobj.toString();
095:
096: if (tobj.isIntType()) {
097: int i = TclInteger.get(interp, tobj);
098: if (i == 0) {
099: tobj.setInternalRep(falseRep);
100: } else {
101: tobj.setInternalRep(trueRep);
102: }
103:
104: if (TclObject.saveObjRecords) {
105: String key = "TclInteger -> TclBoolean";
106: Integer num = (Integer) TclObject.objRecordMap.get(key);
107: if (num == null) {
108: num = new Integer(1);
109: } else {
110: num = new Integer(num.intValue() + 1);
111: }
112: TclObject.objRecordMap.put(key, num);
113: }
114: } else if (tobj.isDoubleType()) {
115: double d = TclDouble.get(interp, tobj);
116: if (d == 0.0) {
117: tobj.setInternalRep(falseRep);
118: } else {
119: tobj.setInternalRep(trueRep);
120: }
121:
122: if (TclObject.saveObjRecords) {
123: String key = "TclDouble -> TclBoolean";
124: Integer num = (Integer) TclObject.objRecordMap.get(key);
125: if (num == null) {
126: num = new Integer(1);
127: } else {
128: num = new Integer(num.intValue() + 1);
129: }
130: TclObject.objRecordMap.put(key, num);
131: }
132: } else {
133: // Copy the string converting its characters to lower case.
134:
135: string = string.toLowerCase();
136: String lowerCase = string.toLowerCase();
137:
138: // Parse the string as a boolean. We use an implementation here that
139: // doesn't report errors in interp if interp is null.
140:
141: boolean b;
142: boolean badBoolean = false;
143:
144: try {
145: b = Util.getBoolean(interp, lowerCase);
146: } catch (TclException te) {
147: // Boolean values can be extracted from ints or doubles. Note
148: // that we don't use strtoul or strtoull here because we don't
149: // care about what the value is, just whether it is equal to
150: // zero or not.
151:
152: badBoolean = true;
153: b = false; // Always reassigned below
154: if (interp != null) {
155: interp.resetResult();
156: }
157:
158: try {
159: b = (Util.getInt(interp, lowerCase) != 0);
160: badBoolean = false;
161: } catch (TclException te2) {
162: }
163:
164: if (badBoolean) {
165: try {
166: b = (Util.getDouble(interp, lowerCase) != 0.0);
167: badBoolean = false;
168: } catch (TclException te2) {
169: }
170: }
171: }
172: if (badBoolean) {
173: if (interp != null) {
174: interp.resetResult();
175: }
176: throw new TclException(interp,
177: "expected boolean value but got \"" + string
178: + "\"");
179: }
180: if (b) {
181: tobj.setInternalRep(trueRep);
182: } else {
183: tobj.setInternalRep(falseRep);
184: }
185:
186: if (TclObject.saveObjRecords) {
187: String key = "TclString -> TclBoolean";
188: Integer num = (Integer) TclObject.objRecordMap.get(key);
189: if (num == null) {
190: num = new Integer(1);
191: } else {
192: num = new Integer(num.intValue() + 1);
193: }
194: TclObject.objRecordMap.put(key, num);
195: }
196: }
197: }
198:
199: /**
200: * Returns the value of the object as an boolean.
201: *
202: * An object with a TclBoolean internal rep has
203: * a boolean value. An object with a TclInteger
204: * internal rep and has the int value "0" or "1"
205: * is also a valid boolean value.
206: *
207: * @param interp current interpreter.
208: * @param tobj the TclObject to use as an boolean.
209: * @return the boolean value of the object.
210: * @exception TclException if the object cannot be converted into a
211: * boolean.
212: */
213: public static boolean get(final Interp interp, final TclObject tobj)
214: throws TclException {
215: if (tobj.isIntType()) {
216: // An integer with the value 0 or 1 can be
217: // considered a boolean value, so there is
218: // no need to change the internal rep.
219: int ival = tobj.ivalue; // Inline TclInteger.get()
220: if (ival == 0) {
221: return false;
222: } else if (ival == 1) {
223: return true;
224: }
225: }
226:
227: InternalRep rep = tobj.getInternalRep();
228: TclBoolean tbool;
229:
230: if (!(rep instanceof TclBoolean)) {
231: setBooleanFromAny(interp, tobj);
232: tbool = (TclBoolean) tobj.getInternalRep();
233: } else {
234: tbool = (TclBoolean) rep;
235: }
236: return tbool.value;
237: }
238: }
|