001: /*
002: * TclByteArray.java
003: *
004: * This class contains the implementation of the Jacl binary data object.
005: *
006: * Copyright (c) 1999 Christian Krone.
007: * Copyright (c) 1997 Sun Microsystems, Inc.
008: *
009: * See the file "license.terms" for information on usage and
010: * redistribution of this file, and for a DISCLAIMER OF ALL
011: * WARRANTIES.
012: *
013: * RCS: @(#) $Id: TclByteArray.java,v 1.4 2003/03/08 02:05:06 mdejong Exp $
014: *
015: */
016:
017: package tcl.lang;
018:
019: import java.io.*;
020:
021: /**
022: * This class implements the binary data object type in Tcl.
023: */
024: public class TclByteArray implements InternalRep {
025:
026: /**
027: * The number of bytes used in the byte array.
028: * The following structure is the internal rep for a ByteArray object.
029: * Keeps track of how much memory has been used. This can be different from
030: * how much has been allocated for the byte array to enable growing and
031: * shrinking of the ByteArray object with fewer allocations.
032: */
033: private int used;
034:
035: /**
036: * Internal representation of the binary data.
037: */
038: private byte[] bytes;
039:
040: /**
041: * Create a new empty Tcl binary data.
042: */
043: private TclByteArray() {
044: used = 0;
045: bytes = new byte[0];
046: }
047:
048: /**
049: * Create a new Tcl binary data.
050: */
051: private TclByteArray(byte[] b) {
052: used = b.length;
053: bytes = new byte[used];
054: System.arraycopy(b, 0, bytes, 0, used);
055: }
056:
057: /**
058: * Create a new Tcl binary data.
059: */
060: private TclByteArray(byte[] b, int position, int length) {
061: used = length;
062: bytes = new byte[used];
063: System.arraycopy(b, position, bytes, 0, used);
064: }
065:
066: /**
067: * Create a new Tcl binary data.
068: */
069: private TclByteArray(char[] c) {
070: used = c.length;
071: bytes = new byte[used];
072: for (int ix = 0; ix < used; ix++) {
073: bytes[ix] = (byte) c[ix];
074: }
075: }
076:
077: /**
078: * Returns a duplicate of the current object.
079: *
080: * @param obj the TclObject that contains this internalRep.
081: */
082: public InternalRep duplicate() {
083: return new TclByteArray(bytes, 0, used);
084: }
085:
086: /**
087: * Implement this no-op for the InternalRep interface.
088: */
089:
090: public void dispose() {
091: }
092:
093: /**
094: * Called to query the string representation of the Tcl object. This
095: * method is called only by TclObject.toString() when
096: * TclObject.stringRep is null.
097: *
098: * @return the string representation of the Tcl object.
099: */
100: public String toString() {
101: char[] c = new char[used];
102: for (int ix = 0; ix < used; ix++) {
103: c[ix] = (char) (bytes[ix] & 0xff);
104: }
105: return new String(c);
106: }
107:
108: /**
109: * Creates a new instance of a TclObject with a TclByteArray internal
110: * rep.
111: *
112: * @return the TclObject with the given byte array value.
113: */
114:
115: public static TclObject newInstance(byte[] b, int position,
116: int length) {
117: return new TclObject(new TclByteArray(b, position, length));
118: }
119:
120: /**
121: * Creates a new instance of a TclObject with a TclByteArray internal
122: * rep.
123: *
124: * @return the TclObject with the given byte array value.
125: */
126:
127: public static TclObject newInstance(byte[] b) {
128: return new TclObject(new TclByteArray(b));
129: }
130:
131: /**
132: * Creates a new instance of a TclObject with an empty TclByteArray
133: * internal rep.
134: *
135: * @return the TclObject with the empty byte array value.
136: */
137:
138: public static TclObject newInstance() {
139: return new TclObject(new TclByteArray());
140: }
141:
142: /**
143: * Called to convert the other object's internal rep to a ByteArray.
144: *
145: * @param interp current interpreter.
146: * @param tobj the TclObject to convert to use the ByteArray internal rep.
147: * @exception TclException if the object doesn't contain a valid ByteArray.
148: */
149: static void setByteArrayFromAny(Interp interp, TclObject tobj) {
150: InternalRep rep = tobj.getInternalRep();
151:
152: if (!(rep instanceof TclByteArray)) {
153: char[] c = tobj.toString().toCharArray();
154: tobj.setInternalRep(new TclByteArray(c));
155: }
156: }
157:
158: /**
159: *
160: * This method changes the length of the byte array for this
161: * object. Once the caller has set the length of the array, it
162: * is acceptable to directly modify the bytes in the array up until
163: * Tcl_GetStringFromObj() has been called on this object.
164: *
165: * Results:
166: * The new byte array of the specified length.
167: *
168: * Side effects:
169: * Allocates enough memory for an array of bytes of the requested
170: * size. When growing the array, the old array is copied to the
171: * new array; new bytes are undefined. When shrinking, the
172: * old array is truncated to the specified length.
173: */
174:
175: public static byte[] setLength(Interp interp, TclObject tobj,
176: int length) {
177: if (tobj.isShared()) {
178: throw new TclRuntimeError(
179: "TclByteArray.setLength() called with shared object");
180: }
181: setByteArrayFromAny(interp, tobj);
182: TclByteArray tbyteArray = (TclByteArray) tobj.getInternalRep();
183:
184: if (length > tbyteArray.bytes.length) {
185: byte[] newBytes = new byte[length];
186: System.arraycopy(tbyteArray.bytes, 0, newBytes, 0,
187: tbyteArray.used);
188: tbyteArray.bytes = newBytes;
189: }
190: tobj.invalidateStringRep();
191: tbyteArray.used = length;
192: return tbyteArray.bytes;
193: }
194:
195: /**
196: * Queries the length of the byte array. If tobj is not a byte array
197: * object, an attempt will be made to convert it to a byte array.
198: *
199: * @param interp current interpreter.
200: * @param tobj the TclObject to use as a byte array.
201: * @return the length of the byte array.
202: * @exception TclException if tobj is not a valid byte array.
203: */
204: public static final int getLength(Interp interp, TclObject tobj) {
205: setByteArrayFromAny(interp, tobj);
206:
207: TclByteArray tbyteArray = (TclByteArray) tobj.getInternalRep();
208: return tbyteArray.used;
209: }
210:
211: /**
212: * Returns the bytes of a ByteArray object. If tobj is not a ByteArray
213: * object, an attempt will be made to convert it to a ByteArray. <p>
214: *
215: * @param interp the current interpreter.
216: * @param tobj the byte array object.
217: * @return a byte array.
218: * @exception TclException if tobj is not a valid ByteArray.
219: */
220: public static byte[] getBytes(Interp interp, TclObject tobj) {
221: setByteArrayFromAny(interp, tobj);
222: TclByteArray tbyteArray = (TclByteArray) tobj.getInternalRep();
223: return tbyteArray.bytes;
224: }
225: }
|