lua 编码转码url

local url={parsed={}} --存储decode出来的key-value

--private
local function escape(w)
	pattern="[^%w%d%._%-%* ]"
	s=string.gsub(w,pattern,function(c)
		local c=string.format("%%%02X",string.byte(c))
		return c
	end)
	s=string.gsub(s," ","+")
	return s
end

local function detail_escape(w)
	local t={}
	for i=1,#w do
		c = string.sub(w,i,i)
		b,e = string.find(c,"[%w%d%._%-'%* ]")
		if not b then
			t[#t+1]=string.format("%%%02X",string.byte(c))
		else
			t[#t+1]=c
		end
	end
	s = table.concat(t)
	s = string.gsub(s," ","+")
	return s
end

local function unescape(w)
	s=string.gsub(w,"+"," ")
	s,n = string.gsub(s,"%%(%x%x)",function(c)
		return string.char(tonumber(c,16))
	end)
	return s
end

---[=[
--public function
function url:new()
	local u={}    --对象
	u.old= nil    --上一次decode 字符串的值
	u.de = nil    --decode字符串后的结果值
	u.en = nil    --encode字符串后的结果值
	u.enold = nil --上一次encode 字符串的值
	u.len = 0     --记录parsed map的长度


	--设置metatable
	setmetatable(u,{__index=self})
	return u
end

function url:decode(line)
	assert(line == nil or type(line) == "string")
	if self.old == line then return print("url:decode have cache") ,self.de end
	if not line then return self.de end

	self.parsed=nil
	self.len = 0
	self.parsed={}
	for k,v in string.gmatch(line,"([^&=]+)=([^&=]+)") do
		self.len = self.len + 1
		self.parsed[k] = unescape(v)
	end

	if  self.len == 0 then return nil  end

	local r={}
	for k,v in pairs(self.parsed) do
		r[#r+1] = k.."="..v
	end
	self.de=table.concat(r,"&")
	self.old=line
	return self.de
end

function url:encode(t)
	if(type(t) == "string") then
			if t == self.enold then
				print("url:encode have cache")
				return self.en
			end

			local r={}
			for k,v in string.gmatch(t,"([^&=]+)=([^&=]+)") do
				r[#r+1] = escape(k) .."=".. escape(v)
			end
			self.en = table.concat(r,"&")
			self.enold = t
			return self.en
	elseif type(t) ~= "table" then return nil
	else
		local r = {}
		for k , v in pairs(t) do
			r[#r+1] = escape(k) .."=".. escape(v)

		end
		self.en = table.concat(r,"&")

		return self.en
	end
end

function url:parse(line)
	assert(line == nil or type(line) == "string")
	if not line then
		if self.len == 0 then return nil
		else return self.parsed end
	end
	if url:decode(line) == nil then return nil end
	return self.parsed
end

function url:get(k)
	if self.len > 0 then
		return self.parsed[k]
	else
		return nil
	end
end

--测试私有函数
test="泰囧<>2a+b=c.*!^()"
test2="tn=baiduhome_pg&ie=utf-8&bs=lua%26%3D+%E5%8C%B9%E9%85%8D%E6%B1%89%E5%AD%97&f=8&rsv_bp=1&rsv_spt=1&wd=%E6%B3%B0%E5%9B%A7%3C%3E2a%2Bb+%3D+c.*%21%5E%28%29&rsv_n=2&rsv_sug3=1&rsv_sug1=1&rsv_sug4=168&inputT=897"
---[[
io.write("test private funcitons\n")
io.write("test:",test,"\n")
io.write("结果:",escape(test),"\n")
io.write("结果:",detail_escape(test),"\n")
dec=detail_escape(test)
io.write("结果:",unescape(dec),"\n")
--]]
--测试公有函数
show = function(m)
	if not m then io.write("empty")
	elseif type(m) == "string" then
		io.write(m)
	elseif type(m) == "table" then
		for k,v in pairs(m) do
			io.write(string.format("k=%-10s  v=%s\n",k,v))
		end
	else
		io.write("unkown")
	end
	io.write("\n")
end

io.write("test public funcitons\n")
local u = url:new()
io.write("encode(test):");show(u:encode(test))
io.write("encode(test2):");show(u:encode(test2))
io.write("decode(encode(test)):");show(u:decode(u:encode(test)))
io.write("decode(test2):");show(u:decode(test2))
io.write("decode(test2):");show(u:decode(test2))
io.write("encode(test2):");show(u:encode(test2))
io.write("parse(encode(test2)):");show(u:parse(u:encode(test2)))
io.write("encode(map):"); show(u:encode({a="x + 3*10 << 1&2",b="q=queryWord!"}))
io.write("decode(encode(map):");show(u:decode(u:encode({a="x + 3*10 << 1&2",b="q=queryWord!"})))
print("decode test2:",test2);
d=u:decode(test2)
print("decode test2 ret:",d);
print("encode d:",d)
e=u:encode(d)
print("encode d ret:",e)
p=u:parse(e)
show(p)
io.write("parse:");show(u:parse(u:encode(u:decode(test2))))

io.write("get f:");show(u:get("f"))
io.write("get a  :");show(u:get("a"))
io.write("get tn :");show(u:get("tn"))
io.write("get bw :");show(u:get("bw"))
io.write("get cda:");show(u:get("cda"))

return url
--]=]

就利用string的正则匹配操作url进行编码和转换,空格转成'+',而不是%20,这主要和浏览器转一样。

做成了一个模块,可以直接用,下面看代码


你可能感兴趣的:(function,function,测试,table,url,lua,lua)