亚洲综合原千岁中文字幕_国产精品99久久久久久久vr_无码人妻aⅴ一区二区三区浪潮_成人h动漫精品一区二区三

主頁 > 知識庫 > Lua源碼中字符串類型的實現

Lua源碼中字符串類型的實現

熱門標簽:地圖標注大廈 漳州智云呼電話機器人 清朝地圖標注哈爾濱 冀州市地圖標注 新岸線智能電銷機器人 怎么去除地圖標注 百度地圖標注早餐區域 武漢外呼防封系統多少錢 個人怎么在地圖標注需要的店鋪

 概述

    Lua完全采用8位編碼,Lua字符串中的字符可以具有任何數值編碼,包括數值0。也就是說,可以將任意二進制數據存儲到一個字符串中。Lua的字符串是不可變的值(immutable values)。如果修改,實質上是新建一個字符串。根據上文《Lua中數據類型的源碼實現》中知道,在Lua中,字符串是自動內存管理機制所管理的對象,并且由聯合體TString來實現存儲字符串值的。下面將通過Lua 5.2.1的源碼來看字符串的實現以及總結了在Lua中使用字符串的注意事項。

    源碼實現

    首先來看字符串對應的數據結構TString,其源碼如下(lobject.h):

410 /* 
411 ** Header for string value; string bytes follow the end of this structure 
412 */ 
413 typedef union TString { 
414  L_Umaxalign dummy; /* ensures maximum alignment for strings */ 
415  struct { 
416   CommonHeader; 
417   lu_byte extra; /* reserved words for short strings; "has hash" for longs */ 
418   unsigned int hash; 
419   size_t len; /* number of characters in string */ 
420  } tsv; 
421 } TString; 

對這個聯合體定義,有幾點值得說明:

    I、聯合體TString中成員L_Umaxalign dummy是用來保證與最大長度的C類型進行對齊,其定義如下(llimits.h):

48 /* type to ensure maximum alignment */ 
49 #if !defined(LUAI_USER_ALIGNMENT_T) 
50 #define LUAI_USER_ALIGNMENT_T  union { double u; void *s; long l; } 
51 #endif 
52    
53 typedef LUAI_USER_ALIGNMENT_T L_Umaxalign; 

在其他可會回收的對象(比如table)的實現中,也可看到這個聯合體成員,這樣做的目的是通過內存對齊,加快CPU訪問內存的速度。

    II、聯合體中成員tsv才是真正用來實現字符串的。其中成員CommonHeader用于GC,它會以宏的形式在所有的可回收對象中定義,代碼如下(lobject.h):

74 /* 
75 ** Common Header for all collectable objects (in macro form, to be 
76 ** included in other objects) 
77 */ 
78 #define CommonHeader  GCObject *next; lu_byte tt; lu_byte marked 

這個宏對應的結構體形式如下(lobject.h):

81 /* 
82 ** Common header in struct form 
83 */ 
84 typedef struct GCheader { 
85  CommonHeader; 
86 } GCheader; 

結構體GCheader在通用的可回收對象union GCObject的定義中有用到。

 III、lu_byte extra對于短字符串,用來記錄這個字符串是否為保留字,對于長字符串,可以用于惰性求Hash值;unsigned int hash成員是字符串對應的Hash值(在后面會具體講Lua是怎么計算字符串的Hash值的);size_t len用來表示字符串的長度。

 IV、上面的結構體只是描述了一個字符串的結構,真正的字符串數據保存是緊隨在結構體后面保存。

 在Lua5.2.1之前,不區分字符串長和短的字符串,所有的字符串保存在一個全局的Hash表中,對于Lua虛擬機來說,相同的字符串只有一份數據,從Lua5.2.1開始,只是把短的字符串字符串(當前定義是長度小于等于40)放在全局Hash表中,而長字符串都是獨立生成,同時在計算Hash值時,引入一個隨機種子,這樣做的目的防止Hash Dos——攻擊者構造出非常多相同Hash值的不同字符串,從而降低Lua從外部壓入字符串進入全局的字符串Hash表的效率。下面是Lua5.2.1中,生成一個新字符串的步驟,其相應的代碼都在lstring.c中:

 (1)若字符串長度大于LUAI_MAXSHORTLEN(默認值是40),則是長字符串,直接調用創建字符串接口的函數createstrobj(當然字符串的長度需要能保存在成員size_t len中,否則直接返回),代碼如下(lstring.c):

 95 /* 
 96 ** creates a new string object 
 97 */                                                  
 98 static TString *createstrobj (lua_State *L, const char *str, size_t l,                
 99                int tag, unsigned int h, GCObject **list) {              
100  TString *ts;                                            
101  size_t totalsize; /* total size of TString object */                       
102  totalsize = sizeof(TString) + ((l + 1) * sizeof(char));                      
103  ts = luaC_newobj(L, tag, totalsize, list, 0)->ts; 
104  ts->tsv.len = l; 
105  ts->tsv.hash = h; 
106  ts->tsv.extra = 0;                                         
107  memcpy(ts+1, str, l*sizeof(char)); 
108  ((char *)(ts+1))[l] = '\0'; /* ending 0 */                            
109  return ts; 
110 }  

