lzio.c
主要有 3 个方法:
LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data)
LUAI_FUNC size_t luaZ_read (ZIO* z, void *b, size_t n)
LUAI_FUNC int luaZ_fill (ZIO *z)
luaZ_init(lzio.c#38)
luaZ_init 主要初始化一个 ZIO
结构体,而这个结构体从参数里面传进来。
LuaZ_init 只在 lapi.c
里的 lua_load
方法内被调用;而 lua_load
方法我暂时看到是在 lauxlib.c
里的 luaL_loadfilex
方法和 luaL_loadbufferx
方法中调用。这两个的不同在于,前者是在执行 lua xxx.lua
的时候调用读入一个文件;后者是在执行 lua -e stat
的时候读入这个字符串
很明显 luaL_loadfilex
和 luaL_loadbufferx
两个方法用不同的参数去调用 lua_load
。一个是 getF
作为 lua_Reader reader
,LoadF lf
作为 void *data
;另一个是 getS
作为 lua_Reader reader
,LoadS ls
作为 void *data
。它们的分别定义是这样的:
这样,我们就可以看出来 lua_load
通过传入的参数调用 luaZ_init
,设置 ZIO z
的 L
, reader
(就是不同的 getF
和 getS
), data
(就是不同的 LoadF lf
和 LoadS ls
), n
(0), p
(NULL)。
luaZ_fill(lzio.c#23)
这个方法主要通过 zgetc
这个宏被外界调用。
zgetc
这儿宏会判断 Zio z
的 n
减一能否大于 0,也就是是否还有未处理的字符,如果有的话,就返回这个字符,并把 p
加一,否则的话,就执行 luaZ_fill(z)
,根据我们之前说到的 luaZ_init
,我们知道 n
是一开始就是 0 的,所以需要调用 luaZ_fill
。一开始我并不明白为什么这个方法叫 fill,我现在觉得是因为这个方法的职责就是把 reader 读到的数据装到 Zio z
里面,可以看到 buff = z->reader(L, z->data, &size);
这句将读到的数据记录到 buff 里面,最后设置 Zio z
的 n
为 size - 1
,p
为 buff
这个指针,最后会自增一,返回当前的第一个字符。
我不清楚大家会不会好奇在什么时候读入了数据,我是好奇的。对于执行命令 lua -e stat
的时候,字符串直接就在 argv 里面了;对于 lua -e xxx.lua
这样的命令,在 getF
里面调用了 fread
来读入文件的内容。
luaZ_read(lzio.c#48)
这个方法会在执行 lua xxx.out
的时候被调用,其中 xxx.out
文件是通过 luac
生成的字节文件。这个方法通过调用 luaZ_fill(z)
来读入内容,不过在外面加入了循环来读入 n 个数据。