Gradually adding support for all features

This commit is contained in:
Pavel Shevaev 2022-12-07 15:32:29 +03:00
parent 8eeeefb7d9
commit f38eed25f3
3 changed files with 182 additions and 10 deletions

View File

@ -122,6 +122,12 @@ function _add_twig_support(\Twig\Environment $twig)
return is_primary_field($o, $f);
}
));
$twig->addFunction(new \Twig\TwigFunction('get_diff_class_units',
function($meta, $o)
{
return get_diff_class_units($meta, $o);
}
));
}
function cs_type(\mtgType $type)
@ -434,3 +440,7 @@ function is_nullable_type(\mtgType $type)
($type instanceof \mtgMetaStruct && !$type->hasToken('POD'));
}
function get_diff_class_units(\mtgMetaInfo $meta, \mtgMetaStruct $struct)
{
return [];
}

View File

@ -4,9 +4,9 @@ using metagen;
{%- import "macro.twig" as macro -%}
{#{% if namespace is defined ~%}
{% if namespace is defined ~%}
namespace {{namespace}} {
{% endif %}#}
{% endif %}
{{ macro.decl_units(meta) }}
@ -61,6 +61,6 @@ static public class AutogenBundle
}
}
{#{% if namespace is defined ~%}
{% if namespace is defined ~%}
} //namespace {{namespace}}
{% endif %}#}
{% endif %}

View File

@ -3,17 +3,17 @@
{%- for u in meta.getunits ~%}
{%- if u.object is instanceof('\\mtgMetaStruct') -%}
{{ _self.decl_struct(u.object) }}
{{ _self.decl_struct(meta, u.object) }}
{%- elseif u.object is instanceof('\\mtgMetaEnum') -%}
{{ _self.decl_enum(u.object) }}
{%- elseif u.object is instanceof('\\mtgMetaRPC') -%}
{{ _self.decl_rpc(u.object) }}
{{ _self.decl_rpc(meta, u.object) }}
{%- endif ~%}
{%- endfor ~%}
{% endmacro %}
{% macro decl_struct(o, extra = '') %}
{% macro decl_struct(meta, o, extra = '') %}
{%- if o.parent and has_token(o, 'POD') -%}
{{Error("@POD structs can't have a parent: " ~ o.name)}}
{%- endif -%}
@ -100,6 +100,17 @@ public {{_self.struct_type(o)}} {{o.name}} {{_self.base_struct_class(o)}}
{{_self.get_itype(o)}}
{%- endif -%}
{%- if has_token(o, 'id') ~%}
public ulong getPrimaryId()
{
return (ulong){{token(o, 'id')}};
}
{%- endif -%}
{%- if has_token(o, 'diffable') ~%}
{{_self.diffable_support(meta, o)}}
{%- endif -%}
{{extra}}
}
@ -282,10 +293,10 @@ public enum {{o.name}}
}
{% endmacro %}
{% macro decl_rpc(o) %}
{% macro decl_rpc(meta, o) %}
{{_self.decl_struct(o.req)}}
{{_self.decl_struct(o.rsp)}}
{{_self.decl_struct(meta, o.req)}}
{{_self.decl_struct(meta, o.rsp)}}
public class {{o.name}} : IRpc
{
@ -320,3 +331,154 @@ public class {{o.name}} : IRpc
}
{% endmacro %}
{%- macro diffable_support(meta, o) -%}
{% for u in get_diff_class_units(meta, o) %}
{{_self.diff_methods(u)}}
{% endfor %}
static public List<ulong> GetClassRemovedIds(List<DataClassIds> removed_ids, uint class_id)
{
if(removed_ids == null)
return null;
DataClassIds res;
if(!FindClassRemovedIds(removed_ids, class_id, out res))
{
res = new DataClassIds();
res.class_id = class_id;
res.ids = new List<ulong>();
removed_ids.Add(res);
}
return res.ids;
}
static bool FindClassRemovedIds(List<DataClassIds> removed_ids, uint class_id, out DataClassIds res)
{
for(int i=0;i<removed_ids.Count;++i)
{
if(removed_ids[i].class_id == class_id)
{
res = removed_ids[i];
return true;
}
}
res = default(DataClassIds);
return false;
}
{% endmacro %}
{%- macro diff_methods(u) -%}
static public bool DiffOne(ref {{u.name}} curr, {{u.name}} old)
{
return !{{_self.compare_func_name(u)}}(ref curr, old);
}
static public bool DiffCollection(List<{{u.name}}> items, List<{{u.name}}> old_items, List<{{u.name}}> changed, List<DataClassIds> removed)
{
bool has_diff = false;
if(changed != null)
changed.Clear();
SortByPrimaryId(ref items);
SortByPrimaryId(ref old_items);
int i = 0;
int old_i = 0;
for(; i < items.Count && old_i < old_items.Count;)
{
var old = old_items[old_i];
var item = items[i];
if(old.getPrimaryId() < item.getPrimaryId())
{
var removed_ids = GetClassRemovedIds(removed, {{u.name}}.STATIC_CLASS_ID);
if(removed_ids != null)
removed_ids.Add(old.getPrimaryId());
old_i++;
has_diff = true;
}
else if(old.getPrimaryId() > item.getPrimaryId())
{
item.SetDirtyMask();
if(changed != null)
changed.Add(item);
i++;
has_diff = true;
}
else
{
if(!{{_self.compare_func_name(u)}}(ref item, old))
{
if(changed != null)
changed.Add(item);
has_diff = true;
}
i++;
old_i++;
}
}
//items leftovers are considered changed
for(; i < items.Count; i++)
{
var item = items[i];
item.SetDirtyMask();
if(changed != null)
changed.Add(item);
has_diff = true;
}
//old items leftovers are considered removed
for(; old_i < old_items.Count; old_i++)
{
var removed_ids = GetClassRemovedIds(removed, {{u.name}}.STATIC_CLASS_ID);
if(removed_ids != null)
removed_ids.Add(old_items[old_i].getPrimaryId());
has_diff = true;
}
//if(changed.Count > 0)
// Meta.LogDebug("Changed in collection {{u.name}}");
//if(removed_ids.Count > 0)
// Meta.LogDebug("Removed in collection {{u.name}}");
return has_diff;
}
class {{u.name}}Compare : IComparer<{{u.name}}>
{
public int Compare({{u.name}} o1, {{u.name}} o2)
{
var id1 = o1.getPrimaryId();
var id2 = o2.getPrimaryId();
if(id1 == id2)
return 0;
return id1 > id2 ? 1 : -1;
}
}
static {{u.name}}Compare {{u.name}}_compare = new {{u.name}}Compare();
static void SortByPrimaryId(ref List<{{u.name}}> list)
{
list.Sort({{u.name}}_compare);
}
public static bool {{_self.compare_func_name(u)}}(ref {{u.name}} a, {{u.name}} b)
{
bool is_equal = true;
$compare_fn_str
return is_equal;
}
{% endmacro %}
{% macro compare_func_name(o) %}
{{has_token(u, 'bitfields')?'CompareAndMarkFields':'IsEqual'}}
{% endmacro %}