private static Object dereferenceArrayDims( Interp interp, // Current // interpreter. Object arrayObj, // Array to dereference. Must be an array. int numDerefDims, // Number of dimensions to dereference. TclObject indexListObj) // Index to dereference in each dim. throws TclException // May encounter bad array index or // dereference a null array value. { // Before derefencing any dimensions, check that the indexList isn't too // large--we want to return an array. int numDims = JavaInfoCmd.getNumDimsFromClass(arrayObj.getClass()); if (numDims < numDerefDims) { throw new TclException( interp, "bad indexList \"" + indexListObj.toString() + "\": javaObj only has " + numDims + " dimension(s)"); } Object subArrayObj = arrayObj; for (int dim = 0; dim < numDerefDims - 1; dim++) { int index = TclInteger.getInt(interp, TclList.index(interp, indexListObj, dim)); try { subArrayObj = Array.get(subArrayObj, index); } catch (ArrayIndexOutOfBoundsException e) { int max = Array.getLength(subArrayObj) - 1; throw new TclException( interp, "array index \"" + index + "\" is out of bounds: must be between 0 and " + max); } if (subArrayObj == null) { throw new TclException( interp, "null value in dimension " + dim + ": can't dereference " + numDims + " dimensions"); } } return subArrayObj; }
public void cmdProc( Interp interp, // Current interpreter. TclObject argv[]) // Argument list. throws TclException // If wrong number of args, a // standard Tcl exception; // If an exception is encountered // during the invokation of the method, // the Exception object will be stored // in the errorCode of the interp. { boolean convert; int optionIdx, numArgs; Object subArrayObj; Class subArrayClass; int option, index, numDims, count; TclObject indexListObj; if (argv.length < 2) { throw new TclNumArgsException(interp, 1, argv, "?-noconvert? option ?arg arg ...?"); } String arg1 = argv[1].toString(); if ((arg1.length() >= 2) && (NOCONVERT.startsWith(arg1))) { // numArgs is the number of optional arguments after the // sub-command. convert = false; optionIdx = 2; numArgs = argv.length - 3; } else { convert = true; optionIdx = 1; numArgs = argv.length - 2; } if (numArgs < 0) { throw new TclNumArgsException(interp, 1, argv, "?-noconvert? option ?arg arg ...?"); } // If the <option> argument to the array object command is one of the // array sub-commands, then proceed to the switch statement below. // Otherwise, the array object behaves as a reflect object by calling // ReflectObject.cmdProc, and <option> will be treated as a method // of the array object. // // We can be sure that there is no conflect between the array // sub-commands and the method of the array object. This is // because the array object is an instance of java.lang.Object, // which has only the following methods (as of JDK 1.1): getClass, // hashCode, equals, wait, toString, notify, notifyAll try { option = TclIndex.get(interp, argv[optionIdx], validCmds, "option", TCL.EXACT); } catch (TclException e) { try { int startIdx = optionIdx + 1; FuncSig.get( interp, javaClass, argv[optionIdx], argv, startIdx, argv.length - startIdx, false); } catch (TclException e1) { throw new TclException( interp, "bad option \"" + argv[optionIdx] + "\": must be length, get, getrange, " + "set, setrange, or a valid method signature"); } super.cmdProc(interp, argv); return; } switch (option) { case OPT_LENGTH: if (numArgs != 0) { throw new TclNumArgsException(interp, optionIdx + 1, argv, ""); } if (convert == false) { throw new TclException( interp, "-noconvert flag not allowed for the \"length\" sub-command"); } interp.setResult(Array.getLength(javaObj)); return; case OPT_GET: if (numArgs != 1) { throw new TclNumArgsException(interp, optionIdx + 1, argv, "indexList"); } indexListObj = argv[optionIdx + 1]; numDims = TclList.getLength(interp, indexListObj); if (numDims == 0) { subArrayObj = javaObj; subArrayClass = dereferenceClassDims(interp, javaClass, 1); index = 0; } else { // Dereference all but the last dimension specified. Set // the interpreter result to the index'th element of the // "subArrayObj". subArrayObj = dereferenceArrayDims(interp, javaObj, numDims, indexListObj); subArrayClass = dereferenceClassDims(interp, javaClass, numDims); index = TclInteger.getInt(interp, TclList.index(interp, indexListObj, numDims - 1)); } // Set the interpreter result to a TclObject containing the index'th // element of "subArrayObj". interp.setResult(getArrayElt(interp, subArrayObj, subArrayClass, index, convert)); return; case OPT_SET: if (numArgs != 2) { throw new TclNumArgsException(interp, optionIdx + 1, argv, "indexList value"); } if (convert == false) { throw new TclException(interp, "-noconvert flag not allowed for the \"set\" sub-command"); } indexListObj = argv[optionIdx + 1]; numDims = TclList.getLength(interp, indexListObj); if (numDims == 0) { subArrayObj = javaObj; subArrayClass = dereferenceClassDims(interp, javaClass, 1); index = 0; } else { // Dereference all but the last dimension specified. Set // the value of index'th element of the "subArrayObj" to // the value in argv[optionIdx + 2]. subArrayObj = dereferenceArrayDims(interp, javaObj, numDims, indexListObj); subArrayClass = dereferenceClassDims(interp, javaClass, numDims); index = TclInteger.getInt(interp, TclList.index(interp, indexListObj, numDims - 1)); } // Set the value of the index'th element of "subArrayObj" to the // value // in the TclObject argv[optionIdx + 2]. setArrayElt(interp, subArrayObj, subArrayClass, index, argv[optionIdx + 2]); interp.resetResult(); return; case OPT_GETRANGE: if (numArgs > 2) { throw new TclNumArgsException(interp, optionIdx + 1, argv, "?indexList ?count??"); } // If an index list is specified, dereference all but the last // dimension specified. If the index list is empty, getrange // behaves as an identity function and returns argv[0]. subArrayObj = javaObj; subArrayClass = dereferenceClassDims(interp, javaClass, 1); index = 0; if (numArgs > 0) { indexListObj = argv[optionIdx + 1]; numDims = TclList.getLength(interp, indexListObj); if (numDims > 0) { subArrayObj = dereferenceArrayDims(interp, javaObj, numDims, indexListObj); subArrayClass = dereferenceClassDims(interp, javaClass, numDims); index = TclInteger.getInt(interp, TclList.index(interp, indexListObj, numDims - 1)); } } // The variable "count" represents the number of elements to // return. The default is the array size less the first index // (the remaining elements of the array). If a count is // specified and is smaller than the default, the default is // overridden. count = Array.getLength(subArrayObj) - index; if (numArgs > 1) { count = Math.min(count, TclInteger.getInt(interp, argv[optionIdx + 2])); } // Set the interpreter result to a TclList containing "count" // elements // of the "subArrayObj", starting with the index'th element. interp.setResult(getArrayElts(interp, subArrayObj, subArrayClass, index, count, convert)); return; case OPT_SETRANGE: if ((numArgs < 1) || (numArgs > 3)) { throw new TclNumArgsException( interp, optionIdx + 1, argv, "?indexList ?count?? valueList"); } if (convert == false) { throw new TclException( interp, "-noconvert flag not allowed for the \"setrange\" sub-command"); } TclObject tclValueListObj = argv[argv.length - 1]; // If an index list is specified, dereference all but the last // dimension specified. If the index list is empty, setrange // initialized the array object as it would in the java::new // command. subArrayObj = javaObj; subArrayClass = dereferenceClassDims(interp, javaClass, 1); index = 0; if (numArgs > 1) { indexListObj = argv[optionIdx + 1]; numDims = TclList.getLength(interp, indexListObj); if (numDims > 0) { subArrayObj = dereferenceArrayDims(interp, javaObj, numDims, indexListObj); subArrayClass = dereferenceClassDims(interp, javaClass, numDims); index = TclInteger.getInt(interp, TclList.index(interp, indexListObj, numDims - 1)); } } // "count" represents the number of elements to set. The // default is the minimum of the valueList size and array size // less the first index (the remaining elements of the array). // If a count is specified and is smaller than the default, // the default is overridden. count = Math.min( TclList.getLength(interp, tclValueListObj), Array.getLength(subArrayObj) - index); if (numArgs > 2) { count = Math.min(count, TclInteger.getInt(interp, argv[optionIdx + 2])); } // Set the value of "count" elements of the "subArrayObj", starting // with the index'th element, to the values in tclValueListObj. setArrayElts(interp, subArrayObj, subArrayClass, index, count, tclValueListObj); interp.resetResult(); return; } }
static Object initArray( Interp interp, // Current interpreter. TclObject sizeListObj, // List of dimension sizes. int sizeListLen, // Size of sizeListObj. int dim, // Current dimension. int numDims, // Number of dimensions to allocate. Class cls, // Type of Array. TclObject valueListObj) // List to populate the Array. throws TclException // May encounter TclList elt of wrong // type in sizeListObj or valueListObj. { Class compCls = cls.getComponentType(); int valueListLen = 0; if (valueListObj != null) { valueListLen = TclList.getLength(interp, valueListObj); } // Set arrayLength to be the dim'th dimension size in sizeListObj. If // sizeListObj doesn't contain dim elts, the array length is the length // of valueListObj. // // Initialize the "arrayObj" to size "arrayLength". int arrayLength; if (dim < sizeListLen) { arrayLength = TclInteger.getInt(interp, TclList.index(interp, sizeListObj, dim)); } else { arrayLength = valueListLen; } if ((arrayLength == 0) && (dim < (numDims - 1))) { throw new TclException( interp, "cannot initialize a " + numDims + " dimensional array with zero size in dimension " + dim); } Object arrayObj; try { arrayObj = Array.newInstance(compCls, arrayLength); } catch (NegativeArraySizeException ex) { throw new TclException(interp, "negative array size " + arrayLength); } if (compCls.isArray()) { // Initialize each subArray "i" according to the dim+1'st elt in // sizeListObj and i'th elt in valueListObj. int nextDim = dim + 1; for (int i = 0; i < arrayLength; i++) { TclObject subValueListObj = null; if (i < valueListLen) { subValueListObj = TclList.index(interp, valueListObj, i); } Object subArrayObj = initArray(interp, sizeListObj, sizeListLen, nextDim, numDims, compCls, subValueListObj); Array.set(arrayObj, i, subArrayObj); } } else if (valueListLen > 0) { // Set the value of "count" elements of the "subArrayObj", starting // with the 0'th element, to the values in valueListObj. int count = Math.min(arrayLength, valueListLen); setArrayElts(interp, arrayObj, compCls, 0, count, valueListObj); } return arrayObj; }