⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ltable.c

📁 MTK上实现虚拟机的一种有效方案
💻 C
📖 第 1 页 / 共 2 页
字号:
/*** $Id: ltable.c,v 2.32 2006/01/18 11:49:02 roberto Exp $** Lua tables (hash)** See Copyright Notice in lua.h*//*** Implementation of tables (aka arrays, objects, or hash tables).** Tables keep its elements in two parts: an array part and a hash part.** Non-negative integer keys are all candidates to be kept in the array** part. The actual size of the array is the largest `n' such that at** least half the slots between 0 and n are in use.** Hash uses a mix of chained scatter table with Brent's variation.** A main invariant of these tables is that, if an element is not** in its main position (i.e. the `original' position that its hash gives** to it), then the colliding element is in its own main position.** Hence even when the load factor reaches 100%, performance remains good.*/#include <math.h>#include <string.h>#define ltable_c#define LUA_CORE#include "lua.h"#include "ldebug.h"#include "ldo.h"#include "lgc.h"#include "lmem.h"#include "lobject.h"#include "lstate.h"#include "ltable.h"/*** max size of array part is 2^MAXBITS*/#if LUAI_BITSINT > 26#define MAXBITS		26#else#define MAXBITS		(LUAI_BITSINT-2)#endif#define MAXASIZE	(1 << MAXBITS)#define hashpow2(t,n)      (gnode(t, lmod((n), sizenode(t))))  #define hashstr(t,str)  hashpow2(t, (str)->tsv.hash)#define hashboolean(t,p)        hashpow2(t, p)/*** for some types, it is better to avoid modulus by power of 2, as** they tend to have many 2 factors.*/#define hashmod(t,n)	(gnode(t, ((n) % ((sizenode(t)-1)|1))))#define hashpointer(t,p)	hashmod(t, IntPoint(p))/*** number of ints inside a lua_Number*/#define numints		cast_int(sizeof(lua_Number)/sizeof(int))#define dummynode		(&dummynode_)static const Node dummynode_ = {  {{NULL}, LUA_TNIL},  /* value */  {{{NULL}, LUA_TNIL, NULL}}  /* key */};/*** hash for lua_Numbers*/static Node *hashnum (const Table *t, lua_Number n) {  unsigned int a[numints];  int i;  n += 1;  /* normalize number (avoid -0) */  lua_assert(sizeof(a) <= sizeof(n));  memcpy(a, &n, sizeof(a));  for (i = 1; i < numints; i++) a[0] += a[i];  return hashmod(t, a[0]);}/*** returns the `main' position of an element in a table (that is, the index** of its hash value)*/static Node *mainposition (const Table *t, const TValue *key) {  switch (ttype(key)) {    case LUA_TNUMBER:      return hashnum(t, nvalue(key));    case LUA_TSTRING:      return hashstr(t, rawtsvalue(key));    case LUA_TBOOLEAN:      return hashboolean(t, bvalue(key));    case LUA_TLIGHTUSERDATA:      return hashpointer(t, pvalue(key));    default:      return hashpointer(t, gcvalue(key));  }}/*** returns the index for `key' if `key' is an appropriate key to live in** the array part of the table, -1 otherwise.*/static int arrayindex (const TValue *key) {  if (ttisnumber(key)) {    lua_Number n = nvalue(key);    int k;    lua_number2int(k, n);    if (luai_numeq(cast_num(k), n))      return k;  }  return -1;  /* `key' did not match some condition */}/*** returns the index of a `key' for table traversals. First goes all** elements in the array part, then elements in the hash part. The** beginning of a traversal is signalled by -1.*/static int findindex (lua_State *L, Table *t, StkId key) {  int i;  if (ttisnil(key)) return -1;  /* first iteration */  i = arrayindex(key);  if (0 < i && i <= t->sizearray)  /* is `key' inside array part? */    return i-1;  /* yes; that's the index (corrected to C) */  else {    Node *n = mainposition(t, key);    do {  /* check whether `key' is somewhere in the chain */      /* key may be dead already, but it is ok to use it in `next' */      if (luaO_rawequalObj(key2tval(n), key) ||            (ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) &&             gcvalue(gkey(n)) == gcvalue(key))) {        i = cast_int(n - gnode(t, 0));  /* key index in hash table */        /* hash elements are numbered after array ones */        return i + t->sizearray;      }      else n = gnext(n);    } while (n);    luaG_runerror(L, "invalid key to " LUA_QL("next"));  /* key not found */    return 0;  /* to avoid warnings */  }}int luaH_next (lua_State *L, Table *t, StkId key) {  int i = findindex(L, t, key);  /* find original element */  for (i++; i < t->sizearray; i++) {  /* try first array part */    if (!ttisnil(&t->array[i])) {  /* a non-nil value? */      setnvalue(key, cast_num(i+1));      setobj2s(L, key+1, &t->array[i]);      return 1;    }  }  for (i -= t->sizearray; i < sizenode(t); i++) {  /* then hash part */    if (!ttisnil(gval(gnode(t, i)))) {  /* a non-nil value? */      setobj2s(L, key, key2tval(gnode(t, i)));      setobj2s(L, key+1, gval(gnode(t, i)));      return 1;    }  }  return 0;  /* no more elements */}/*** {=============================================================** Rehash** ==============================================================*/static int computesizes (int nums[], int *narray) {  int i;  int twotoi;  /* 2^i */  int a = 0;  /* number of elements smaller than 2^i */  int na = 0;  /* number of elements to go to array part */  int n = 0;  /* optimal size for array part */  for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) {    if (nums[i] > 0) {      a += nums[i];      if (a > twotoi/2) {  /* more than half elements present? */        n = twotoi;  /* optimal size (till now) */        na = a;  /* all elements smaller than n will go to array part */      }    }    if (a == *narray) break;  /* all elements already counted */  }  *narray = n;  lua_assert(*narray/2 <= na && na <= *narray);  return na;}static int countint (const TValue *key, int *nums) {  int k = arrayindex(key);  if (0 < k && k <= MAXASIZE) {  /* is `key' an appropriate array index? */    nums[ceillog2(k)]++;  /* count as such */    return 1;  }  else    return 0;}static int numusearray (const Table *t, int *nums) {  int lg;  int ttlg;  /* 2^lg */  int ause = 0;  /* summation of `nums' */  int i = 1;  /* count to traverse all array keys */  for (lg=0, ttlg=1; lg<=MAXBITS; lg++, ttlg*=2) {  /* for each slice */    int lc = 0;  /* counter */    int lim = ttlg;    if (lim > t->sizearray) {      lim = t->sizearray;  /* adjust upper limit */      if (i > lim)        break;  /* no more elements to count */    }    /* count elements in range (2^(lg-1), 2^lg] */    for (; i <= lim; i++) {      if (!ttisnil(&t->array[i-1]))        lc++;    }    nums[lg] += lc;    ause += lc;  }  return ause;}static int numusehash (const Table *t, int *nums, int *pnasize) {  int totaluse = 0;  /* total number of elements */  int ause = 0;  /* summation of `nums' */  int i = sizenode(t);  while (i--) {    Node *n = &t->node[i];    if (!ttisnil(gval(n))) {      ause += countint(key2tval(n), nums);      totaluse++;    }  }  *pnasize += ause;  return totaluse;}static void setarrayvector (lua_State *L, Table *t, int size) {  int i;  luaM_reallocvector(L, t->array, t->sizearray, size, TValue);  for (i=t->sizearray; i<size; i++)     setnilvalue(&t->array[i]);  t->sizearray = size;}static void setnodevector (lua_State *L, Table *t, int size) {  int lsize;  if (size == 0) {  /* no elements to hash part? */    t->node = cast(Node *, dummynode);  /* use common `dummynode' */    lsize = 0;  }  else {    int i;    lsize = ceillog2(size);    if (lsize > MAXBITS)      luaG_runerror(L, "table overflow");    size = twoto(lsize);    t->node = luaM_newvector(L, size, Node);    for (i=0; i<size; i++) {      Node *n = gnode(t, i);      gnext(n) = NULL;      setnilvalue(gkey(n));      setnilvalue(gval(n));    }  }  t->lsizenode = cast_byte(lsize);  t->lastfree = gnode(t, size);  /* all positions are free */}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -