802 lines
20 KiB
Twig
802 lines
20 KiB
Twig
{% macro decl_units(meta) %}
|
|
|
|
{%- for u in meta.getunits ~%}
|
|
{%- if u.object is instanceof('\\mtgMetaStruct') -%}
|
|
{{ _self.decl_struct(u.object) }}
|
|
{%- elseif u.object is instanceof('\\mtgMetaEnum') -%}
|
|
{{ _self.decl_enum(u.object) }}
|
|
{%- elseif u.object is instanceof('\\mtgMetaRPC') -%}
|
|
{{ _self.decl_rpc(u.object) }}
|
|
{%- endif ~%}
|
|
{%- endfor ~%}
|
|
|
|
{%- for ai in get_all_declarable_accessor_interfaces(meta) ~%}
|
|
{{ _self.decl_accessor_interface(ai) }}
|
|
{%- endfor ~%}
|
|
|
|
{% endmacro %}
|
|
|
|
{% macro decl_struct(o, extra = '') %}
|
|
|
|
{% set pkey_fields = token(o, 'table_pkey')|split(',') %}
|
|
{% set pkey = pkey_fields|filter(f => f|length > 0)|map(f => o.getField(f)) %}
|
|
|
|
{%- if o.parent and has_token(o, 'POD') -%}
|
|
{{Error("@POD structs can't have a parent: " ~ o.name)}}
|
|
{%- endif -%}
|
|
{%- if o.parent and has_token(o, 'bitfields') -%}
|
|
{{Error("@bitfields structs can't have a parent: " ~ o.name)}}
|
|
{%- endif -%}
|
|
|
|
{{_self.attributes(o)}}
|
|
public {{_self.struct_type(o)}} {{o.name}} {{_self.base_struct_class(o)}}
|
|
{
|
|
{{token(o, 'cs_embed', '')}}
|
|
|
|
{{_self.decl_struct_fields(o)}}
|
|
|
|
public {{o.parent ? 'new'}} const uint STATIC_CLASS_ID = {{o.classid}};
|
|
|
|
public {{_self.override(o)}} uint CLASS_ID()
|
|
{
|
|
return {{o.classid}};
|
|
}
|
|
|
|
{{_self.comment_POD_begin(o)}}
|
|
public {{o.name}}()
|
|
{
|
|
Reset();
|
|
}
|
|
{{_self.comment_POD_end(o)}}
|
|
|
|
public {{_self.override(o)}} void Reset()
|
|
{
|
|
{{_self.struct_fields_reset(o)}}
|
|
}
|
|
|
|
{{_self.comment_non_cloneable_begin(o)}}
|
|
public void CloneTo(ref {{o.name}} dst)
|
|
{
|
|
MetaIO.Clone(this, ref dst, AutogenBundle.createById);
|
|
}
|
|
|
|
public {{_self.virtual_clone(o)}} IMetaStruct Clone()
|
|
{
|
|
var dst = new {{o.name}}();
|
|
CloneTo(ref dst);
|
|
return dst;
|
|
}
|
|
{{_self.comment_non_cloneable_end(o)}}
|
|
|
|
public {{_self.override(o)}} void SyncFields(MetaSyncContext ctx)
|
|
{
|
|
{{_self.sync_fields(o)}}
|
|
}
|
|
|
|
public {{_self.override(o)}} int GetFieldsCount()
|
|
{
|
|
return {{fields_count(o)}};
|
|
}
|
|
|
|
public {{_self.override(o)}} int GetDirtyFieldsCount()
|
|
{
|
|
{%~ if has_token(o, 'bitfields') ~%}
|
|
return fields_mask.GetDirtyFieldsCount();
|
|
{% else %}
|
|
return GetFieldsCount();
|
|
{%- endif ~%}
|
|
}
|
|
|
|
{%- if has_token(o, 'bitfields') ~%}
|
|
{{_self.bitmask_helpers(o)}}
|
|
{%- endif -%}
|
|
|
|
{%- if has_token(o, 'table') ~%}
|
|
public static bool operator <({{o.name}} o1, {{o.name}} o2)
|
|
{
|
|
return {{o.name}}Comparer.self.Compare(o1, o2) < 0;
|
|
}
|
|
|
|
public static bool operator >({{o.name}} o1, {{o.name}} o2)
|
|
{
|
|
return {{o.name}}Comparer.self.Compare(o1, o2) > 0;
|
|
}
|
|
|
|
public {{o.name}}Id MakeId()
|
|
{
|
|
return new {{o.name}}Id{
|
|
{% for f in pkey %}
|
|
{{f.name}} = {{f.name}},
|
|
{% endfor %}
|
|
};
|
|
}
|
|
{%- endif -%}
|
|
|
|
{%- if has_token(o, 'diffable') ~%}
|
|
{{_self.diffable_support(o)}}
|
|
{%- endif -%}
|
|
|
|
{{_self.decl_struct_accessor_implements(o)}}
|
|
|
|
{{extra}}
|
|
}
|
|
|
|
{%- if has_token(o, 'table') ~%}
|
|
public class {{o.name}}Comparer : IComparer<{{o.name}}>
|
|
{
|
|
public readonly static {{o.name}}Comparer self = new {{o.name}}Comparer();
|
|
|
|
public int Compare({{o.name}} o1, {{o.name}} o2)
|
|
{
|
|
int result;
|
|
|
|
{% set comparable = pkey %}
|
|
{% if comparable|length > 1 %}
|
|
{% set comparable = comparable [1:] %}
|
|
{% endif %}
|
|
|
|
{% for f in comparable %}
|
|
{% if not loop.first %}
|
|
if(result == 0)
|
|
{% endif %}
|
|
result = o1.{{f.name}}.CompareTo(o2.{{f.name}});
|
|
{% endfor %}
|
|
|
|
return result;
|
|
}
|
|
}
|
|
{%- endif ~%}
|
|
|
|
{% endmacro %}
|
|
|
|
{%- macro decl_struct_fields(o) -%}
|
|
{%- if has_token(o, 'bitfields') ~%}
|
|
public FieldsMask fields_mask;
|
|
{%- endif -%}
|
|
{%- for f in o.fields ~%}
|
|
{{_self.decl_struct_field(o, f)}}
|
|
{%- endfor -%}
|
|
{%- endmacro -%}
|
|
|
|
{%- macro decl_struct_field(o, f) -%}
|
|
{{_self.attributes(f)}}
|
|
{% if has_token(f, 'flt_i18n') -%}
|
|
{{f.type}} _{{f.name}} = "";
|
|
List<{{f.type}}> __{{f.name}} = new List<{{f.type}}>();
|
|
{%- endif ~%}
|
|
public {{f.type|cs_type|obscure_type(f)}} {{f.name}} {% if not has_token(o, 'POD') -%} {{_self.decl_init_value(f)}} {%- endif -%} {% if not has_token(f, 'flt_i18n') -%};{%- endif -%}
|
|
{%- endmacro -%}
|
|
|
|
{% macro decl_init_value(f) %}
|
|
{%- if f.type is instanceof('\\mtgBuiltinType') -%}
|
|
{%- if f.type.isstring -%}
|
|
{% if has_token(f, 'flt_i18n') -%}
|
|
{get{return plural_{{f.name}}(double.NaN);}set{_{{f.name}}=value;}}
|
|
{{f.type}} plural_{{f.name}}(double force_n){return MetaI18N.I18NPick(_{{f.name}},__{{f.name}},"#",force_n);}
|
|
{%- else -%}
|
|
= ""
|
|
{%- endif ~%}
|
|
{%- endif -%}
|
|
{%- else -%}
|
|
{%- if has_token(f, 'default') and token(f, 'default') == 'null' -%}
|
|
/*null*/
|
|
{%- else -%}
|
|
= new {{f.type|cs_type}}()
|
|
{%- endif -%}
|
|
{%- endif -%}
|
|
{% endmacro %}
|
|
|
|
{% macro struct_fields_reset(o) %}
|
|
{%- if o.parent ~%}
|
|
base.Reset();
|
|
{%- endif -%}
|
|
{%- for f in o.fields ~%}
|
|
{% set fname = f.name %}
|
|
{% if has_token(f, 'flt_i18n') -%}
|
|
{% set fname = '_' ~ f.name %}
|
|
if(_{{fname}} == null) _{{fname}} = new(); else _{{fname}}.Clear();
|
|
{%- endif ~%}
|
|
{{var_reset(fname, f.type, token_or(f, 'default', null))}}
|
|
{%- endfor -%}
|
|
{%- if has_token(o, 'bitfields') ~%}
|
|
ResetFieldMask();
|
|
{%- endif -%}
|
|
{% endmacro %}
|
|
|
|
{%- macro attributes(o) %}
|
|
{% if has_token(o, "cs_obsolete") %}
|
|
/// <summary>
|
|
/// {{token(o, "cs_obsolete")}}
|
|
/// </summary>
|
|
[Obsolete]
|
|
{% endif %}
|
|
{%- if has_token(o, 'cs_attributes') -%}
|
|
{%- for attr in token(o, 'cs_attributes')|split(',') -%}
|
|
[{{attr}}]
|
|
{%- endfor -%}
|
|
{%- endif -%}
|
|
{%- endmacro %}
|
|
|
|
{%- macro struct_type(o) -%}
|
|
{{has_token(o, 'POD') ? 'struct' : 'class'}}
|
|
{%- endmacro -%}
|
|
|
|
{%- macro base_struct_class(o) -%}
|
|
{%- if has_token(o, 'POD') -%}
|
|
: IMetaStruct
|
|
{%- else -%}
|
|
: {{o.parent ? o.parent.name : 'BaseMetaStruct'}}
|
|
{{- has_token(o, 'cloneable') and not o.parent ? ', IMetaCloneable' -}}
|
|
{%- endif -%}
|
|
{%- if has_token(o, "cs_implements") -%}
|
|
{%- for ifs in token(o, "cs_implements")|split(',') -%}
|
|
, {{ifs}}
|
|
{%- endfor -%}
|
|
{%- endif -%}
|
|
|
|
{%- for ai in get_accessor_interfaces(o) -%}
|
|
, {{ai.interfacename}}
|
|
{%- endfor -%}
|
|
{%- endmacro -%}
|
|
|
|
{%- macro override(o) -%}
|
|
{%- if not has_token(o, 'POD') -%}
|
|
override
|
|
{%- endif -%}
|
|
{%- endmacro -%}
|
|
|
|
{%- macro virtual(o) -%}
|
|
{%- if not has_token(o, 'POD') -%}
|
|
{{o.parent ? 'override' : 'virtual'}}
|
|
{%- endif -%}
|
|
{%- endmacro -%}
|
|
|
|
{%- macro comment_POD_begin(o) -%}
|
|
{%- if has_token(o, 'POD') -%}
|
|
/* commented in POD
|
|
{%- endif -%}
|
|
{%- endmacro -%}
|
|
|
|
{%- macro comment_POD_end(o) -%}
|
|
{%- if has_token(o, 'POD') -%}
|
|
*/
|
|
{%- endif -%}
|
|
{%- endmacro -%}
|
|
|
|
{%- macro comment_non_cloneable_begin(o) -%}
|
|
{%- if not has_token(o, 'cloneable') -%}
|
|
/* commented in non-cloneable
|
|
{%- endif -%}
|
|
{%- endmacro -%}
|
|
|
|
{%- macro comment_non_cloneable_end(o) -%}
|
|
{%- if not has_token(o, 'cloneable') -%}
|
|
*/
|
|
{%- endif -%}
|
|
{%- endmacro -%}
|
|
|
|
{%- macro virtual_clone(o) -%}
|
|
{%- if has_token(o, 'cloneable') -%}
|
|
{%- if has_token(o, 'POD') -%}
|
|
{%- elseif o.parent and has_token_in_parent(o.parent, 'cloneable') -%}
|
|
override
|
|
{%- else -%}
|
|
virtual
|
|
{%- endif -%}
|
|
{%- endif -%}
|
|
{%- endmacro -%}
|
|
|
|
{%- macro sync_fields(o) -%}
|
|
{%- if has_token(o, 'bitfields') ~%}
|
|
var bitctx = new MetaIO.BitfieldsContext(ctx, fields_mask);
|
|
bitctx.SyncMaskHeader();
|
|
{%- endif -%}
|
|
{%- if o.parent ~%}
|
|
base.SyncFields(ctx);
|
|
{%- endif -%}
|
|
{%- for f in o.fields ~%}
|
|
{% set fname = f.name %}
|
|
{% if has_token(f, 'flt_i18n') -%}
|
|
{% set fname = '_' ~ f.name %}
|
|
{%- endif -%}
|
|
{{var_sync(fname, f.type, 'ctx', f.tokens, get_sync_opts(o, 'bitctx'))}}
|
|
{%- endfor -%}
|
|
{%- endmacro -%}
|
|
|
|
{%- macro bitmask_helpers(o) ~%}
|
|
|
|
public void ResetFieldMask()
|
|
{
|
|
fields_mask = FieldsMask.MakeClean(fields_amount: {{fields_count(o)}});
|
|
}
|
|
|
|
public void SetPrimaryFieldsChanged()
|
|
{
|
|
SetPrimaryFieldsChanged(ref this.fields_mask);
|
|
}
|
|
|
|
static void SetPrimaryFieldsChanged(ref FieldsMask mask)
|
|
{
|
|
{%- for f in o.fields ~%}
|
|
{%- if is_primary_field(o, f) ~%}
|
|
MetaIO.SetFieldDirty(ref mask, {{loop.index0}});
|
|
{%- endif -%}
|
|
{%- endfor ~%}
|
|
}
|
|
|
|
public bool IsContentDirty()
|
|
{
|
|
int fields_amount = {{fields_count(o)}};
|
|
var primary_id_mask = FieldsMask.MakeClean(fields_amount);
|
|
SetPrimaryFieldsChanged(ref primary_id_mask);
|
|
for(int i = 0; i < fields_amount; i++)
|
|
{
|
|
bool is_primary_id = primary_id_mask.IsDirty(i);
|
|
if(!is_primary_id && fields_mask.IsDirty(i))
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public void SetDirtyMask()
|
|
{
|
|
fields_mask = FieldsMask.MakeDirty(fields_amount: {{fields_count(o)}});
|
|
}
|
|
|
|
public void SetDirtyMaskDeep()
|
|
{
|
|
SetDirtyMask();
|
|
{%- for f in o.fields ~%}
|
|
{%- if f.type is instanceof('\\mtgMetaStruct') and has_token(f.type, 'bitfields') ~%}
|
|
{{f.name}}.SetDirtyMaskDeep();
|
|
{%- elseif f.type is instanceof('\\mtgArrType') and f.type.value is instanceof('\\mtgMetaStruct') and has_token(f.type.value, "bitfields") ~%}
|
|
{
|
|
for(int i=0;i<{{f.name}}.Count;++i)
|
|
{
|
|
var __tmp = {{f.name}}[i];
|
|
__tmp.SetDirtyMaskDeep();
|
|
{{f.name}}[i] = __tmp;
|
|
}
|
|
}
|
|
{%- endif -%}
|
|
{%- endfor ~%}
|
|
}
|
|
|
|
{%- endmacro -%}
|
|
|
|
{% macro decl_enum(o) %}
|
|
{{_self.attributes(o)}}
|
|
public enum {{o.name}}
|
|
{
|
|
{%- for n,v in o.values ~%}
|
|
{{n}} = {{v}},
|
|
{%- endfor ~%}
|
|
}
|
|
{% endmacro %}
|
|
|
|
{% macro decl_rpc(o, is_global = true) %}
|
|
|
|
{% if is_global %}
|
|
{{_self.decl_struct(o.req)}}
|
|
{{_self.decl_struct(o.rsp)}}
|
|
{% endif %}
|
|
|
|
public class {{o.name}} : IRpc
|
|
{
|
|
{% if not is_global %}
|
|
{{_self.decl_struct(o.req)}}
|
|
{{_self.decl_struct(o.rsp)}}
|
|
{% endif %}
|
|
|
|
public IRpcError error = null;
|
|
public {{o.req.name}} req = new {{o.req.name}}();
|
|
public {{o.rsp.name}} rsp = new {{o.rsp.name}}();
|
|
|
|
public int GetCode()
|
|
{
|
|
return {{o.code}};
|
|
}
|
|
|
|
public void SetError(IRpcError error)
|
|
{
|
|
this.error = error;
|
|
}
|
|
|
|
public IRpcError GetError()
|
|
{
|
|
return error;
|
|
}
|
|
|
|
public IMetaStruct GetRequest()
|
|
{
|
|
return req as IMetaStruct;
|
|
}
|
|
|
|
public IMetaStruct GetResponse()
|
|
{
|
|
return rsp as IMetaStruct;
|
|
}
|
|
}
|
|
|
|
{% endmacro %}
|
|
|
|
{%- macro diffable_support(o) -%}
|
|
|
|
public bool GetDiff({{o.name}} old, {{o.name}} diff = null, {{o.name}}RemovedIds removed = null)
|
|
{
|
|
if(diff != null)
|
|
diff.Reset();
|
|
if(removed != null)
|
|
removed.Reset();
|
|
bool no_changes = true;
|
|
|
|
{% set field_idx = -1 %}
|
|
{%- for f in o.fields ~%}
|
|
{% set field_idx = field_idx + 1 %}
|
|
|
|
{%- if not has_token(f, 'nodiff') -%}
|
|
{{_self.field_diff(f, field_idx, o)}}
|
|
{%- endif -%}
|
|
{% endfor %}
|
|
|
|
return !no_changes;
|
|
}
|
|
|
|
{% set unique_diff_units = [] %}
|
|
{% for u in get_diff_related_units(o) %}
|
|
{% if u not in unique_diff_units %}
|
|
{{_self.diff_methods_for(u)}}
|
|
{% set unique_diff_units = unique_diff_units|merge([u]) %}
|
|
{% endif %}
|
|
{% endfor %}
|
|
|
|
{% endmacro %}
|
|
|
|
{%- macro diff_methods_for(u) -%}
|
|
{% if has_token(u, 'table') %}
|
|
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<{{u.name}}Id> removed)
|
|
{
|
|
bool has_diff = false;
|
|
if(changed != null)
|
|
changed.Clear();
|
|
|
|
items.Sort({{u.name}}Comparer.self);
|
|
old_items.Sort({{u.name}}Comparer.self);
|
|
|
|
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 < item)
|
|
{
|
|
if(removed != null)
|
|
removed.Add(old.MakeId());
|
|
old_i++;
|
|
has_diff = true;
|
|
}
|
|
else if(old > item)
|
|
{
|
|
item.SetDirtyMaskDeep();
|
|
if(changed != null)
|
|
changed.Add(item);
|
|
i++;
|
|
has_diff = true;
|
|
}
|
|
else
|
|
{
|
|
if(!{{_self.compare_func_name(u)}}(ref item, old) && item.IsContentDirty())
|
|
{
|
|
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.SetDirtyMaskDeep();
|
|
if(changed != null)
|
|
changed.Add(item);
|
|
has_diff = true;
|
|
}
|
|
|
|
//old items leftovers are considered removed
|
|
for(; old_i < old_items.Count; old_i++)
|
|
{
|
|
if(removed != null)
|
|
removed.Add(old_items[old_i].MakeId());
|
|
has_diff = true;
|
|
}
|
|
|
|
//if(changed.Count > 0)
|
|
// MetaIO.LogDebug("Changed in collection {{u.name}}");
|
|
//if(removed_ids.Count > 0)
|
|
// MetaIO.LogDebug("Removed in collection {{u.name}}");
|
|
|
|
return has_diff;
|
|
}
|
|
{% endif %}
|
|
|
|
public static bool {{_self.compare_func_name(u)}}(ref {{u.name}} a, {{u.name}} b)
|
|
{
|
|
bool is_equal = true;
|
|
|
|
{%- if has_token(u, 'bitfields') ~%}
|
|
a.ResetFieldMask();
|
|
{%- endif -%}
|
|
|
|
{%- for f in u.fields ~%}
|
|
{{_self.field_compare(u, f, loop.index0)}}
|
|
{%- endfor -%}
|
|
|
|
{%- if has_token(u, 'bitfields') ~%}
|
|
if(!is_equal)
|
|
a.SetPrimaryFieldsChanged();
|
|
{%- endif -%}
|
|
|
|
return is_equal;
|
|
}
|
|
|
|
{% endmacro %}
|
|
|
|
{% macro compare_func_name(o) %}
|
|
{{has_token(o, 'bitfields')?'CompareAndMarkFields':'IsEqual'}}
|
|
{%- endmacro %}
|
|
|
|
{% macro field_compare_array_bitfields_nested_diffable(o, f, field_idx) %}
|
|
{
|
|
int {{f.name}}_count_a = a.{{f.name}} == null ? 0 : a.{{f.name}}.Count;
|
|
int {{f.name}}_count_b = b.{{f.name}} == null ? 0 : b.{{f.name}}.Count;
|
|
|
|
//For NESTED arrays of DIFFABLE structs:
|
|
//for DB compatibility we must add the WHOLE ARRAY to the diff if ANY ELEMENT of the array has changed.
|
|
//That means marking each element's fields_mask as dirty
|
|
|
|
//Changed size means the array has changed, no furhter checks required.
|
|
bool {{f.name}}_equal = {{f.name}}_count_a == {{f.name}}_count_b;
|
|
|
|
//For same size arrays - check contents for changes.
|
|
if({{f.name}}_equal)
|
|
{
|
|
for(int i=0;i<{{f.name}}_count_a && i<{{f.name}}_count_b;++i)
|
|
{
|
|
var tmp_{{f.name}} = a.{{f.name}}[i];
|
|
if(!CompareAndMarkFields(ref tmp_{{f.name}}, b.{{f.name}}[i]))
|
|
{
|
|
{{f.name}}_equal = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//If change detected - mark top-level field as changed and add the whole array to the diff
|
|
if(!{{f.name}}_equal)
|
|
{
|
|
MetaIO.SetFieldDirty(ref a.fields_mask, {{field_idx}});
|
|
for(int i=0; i<{{f.name}}_count_a;++i)
|
|
{
|
|
var tmp_{{f.name}} = a.{{f.name}}[i];
|
|
tmp_{{f.name}}.SetDirtyMaskDeep();
|
|
a.{{f.name}}[i] = tmp_{{f.name}};
|
|
is_equal = false;
|
|
}
|
|
}
|
|
}
|
|
{%- endmacro %}
|
|
|
|
{% macro field_compare_array_bitfields_nested_plain(o, f, field_idx) %}
|
|
if(a.{{f.name}} == null ||
|
|
b.{{f.name}} == null ||
|
|
a.{{f.name}}.Count != b.{{f.name}}.Count)
|
|
{
|
|
MetaIO.SetFieldDirty(ref a.fields_mask, {{field_idx}});
|
|
is_equal = false;
|
|
}
|
|
else
|
|
{
|
|
for(int i=0;i<a.{{f.name}}.Count;++i)
|
|
{
|
|
{%- if f.type.value is instanceof('\\mtgMetaStruct') ~%}
|
|
var tmp_{{f.name}} = a.{{f.name}}[i];
|
|
if(!{{_self.compare_func_name(f.type.value)}}(ref tmp_{{f.name}}, b.{{f.name}}[i]))
|
|
{
|
|
MetaIO.SetFieldDirty(ref a.fields_mask, {{field_idx}});
|
|
is_equal = false;
|
|
break;
|
|
}
|
|
{%- else -%}
|
|
if(a.{{f.name}}[i] != b.{{f.name}}[i])
|
|
{
|
|
MetaIO.SetFieldDirty(ref a.fields_mask, {{field_idx}});
|
|
is_equal = false;
|
|
break;
|
|
}
|
|
{%- endif -%}
|
|
}
|
|
}
|
|
{%- endmacro %}
|
|
|
|
{% macro field_compare_array_plain(o, f, field_idx) %}
|
|
if(a.{{f.name}} == null ||
|
|
b.{{f.name}} == null ||
|
|
a.{{f.name}}.Count != b.{{f.name}}.Count)
|
|
return false;
|
|
for(int i=0;i<a.{{f.name}}.Count;++i)
|
|
{
|
|
{%- if f.type.value is instanceof('\\mtgMetaStruct') ~%}
|
|
var tmp_{{f.name}} = a.{{f.name}}[i];
|
|
if(!{{_self.compare_func_name(f.type.value)}}(ref tmp_{{f.name}}, b.{{f.name}}[i]))
|
|
return false;
|
|
{%- else -%}
|
|
if(a.{{f.name}}[i] != b.{{f.name}}[i])
|
|
return false;
|
|
{%- endif -%}
|
|
}
|
|
{%- endmacro %}
|
|
|
|
{%- macro field_compare(o, f, field_idx) -%}
|
|
|
|
{% if f.type is instanceof('\\mtgArrType') ~%}
|
|
{% if has_token(o, 'bitfields') ~%}
|
|
{% if has_token(f.type.value, 'bitfields') ~%}
|
|
{{_self.field_compare_array_bitfields_nested_diffable(o, f, field_idx)}}
|
|
{% else ~%}
|
|
{{_self.field_compare_array_bitfields_nested_plain(o, f, field_idx)}}
|
|
{% endif ~%}
|
|
{% else ~%}
|
|
{{_self.field_compare_array_plain(o, f, field_idx)}}
|
|
{% endif ~%}
|
|
|
|
{% elseif f.type is instanceof('\\mtgMetaStruct') ~%}
|
|
var tmp_{{f.name}} = a.{{f.name}}[i];
|
|
if(!{{_self.compare_func_name(f.type.value)}}(ref tmp_{{f.name}}, b.{{f.name}}))
|
|
{% if has_token(o, 'bitfields') ~%}
|
|
{
|
|
MetaIO.SetFieldDirty(ref a.fields_mask, {{field_idx}});
|
|
is_equal = false;
|
|
}
|
|
{% else ~%}
|
|
return false;
|
|
{% endif ~%}
|
|
{% elseif f.type is instanceof('\\mtgBuiltinType') and f.type.isstring ~%}
|
|
if((a.{{f.name}} == null ? "" : a.{{f.name}})
|
|
!= (b.{{f.name}} == null ? "" : b.{{f.name}}))
|
|
{% if has_token(o, 'bitfields') ~%}
|
|
{
|
|
MetaIO.SetFieldDirty(ref a.fields_mask, {{field_idx}});
|
|
is_equal = false;
|
|
}
|
|
{% else ~%}
|
|
return false;
|
|
{%- endif -%}
|
|
{% else ~%}
|
|
if(a.{{f.name}} != b.{{f.name}})
|
|
{% if has_token(o, 'bitfields') ~%}
|
|
{
|
|
MetaIO.SetFieldDirty(ref a.fields_mask, {{field_idx}});
|
|
is_equal = false;
|
|
}
|
|
{% else ~%}
|
|
return false;
|
|
{%- endif -%}
|
|
{%- endif -%}
|
|
|
|
{% endmacro %}
|
|
|
|
{%- macro field_diff(f, field_idx, o) -%}
|
|
|
|
{% if f.type is instanceof('\\mtgMetaStruct') %}
|
|
{%- if not has_token(f.type, 'POD') -%}
|
|
{{Error("Diffable struct '" ~ f.type ~ "' must be POD")}}
|
|
{%- endif -%}
|
|
|
|
{
|
|
var __tmp = {{f.name}};
|
|
if(DiffOne(ref __tmp, old.{{f.name}}))
|
|
{
|
|
no_changes &= false;
|
|
if(diff != null)
|
|
{
|
|
diff.{{f.name}} = __tmp;
|
|
MetaIO.SetFieldDirty(ref diff.fields_mask, {{field_idx}});
|
|
}
|
|
}
|
|
}
|
|
{% elseif f.type is instanceof('\\mtgArrType') %}
|
|
{%- if not has_token(f.type.value, 'POD') -%}
|
|
{{Error("Diffable struct '" ~ f.type.value ~ "' must be POD")}}
|
|
{%- endif -%}
|
|
|
|
if(DiffCollection({{f.name}}, old.{{f.name}},
|
|
diff == null ? null : diff.{{f.name}},
|
|
removed == null ? null : removed.{{f.name}}
|
|
))
|
|
{
|
|
no_changes &= false;
|
|
if(diff != null)
|
|
MetaIO.SetFieldDirty(ref diff.fields_mask, {{field_idx}});
|
|
if(removed != null && removed.{{f.name}}.Count > 0)
|
|
MetaIO.SetFieldDirty(ref removed.fields_mask, {{ field_index(find_struct(o.name ~ 'RemovedIds'), f.name) }});
|
|
}
|
|
{% elseif f.type is instanceof('\\mtgBuiltinType') %}
|
|
if(diff != null)
|
|
diff.{{f.name}} = {{f.name}};
|
|
|
|
if({{f.name}} != old.{{f.name}})
|
|
{
|
|
no_changes &= false;
|
|
if(diff != null)
|
|
MetaIO.SetFieldDirty(ref diff.fields_mask, {{field_idx}});
|
|
}
|
|
{% else %}
|
|
{{Error("Diff for field '"~ f.name ~"' is not supported") }}
|
|
{% endif %}
|
|
|
|
{% endmacro %}
|
|
|
|
{% macro decl_accessor_interface(ai) ~%}
|
|
public interface {{ai.interfacename}}
|
|
{
|
|
{%- for aif in ai.fields ~%}
|
|
{% if aif.is_accessor -%}
|
|
{{aif.field.type|cs_type}} Get{{aif.camelfieldname}}();
|
|
void Set{{aif.camelfieldname}}({{aif.field.type|cs_type}} v);
|
|
{% endif -%}
|
|
|
|
{%- if aif.is_propget -%}
|
|
{{aif.field.type|cs_type}} {{aif.camelfieldname}} {
|
|
{%- if aif.is_propget -%}
|
|
get;
|
|
{%- endif %}
|
|
{%- if aif.is_propset -%}
|
|
set;
|
|
{%- endif -%}
|
|
}
|
|
{%- endif ~%}
|
|
{%- endfor ~%}
|
|
}
|
|
{% endmacro %}
|
|
|
|
{%- macro decl_struct_accessor_implements(o) -%}
|
|
{%- for ai in get_accessor_interfaces(o) ~%}
|
|
{%- for aif in ai.fields ~%}
|
|
{% if aif.is_accessor %}
|
|
public {{aif.field.type|cs_type}} Get{{aif.camelfieldname}}()
|
|
{
|
|
return {{aif.field.name}};
|
|
}
|
|
public void Set{{aif.camelfieldname}}({{aif.field.type|cs_type}} v)
|
|
{
|
|
this.{{aif.field.name}} = v;
|
|
}
|
|
{% endif %}
|
|
|
|
{% if aif.is_propget or aif.is_propset %}
|
|
public {{aif.field.type|cs_type}} {{aif.camelfieldname}} {
|
|
{%- if aif.is_propget -%}
|
|
get => this.{{aif.field.name}};
|
|
{%- endif -%}
|
|
{%- if aif.is_propset -%}
|
|
set => this.{{aif.field.name}} = value;
|
|
{%- endif -%}
|
|
}
|
|
{%- endif ~%}
|
|
{% endfor %}
|
|
{%- endfor ~%}
|
|
{% endmacro %}
|