lua处理PHP序列化过后的数据为table

代码来自互联网,稍有修改:

-- unserialize.lua
-- author:(from internet)

--[[
  @file
  Lua port of PHP serialization functions.
  
  Port based on PHPSerialize and PHPUnserialize by Scott Hurring
  http://hurring.com/scott/code/python/serialize/v0.4
  
  @version v0.1 BETA
  @author Fernando P. García; fernando at develcuy dot com
  @copyright Copyright (c) 2009 Fernando P. García
  @license http://opensource.org/licenses/gpl-license.php GNU Public License
  
  $Id$
]]
local _serialize_key, _read_chars, _read_until, _unknown_type

function _serialize_key(data)
  --[[
  Serialize a key, which follows different rules than when 
  serializing values.  Many thanks to Todd DeLuca for pointing 
  out that keys are serialized differently than values!
  
  From http://us2.php.net/manual/en/language.types.array.php
  A key may be either an integer or a string. 
  If a key is the standard representation of an integer, it will be
  interpreted as such (i.e. "8" will be interpreted as int 8,
  while "08" will be interpreted as "08"). 
  Floats in key are truncated to integer. 
  ]]
  -- Integer, Long, Float
  if type(data) == 'number' then
    return 'i:' .. tonumber(data) .. ';'
  -- Boolean => integer
  elseif type(data) == 'boolean' then
    if data then
      return 'i:1;'
    else
      return 'i:0;'
    end
  -- String => string or String => int (if string looks like int)
  elseif type(data) == 'string' then
    if tonumber(data) == nil then
      return 's:' .. string.len(data) .. ':"' .. data .. '";'
    else
      return 'i:' .. tonumber(data) .. ';'
    end
  
  -- None / NULL => empty string
  elseif type(data) == 'nil' then
    return 's:0:"";'
  
  -- I dont know how to serialize this
  else
    error('Unknown / Unhandled key  type (' .. type(data) .. ')!')
  end
end

function serialize(data)
  --[[
  Serialize a value.
  ]]
  local i, out, key, value
  -- Numbers
  if type(data) == 'number' then
    -- Integer => integer
    if  math.floor(data) == data then
      return 'i:' .. data .. ';'
    -- Float, Long => double
    else
      return 'd:' .. data .. ';'
    end
  -- String => string or String => int (if string looks like int)
  -- Thanks to Todd DeLuca for noticing that PHP strings that
  -- look like integers are serialized as ints by PHP 
  elseif type(data) == 'string' then
    if tonumber(data) == nil then
      return 's:' .. string.len(data) .. ':"' .. data .. '";'
    else
      return 'i:' .. tonumber(data) .. ';'
    end
  -- Nil / NULL
  elseif type(data) == 'nil' then
    return 'N;'
  -- Tuple and List => array
  -- The 'a' array type is the only kind of list supported by PHP.
  -- array keys are automagically numbered up from 0
  elseif type(data) == 'table' then
    i = 0
    out = {}
    -- All arrays must have keys
    for key, value in pairs(data) do
      table.insert(out, _serialize_key(key))
      table.insert(out, serialize(value))
      i = i + 1
    end
    return 'a:' .. i .. ':{' .. table.concat(out) .. '}'
  -- Boolean => bool
  elseif type(data) == 'boolean' then
    if data then
      return 'b:1;'
    else
      return 'b:0;'
    end
  --~ TODO:
  --~ -- Table + Functions => stdClass
  --~ elseif type(data) == 'function' then
  --~ # I dont know how to serialize this
  else
   error('Unknown / Unhandled data type (' .. type(data) .. ')!')
  end
end

function _read_until(data, offset, stopchar)
  --[[
  Read from data[offset] until you encounter some char 'stopchar'.
  ]]
  local buf = {}
  local char = string.sub(data, offset + 1, offset + 1)
  local i = 2
  while not (char == stopchar) do
    -- Consumed all the characters and havent found ';'
    if i + offset > string.len(data) then
      error('Invalid')
    end
    table.insert(buf, char)
    char = string.sub(data, offset + i, offset + i)
    i = i + 1
  end
  -- (chars_read, data)
  return i - 2, table.concat(buf)
end

function _read_chars(data, offset, length)
  --[[
  Read 'length' number of chars from data[offset].
  ]]
  local buf = {}, char
  -- Account for the starting quote char
  -- offset += 1
  for i = 0, length -1 do
    char = string.sub(data, offset + i, offset + i)
    table.insert(buf, char)
  end
  -- (chars_read, data)
  return length, table.concat(buf)
end

