ArrayCmd.java :  » Scripting » jacl » tcl » lang » Java Open Source

Java Open Source » Scripting » jacl 
jacl » tcl » lang » ArrayCmd.java
/*
 * ArrayCmd.java
 *
 * Copyright (c) 1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and
 * redistribution of this file, and for a DISCLAIMER OF ALL
 * WARRANTIES.
 * 
 * RCS: @(#) $Id: ArrayCmd.java,v 1.7 2006/05/23 05:34:33 mdejong Exp $
 *
 */

package tcl.lang;
import java.util.*;

/**
 * This class implements the built-in "array" command in Tcl.
 */

class ArrayCmd implements Command {
    static Class procClass = null;

    static final private String validCmds[] = {
  "anymore",
  "donesearch",
  "exists",
  "get",
  "names",
  "nextelement",
  "set",
  "size",
  "startsearch",
  "unset"
    };

    static final int OPT_ANYMORE   = 0;
    static final int OPT_DONESEARCH   = 1;
    static final int OPT_EXISTS   = 2;
    static final int OPT_GET     = 3;
    static final int OPT_NAMES     = 4;
    static final int OPT_NEXTELEMENT   = 5;
    static final int OPT_SET     = 6;
    static final int OPT_SIZE     = 7;
    static final int OPT_STARTSEARCH   = 8;
    static final int OPT_UNSET     = 9;

    /**
     * This procedure is invoked to process the "array" Tcl command.
     * See the user documentation for details on what it does.
     */

