All correcthg diff util/xmppstream.lua

Mon, 03 Jan 2011 21:55:58 +0000

author
Matthew Wild <mwild1@gmail.com>
date
Mon, 03 Jan 2011 21:55:58 +0000
changeset 3992
de77ec2b49bc
parent 3991
7a2856c8ab7a
child 3994
b3dffb6bc1aa

All correcthg diff util/xmppstream.lua

util/xmllex.lua file | annotate | diff | comparison | revisions
--- a/util/xmllex.lua	Mon Jan 03 18:31:08 2011 +0000
+++ b/util/xmllex.lua	Mon Jan 03 21:55:58 2011 +0000
@@ -1,15 +1,16 @@
-local ipairs , pairs , setmetatable = ipairs , pairs , setmetatable
+local assert, ipairs , pairs , setmetatable , rawget , rawset , tostring =
+	assert, ipairs , pairs , setmetatable , rawget , rawset , tostring
 local strsub = string.sub
 local tblconcat = table.concat
 local tblinsert = table.insert
 
-local function getstring ( stringindex , startmsg , startpos , finishmsg , finishpos )
-	if startmsg == finishmsg then --All originated in same string
-		return strsub ( stringindex [ startmsg ] , startpos , finishpos )
+local function getstring ( msgs , startpos , finishpos )
+	if #msgs == 1 then --All originated in same string
+		return strsub ( msgs[1] , startpos , finishpos )
 	else -- Over multiple source strings
