{% macro decl_units(meta) %} {%- for u in meta.getunits ~%} {%- if u.object is instanceof('\\mtgMetaStruct') -%} {{ _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(meta, u.object) }} {%- endif ~%} {%- endfor ~%} {% endmacro %} {% 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 -%} {%- 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)}} { {{_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 {{_self.virtual_clone(o)}} void copy(IMetaStruct other) { copyFrom(({{o.name}})other); } public void copyFrom({{o.name}} other) { var ctx = Meta.PrepareForClone(ref other); ctx.factory = AutogenBundle.createById; ctx.reader.BeginContainer(); reset(); syncFields(ctx); ctx.reader.EndContainer(); {%- if has_token(o, 'bitfields') ~%} fields_mask = other.fields_mask; {%- endif ~%} } public {{_self.virtual_clone(o)}} IMetaStruct clone() { var copy = new {{o.name}}(); copy.copy(this); return copy; } {{_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 getWritableFieldsCount() { {%~ if has_token(o, 'bitfields') ~%} return Meta.GetDirtyFieldsCount(fields_mask, fields_count: {{fields_count(o)}}) + Meta.MASK_HEADER_FIELDS_COUNT; {% else %} return {{fields_count(o)}}; {%- endif ~%} } {%- if has_token(o, 'bitfields') ~%} {{_self.bitmask_helpers(o)}} {%- endif -%} {%- if has_token(o, 'bhl_bind') ~%} {{_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}} } {% endmacro %} {%- macro decl_struct_fields(o) -%} {%- if has_token(o, 'bitfields') ~%} public long 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)}} public {{f.type|cs_type}} {{f.name}} {% if not has_token(o, 'POD') -%} {{_self.decl_init_value(f.type)}} {%- endif -%}; {%- endmacro -%} {% macro decl_init_value(type) %} {%- if type is instanceof('\\mtgBuiltinType') -%} {%- if type.isstring -%} = ""{%- endif -%} {%- else -%} = new {{type|cs_type}}() {%- endif -%} {% endmacro %} {% macro struct_fields_reset(o) %} {%- if o.parent ~%} base.reset(); {%- endif -%} {%- for f in o.fields ~%} {{var_reset(f.name, f.type, token_or(f, 'default', null))}} {%- endfor -%} {%- if has_token(o, 'bitfields') ~%} fields_mask = 0L; {%- endif -%} {% endmacro %} {%- macro attributes(o) %} {%- 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' -}} {{- has_token(o, 'bhl_bind') and not o.parent ? ', bhl.ITyped' -}} {%- endif -%} {%- 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 Meta.BitfieldsContext(ctx, fields_mask); bitctx.SyncMaskHeader(); {%- endif -%} {%- if o.parent ~%} base.syncFields(ctx); {%- endif -%} {%- for f in o.fields ~%} {{var_sync(f.name, f.type, 'ctx', f.tokens, get_sync_opts(o, 'bitctx'))}} {%- endfor -%} {%- endmacro -%} {%- macro bitmask_helpers(o) ~%} public void ResetFieldMask() { fields_mask = 0L; } public void SetPrimaryFieldsChanged() { {%- for f in o.fields ~%} {%- if is_primary_field(o, f) ~%} Meta.SetFieldDirty(ref fields_mask, {{loop.index0}}); {%- endif -%} {%- endfor ~%} } public void SetDirtyMask() { fields_mask = ~0L; } 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 get_itype(o) %} public {{_self.virtual(o)}} bhl.IType GetIType() { return bhl.BHL_Types.Type_{{o.name}}; } {%- 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(meta, o) %} {{_self.decl_struct(meta, o.req)}} {{_self.decl_struct(meta, o.rsp)}} public class {{o.name}} : IRpc { 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(meta, o) -%} {% for u in get_diff_class_units(meta, o) %} {{_self.diff_methods(u)}} {% endfor %} static public List GetClassRemovedIds(List 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(); removed_ids.Add(res); } return res.ids; } static bool FindClassRemovedIds(List removed_ids, uint class_id, out DataClassIds res) { for(int i=0;i items, List<{{u.name}}> old_items, List<{{u.name}}> changed, List 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 %}