Lua1.0 程式碼分析 hash.c

來源:互聯網
上載者:User

標籤:io   ar   for   資料   cti   代碼   sp   amp   on   

hash.c 程式碼分析

Lua 中最重要的一個資料結構及相關操作。

主要看下幾個對外的介面。

/*** Create a new hash. Return the hash pointer or NULL on error.*/Hash *lua_hashcreate (unsigned int nhash){ Hash *t = new (Hash); if (t == NULL) {  lua_error ("not enough memory");  return NULL; } nhash(t) = nhash; markarray(t) = 0; nodelist(t) = newvector (nhash, Node*); if (nodelist(t) == NULL) {  lua_error ("not enough memory");  return NULL; } return t;}

建立一個關聯陣列,入參是關聯陣列的大小。
建立一個關聯陣列。
設定大小。
打標記。
建立指標數組。

void lua_hashdelete (Hash *h);
釋放關聯陣列。


/*** If the hash node is present, return its pointer, otherwise create a new** node for the given reference and also return its pointer.** On error, return NULL.*/Object *lua_hashdefine (Hash *t, Object *ref){ int h; Node *n; h = head (t, ref); if (h < 0) return NULL; n = present(t, ref, h); if (n == NULL) {  n = new(Node);  if (n == NULL)  {   lua_error ("not enough memory");   return NULL;  }  n->ref = *ref;  tag(&n->val) = T_NIL;  n->next = list(t,h); /* link node to head of list */  list(t,h) = n; } return (&n->val);}

在關聯陣列中查看指定項是否存在,如果存在,返回它的指標。
如果不存在,建立一個結點,也同樣返回它的指標。
返回關聯引用在關聯陣列中的頭。
跟據關聯陣列的頭,查看引用在關聯陣列中是否存在:
如果不存在,建立一個結點,設定其引用為傳入的參數,同時設定其值為空白,把建立的結點插入到表頭。
如果存在,直接返回它的值。

來看看 head 和 present 的實現:

static int head (Hash *t, Object *ref) /* hash function */{ if (tag(ref) == T_NUMBER) return (((int)nvalue(ref))%nhash(t)); else if (tag(ref) == T_STRING) {  int h;  char *name = svalue(ref);  for (h=0; *name!=0; name++) /* interpret name as binary number */  {   h <<= 8;   h += (unsigned char) *name; /* avoid sign extension */   h %= nhash(t); /* make it a valid index */  }  return h; } else {  lua_reportbug ("unexpected type to index table");  return -1; }}

關聯陣列分為兩個部分,數值部分和引用部分。
數值部分的下標是通過數值的大小和關聯陣列的大小取餘得到的。
而引用部分目前只支援字串類型。
字串部分是通過一個演算法得到它的散列值的。
具體演算法是把字串的 ASCII 碼左移 8 位後相加之和與關聯陣列的大小取餘。

再看 present 的實現

static Node *present(Hash *t, Object *ref, int h){ Node *n=NULL, *p; if (tag(ref) == T_NUMBER) {  for (p=NULL,n=list(t,h); n!=NULL; p=n, n=n->next)   if (ref_tag(n) == T_NUMBER && nvalue(ref) == ref_nvalue(n)) break; } else if (tag(ref) == T_STRING) {  for (p=NULL,n=list(t,h); n!=NULL; p=n, n=n->next)   if (ref_tag(n) == T_STRING && streq(svalue(ref),ref_svalue(n))) break; } if (n==NULL) /* name not present */  return NULL;#if 0 if (p!=NULL) /* name present but not first */ {  p->next=n->next; /* move-to-front self-organization */  n->next=list(t,h);  list(t,h)=n; }#endif return n;}

通過數組和下標找到相應的鏈表,在鏈表中尋找是否有指定的值。如果有,返回結點,如果沒有,返回空。

void lua_hashmark (Hash *h)
標記關聯陣列中所有的結點。

再看看 lua_next 的實現

void lua_next (void){ Hash *a; Object *o = lua_getparam (1); Object *r = lua_getparam (2); if (o == NULL || r == NULL) { lua_error ("too few arguments to function `next‘"); return; } if (lua_getparam (3) != NULL) { lua_error ("too many arguments to function `next‘"); return; } if (tag(o) != T_ARRAY) { lua_error ("first argument of function `next‘ is not a table"); return; } a = avalue(o); if (tag(r) == T_NIL) {  firstnode (a, 0);  return; } else {  int h = head (a, r);  if (h >= 0)  {   Node *n = list(a,h);   while (n)   {    if (memcmp(&n->ref,r,sizeof(Object)) == 0)    {     if (n->next == NULL)     {      firstnode (a, h+1);      return;     }     else if (tag(&n->next->val) != T_NIL)     {      lua_pushobject (&n->next->ref);      lua_pushobject (&n->next->val);      return;     }     else     {      Node *next = n->next->next;      while (next != NULL && tag(&next->val) == T_NIL) next = next->next;      if (next == NULL)      {       firstnode (a, h+1);       return;      }      else      {       lua_pushobject (&next->ref);       lua_pushobject (&next->val);      }      return;     }    }    n = n->next;   }   if (n == NULL)    lua_error ("error in function ‘next‘: reference not found");  } }}

在 Lua 指令碼中調用 next 時調用的就是它。作用是數組遍曆。
給定一個數組和引用,返回數組中給定引用的下一個結點。
如果給的是一個空值,返回數組的頭一個結點。
否則返回數組中該值的下一個非空結點。
這裡返回了兩個值到 Lua 的指令碼中。
看下內建的一個用到它的測試程式(array.lua):

a = @()i=0while i<10 do a[i] = i*i i=i+1endr,v = next(a,nil)while r ~= nil do print ("array["..r.."] = "..v) r,v = next(a,r)end

這個程式會列印出以下:
array[0] = 0
array[1] = 1
array[2] = 4
array[3] = 9
array[4] = 16
array[5] = 25
array[6] = 36
array[7] = 49
array[8] = 64
array[9] = 81

Lua1.0 程式碼分析 hash.c

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.