Beispiel #1
0
 public LuaValue rawget(int key) {
   if (key > 0 && key <= array.length) {
     LuaValue v = m_metatable == null ? array[key - 1] : m_metatable.arrayget(array, key - 1);
     return v != null ? v : NIL;
   }
   return hashget(LuaInteger.valueOf(key));
 }
Beispiel #2
0
  /**
   * Get the next element after a particular key in the table
   *
   * @return key,value or nil
   */
  public Varargs next(LuaValue key) {
    int i = 0;
    do {
      // find current key index
      if (!key.isnil()) {
        if (key.isinttype()) {
          i = key.toint();
          if (i > 0 && i <= array.length) {
            break;
          }
        }
        if (hash.length == 0) error("invalid key to 'next'");
        i = hashSlot(key);
        boolean found = false;
        for (Slot slot = hash[i]; slot != null; slot = slot.rest()) {
          if (found) {
            StrongSlot nextEntry = slot.first();
            if (nextEntry != null) {
              return nextEntry.toVarargs();
            }
          } else if (slot.keyeq(key)) {
            found = true;
          }
        }
        if (!found) {
          error("invalid key to 'next'");
        }
        i += 1 + array.length;
      }
    } while (false);

    // check array part
    for (; i < array.length; ++i) {
      if (array[i] != null) {
        LuaValue value = m_metatable == null ? array[i] : m_metatable.arrayget(array, i);
        if (value != null) {
          return varargsOf(LuaInteger.valueOf(i + 1), value);
        }
      }
    }

    // check hash part
    for (i -= array.length; i < hash.length; ++i) {
      Slot slot = hash[i];
      while (slot != null) {
        StrongSlot first = slot.first();
        if (first != null) return first.toVarargs();
        slot = slot.rest();
      }
    }

    // nothing found, push nil, return nil.
    return NIL;
  }
Beispiel #3
0
  /*
   * newKey > 0 is next key to insert
   * newKey == 0 means number of keys not changing (__mode changed)
   * newKey < 0 next key will go in hash part
   */
  private void rehash(int newKey) {
    if (m_metatable != null && (m_metatable.useWeakKeys() || m_metatable.useWeakValues())) {
      // If this table has weak entries, hashEntries is just an upper bound.
      hashEntries = countHashKeys();
      if (m_metatable.useWeakValues()) {
        dropWeakArrayValues();
      }
    }
    int[] nums = new int[32];
    int total = countIntKeys(nums);
    if (newKey > 0) {
      total++;
      nums[log2(newKey)]++;
    }

    // Choose N such that N <= sum(nums[0..log(N)]) < 2N
    int keys = nums[0];
    int newArraySize = 0;
    for (int log = 1; log < 32; ++log) {
      keys += nums[log];
      if (total * 2 < 1 << log) {
        // Not enough integer keys.
        break;
      } else if (keys >= (1 << (log - 1))) {
        newArraySize = 1 << log;
      }
    }

    final LuaValue[] oldArray = array;
    final Slot[] oldHash = hash;
    final LuaValue[] newArray;
    final Slot[] newHash;

    // Copy existing array entries and compute number of moving entries.
    int movingToArray = 0;
    if (newKey > 0 && newKey <= newArraySize) {
      movingToArray--;
    }
    if (newArraySize != oldArray.length) {
      newArray = new LuaValue[newArraySize];
      if (newArraySize > oldArray.length) {
        for (int i = log2(oldArray.length + 1), j = log2(newArraySize) + 1; i < j; ++i) {
          movingToArray += nums[i];
        }
      } else if (oldArray.length > newArraySize) {
        for (int i = log2(newArraySize + 1), j = log2(oldArray.length) + 1; i < j; ++i) {
          movingToArray -= nums[i];
        }
      }
      System.arraycopy(oldArray, 0, newArray, 0, Math.min(oldArray.length, newArraySize));
    } else {
      newArray = array;
    }

    final int newHashSize =
        hashEntries
            - movingToArray
            + ((newKey < 0 || newKey > newArraySize) ? 1 : 0); // Make room for the new entry
    final int oldCapacity = oldHash.length;
    final int newCapacity;
    final int newHashMask;

    if (newHashSize > 0) {
      // round up to next power of 2.
      newCapacity = (newHashSize < MIN_HASH_CAPACITY) ? MIN_HASH_CAPACITY : 1 << log2(newHashSize);
      newHashMask = newCapacity - 1;
      newHash = new Slot[newCapacity];
    } else {
      newCapacity = 0;
      newHashMask = 0;
      newHash = NOBUCKETS;
    }

    // Move hash buckets
    for (int i = 0; i < oldCapacity; ++i) {
      for (Slot slot = oldHash[i]; slot != null; slot = slot.rest()) {
        int k;
        if ((k = slot.arraykey(newArraySize)) > 0) {
          StrongSlot entry = slot.first();
          if (entry != null) newArray[k - 1] = entry.value();
        } else {
          int j = slot.keyindex(newHashMask);
          newHash[j] = slot.relink(newHash[j]);
        }
      }
    }

    // Move array values into hash portion
    for (int i = newArraySize; i < oldArray.length; ) {
      LuaValue v;
      if ((v = oldArray[i++]) != null) {
        int slot = hashmod(LuaInteger.hashCode(i), newHashMask);
        Slot newEntry;
        if (m_metatable != null) {
          newEntry = m_metatable.entry(valueOf(i), v);
          if (newEntry == null) continue;
        } else {
          newEntry = defaultEntry(valueOf(i), v);
        }
        newHash[slot] = (newHash[slot] != null) ? newHash[slot].add(newEntry) : newEntry;
      }
    }

    hash = newHash;
    array = newArray;
    hashEntries -= movingToArray;
  }
Beispiel #4
0
 /**
  * Get the next element after a particular key in the contiguous array part of a table
  *
  * @return key,value or none
  */
 public Varargs inext(LuaValue key) {
   int k = key.checkint() + 1;
   LuaValue v = rawget(k);
   return v.isnil() ? NONE : varargsOf(LuaInteger.valueOf(k), v);
 }
Beispiel #5
0
 public LuaValue len() {
   return LuaInteger.valueOf(length());
 }
Beispiel #6
0
 public void rawset(int key, LuaValue value) {
   if (!arrayset(key, value)) hashset(LuaInteger.valueOf(key), value);
 }
Beispiel #7
0
 public void set(int key, LuaValue value) {
   if (m_metatable == null
       || !rawget(key).isnil()
       || !settable(this, LuaInteger.valueOf(key), value)) rawset(key, value);
 }
Beispiel #8
0
 public int keyindex(int mask) {
   return hashmod(LuaInteger.hashCode(key), mask);
 }
Beispiel #9
0
 public LuaValue mul(int lhs) {
   return LuaInteger.valueOf(lhs * (long) v);
 }
Beispiel #10
0
 public LuaValue subFrom(int lhs) {
   return LuaInteger.valueOf(lhs - (long) v);
 }
Beispiel #11
0
 public LuaValue add(int lhs) {
   return LuaInteger.valueOf(lhs + (long) v);
 }