可以看到把傳入的字符串具體內存放在緊隨結構體TString內存后面,并且注意108行,字符串以”\0”結束與C語言字符串兼容的。

 (2)若字符串是短字符串,首先計算字符串的Hash值,找到對應的鏈表(短字符串的全局Hash表,使用的是鏈接法的方法,即把所有沖突的元素放在同一個鏈表中),查找當前要創建的字符串是否已經在Hash表中,若已經存在,則直接返回這個字符串。否則會調用函數newshrstr,而函數newshrstr會調用上面的createstrobj函數創建新字符串,并把新創建的字符串放到Hash表中,代碼如下(lstring.c)):

130 /* 
131 ** checks whether short string exists and reuses it or creates a new one 
132 */ 
133 static TString *internshrstr (lua_State *L, const char *str, size_t l) { 
134  GCObject *o; 
135  global_State *g = G(L); 
136  unsigned int h = luaS_hash(str, l, g->seed); 
137  for (o = g->strt.hash[lmod(h, g->strt.size)]; 
138    o != NULL; 
139    o = gch(o)->next) { 
140   TString *ts = rawgco2ts(o); 
141   if (h == ts->tsv.hash  
142     ts->tsv.len == l  
143     (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) { 
144    if (isdead(G(L), o)) /* string is dead (but was not collected yet)? */ 
145     changewhite(o); /* resurrect it */ 
146    return ts; 
147   } 
148  } 
149  return newshrstr(L, str, l, h); /* not found; create a new string */ 
150 } 

全局的字符串Hash表是保存在虛擬機全局狀態成員strt中的(lstate.h):

119  stringtable strt; /* hash table for strings */ 

而類型stringtable是一個結構體,其定義如下(lstate.h):

59 typedef struct stringtable {                                     
60  GCObject **hash; 
61  lu_int32 nuse; /* number of elements */ 
62  int size; 
63 } stringtable; 

其中成員GCObject **hash是一個指針數組,數組中每個成員實質指向TString(注意TString中包括宏CommonHeader,該宏中的next成員可以構造出Hash表中開散的鏈表);nuse是數組hash中已經被使用的元素個數;size是當前數組hash的大小。

在函數newshrstr插入新的字符串前,都會判斷nuse值是否大于size,若大于,表明Hash表大小不夠需要擴充,則把Hash表的大小擴充到原來的2倍,對應的代碼如下(lstring.c):

121  if (tb->nuse >= cast(lu_int32, tb->size)  tb->size = MAX_INT/2)                 
122   luaS_resize(L, tb->size*2); /* too crowded */  

在gc的時候,會判斷nuse是否比size/2還小(在Lua 5.1中是把nuse與size/4比較),如果是的話就重新resize這個stringtable的大小為原來的一半。對應的代碼如下(lgc.c):

783   int hs = g->strt.size / 2; /* half the size of the string table */               
784   if (g->strt.nuse  cast(lu_int32, hs)) /* using less than that half? */            
785    luaS_resize(L, hs); /* halve its size */ 

對于字符串比較,首先比較類型,若是不同類型字符串,則肯定不相同,然后區分短字符串和長字符串,對于短字符串,若兩者指針值相等,則相同,否則不相同;對應長字符串,則首先比較指針值,若不同,則比較長度值和內容逐字符比較。

  總結

 (1)Lua中的保留字和元方法名都是做為短字符串的,他們在虛擬機啟動的時候就已經放入到全局短的字符串Hash表,并且是不回收的。

 (2)查找字符是比較高效的,但是修改或插入字符串都是比較低效的,這里面除了計算外,至少要把外面的字符串拷貝到虛擬機中。

 (3)對應長字符串的Hash值,Lua是不會考察每個字符的,因而能避免快速計算長字符串的散列值,其相應的代碼如下(lstring.c):

51 unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) {               
52  unsigned int h = seed ^ l;                                     
53  size_t l1;                                             
54  size_t step = (l >> LUAI_HASHLIMIT) + 1;                              
55  for (l1 = l; l1 >= step; l1 -= step)                                
56   h = h ^ ((h5) + (h>>2) + cast_byte(str[l1 - 1]));                       
57  return h;                                             
58 }  
21 /*                                                 
22 ** Lua will use at most ~(2^LUAI_HASHLIMIT) bytes from a string to                 
23 ** compute its hash                                         
24 */                                                  
25 #if !defined(LUAI_HASHLIMIT)                                     
26 #define LUAI_HASHLIMIT   5                                    
27 #endif 

 (4)當有多個字符串連接時,不應該直接用字符串連接運算符”..”,而是用table.concat操作或者是string.format來加快字符串連接的操作。

 (5)Lua中字符串Hash算法用的是JSHash,關于字符串的各種Hash函數,網絡有篇文章對它進行了總結:https://www.byvoid.com/blog/string-hash-compare

