--- Update existing CE structure with with new offset / fields from a Mono class
-- Allows you to update structure offsets wtihout losing changes to existing fields
-- like structure pointers and local structures
-- @param idx_struct: integer index of CE Structure you want updated
-- @param className: string containing the mono class you want to take fields from
-- @param doDelete: Optional bool, deletes struct entries that don't correspond to current class fields
-- @param verbose: Optional integer; >0 prints info on structure changes, >1 prints all actions
-- @return true if structure was changed, false if not
function updateStructFromMonoClass( idx_struct, className, doDelete, verbose )
if not idx_struct or not className then error('ERROR updateStructFromMonoClass: arguments malformed or missing!') end
if idx_struct + 1 > getStructureCount() then error('ERROR updateStructFromMonoClass: structure index out of bounds!') end
local classId = mono_findClass('', className)
if not classId then error('ERROR updateStructFromMonoClass: no class ID found for given class name!') end
verbose = type(verbose) == 'number' and verbose or 0
local ver1 = verbose > 0 and true or false
local ver2 = verbose > 1 and true or false
local changed = false
local st = getStructure(idx_struct)
local st_name = st.getName()
if ver1 then print( string.format('== Updating structure %s with mono class %s ==',st_name, className) ) end
local st_count = st.Count
local st_entry = {}
for i = 1, st_count do st_entry[i] = st.getElement(i-1) end
local st2 = monoform_exportStructInternal(createStructure(''), classId, true --[[recursive]], false --[[not static]], {'some struct map thing'}, false --[[not global]])
local st2_count = st2.Count
local st2_entry = {}
for i = 1, st2_count do st2_entry[i] = st2.getElement(i-1) end
local st2_tName = {}
local st2_tOffset = {}
for i = 1, st2_count do st2_tName[ st2_entry[i].Name ] = st2_entry[i].Offset end
for i = 1, st2_count do st2_tOffset[ st2_entry[i].Offset ] = st2_entry[i].Name end
-- simple offset adjust for existing fields
st.beginUpdate()
for i = 1, st_count do
local ename = st_entry[i].Name
if st2_tName[ename] then
local newoff = st2_tName[ename]
if st_entry[i].Offset ~= newoff then
if ver1 then print( string.format('Updated offset of %s from %X to %X',ename,st_entry[i].Offset,newoff) ) end
st_entry[i].Offset = newoff
changed = true
else
if ver2 then print( string.format('Offset of %s unchanged from %X',ename,newoff) ) end
end
elseif doDelete then
if ver1 then print( string.format( 'Entry %s not found, removed from structure', ename ) ) end
st_entry[i].destroy()
else
if ver1 then print( string.format( 'Entry %s not found in new field list', ename ) ) end
end
end
st.endUpdate()
if st.Count ~= st_count then -- refresh if struct changed
if ver2 then print('> Structure size changed, updating tables') end
st_entry = {}
st_count = st.Count
for i = 1, st_count do st_entry[i] = st.getElement(i-1) end
changed = true
end
local st_tName = {}
for i = 1, st_count do st_tName[ st_entry[i].Name ] = st_entry[i].Offset end
st.beginUpdate()
for _,v in ipairs(st2_entry) do
if not st_tName[v.Name] then -- check if new entry is in old struct
if ver1 then print( string.format('Field %s not found, adding as new entry',v.Name) ) end
local e = st.addElement()
e.setName( v.getName() )
e.setOffset( v.getOffset() )
e.setVartype( v.getVartype() )
e.setBytesize( v.getBytesize() )
changed = true
end
end
st.endUpdate()
return changed
end
--- Bonus function to update all structures at once.
-- @param doDelete: Optional bool, deletes struct entries that don't correspond to current class fields
-- @param verbose: Optional integer; >0 prints info on structure changes, >1 prints all actions
function updateAllMonoStructs( doDelete, verbose )
verbose = type(verbose) == 'number' and verbose or 0
local numStructs = getStructureCount()
local numMonos = 0
local numChanged = 0
for i=0, numStructs-1 do
repeat -- workaround to continue for loop on break
local stName = getStructure(i).Name
local classId = mono_findClass('', stName)
if not classId or stName == 'String' then break end
numMonos = numMonos + 1
local changed = updateStructFromMonoClass(i, stName, doDelete, verbose)
if changed then
numChanged = numChanged + 1
if verbose > 0 then print(string.format('CHANGED: %s\n',stName)) end
else
if verbose > 0 then print(string.format('UNCHANGED: %s\n',stName)) end
end
until true
end
if verbose > 0 then print('Number of Mono Structures found:', numMonos) end
if verbose > 0 then print('Number of Structures updated:', numChanged) end
end
Comments