-		return strsub ( stringindex [ startmsg ] , startpos , -1 )
-			.. tblconcat ( stringindex , "" , startmsg + 1 , finishmsg - 1 )
-			.. strsub ( stringindex [ finishmsg ] , 1 , finishpos )
+		return strsub ( msgs[1] , startpos , -1 )
+			.. tblconcat ( msgs , "" , 2 , #msgs - 1 )
+			.. strsub ( msgs[#msgs] , 1 , finishpos )
 	end
 end
 
@@ -19,74 +20,96 @@
 		if str then
 			return str
 		else
-			str = getstring ( v.stringindex , v.startmsg , v.start , v.finishmsg , v.finish )
-			rawset ( v , "stringform" , str )
+			str = getstring ( v.msgs , v.start , v.finish )
+			v.stringform = str
 			return str
 		end
 	end
 }
 
-local function index ( str , r )
-	local stringindex
-	local curstr , nexti
-	if r then
-		stringindex = r.stringindex or { }
-		curstr = #stringindex + 1
-		stringindex [ curstr ] = str
-		
-		nexti = #r
-	else
-		stringindex = { str }
-		curstr = 1
-		
-		r = { stringindex = stringindex }
-		
-		nexti = 0
+local function handleoutside ( str , r , initial )
+	local a , b , close = str:find ( "<(/?)" , initial )
+	if not a then
+		r.state = "outside"
+		return false
 	end
 	
-	local m
-	do
-		local t = r [ nexti ]
-		if t and not t.finish then
-			m = t
-		else
-			m = setmetatable ( { stringindex = stringindex } , m_mt )
-			nexti = nexti + 1
-		end
+	--Finalise text object
+	local m = r[#r]
+	m.finish = a - 1
+	m.type = "text"
+	
+	local m = setmetatable ( {
+		msgs = { str } ;
+		start = a ;
+		starte = b + 1 ;
+	} , m_mt )
+	
+	if close ~= "/" then
+		r.depth = r.depth + 1
+		m.type = "open"
+	else
+		r.depth = r.depth - 1
+		m.type = "close"
+	end
+	
+	tblinsert ( r , m )
+
+	r.state = "inside"
+	return true
+end
+
+local function handleinside ( str, r , initial )
+	local c , d , selfclosing = str:find ( "(/?)>" , initial )
+	if not c then
+		r.state = "inside"
+		return false
 	end
 	
-	local d = 0
-	while true do
-		local a , b , c , close , selfclosing
+	local m = r[#r]
+	m.finish = d
+	m.finishs = c - 1
+	if selfclosing == "/" then
+		m.type = "selfclosing"
+		r.depth = r.depth - 1
+	end
+
+	local m = setmetatable ( {
+		msgs = { str } ;
+		start = d + 1 ;
+		type = "text" ;
+	} , m_mt )
+	tblinsert ( r , m )
+	
+	r.state = "outside"
+	return true
+end
 
-		if not m.start then
-			a , b , close = str:find ( "<(/?)" , d )
-			
-			if not a then break end
-			m.startmsg = curstr
-			m.start = a
-			m.starte = b
-			if close == "/" then
-				m.closed = true
-			else
-				m.closed = false
+local function index ( str , r )
+	r = r or { depth = 0, state = "outside" }
+	
+	if not r[#r] then
+		r[1] = setmetatable ( {
+			msgs = { str } ;
+			type = "text" ;
+			start = 1 ;
+		} , m_mt )
+	else
+		tblinsert ( r[#r].msgs , str )
+	end
+	
+	repeat
+		if r.state == "outside" then
+			if not handleoutside ( str , r , r[#r].start ) then
+				break
+			end
+		else
+			if not handleinside ( str , r , r[#r].start ) then
+				break
 			end
 		end
-		
-		r [ nexti ] = m
-		nexti = nexti + 1
-		
-		c , d , selfclosing = str:find ( "(/?)>" , b )
-		if not c then
-			return false , r
-		end
-		m.finishmsg = curstr
-		m.finish = d
-		m.finishs = c
-		m.selfclosed = selfclosing == "/"
-		
-		m = setmetatable ( { stringindex = stringindex } , m_mt )
-	end
+	until false
+
 	return r
 end
 
@@ -109,13 +132,14 @@
 			rawset ( t , "attr" , attr )
 			return rawget ( t , k )
 		else
+			print("METHOD",k)
 			return stanza_methods [ k ]
 		end
 	end ;
 	__tostring = function ( t )
 		local opentag = t.opentag
 		local endtag = assert ( rawget ( t , "endtag" ) or rawget ( t , "selfclosing" ) and t.opentag )
-		return getstring ( opentag.stringindex , opentag.startmsg , opentag.start , endtag.finishmsg , endtag.finish )
+		return getstring ( opentag.msgs , opentag.start , endtag.finish )
 	end ;
 }
 
@@ -123,49 +147,35 @@
 	return setmetatable ( { tags = { } } , stanza_mt )
 end
 
-local function add_inbetween ( stringindex , leaf , last_finishmsg , last_finish , new_startmsg , new_start )
-	if last_finishmsg ~= new_startmsg and last_finish + 1 ~= new_start - 1 then -- Don't bother with obviously zero length strings
-		tblinsert ( leaf , setmetatable ( { 
-			stringindex = stringindex ;
-			startmsg = last_finishmsg ; start = last_finish + 1 ;
-			finishmsg = new_startmsg ; finish = new_start - 1 ; 
-			} , m_mt ) )
-	end
-end
-
 local function tagindex_to_tree(indices)
 	local root = { tags = { } }
 	local leaf = root
-	local stringindex = indices.stringindex
-	
-	local last_finishmsg , last_finish = 1 , 1
 	
 	for k ,v in ipairs ( indices ) do
-		add_inbetween ( stringindex , leaf , last_finishmsg , last_finish , v.startmsg , v.start )
-		last_finishmsg = v.finishmsg
-		last_finish = v.finish
-		
-		if v.selfclosed then
+		if v.type == "selfclosing" then
 			local newleaf = new_stanza ( )
 			newleaf.opentag = v
 			newleaf.selfclosing = true
 			newleaf.parent = leaf
+			
 			tblinsert ( leaf , newleaf )
 			tblinsert ( leaf.tags , newleaf )
-		elseif v.closed then -- Close tag
+		elseif v.type == "close" then -- Close tag
 			leaf.endtag = v
 			leaf = leaf.parent
+		elseif v.type == "text" then
+			tblinsert ( leaf, v )
 		else -- Open tag
 			local newleaf = new_stanza ( )
 			newleaf.opentag = v
 			newleaf.parent = leaf
+			
 			tblinsert ( leaf , newleaf )
 			tblinsert ( leaf.tags , newleaf )
 			
 			leaf = newleaf
 		end
 	end
-	add_inbetween ( stringindex , leaf , last_finishmsg , last_finish , #stringindex , -1 )
 	
 	assert ( leaf == root , "Mismatched opening/closing tags" )
 	return root;

mercurial