以上所述誰就是本文的全部內容了,希望能對大家學習lua有所幫助。

您可能感興趣的文章:
  • Lua中使用table.concat連接大量字符串實例
  • Lua教程(五):C/C++操作Lua數組和字符串示例
  • Lua中字符串(string)淺析
  • Lua字符串庫中的幾個重點函數介紹
  • Lua函數與字符串處理簡明總結
  • 使用lua實現split字符串分隔
  • Lua中的string庫(字符串函數庫)總結
  • Lua字符串模式匹配函數小結
  • Lua字符串庫(string庫)學習筆記

標簽:金昌 天門 臺灣 儋州 宣城 德宏 天門 濰坊

巨人網絡通訊聲明:本文標題《Lua源碼中字符串類型的實現》,本文關鍵詞  Lua,源碼,中,字符串,類型,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《Lua源碼中字符串類型的實現》相關的同類信息!
  • 本頁收集關于Lua源碼中字符串類型的實現的相關信息資訊供網民參考!
  • 推薦文章
    久久国产一久久高清| 国产一区二区福利久久| 久草免费在线观看| 国产a视频精品免费观看| 精品在线观看国产| 国产原创中文字幕| 四虎影视久久久| 青草国产在线| 精品国产三级a∨在线观看| 成人免费一级毛片在线播放视频| 国产伦精品一区二区三区无广告 | 韩国毛片免费大片| 精品久久久久久中文| 尤物视频网站在线| 久草免费在线视频| 香蕉视频三级| 午夜家庭影院| 国产不卡精品一区二区三区| 国产精品1024在线永久免费| 91麻豆精品国产综合久久久| 久久国产精品只做精品| 美女免费毛片| 日韩中文字幕一区| 国产精品自拍亚洲| 国产福利免费视频| 精品国产一级毛片| 黄视频网站在线看| 欧美a免费| 黄色福利| 韩国三级香港三级日本三级| 九九精品影院| 夜夜操网| 欧美激情一区二区三区在线播放 | 99久久视频| 欧美国产日韩久久久| 黄色短视频网站| 黄色短视频网站| 国产成人欧美一区二区三区的| 精品久久久久久免费影院| 夜夜操天天爽| 青青青草影院 | 久久精品欧美一区二区| 91麻豆精品国产片在线观看| 成人影视在线观看| 99久久视频| 91麻豆爱豆果冻天美星空| 欧美激情一区二区三区在线 | 国产一区二区福利久久| 国产美女在线观看| 一级毛片视频免费| 亚洲女初尝黑人巨高清在线观看| 麻豆污视频| 韩国毛片免费大片| 国产麻豆精品| 欧美一区二区三区在线观看| 亚欧成人乱码一区二区| 国产成人啪精品| 一级女性全黄久久生活片| 亚洲精品永久一区| 四虎久久精品国产| 日韩专区第一页| 国产不卡在线观看视频| 欧美国产日韩在线| 日本在线不卡免费视频一区| 久久99中文字幕久久| 国产不卡高清在线观看视频| 国产一区二区精品| 欧美激情一区二区三区视频高清 | 精品国产三级a| 国产福利免费观看| 国产欧美精品午夜在线播放| 一级毛片视频播放| 亚洲 欧美 成人日韩| 欧美大片一区| 国产亚洲精品成人a在线| 二级片在线观看| 一级毛片视频播放| 国产韩国精品一区二区三区| 四虎影视久久| 欧美α片无限看在线观看免费| 黄色福利片| 天堂网中文字幕| 香蕉视频久久| 九九精品久久| 久久国产影视免费精品| 99久久精品国产国产毛片| 日本伦理片网站| 毛片电影网| 日日爽天天| 国产成人啪精品| 麻豆午夜视频| 青青久久网| 麻豆系列 在线视频| 九九干| 亚洲精品中文一区不卡| 国产激情一区二区三区| 麻豆午夜视频| a级黄色毛片免费播放视频| 国产网站免费观看| 国产91丝袜在线播放0| 国产视频久久久久| 国产综合91天堂亚洲国产| 国产综合成人观看在线| 黄视频网站在线看| 日本久久久久久久 97久久精品一区二区三区 狠狠色噜噜狠狠狠狠97 日日干综合 五月天婷婷在线观看高清 九色福利视频 | 欧美激情一区二区三区在线播放 | 99热精品在线| 可以免费看污视频的网站| 欧美国产日韩在线| 国产国语在线播放视频| 四虎久久精品国产| 欧美1区2区3区| 欧美激情一区二区三区在线 | 好男人天堂网 久久精品国产这里是免费 国产精品成人一区二区 男人天堂网2021 男人的天堂在线观看 丁香六月综合激情 | 日韩专区亚洲综合久久| 一级毛片视频免费| 尤物视频网站在线| 黄视频网站免费看| 91麻豆国产| 国产伦久视频免费观看 视频| 日本免费看视频| 免费一级片在线| 国产91精品露脸国语对白| 午夜家庭影院| 四虎论坛| 黄色免费三级| 一级女性全黄久久生活片| 日韩欧美一二三区| 一 级 黄 中国色 片| 99久久精品国产高清一区二区| 欧美大片a一级毛片视频| 二级特黄绝大片免费视频大片| 国产91精品系列在线观看| 国产伦理精品| 精品国产亚洲人成在线| 黄视频网站免费看| 欧美一级视频免费| 国产精品自拍在线观看| 中文字幕一区二区三区精彩视频| 二级片在线观看| 成人a级高清视频在线观看| 亚飞与亚基在线观看| 国产a毛片| 日韩免费在线观看视频| 夜夜操天天爽| 欧美a免费| 四虎影视久久久| 欧美另类videosbestsex久久| 精品国产三级a| 欧美激情一区二区三区在线| 欧美激情一区二区三区在线播放 | 日本特黄特色aaa大片免费| 国产亚洲免费观看| 久久国产影视免费精品| 日韩专区在线播放| 一级女性全黄久久生活片| 久久国产精品永久免费网站| 天天做日日爱| 香蕉视频三级| 欧美激情在线精品video| 久久成人亚洲| 免费国产在线视频| 国产精品自拍在线| 日韩免费在线观看视频| 91麻豆精品国产综合久久久| 欧美大片a一级毛片视频| 毛片高清| 欧美另类videosbestsex久久| 欧美国产日韩精品| 好男人天堂网 久久精品国产这里是免费 国产精品成人一区二区 男人天堂网2021 男人的天堂在线观看 丁香六月综合激情 | 色综合久久天天综合观看| 91麻豆精品国产片在线观看| 可以免费看污视频的网站| 成人免费高清视频| 亚飞与亚基在线观看| 国产极品白嫩美女在线观看看| 99色视频在线观看| 99久久视频| 久久久久久久男人的天堂| 精品视频免费看| 精品毛片视频| 国产a视频| 中文字幕97| 久久99中文字幕| 国产a视频| 高清一级淫片a级中文字幕| 成人高清视频在线观看| 欧美大片a一级毛片视频| 精品国产三级a| 日本特黄特黄aaaaa大片| 成人高清视频在线观看| 亚洲 欧美 成人日韩| 91麻豆精品国产综合久久久| 成人免费网站久久久| 日韩欧美一及在线播放| 国产综合91天堂亚洲国产| 精品视频在线看| 美女免费精品视频在线观看| 日韩综合| 国产高清在线精品一区a|