    public void cmdProc(Interp interp, TclObject[] objv)
            throws TclException {
  Var var = null, array = null;
  boolean notArray = false;
  String varName, msg;
  int index, result;

  if (objv.length < 3) {
      throw new TclNumArgsException(interp, 1, objv, 
        "option arrayName ?arg ...?");
  }

  index = TclIndex.get(interp, objv[1], validCmds, "option", 0);

  // Locate the array variable (and it better be an array).
  
  varName = objv[2].toString();
  Var[] retArray = Var.lookupVar(interp, varName, null, 0,
               null, false, false);

  // Assign the values returned in the array
  if (retArray != null) {
      var = retArray[0];
      array = retArray[1];
  }

  if ((var == null) || !var.isVarArray() ||
      var.isVarUndefined()) {
      notArray = true;
  }

  // Special array trace used to keep the env array in sync for
  // array names, array get, etc.

  if (var != null && var.traces != null) {
      msg = Var.callTraces(interp, array, var, varName, null,
        (TCL.LEAVE_ERR_MSG|TCL.NAMESPACE_ONLY|TCL.GLOBAL_ONLY|
         TCL.TRACE_ARRAY));
      if (msg != null) {
    throw new TclVarException(interp, varName, null,
            "trace array", msg);
      }
  }

  switch (index) {
      case OPT_ANYMORE: {
          if (objv.length != 4) {
        throw new TclNumArgsException(interp, 2, objv, 
                "arrayName searchId");
          }
          if (notArray) {
              errorNotArray(interp, objv[2].toString());
          }

          if (var.sidVec == null) {
              errorIllegalSearchId(interp, objv[2].toString(),
                            objv[3].toString());
          }

          Iterator iter = var.getSearch(objv[3].toString());
          if (iter == null) {
              errorIllegalSearchId(interp, objv[2].toString(),
                            objv[3].toString());
          }

          if (iter.hasNext()) {
              interp.setResult(true);
          } else {
              interp.setResult(false);
          }
    break;
      }
      case OPT_DONESEARCH: {

          if (objv.length != 4) {
        throw new TclNumArgsException(interp, 2, objv, 
                "arrayName searchId");
          }
          if (notArray) {
              errorNotArray(interp, objv[2].toString());
          }

    boolean rmOK = true;
          if (var.sidVec != null) {
      rmOK = (var.removeSearch(objv[3].toString()));
    }
    if ((var.sidVec == null) || !rmOK) {
              errorIllegalSearchId(interp, objv[2].toString(),
                            objv[3].toString());
    }
    break;
      }
      case OPT_EXISTS: {

                if (objv.length != 3) {
        throw new TclNumArgsException(interp, 2, objv, 
                "arrayName");
          }
          interp.setResult(!notArray);
    break;
      }
      case OPT_GET: {
    // Due to the differences in the hashtable implementation 
    // from the Tcl core and Java, the output will be rearranged.
    // This is not a negative side effect, however, test results 
    // will differ.

          if ((objv.length != 3) && (objv.length != 4) ) {
        throw new TclNumArgsException(interp, 2, objv, 
                "arrayName ?pattern?");
          }
    if (notArray) {
              return;
          }

          String pattern = null;
          if (objv.length == 4) {
              pattern = objv[3].toString();
          }

    HashMap table = var.arraymap;
          TclObject tobj = TclList.newInstance();
          String arrayName = objv[2].toString();
          String key, strValue;
    Var var2;

    // Go through each key in the hash table.  If there is a 
    // pattern, test for a match.  Each valid key and its value 
    // is written into sbuf, which is returned.

    // FIXME : do we need to port over the 8.1 code for this loop?

    for (Iterator iter = table.entrySet().iterator(); iter.hasNext() ;) {
               Map.Entry entry = (Map.Entry) iter.next();
               key = (String) entry.getKey();
               var2 = (Var) entry.getValue();
        if (var2.isVarUndefined()) {
      continue;
        }

        if (pattern != null && !Util.stringMatch(key, pattern)) {
      continue;
        }

        strValue = interp.getVar(arrayName, key, 0).toString();
        
        TclList.append(interp, tobj, 
           TclString.newInstance(key));
        TclList.append(interp, tobj, 
           TclString.newInstance(strValue));
    }
    interp.setResult(tobj);
    break;
      }
      case OPT_NAMES: {

          if ((objv.length != 3) && (objv.length != 4)) {
        throw new TclNumArgsException(interp, 2, objv, 
                "arrayName ?pattern?");
          }
          if (notArray) {
              return;
          }

          String pattern = null;
          if (objv.length == 4) {
              pattern = objv[3].toString();
          }

    HashMap table = var.arraymap;
          TclObject tobj = TclList.newInstance();
          String key;

    // Go through each key in the hash table.  If there is a 
    // pattern, test for a match. Each valid key and its value 
    // is written into sbuf, which is returned.

    for (Iterator iter = table.entrySet().iterator(); iter.hasNext() ;) {
        Map.Entry entry = (Map.Entry) iter.next();
               key = (String) entry.getKey();
               Var elem = (Var) entry.getValue();
        if (! elem.isVarUndefined()) {
      if (pattern != null) {
          if (!Util.stringMatch(key, pattern)) {
        continue;
          }
      }
      TclList.append(interp, tobj,
        TclString.newInstance(key));
        }
    }
    interp.setResult(tobj);
    break;
      }
      case OPT_NEXTELEMENT: {

                if (objv.length != 4) {
        throw new TclNumArgsException(interp, 2, objv, 
                "arrayName searchId");
          }
          if (notArray) {
              errorNotArray(interp, objv[2].toString());
          }

          if (var.sidVec == null) {
              errorIllegalSearchId(interp, objv[2].toString(),
                            objv[3].toString());
          }

          Iterator iter = var.getSearch(objv[3].toString());
          if (iter == null) {
              errorIllegalSearchId(interp, objv[2].toString(),
                            objv[3].toString());
          }
          if (iter.hasNext()) {
        Map.Entry entry = (Map.Entry) iter.next();
               String key = (String) entry.getKey();
        Var elem = (Var) entry.getValue();

        if (!elem.isVarUndefined()) {
            interp.setResult(key);
        } else {
            interp.setResult("");
        }
    }
    break;
      }
      case OPT_SET: {

                if (objv.length != 4) {
        throw new TclNumArgsException(interp, 2, objv, 
                "arrayName list");
          }
          int size = TclList.getLength(interp, objv[3]);
          if ( size%2 != 0 ) {
              throw new TclException(interp, 
                            "list must have an even number of elements");
          }
      
    int i;
    String name1 = objv[2].toString();
    String name2, strValue;

    // Set each of the array variable names in the interp

    for ( i=0; i<size; i++) {
        name2 = TclList.index(interp, objv[3], i++).toString();
              strValue = TclList.index(interp, objv[3], i).toString();
        interp.setVar(name1, name2, 
                            TclString.newInstance(strValue), 0); 
          }
    break;
      }
      case OPT_SIZE: {

          if (objv.length != 3) {
        throw new TclNumArgsException(interp, 2, objv, 
                "arrayName");
          }
          if (notArray) {
        interp.setResult(0);
          } else {
        HashMap table = var.arraymap;
        int size = 0;

        for (Iterator iter = table.entrySet().iterator();
                            iter.hasNext() ;) {
            Map.Entry entry = (Map.Entry) iter.next();
            String key = (String) entry.getKey();
            Var elem = (Var) entry.getValue();
      if (!elem.isVarUndefined()) {
          size++;
      }
                    }
              interp.setResult(size);
          }
    break;
      }
      case OPT_STARTSEARCH: {

                if (objv.length != 3) {
        throw new TclNumArgsException(interp, 2, objv, 
                "arrayName");
          }
          if (notArray) {
              errorNotArray(interp, objv[2].toString());
          }
      
    if (var.sidVec == null) {
              var.sidVec = new ArrayList();
    }

    // Create a SearchId Object:
    // To create a new SearchId object, a unique string
    // identifier needs to be composed and we need to
    // create an Iterator of the array keys.  The
    // unique string identifier is created from three
    // strings:
    //
    //     "s-"   is the default prefix
    //     "i"    is a unique number that is 1+ the greatest
    //        SearchId index currently on the ArrayVar.
    //     "name" is the name of the array
    //
    // Once the SearchId string is created we construct a
    // new SearchId object using the string and the
    // Iterator.  From now on the string is used to
    // uniquely identify the SearchId object.

    int i = var.getNextIndex();
    String s = "s-" + i  + "-" + objv[2].toString();
    HashMap table = var.arraymap;
    Iterator iter = table.entrySet().iterator();
    var.sidVec.add(new SearchId(iter,s,i));
    interp.setResult(s);
    break;
      }
      case OPT_UNSET: {
          String pattern;
          String name;

          if ((objv.length != 3) && (objv.length != 4)) {
        throw new TclNumArgsException(interp, 2, objv, 
                "arrayName ?pattern?");
          }
          if (notArray) {
              errorNotArray(interp, objv[2].toString());
          }
          if (objv.length == 3) {
              // When no pattern is given, just unset the whole array

              interp.unsetVar(objv[2], 0);
          } else {
              pattern = objv[3].toString();
              HashMap table = var.arraymap;

              for (Iterator iter = table.entrySet().iterator();
                      iter.hasNext() ;) {
                  Map.Entry entry = (Map.Entry) iter.next();
                  name = (String) entry.getKey();
                  Var elem = (Var) entry.getValue();
      if (elem.isVarUndefined()) {
          continue;
      }
      if (Util.stringMatch(name, pattern)) {
          interp.unsetVar(varName, name, 0);
          // Reset iterator in case unset
          // modified the table.
          iter = table.entrySet().iterator();
      }
              }
          }
    break;
      }
  }
    }

