# HG changeset patch # User Matthew Wild # Date 1294091758 0 # Node ID de77ec2b49bc1d759dba0995750cfde52d8af760 # Parent 7a2856c8ab7a9aa87c548aa0216dd3abcdec0218 All correcthg diff util/xmppstream.lua diff -r 7a2856c8ab7a -r de77ec2b49bc util/xmllex.lua --- 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;