# 内置库

require 加载某个模块,比如local math = require 'math'

内置模块有string, table, math, time, json, safemath,使用时不需要require

另外,非合约模式下还可以使用更多内置模块os, net, io, http, jsonrpc等

默认引入库

# os模块

os.clock() 返回执行该程序CPU花去的时钟秒数

os.date(format, time) 参数时间戳可选,如果没有给出时间用当前时间,返回格式化的字符串或table类型的时间信息

os.difftime(t2, t1) 返回时间戳t2-t1的差值

os.execute(command) 执行系统命令command

os.exit(code, close) 退出进程,code是错误码,close表示是否退出当前虚拟堆栈

os.getenv(varname) 获取环境变量

os.remove(filename) 删除文件或空文件夹

os.rename(oldname, newname) 重命名文件

os.setlocale(locale, category) 设置当前程序的时区,category可选默认值all,表示locale作用的范围

os.time(table) table表示时间信息的table,默认是当前时间的信息,返回时间戳

os.tmpname() 返回一个临时文件名称

# io模块

io.close(file) 关闭文件

io.flush() flush输出缓冲区

io.input(file) 读取模式打开文件

io.lines(filename) 读取模式打卡文件并返回遍历文件内容中各行的迭代器

io.open(filename, mode) 按指定模式打开文件,mode可选值为读取模式'r', 写入模式'w', 添加模式'a', 保留旧内容更新模式'r+', 抛弃旧内容更新模式'w+', 保留旧内容并且只能文件尾添加的更新模式'a+',默认是'r'

io.read(read_mode) 读取当前打开输入文件的内容并返回,参数read_mode可以有多个可选值,不同值的作用如下:

"*all"    读取整个文件
"*line"    读取下一行
"*number"    读取一个数字
<num>    读取一个不超过<num>个字符的字符串

io.seek(pos ?: int) 设置或获取当前打开文件的读写位置,如果提供pos参数,就是修改当前打开文件的读写位置,如果不提供pos参数,则是返回当前打开文件的读写位置

io.write(content: string) 把content的内容写入当前打开的文件

例如:

let io = require 'io';
let lines = io.lines("test/in.txt")     -- 读取文件内容,每行文本内容放入lines(table类型)
let text = table.concat(lines, ',')    
io.open("test/out.txt", "w")            -- 写入模式打开文件(然后当前的打开文件是test/out.txt)
io.write(text)                          -- 把text内容写入当前打开的文件(也就是test/out.txt)
let cur_pos = io.seek()                 -- 当前打开文件的读写位置是cur_pos
io.close()                              -- 关闭当前打开的文件

# net模块

net.listen(address, port) TCP监听address地址的port端口,监听所有地址的port端口用'0.0.0.0', 返回TcpServer对象

net.connect(address, port) 发起TCP连接

net.accept(server: TcpServer) tcp监听端阻塞等待TCP客户端连接,返回TcpSocket

net.accept_async(server: TcpServer, handler: Function) tcp异步监听TCP客户端连接,当出现新连接时,使用连接socket触发handler函数

net.start_io_loop(server: TcpServer) 启动TCP异步服务端事件循环,如果使用accept_async异步TCP服务,需要之后调用这个函数

net.read(socket, count) 从socket中读取count个字节

net.read_until(socket, end: string) 从socket读取字节流直到遇到end,返回结果包含end

net.write(socket, data) 把字节流或字符串写入socket

net.close_socket(socket) 关闭socket连接

net.close_server(server) 关闭TcpServer

net.shutdown() 关闭整个IO事件循环

例如:

let server = net.listen("127.0.0.1", 3000)
while true do
    let ctx = net.accept(server)
    let data = net.read(ctx, 10)
    pprint(data)
end

# http模块

http.listen(address: string, port: int) 监听address地址的PORT端口的HTTP请求

http.connect(address: string, port: int) 连接到HTTP服务器端(一般不需要直接用)

http.request(method: string, url: string, body: string, headers: table) 发送http请求,返回http回复

http.close(ctx) 关闭http请求上下文

http.accept(server: HttpServer) 等待http请求,返回http请求上下文ctx

http.accept_async(server: HttpServer, handler: Function) 异步监听http请求,当接收到新http请求时,使用HttpContext对象作为参数调用handler函数

http.start_io_loop(server: HttpServer) 启动http异步服务端事件循环,如果使用accept_async异步TCP服务,需要之后调用这个函数

http.get_req_header(ctx, key: string) 获取http请求中的头信息中key的值

http.get_res_header(ctx, key: string) 获取Http回复中头信息中key的值

http.get_req_http_method(ctx) 获取http请求中的HTTP方法(字符串)

http.get_req_path(ctx) 获取http请求中的path部分

http.get_req_http_protocol 获取http请求的HTTP协议(字符串)

http.get_req_body(ctx) 获取http请求中的body内容

http.set_res_header(ctx, key: string, value: string) 设置http回复中的头信息

http.write_res_body(ctx, data: string) 向http回复中追加写入数据

http.set_status(ctx, status_code: int, status_message: string) 设置http回复中的状态码和信息

http.get_status(ctx) 获取http回复的状态码

http.get_status_message(ctx) 获取http回复中的状态信息(字符串)

http.get_res_body(ctx) 获取http回复中的body内容

http.finish_res(ctx) 把http回复内容传给客户端,必须调用这个函数才会实际回复

下面给出一个最简单的阻塞式HTTP模块的使用例子(注意这只是阻塞式API的代码例子,不建议直接使用):

let http = require 'http'
let net = require 'net'

let res = http.request('GET', "http://www.gov.cn/", '', {
    Accept="text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
    ["User-Agent"]="Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36"
})
pprint(http.get_res_header(res, "Content-Length"))
pprint(http.get_res_body(res))
http.close(res)

let server = http.listen("0.0.0.0", 3000)

pprint("listening on 0.0.0.0:3000\n")

-- async api

let function handler(ctx)
    let net = require 'net'
    pprint("got new connection", ctx)
    -- pprint('get req body', http.get_req_body(ctx), '\n')
    net.write(ctx, "HTTP/1.1 200 OK\r\nContent-Type:text/html; utf-8\r\nContent-Length:5\r\n\r\nhello")
    net.close_socket(ctx)
end

net.accept_async(server, handler)
net.start_io_loop(server)

pprint("starting sync http server")

while true do
    let ctx = http.accept(server)
    pprint('get req body', http.get_req_body(ctx), '\n')
    http.write_res_body(ctx, "hello world")
    http.set_status(ctx, 200, 'OK')
    http.set_res_header(ctx, "Content-Type", "text/html; utf-8")
    http.finish_res(ctx)
    http.close(ctx)
end

全局变量表

# 一些合约相关的API