--[[-- 带Map的数组 --By: Stephen.tao --2013/11/25 --Modified: New OBS encoding system with proper escaping ]] MEMapArray = class("MEMapArray", TFArray) function MEMapArray:ctor() self.super.ctor(self) self.map = {} end --[[-- New OBS Decode Function - Safe version with proper escaping Decodes one record at a time to avoid "too complex" error Encoding rules: 1. ~LB~ = { 2. ~RB~ = } 3. ~EQ~ = = 4. ~CM~ = , 5. ~TL~ = ~ (escape tilde itself) @param str: OBS encoded string @return nil ]] function MEMapArray:pushAllNew(str) -- Decode the OBS format with safe markers str = string.gsub(str, "~LB~", "{") str = string.gsub(str, "~RB~", "}") str = string.gsub(str, "~EQ~", "=") str = string.gsub(str, "~CM~", ",") str = string.gsub(str, "~TL~", "~") -- Split into individual records and process one by one -- Records are separated by "},{" local records = {} local current = "" local depth = 0 local in_string = false local escape_next = false for i = 1, #str do local char = string.sub(str, i, i) if escape_next then current = current .. char escape_next = false elseif char == "\\" then current = current .. char escape_next = true elseif char == '"' then in_string = not in_string current = current .. char elseif not in_string then if char == "{" then depth = depth + 1 current = current .. char elseif char == "}" then depth = depth - 1 current = current .. char if depth == 0 and #current > 0 then table.insert(records, current) current = "" end else current = current .. char end else current = current .. char end end -- Process each record for i, record in ipairs(records) do -- Trim leading comma and whitespace record = string.gsub(record, "^%s*,%s*", "") record = string.gsub(record, "^%s+", "") if #record > 0 then local func, err = loadstring("return " .. record) if not func then print("MEMapArray:pushAllNew() - loadstring error at record " .. i .. ": " .. tostring(err)) print("Record sample: " .. string.sub(record, 1, 100)) else local success, obj = pcall(func) if success and type(obj) == "table" then self:push(obj) else print("MEMapArray:pushAllNew() - execution error at record " .. i .. ": " .. tostring(obj)) end end end end end --[[-- Old OBS Decode Function - Keep for backward compatibility @param str: OBS encoded string (old format) @return nil ]] function MEMapArray:pushAll(str) str = string.gsub(string.gsub(string.gsub(str, "%-t", "{"), "%-s", "}"), "%$%-", "=") local data = loadstring("return " .. string.gsub(str, "04sb", ","))() for i=1,#data do local obj = data[i] self:push(obj) end end --[[-- Encode table array to new OBS format @param dataArray: Array of tables to encode @return string: OBS encoded string ]] function MEMapArray:encodeToOBS(dataArray) local result = {} for i, record in ipairs(dataArray) do local fields = {} -- Convert each field in the record for key, value in pairs(record) do local encodedKey = self:escapeString(tostring(key)) local encodedValue = self:escapeValue(value) table.insert(fields, encodedKey .. "~EQ~" .. encodedValue) end -- Join fields with ~CM~ and wrap with ~LB~ ~RB~ local recordStr = "~LB~" .. table.concat(fields, "~CM~") .. "~RB~" table.insert(result, recordStr) end -- Join all records with comma return table.concat(result, ",") end --[[-- Escape special characters in strings @param str: String to escape @return string: Escaped string ]] function MEMapArray:escapeString(str) -- Escape tilde first (most important) str = string.gsub(str, "~", "~TL~") return str end --[[-- Escape value based on type @param value: Value to escape @return string: Escaped value as string ]] function MEMapArray:escapeValue(value) local valueType = type(value) if valueType == "string" then -- Escape tilde in string values local escaped = string.gsub(value, "~", "~TL~") return '"' .. escaped .. '"' elseif valueType == "number" then return tostring(value) elseif valueType == "boolean" then return value and "true" or "false" elseif valueType == "table" then -- Handle nested tables (if needed) return self:encodeTable(value) else return '""' end end --[[-- Encode nested table @param tbl: Table to encode @return string: Encoded table string ]] function MEMapArray:encodeTable(tbl) local parts = {} for k, v in pairs(tbl) do local key = self:escapeString(tostring(k)) local val = self:escapeValue(v) table.insert(parts, key .. "~EQ~" .. val) end return "~LB~" .. table.concat(parts, "~CM~") .. "~RB~" end --[[-- 在数组末尾插入新的元素 @param obj: 元素 @return nil ]] function MEMapArray:push(obj) self.super.push(self, obj) if obj.id then self.map[obj.id] = obj end end --[[-- 在数组末尾插入新的元素 @param obj: 元素 @return nil ]] function MEMapArray:pushbyid(id,obj) self.super.push(self, obj) if id then self.map[id] = obj end end function MEMapArray:getMap() return self.map; end --[[-- 删除数组首元素,并返回其值 @return 首元素值 ]] function MEMapArray:popFront() local obj = self.super.popFront(self) obj = self:getTableObj(obj); return obj end --[[-- 删除数组末元素,并返回其值 @return 首元素值 ]] function MEMapArray:popBack() local obj = self.super.popBack(self) obj = self:getTableObj(obj); return obj end --[[-- 返回数组首元素 ]] function MEMapArray:front() local obj = self.super.front(self) local tbobj = self:getTableObj(obj); if tbobj ~= obj then local nIndex = self.head; self:removeObjectAt(nIndex) self:insertAt(nIndex, tbobj) end return tbobj end --[[-- 返回数组末尾元素 ]] function MEMapArray:back() local obj = self.super.back(self) local tbobj = self:getTableObj(obj); if tbobj ~= obj then local nIndex = self.tail - 1; self:removeObjectAt(nIndex) self:insertAt(nIndex, tbobj) end return tbobj end --[[-- 返回指定位置索引的元素 @param nIndex: 索引 @return 指定位置的元素 ]] function MEMapArray:getObjectAt(nIndex) local obj = self.super.getObjectAt(self,nIndex) local tbobj = self:getTableObj(obj); if tbobj ~= obj then self:removeObjectAt(nIndex) self:insertAt(nIndex, tbobj) end return tbobj end --[[-- 返回指定位置索引的元素 @param nIndex: 索引 @return 指定位置的元素 ]] function MEMapArray:objectAt(nIndex) local obj = self.super.objectAt(self,nIndex) local tbobj = self:getTableObj(obj); if tbobj ~= obj then self:removeObjectAt(nIndex) self:insertAt(nIndex, tbobj) end return tbobj end --[[-- 返回指定Key值的元素 @param id: Key值 @return 指定Key值的元素 ]] function MEMapArray:objectByID(id) if id == nil then return nil end local obj = self.map[id]; obj = self:getTableObj(obj); self.map[id] = obj return obj; end function MEMapArray:getTableObj(obj) if obj == nil then return nil end if obj and type(obj) =="string" then obj = loadstring('do return ' .. obj .. ' end')() if self.item_mt then obj.__index = self.item_mt setmetatable(obj, self.item_mt) end end return obj; end --[[-- 清空数组 ]] function MEMapArray:clear() self.super.clear(self) self.map = {} end --[[-- 删除指定元素 @param obj: 元素 ]] function MEMapArray:removeInMapList(obj) -- print("self.super = ", self.super) self:removeObject(obj) if obj then local id = obj.id self.map[id] = nil end end --[[-- 删除指定元素 @param obj: 元素 ]] function MEMapArray:removeById(id) if self.map[id] then self:removeObject(self.map[id]) self.map[id] = nil end end return MEMapArray