Lua解析plist成Lua tabel

来源:互联网 发布:soho程序员兼职平台 编辑:程序博客网 时间:2024/06/05 15:59
local plistParser = {}


function plistParser.nextTag(s, i)
    return string.find(s, "<(%/?)([%w:]+)(%/?)>", i)
end


function plistParser.array(s, i)
    local arr, nextTag, array, dictionary = {}, plistParser.nextTag, plistParser.array, plistParser.dictionary
    local ni, j, c, label, empty


    while true do
        ni, j, c, label, empty = nextTag(s, i)
        assert(ni)


        if c == "" then
            if empty == "/" then
                if label == "dict" or label == "array" then
                    arr[#arr+1] = {}
                else
                    arr[#arr+1] = (label == "true") and true or false
                end
            elseif label == "array" then
                arr[#arr+1], i, j = array(s, j+1)
            elseif label == "dict" then
                arr[#arr+1], i, j = dictionary(s, j+1)
            else
                i = j + 1
                ni, j, c, label, empty = nextTag(s, i)


                local val = string.sub(s, i, ni-1)
                if label == "integer" or label == "real" then
                    arr[#arr+1] = tonumber(val)
                else
                    arr[#arr+1] = val
                end
            end
        elseif c == "/" then
            assert(label == "array")
            return arr, j+1, j
        end


        i = j + 1
    end
end


function plistParser.dictionary(s, i)
    local dict, nextTag, array, dictionary = {}, plistParser.nextTag, plistParser.array, plistParser.dictionary
    local ni, j, c, label, empty


    while true do
        ni, j, c, label, empty = nextTag(s, i)
        assert(ni)


        if c == "" then
            if label == "key" then
                i = j + 1
                ni, j, c, label, empty = nextTag(s, i)
                assert(c == "/" and label == "key")


                local key = string.sub(s, i, ni-1)


                i = j + 1
                ni, j, c, label, empty = nextTag(s, i)


                if empty == "/" then
                    if label == "dict" or label == "array" then
                        dict[key] = {}
                    else
                        dict[key] = (label == "true") and true or false
                    end
                else
                    if label == "dict" then
                        local dictData = nil;
                        dictData, i, j = dictionary(s, j+1)
                        local position = string.find(key,"New item");
                        if position then
                            table.insert(dict,dictData);
                            dump(dictData);
                        else
                            dict[key] = dictData;
                        end
                    elseif label == "array" then
                        dict[key], i, j = array(s, j+1)
                    else
                        i = j + 1
                        ni, j, c, label, empty = nextTag(s, i)


                        local val = string.sub(s, i, ni-1)
                        if label == "integer" or label == "real" then
                            dict[key] = tonumber(val)
                        else 
                            local position = string.find(key,"New item");
                            if position then
                                table.insert(dict,val);
                            else
                                dict[key] = val
                            end
                        end
                    end
                end
            end
        elseif c == "/" then
            assert(label == "dict")
            return dict, j+1, j
        end
    
        i = j + 1
    end
end


function plistParse(s)
    local i, ni, tag, version, empty = 0
    local label = 0;
    while label ~= "plist" do
        ni, i, label, version = string.find(s, "<([%w:]+)(.-)>", i+1)
        assert(ni)
    end
    
    ni, i, _, label, empty = plistParser.nextTag(s, i)


    if empty == "/" then
        return {}
    elseif label == "dict" then
        return plistParser.dictionary(s, i+1)
    elseif label == "array" then
        return plistParser.array(s, i+1)
    end
end
0 0
原创粉丝点击