function unserialize(data, offset)
  offset = offset or 0
  --[[
  Find the next token and unserialize it.
  Recurse on array.
  offset = raw offset from start of data
  --]]
  local buf, dtype, dataoffset, typeconvert, datalength, chars, readdata, i,
         key, value, keys, properties, otchars, otype, property
  buf = {}
  dtype = string.lower(string.sub(data, offset + 1, offset + 1))
  -- 't:' = 2 chars
  dataoffset = offset + 2
  typeconvert = function(x) return x end
  datalength = 0
  chars = datalength 
  -- int or double => Number
  if dtype == 'i' or dtype == 'd' then
    typeconvert = function(x) return tonumber(x) end
    chars, readdata = _read_until(data, dataoffset, ';')
    -- +1 for end semicolon
    dataoffset = dataoffset + chars + 1
  -- bool => Boolean
  elseif dtype == 'b' then
    typeconvert = function(x) return tonumber(x) == 1 end
    chars, readdata = _read_until(data, dataoffset, ';')
    -- +1 for end semicolon
    dataoffset = dataoffset + chars + 1
  -- n => None
  elseif dtype == 'n' then
    readdata = nil
  -- s => String
  elseif dtype == 's' then
    chars, stringlength = _read_until(data, dataoffset, ':')
    -- +2 for colons around length field
    dataoffset = dataoffset + chars + 2
    -- +1 for start quote
    chars, readdata = _read_chars(data, dataoffset + 1, tonumber(stringlength))
    -- +2 for endquote semicolon
    dataoffset = dataoffset + chars + 2
    --[[
    TODO
    review original: if chars != int(stringlength) != int(readdata):
    ]]
    if not (chars == tonumber(stringlength)) then
      error('String length mismatch')
    end
  -- array => Table
  -- If you originally serialized a Tuple or List, it will
  -- be unserialized as a Dict.  PHP doesn't have tuples or lists,
  -- only arrays - so everything has to get converted into an array
  -- when serializing and the original type of the array is lost
  elseif dtype == 'a' then
    readdata = {}
    -- How many keys does this list have?
    chars, keys = _read_until(data, dataoffset, ':')
    -- +2 for colons around length field
    dataoffset = dataoffset + chars + 2
    -- Loop through and fetch this number of key/value pairs
    for i = 0, tonumber(keys) - 1 do
      -- Read the key
      key, ktype, kchars = unserialize(data, dataoffset)
      dataoffset = dataoffset + kchars
      -- Read value of the key
      value, vtype, vchars = unserialize(data, dataoffset)
      -- Cound ending bracket of nested array
      if vtype == 'a' then
        vchars = vchars + 1
      end
      dataoffset = dataoffset + vchars
      -- Set the list element
      readdata[key] = value
    end
  -- object => Table
  elseif dtype == 'o' then
    readdata = {}
    -- How log is the type of this object?
    chars, otchars = _read_until(data, dataoffset, ':')
    dataoffset = dataoffset + chars + 2
    -- Which type is this object?
    otype = string.sub(data, dataoffset + 1, dataoffset + otchars)
    dataoffset = dataoffset + otchars + 2
    if otype == 'stdClass' then
      -- How many properties does this list have?
      chars, properties = _read_until(data, dataoffset, ':')
      -- +2 for colons around length field
      dataoffset = dataoffset + chars + 2
      -- Loop through and fetch this number of key/value pairs
      for i = 0, tonumber(properties) - 1 do
        -- Read the key
        property, ktype, kchars = unserialize(data, dataoffset)
        dataoffset = dataoffset + kchars
        -- Read value of the key
        value, vtype, vchars = unserialize(data, dataoffset)
        -- Cound ending bracket of nested array
        if vtype == 'a' then
          vchars = vchars + 1
        end
        dataoffset = dataoffset + vchars
        -- Set the list element
        readdata[property] = value
      end
    else
      _unknown_type(dtype)
    end
  else
    _unknown_type(dtype)
  end
  --~ return (dtype, dataoffset-offset, typeconvert(readdata))
  return typeconvert(readdata), dtype, dataoffset - offset
end
-- I don't know how to unserialize this

function _unknown_type(type_)
  error('Unknown / Unhandled data type (' .. type_ .. ')!', 2)
end



-- test-demo

local seriailzestr  = 'a:5:{s:7:"fdsafdf";i:54;s:6:"fdsafd";s:6:"fdsfdf";s:3:"fff";i:888;i:0;s:7:"fdsafdf";i:1;i:5454;}'
local sertab  = unserialize(seriailzestr)

for k,v in pairs(sertab) do
	print(k,v)
end



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值