    /**
     * Error meassage thrown when an invalid identifier is used
     * to access an array.
     *
     * @param interp currrent interpreter.
     * @param String var is the string representation of the 
     *     variable that was passed in.
     */

    private static void errorNotArray(Interp interp, String var)
            throws TclException {
        throw new TclException(interp, "\"" + var + "\" isn't an array");
    }


    /**
     * Error message thrown when an invalid SearchId is used.  The 
     * string used to reference the SearchId is parced to determine
     * the reason for the failure. 
     * 
     * @param interp currrent interpreter.
     * @param String sid is the string represenation of the 
     *     SearchId that was passed in.
     */

    static void errorIllegalSearchId(Interp interp, String varName, 
      String sid) throws TclException {  

       int val = validSearchId(sid.toCharArray(), varName);

       if (val == 1) {
     throw new TclException(interp, "couldn't find search \"" +
        sid + "\"");
       } else if (val == 0) {
     throw new TclException(interp, "illegal search identifier \"" +
        sid + "\"");
       } else {
     throw new TclException(interp, "search identifier \"" + sid +
                    "\" isn't for variable \"" + varName +"\"");
       }
    }

    /**
     * A valid SearchId is represented by the format s-#-arrayName.  If
     * the SearchId string does not match this format than it is illegal,
     * else we cannot find it.  This method is used by the 
     * ErrorIllegalSearchId method to determine the type of error message.
     *
     * @param char pattern[] is the string use dto identify the SearchId
     * @return 1 if its a valid searchID; 0 if it is not a valid searchId, 
     * but it is for the array, -1 if it is not a valid searchId and NOT 
     * for the array.
     */

    private static int validSearchId(char pattern[], String varName) {
        int i;

        if ((pattern[0] != 's') || (pattern[1] != '-') || 
          (pattern[2]<'0') || (pattern[2]>'9')) {
      return 0;
  }
      for (i = 3; ( i < pattern.length && pattern[i] != '-'); i++) {
    if(pattern[i]<'0' || pattern[i]>'9') {
      return 0;
    }
  }
  if (++i >= pattern.length) {
      return 0;
  }
  if ( varName.equals(new String(pattern, i, (pattern.length-i)))) {
      return 1;
  } else {
      return -1;

  }
    }
}

java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.