《lua设计与实现》第3章 字符串

3.1 概述

    字符串在Lua中是不可变的数据。每当使用不存在的字符串时,就会创建一份新的数据,创建之后是不可更改的。

3.2 字符串实现

 

//luaconf.h:595
// 用于8字节对齐
#define LUAI_USER_ALIGNMENT_T    union { double u; void *s; long l; }

//limits.h:47
// 用于8字节对齐typedef LUAI_USER_ALIGNMENT_T L_Umaxalign;

//lobject.h:199
typedef union TString {
  L_Umaxalign dummy;  /* ensures maximum alignment for strings */
  struct {
    CommonHeader;
    lu_byte reserved;  //1:系统保留,不会在GC阶段回收
    unsigned int hash;
    size_t len;
  } tsv;
} TString;


//lstate.h:68
typedef struct global_State {
  stringtable strt;  /* hash table for strings */
  //......
} global_State;

//lstate.h:38
typedef struct stringtable {
  GCObject **hash; //哈希桶,每个槽又是一个GCObject *,数据TString使用链式存储
  lu_int32 nuse;   /* number of elements */
  int size;
} stringtable;

//为了避免数据(TString)量太大导致查找退化成线性操作,需要重新散列:
//lstring.c:22
void luaS_resize (lua_State *L, int newsize) {
  GCObject **newhash;
  stringtable *tb;
  int i;
  if (G(L)->gcstate == GCSsweepstring)
    return;  /* cannot resize during GC traverse */
  newhash = luaM_newvector(L, newsize, GCObject *);
  tb = &G(L)->strt;
  for (i=0; i<newsize; i++) newhash[i] = NULL;
  /* rehash 重新散列*/
  for (i=0; i<tb->size; i++) {
    GCObject *p = tb->hash[i];
    while (p) {  /* for each node in the list */
      GCObject *next = p->gch.next;  /* save next */
      unsigned int h = gco2ts(p)->hash;
      int h1 = lmod(h, newsize);  /* new position */
      lua_assert(cast_int(h%newsize) == lmod(h, newsize));
      p->gch.next = newhash[h1];  /* chain it */
      newhash[h1] = p;
      p = next;
    }
  }
  luaM_freearray(L, tb->hash, tb->size, TString *); //释放旧的散列桶
  tb->size = newsize;
  tb->hash = newhash;
}

 

上一篇:6款PC脑图工具,你pick哪一款呢


下一篇:iOS LeetCode ☞ 猜数字大小