2009-03-29 07:30:54 +00:00
|
|
|
# This file is part of Metasm, the Ruby assembly manipulation suite
|
2010-09-09 18:19:35 +00:00
|
|
|
# Copyright (C) 2006-2009 Yoann GUILLOT
|
2009-03-29 07:30:54 +00:00
|
|
|
#
|
|
|
|
# Licence is LGPL, see LICENCE in the top-level directory
|
|
|
|
|
|
|
|
|
|
|
|
# computes the difference beetween two ruby objects
|
|
|
|
# walks accessors, arrays and hashes
|
|
|
|
|
|
|
|
def Object.diff(o1, o2)
|
2013-08-30 21:28:33 +00:00
|
|
|
if o1.class == o2.class
|
|
|
|
h = {}
|
|
|
|
case o1
|
|
|
|
when Array, Hash
|
|
|
|
if o1.kind_of? Array
|
|
|
|
keys = (0...[o1.length, o2.length].max).to_a
|
|
|
|
else
|
|
|
|
keys = o1.keys | o2.keys
|
|
|
|
end
|
|
|
|
keys.each { |k|
|
|
|
|
d = diff(o1[k], o2[k])
|
|
|
|
h["[#{k.inspect}]"] = d if not d.empty?
|
|
|
|
}
|
|
|
|
else
|
|
|
|
a = (@@diff_accessor_cache ||= {})[o1.class] ||= (im = o1.class.public_instance_methods.grep(/^[a-z]/) ; (im & im.map { |m| m + '=' }).map { |m| m.chop }.find_all { |m| o1.instance_variable_get('@'+m) })
|
|
|
|
if a.empty?
|
|
|
|
return o1 == o2 ? h : [o1, o2]
|
|
|
|
end
|
|
|
|
a.each { |k|
|
|
|
|
d = diff(o1.send(k), o2.send(k))
|
|
|
|
h['.' + k] = d if not d.empty?
|
|
|
|
}
|
|
|
|
end
|
2009-03-29 07:30:54 +00:00
|
|
|
|
2013-08-30 21:28:33 +00:00
|
|
|
# simplify tree
|
|
|
|
h.keys.each { |k|
|
|
|
|
if h[k].kind_of? Hash and h[k].length == 1
|
|
|
|
v = h.delete k
|
|
|
|
h[k + v.keys.first] = v.values.first
|
|
|
|
end
|
|
|
|
}
|
2009-03-29 07:30:54 +00:00
|
|
|
|
2013-08-30 21:28:33 +00:00
|
|
|
h
|
|
|
|
else
|
|
|
|
[o1, o2]
|
|
|
|
end
|
2009-03-29 07:30:54 +00:00
|
|
|
end
|