Jump to content

Module:User:Mr. Stradivarius/sandbox

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Mr. Stradivarius (talk | contribs) at 02:17, 15 July 2015 (copy some parts of the mw.uri library). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
local uri = {}

local function rawencode( s, space )
	space = space or '%20'
	local ret = string.gsub( s, '([^a-zA-Z0-9_.~-])', function ( c )
		if c == ' ' then
			return space
		else
			return string.format( '%%%02X', string.byte( c, 1, 1 ) )
		end
	end );
	return ret
end

local function rawdecode( s )
	local ret = string.gsub( s, '%%(%x%x)', function ( hex )
		return string.char( tonumber( hex, 16 ) )
	end );
	return ret
end

-- Lua tables are unsorted, but we want to preserve the insertion order.
-- So, track the insertion order explicitly.
local function makeQueryTable()
	local ret = {}
	local keys = {}
	local seenkeys = {}

	setmetatable( ret, {
		__newindex = function ( t, k, v )
			if seenkeys[k] and not t[k] then
				for i = 1, #keys do
					if keys[i] == k then
						table.remove( keys, i )
						break
					end
				end
			end
			seenkeys[k] = 1
			keys[#keys+1] = k
			rawset( t, k, v )
		end,
		__pairs = function ( t )
			local i, l = 0, #keys
			return function ()
				while i < l do
					i = i + 1
					local k = keys[i]
					if t[k] ~= nil then
						return k, t[k]
					end
				end
				return nil
			end
		end
	} )

	return ret
end

function uri.parseQueryString( s, i, j )
	checkType( 'parseQueryString', 1, s, 'string' )
	checkType( 'parseQueryString', 2, i, 'number', true )
	checkType( 'parseQueryString', 3, j, 'number', true )

	s = string.gsub( string.sub( s, i or 1, j or -1 ), '%+', ' ' )
	i = 1
	j = string.len( s )

	local qs = makeQueryTable()
	if string.sub( s, i, 1 ) == '?' then
		i = i + 1
	end
	while i <= j do
		local amp = string.find( s, '&', i, true )
		if not amp or amp > j then
			amp = j + 1
		end
		local eq = string.find( s, '=', i, true )
		local k, v
		if not eq or eq > amp then
			k = rawdecode( string.sub( s, i, amp - 1 ) )
			v = false
		else
			k = rawdecode( string.sub( s, i, eq - 1 ) )
			v = rawdecode( string.sub( s, eq + 1, amp - 1 ) )
		end
		if qs[k] then
			if type( qs[k] ) ~= table then
				qs[k] = { qs[k], v }
			else
				table.insert( qs[k], v )
			end
		else
			qs[k] = v
		end
		i = amp + 1
	end
	return qs
end

function uri.buildQueryString( qs )
	checkType( 'buildQueryString', 1, qs, 'table' )

	local t = {}
	for k, v in pairs( qs ) do
		if type( v ) ~= 'table' then
			v = { v }
		end
		for i = 1, #v do
			t[#t+1] = '&'
			t[#t+1] = rawencode( k, '+' )
			if v[i] then
				t[#t+1] = '='
				t[#t+1] = rawencode( v[i], '+' )
			end
		end
	end
	return table.concat( t, '', 2 )
end

return uri