703 lines
19 KiB
PHP
703 lines
19 KiB
PHP
|
<?php
|
||
|
|
||
|
require_once(dirname(__FILE__) . '/../../metagen.inc.php');
|
||
|
require_once(dirname(__FILE__) . '/cs_tpl.inc.php');
|
||
|
|
||
|
class mtgCsCodegen extends mtgCodegen
|
||
|
{
|
||
|
public $namespace = 'game';
|
||
|
|
||
|
function genUnit(mtgMetaInfoUnit $unit)
|
||
|
{
|
||
|
$obj = $unit->object;
|
||
|
if($obj instanceof mtgMetaEnum)
|
||
|
return $this->genEnum($obj);
|
||
|
else if($obj instanceof mtgMetaStruct)
|
||
|
return $this->genStruct($obj);
|
||
|
else if($obj instanceof mtgMetaRPC)
|
||
|
return $this->genRPC($obj);
|
||
|
else
|
||
|
{
|
||
|
echo "WARN: skipping meta unit '{$obj->getId()}'\n";
|
||
|
return '';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function genEnum(mtgMetaEnum $struct)
|
||
|
{
|
||
|
$templater = new mtg_cs_templater();
|
||
|
|
||
|
$repl = array();
|
||
|
$repl['%namespace%'] = $this->namespace;
|
||
|
$repl['%class%'] = $struct->getName();
|
||
|
$repl['%class_id%'] = $struct->getClassId();
|
||
|
|
||
|
$tpl = $templater->tpl_enum();
|
||
|
|
||
|
$this->fillEnumRepls($struct, $repl);
|
||
|
|
||
|
return mtg_fill_template($tpl, $repl);
|
||
|
}
|
||
|
|
||
|
function fillEnumRepls(mtgMetaEnum $enum, &$repl)
|
||
|
{
|
||
|
$repl['%fields%'] = '';
|
||
|
$repl['%attributes%'] = '';
|
||
|
$fields =& $repl['%fields%'];
|
||
|
if($enum->hasToken('cs_attributes'))
|
||
|
{
|
||
|
$attrs = explode(",", $enum->getToken('cs_attributes'));
|
||
|
foreach($attrs as $attr)
|
||
|
$repl['%attributes%'] .= "[$attr] ";
|
||
|
}
|
||
|
foreach($enum->getValues() as $vname => $value)
|
||
|
$fields .= sprintf("\n %s = %s,", $vname, $value);
|
||
|
}
|
||
|
|
||
|
function genRPC(mtgMetaRPC $rpc)
|
||
|
{
|
||
|
$templater = new mtg_cs_templater();
|
||
|
|
||
|
$repl = array();
|
||
|
$repl['%namespace%'] = $this->namespace;
|
||
|
$repl['%class%'] = $rpc->getName();
|
||
|
$repl['%code%'] = $rpc->getCode();
|
||
|
$repl['%req_class%'] = $rpc->getReq()->getName();
|
||
|
$repl['%rsp_class%'] = $rpc->getRsp()->getName();
|
||
|
|
||
|
$tpl = $templater->tpl_rpc();
|
||
|
|
||
|
return
|
||
|
mtg_fill_template($tpl, $repl) .
|
||
|
$this->genStruct($rpc->getReq()) .
|
||
|
$this->genStruct($rpc->getRsp());
|
||
|
}
|
||
|
|
||
|
function genStruct(mtgMetaStruct $struct)
|
||
|
{
|
||
|
$templater = new mtg_cs_templater();
|
||
|
|
||
|
$repl = array();
|
||
|
$repl['%namespace%'] = $this->namespace;
|
||
|
$repl['%class%'] = $struct->getName();
|
||
|
$repl['%class_id%'] = $struct->getClassId();
|
||
|
|
||
|
$tpl = $templater->tpl_struct();
|
||
|
|
||
|
$this->fillStructRepls($struct, $repl);
|
||
|
|
||
|
return mtg_fill_template($tpl, $repl);
|
||
|
}
|
||
|
|
||
|
function preprocessField(mtgMetaStruct $struct, mtgMetaField $field)
|
||
|
{}
|
||
|
|
||
|
function countFields(mtgMetaStruct $struct)
|
||
|
{
|
||
|
$fields = $struct->getFields();
|
||
|
$count = 0;
|
||
|
foreach($fields as $field)
|
||
|
{
|
||
|
if($field->hasToken('i18n'))
|
||
|
$count += 2;
|
||
|
else
|
||
|
$count += 1;
|
||
|
}
|
||
|
|
||
|
return $count;
|
||
|
}
|
||
|
|
||
|
function fillStructRepls(mtgMetaStruct $struct, &$repl)
|
||
|
{
|
||
|
foreach($struct->getFields() as $field)
|
||
|
$this->preprocessField($struct, $field);
|
||
|
|
||
|
$all_fields = mtg_get_all_fields($this->info, $struct);
|
||
|
$all_fields_count = $this->countAllFields($struct);
|
||
|
|
||
|
$repl['%includes%'] = '';
|
||
|
$repl['%fields%'] = '';
|
||
|
$repl['%fields_reset%'] = '';
|
||
|
$repl['%attributes%'] = '';
|
||
|
|
||
|
$repl['%sync_buffer%'] = '';
|
||
|
$repl['%fields_count%'] = $all_fields_count;
|
||
|
$repl["%ext_methods%"] = "";
|
||
|
|
||
|
$repl['%new_method%'] = '';
|
||
|
$repl['%virt_method%'] = ' virtual ';
|
||
|
$repl['%commented_in_child_begin%'] = '';
|
||
|
$repl['%commented_in_child_end%'] = '';
|
||
|
$repl['%commented_in_pod_begin%'] = '';
|
||
|
$repl['%commented_in_pod_end%'] = '';
|
||
|
|
||
|
$has_bitfields_token = $struct->hasToken("bitfields");
|
||
|
|
||
|
$bitctx_name = 'bitctx';
|
||
|
|
||
|
$repl['%bitfields_sync_context%'] = "";
|
||
|
if($has_bitfields_token)
|
||
|
{
|
||
|
$repl['%bitfields_sync_context%'] .= $this->offset(2)."var $bitctx_name = new Meta.BitfieldsContext(ctx, fields_mask);\n";
|
||
|
$repl['%bitfields_sync_context%'] .= $this->offset(2)."$bitctx_name.SyncMaskHeader();\n";
|
||
|
}
|
||
|
|
||
|
if($struct->hasToken('cs_attributes'))
|
||
|
{
|
||
|
$attrs = explode(",", $struct->getToken('cs_attributes'));
|
||
|
foreach($attrs as $attr)
|
||
|
$repl['%attributes%'] .= "[$attr] ";
|
||
|
}
|
||
|
|
||
|
$parent = $struct->getParent();
|
||
|
$is_pod = $struct->hasToken('POD');
|
||
|
|
||
|
if($parent && $has_bitfields_token)
|
||
|
throw new Exception("@bitfields struct can't have a parent: {$struct->getName()}");
|
||
|
|
||
|
if($is_pod)
|
||
|
{
|
||
|
$fields = $all_fields;
|
||
|
$repl['%type_name%'] = 'struct';
|
||
|
$repl['%parent%'] = " : IMetaStruct";
|
||
|
$repl['%virt_method%'] = '';
|
||
|
$repl['%commented_in_pod_begin%'] = '/*';
|
||
|
$repl['%commented_in_pod_end%'] = '*/';
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
$repl['%type_name%'] = 'class';
|
||
|
$repl['%parent%'] = " : " . ($parent ? $parent : " BaseMetaStruct");
|
||
|
if($parent)
|
||
|
$repl['%sync_buffer%'] .= "\n base.syncFields(ctx);\n";
|
||
|
$repl['%commented_in_child_begin%'] = '/*';
|
||
|
$repl['%commented_in_child_end%'] = '*/';
|
||
|
$repl['%virt_method%'] = " override ";
|
||
|
|
||
|
if($parent)
|
||
|
{
|
||
|
$repl['%new_method%'] = " new ";
|
||
|
$repl['%fields_reset%'] = "base.reset();\n";
|
||
|
}
|
||
|
|
||
|
$fields = $struct->getFields();
|
||
|
}
|
||
|
|
||
|
$repl['%copy_fields%'] = '';
|
||
|
$repl['%virt_clone_method%'] = '';
|
||
|
|
||
|
if($struct->hasToken("cloneable"))
|
||
|
{
|
||
|
$repl['%parent%'] .= ",IMetaCloneable";
|
||
|
$repl['%commented_in_non_cloneable_begin%'] = '';
|
||
|
$repl['%commented_in_non_cloneable_end%'] = '';
|
||
|
|
||
|
if($is_pod)
|
||
|
$repl['%virt_clone_method%'] = '';
|
||
|
else if($parent && $parent->hasTokenInParent("cloneable"))
|
||
|
$repl['%virt_clone_method%'] = ' override ';
|
||
|
else
|
||
|
$repl['%virt_clone_method%'] = ' virtual ';
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
$repl['%commented_in_non_cloneable_begin%'] = '/*';
|
||
|
$repl['%commented_in_non_cloneable_end%'] = '*/';
|
||
|
}
|
||
|
|
||
|
$field_index = 0;
|
||
|
foreach($fields as $field)
|
||
|
{
|
||
|
$repl['%fields%'] .= $this->offset() . $this->genFieldDecl($struct, $field)."\n";
|
||
|
|
||
|
$repl['%fields_reset%'] .= $this->offset() . $this->genFieldReset($field)."\n";
|
||
|
|
||
|
$sync_opts = $this->resolveSyncOpts($struct, $bitctx_name);
|
||
|
|
||
|
$repl['%sync_buffer%'] .= $this->offset(2) . $this->genBufSyncRegular($field, "ctx", $sync_opts)."\n";
|
||
|
|
||
|
$field_index++;
|
||
|
}
|
||
|
|
||
|
if($has_bitfields_token)
|
||
|
{
|
||
|
$repl['%fields%'] .= "\n".$this->offset()."public long fields_mask;\n";
|
||
|
|
||
|
$repl['%ext_methods%'] .= "\n".$this->genBitmaskHelpers($struct, $fields);
|
||
|
|
||
|
$repl['%copy_fields%'] .= $this->offset() . "fields_mask = other.fields_mask;\n";
|
||
|
$repl['%fields_reset%'] .= $this->offset() . "fields_mask = 0L;\n";
|
||
|
|
||
|
$repl['%dirty_fields_count%'] = "Meta.GetDirtyFieldsCount(fields_mask, fields_count: $all_fields_count) + Meta.MASK_HEADER_FIELDS_COUNT";
|
||
|
}
|
||
|
else
|
||
|
$repl['%dirty_fields_count%'] = "$all_fields_count /* equal to getFieldsCount */ ";
|
||
|
|
||
|
$repl['%fields%'] = trim($repl['%fields%'], "\n ");
|
||
|
|
||
|
$this->undoTemp();
|
||
|
}
|
||
|
|
||
|
function resolveSyncOpts(mtgMetaStruct $struct, string $bitctx_name)
|
||
|
{
|
||
|
$opts = array();
|
||
|
if($struct->hasToken("bitfields"))
|
||
|
$opts[] = "$bitctx_name.GetNextOpts()";
|
||
|
|
||
|
if(count($opts) == 0)
|
||
|
return "0";
|
||
|
|
||
|
return implode(" | ", $opts);
|
||
|
}
|
||
|
|
||
|
function countAllFields(mtgMetaStruct $struct)
|
||
|
{
|
||
|
$count = count($struct->getFields()); //preprocessed fields list
|
||
|
|
||
|
//raw fields lists
|
||
|
$curr = $struct->getParent();
|
||
|
while($curr)
|
||
|
{
|
||
|
$count += $this->countFields($curr);
|
||
|
$curr = $curr->getParent();
|
||
|
}
|
||
|
|
||
|
return $count;
|
||
|
}
|
||
|
|
||
|
function genNativePlainType(mtgType $type)
|
||
|
{
|
||
|
if($type instanceof mtgBuiltinType)
|
||
|
{
|
||
|
switch($type->getName())
|
||
|
{
|
||
|
case "int8":
|
||
|
return "sbyte";
|
||
|
case "uint8":
|
||
|
return "byte";
|
||
|
case "int16":
|
||
|
return "short";
|
||
|
case "uint16":
|
||
|
return "ushort";
|
||
|
case "int32":
|
||
|
case "int":
|
||
|
return "int";
|
||
|
case "uint32":
|
||
|
case "uint":
|
||
|
return "uint";
|
||
|
case "float":
|
||
|
return "float";
|
||
|
case "double":
|
||
|
return "double";
|
||
|
case "uint64":
|
||
|
return "ulong";
|
||
|
case "int64":
|
||
|
return "long";
|
||
|
case "string":
|
||
|
return "string";
|
||
|
case "bool":
|
||
|
return "bool";
|
||
|
case "blob":
|
||
|
return "byte[]";
|
||
|
}
|
||
|
throw new Exception("Unknown type '{$type}'");
|
||
|
}
|
||
|
return $type->getName();
|
||
|
}
|
||
|
|
||
|
function genTypePrefix(mtgType $type)
|
||
|
{
|
||
|
switch($type->getName())
|
||
|
{
|
||
|
case "float":
|
||
|
return "Float";
|
||
|
case "double":
|
||
|
return "Double";
|
||
|
case "uint64":
|
||
|
return "U64";
|
||
|
case "int64":
|
||
|
return "I64";
|
||
|
case "uint":
|
||
|
case "uint32":
|
||
|
return "U32";
|
||
|
case "uint16":
|
||
|
return "U16";
|
||
|
case "uint8":
|
||
|
return "U8";
|
||
|
case "int":
|
||
|
case "int32":
|
||
|
return "I32";
|
||
|
case "int16":
|
||
|
return "I16";
|
||
|
case "int8":
|
||
|
return "I8";
|
||
|
case "string":
|
||
|
return "String";
|
||
|
case "bool":
|
||
|
return "Bool";
|
||
|
case "blob":
|
||
|
return "Blob";
|
||
|
default:
|
||
|
throw new Exception("Unknown type '{$type}'");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function genBufSyncRegular(mtgMetaField $field, $buf, $opts = "")
|
||
|
{
|
||
|
return $this->genBufSync($field->getName(), $field, $buf, $opts);
|
||
|
}
|
||
|
|
||
|
function genBufSync(string $fname, mtgMetaField $field, $buf, $opts)
|
||
|
{
|
||
|
return $this->genBufSyncEx($fname, $field->getType(), $buf, $field->getTokens(), $opts);
|
||
|
}
|
||
|
|
||
|
function genBufSyncEx($fname, mtgType $type, $buf, array $tokens = array(), $opts = "")
|
||
|
{
|
||
|
$optional = array_key_exists('optional', $tokens);
|
||
|
if($optional)
|
||
|
$opts .= " | MetaSyncFieldOpts.SKIP_OPTIONAL";
|
||
|
|
||
|
$str = '';
|
||
|
if($type instanceof mtgBuiltinType)
|
||
|
{
|
||
|
$str .= "Meta.Sync({$buf}, ref {$fname}, {$opts});\n";
|
||
|
}
|
||
|
else if($type instanceof mtgMetaStruct)
|
||
|
{
|
||
|
if(array_key_exists('virtual', $tokens))
|
||
|
$str .= "{$fname} = ({$type->getName()})Meta.SyncGeneric({$buf}, {$fname}, {$opts});\n";
|
||
|
else
|
||
|
$str .= "Meta.Sync({$buf}, ref {$fname}, {$opts});\n";
|
||
|
}
|
||
|
else if($type instanceof mtgMetaEnum)
|
||
|
{
|
||
|
$str .= "int __tmp_{$fname} = (int)$fname;\n";
|
||
|
$str .= "Meta.Sync({$buf}, ref __tmp_{$fname}, {$opts});\n";
|
||
|
$str .= "if($buf.is_read) {$fname} = ({$type->getName()})__tmp_{$fname};\n";
|
||
|
}
|
||
|
else if($type instanceof mtgArrType)
|
||
|
{
|
||
|
if(array_key_exists('virtual', $tokens))
|
||
|
$str .= "Meta.SyncGeneric({$buf}, {$fname}, {$opts});\n";
|
||
|
else
|
||
|
{
|
||
|
if($type->getValue() instanceof mtgMetaEnum)
|
||
|
{
|
||
|
$str .= "Meta.tmp_enums_list.Clear(); if(!{$buf}.is_read) { foreach(var _enum_tmp in {$fname}) Meta.tmp_enums_list.Add((int)_enum_tmp); }\n";
|
||
|
$str .= "Meta.Sync({$buf}, Meta.tmp_enums_list, {$opts});\n";
|
||
|
$str .= "if({$buf}.is_read) foreach(var _int_tmp in Meta.tmp_enums_list) { {$fname}.Add(({$type->getValue()->getName()}) _int_tmp); }\n";
|
||
|
}
|
||
|
else
|
||
|
$str .= "Meta.Sync({$buf}, {$fname}, {$opts});\n";
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
throw new Exception("Unknown type '$type'");
|
||
|
|
||
|
return $str;
|
||
|
}
|
||
|
|
||
|
function genConstructArgs($type)
|
||
|
{
|
||
|
if($type == "string")
|
||
|
return '""';
|
||
|
return "new {$type}()";
|
||
|
}
|
||
|
|
||
|
function isPOD(mtgMetaStruct $struct)
|
||
|
{
|
||
|
return $struct->hasToken('POD');
|
||
|
}
|
||
|
|
||
|
function genFieldDecl(mtgMetaStruct $struct, mtgMetaField $field)
|
||
|
{
|
||
|
$str = "";
|
||
|
|
||
|
if($field->hasToken('cs_attributes'))
|
||
|
{
|
||
|
$attrs = explode(",", $field->getToken('cs_attributes'));
|
||
|
foreach($attrs as $attr)
|
||
|
$str .= "[$attr] ";
|
||
|
}
|
||
|
|
||
|
$str .= "public " . $this->genFieldNativeType($field) . " ";
|
||
|
|
||
|
if(!$this->isPOD($struct))
|
||
|
$str .= $this->genFieldDeclInit($field);
|
||
|
else
|
||
|
$str .= $this->genFieldName($field) . ";";
|
||
|
|
||
|
return $str;
|
||
|
}
|
||
|
|
||
|
function offset($amount = 1)
|
||
|
{
|
||
|
return str_repeat(" ", $amount);
|
||
|
}
|
||
|
|
||
|
function genFieldCopy(mtgMetaField $field)
|
||
|
{
|
||
|
$tokens = $field->getTokens();
|
||
|
$name = $this->genFieldName($field);
|
||
|
$type = $field->getType();
|
||
|
$str = '';
|
||
|
|
||
|
if($type instanceof mtgArrType)
|
||
|
{
|
||
|
$str .= "for(int i=0;other.{$name} != null && i<other.{$name}.Count;++i) { \n";
|
||
|
|
||
|
$vtype = $type->getValue();
|
||
|
if($vtype instanceof mtgMetaStruct)
|
||
|
{
|
||
|
if(array_key_exists('virtual', $tokens))
|
||
|
$str .= $this->offset(3)."var tmp = ({$vtype->getName()})other.{$name}[i].clone();\n";
|
||
|
else
|
||
|
$str .= $this->offset(3)."var tmp = new {$vtype->getName()}(); tmp.copyFrom(other.{$name}[i]);\n";
|
||
|
$str .= $this->offset(3)."{$name}.Add(tmp);\n";
|
||
|
}
|
||
|
else
|
||
|
$str .= $this->offset(3)."{$name}.Add(other.{$name}[i]);\n";
|
||
|
|
||
|
$str .= $this->offset(2)."}\n";
|
||
|
}
|
||
|
else if($type instanceof mtgMetaStruct)
|
||
|
{
|
||
|
if(array_key_exists('virtual', $tokens))
|
||
|
$str .= $this->offset(2)."{$name} = ({$type->getName()})other.{$name}.clone();\n";
|
||
|
else
|
||
|
$str .= $this->offset(2)."{$name}.copyFrom(other.{$name});\n";
|
||
|
}
|
||
|
else
|
||
|
$str .= $this->offset()."{$name} = other.{$name};\n";
|
||
|
|
||
|
return $str;
|
||
|
}
|
||
|
|
||
|
function genFieldDeclInit(mtgMetaField $field)
|
||
|
{
|
||
|
$tokens = $field->getTokens();
|
||
|
|
||
|
$str = $this->genFieldName($field);
|
||
|
$type = $field->getType();
|
||
|
if($type instanceof mtgBuiltinType)
|
||
|
{
|
||
|
if($type->isString())
|
||
|
$str .= ' = ""';
|
||
|
}
|
||
|
else
|
||
|
$str .= " = new ".$this->genFieldNativeType($field)."()";
|
||
|
$str .= ";";
|
||
|
return $str;
|
||
|
}
|
||
|
|
||
|
function genFieldReset(mtgMetaField $field)
|
||
|
{
|
||
|
$tokens = $field->getTokens();
|
||
|
$default = array_key_exists('default', $tokens) ? $tokens['default'] : null;
|
||
|
|
||
|
return $this->genFieldResetEx($this->genFieldName($field), $field->getType(), $default);
|
||
|
}
|
||
|
|
||
|
function genFieldResetEx($name, mtgType $type, $default = null)
|
||
|
{
|
||
|
$str = '';
|
||
|
if($type instanceof mtgBuiltinType)
|
||
|
{
|
||
|
if($type->isNumeric())
|
||
|
{
|
||
|
$str = $name;
|
||
|
//NOTE: numeric check is against str2num
|
||
|
if($default && is_numeric($default))
|
||
|
{
|
||
|
if($type->isFloat())
|
||
|
$default .= "f";
|
||
|
$str .= " = $default;";
|
||
|
}
|
||
|
else
|
||
|
$str .= " = 0;";
|
||
|
}
|
||
|
else if($type->isString())
|
||
|
{
|
||
|
$str = $name;
|
||
|
if($default)
|
||
|
{
|
||
|
$str .= " = \"".trim($default, '"')."\";";
|
||
|
}
|
||
|
else
|
||
|
$str .= ' = "";';
|
||
|
}
|
||
|
else if($type->isBool())
|
||
|
{
|
||
|
$str = $name;
|
||
|
if($default)
|
||
|
{
|
||
|
$str .= " = ".trim($default, '"').";";
|
||
|
}
|
||
|
else
|
||
|
$str .= ' = false;';
|
||
|
}
|
||
|
else if($type->isBlob())
|
||
|
{
|
||
|
$str = $name;
|
||
|
if($default)
|
||
|
{
|
||
|
$str .= " = ".trim($default, '"').";";
|
||
|
}
|
||
|
else
|
||
|
$str .= ' = null;';
|
||
|
}
|
||
|
else
|
||
|
throw new Exception("Unknown type '$type'");
|
||
|
}
|
||
|
else if($type instanceof mtgArrType)
|
||
|
{
|
||
|
$str = "Meta.ClearList(ref $name);";
|
||
|
|
||
|
if($default)
|
||
|
{
|
||
|
$default_arr = is_array($default) ? $default : json_decode($default, true);
|
||
|
if(!is_array($default_arr))
|
||
|
throw new Exception("Bad default value for array: '$default'");
|
||
|
|
||
|
if($default_arr)
|
||
|
{
|
||
|
$type_str = $this->genNativeType($type->getValue());
|
||
|
$str .= "{ $type_str tmp__";
|
||
|
if($this->isNullableType($type->getValue()))
|
||
|
$str .= " = null";
|
||
|
$str .= ";";
|
||
|
foreach($default_arr as $v)
|
||
|
{
|
||
|
$str .= $this->genFieldResetEx("tmp__", $type->getValue(), $v);
|
||
|
$str .= "$name.Add(tmp__);";
|
||
|
}
|
||
|
$str .= "}";
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if($type instanceof mtgMetaEnum)
|
||
|
{
|
||
|
if($default)
|
||
|
$str = "$name = ".$this->genNativeType($type).".".trim($default,'"')."; ";
|
||
|
else
|
||
|
$str = "$name = new ".$this->genNativeType($type)."(); ";
|
||
|
}
|
||
|
else if($type instanceof mtgMetaStruct)
|
||
|
{
|
||
|
$str = "";
|
||
|
$is_pod = $type->hasToken('POD');
|
||
|
if($is_pod)
|
||
|
$str .= "$name.reset(); ";
|
||
|
else
|
||
|
$str .= "Meta.Reset(ref $name); ";
|
||
|
|
||
|
if($default)
|
||
|
{
|
||
|
$default = is_array($default) ? $default : json_decode($default, true);
|
||
|
if(!is_array($default))
|
||
|
throw new Exception("Bad default value for struct: $default");
|
||
|
|
||
|
foreach($default as $k => $v)
|
||
|
{
|
||
|
$kf = $type->getField($k);
|
||
|
$str .= $this->genFieldResetEx("$name." . $this->genFieldName($kf), $kf->getType(), $v);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
throw new Exception("Bad type '$type'");
|
||
|
return $str;
|
||
|
}
|
||
|
|
||
|
function isNullableType(mtgType $type)
|
||
|
{
|
||
|
return $type instanceof mtgArrType ||
|
||
|
($type instanceof mtgMetaStruct && !$type->hasToken('POD'));
|
||
|
}
|
||
|
|
||
|
function genFieldName(mtgMetaField $field)
|
||
|
{
|
||
|
return $field->getName();
|
||
|
}
|
||
|
|
||
|
function genFieldNativeType(mtgMetaField $field)
|
||
|
{
|
||
|
return $this->genNativeType($field->getType(), $field->getTokens());
|
||
|
}
|
||
|
|
||
|
function genNativeType(mtgType $type, array $tokens = array())
|
||
|
{
|
||
|
if($type instanceof mtgBuiltinType || $type instanceof mtgUserType)
|
||
|
return $this->genNativePlainType($type);
|
||
|
else if($type instanceof mtgArrType)
|
||
|
return "List<" . $this->genNativePlainType($type->getValue()) . ">";
|
||
|
else
|
||
|
throw new Exception("Unknown type '{$type}'");
|
||
|
}
|
||
|
|
||
|
function genBitmaskHelpers(mtgMetaStruct $struct, array $fields)
|
||
|
{
|
||
|
//RESET FIELD MASK
|
||
|
$str = $this->offset()."public void ResetFieldMask()\n";
|
||
|
$str .= $this->offset()."{\n";
|
||
|
$str .= $this->offset(2)."fields_mask = 0L;\n";
|
||
|
$str .= $this->offset()."}\n\n";
|
||
|
|
||
|
//SET PRIMARY FIELDS CHANGED
|
||
|
$primary_fields = array();
|
||
|
if($struct->hasToken("id"))
|
||
|
$primary_fields[] = $struct->getToken("id");
|
||
|
|
||
|
if($struct->hasToken("owner"))
|
||
|
$primary_fields[] = $struct->getToken("owner");
|
||
|
|
||
|
if($struct->hasToken("pkey"))
|
||
|
{
|
||
|
foreach(explode(",", $struct->getToken("pkey")) as $name)
|
||
|
$primary_fields[] = $name;
|
||
|
}
|
||
|
|
||
|
$str .= $this->offset()."public void SetPrimaryFieldsChanged()\n";
|
||
|
$str .= $this->offset()."{\n";
|
||
|
$field_index = 0;
|
||
|
foreach($fields as $field)
|
||
|
{
|
||
|
if(in_array($field->getName(), $primary_fields))
|
||
|
$str .= $this->offset(2)."Meta.SetFieldDirty(ref fields_mask, $field_index);\n";
|
||
|
|
||
|
$field_index++;
|
||
|
}
|
||
|
$str .= $this->offset()."}\n\n";
|
||
|
|
||
|
//DIRTY FIELD MASK
|
||
|
$str .= $this->offset()."public void SetDirtyMask()\n";
|
||
|
$str .= $this->offset()."{\n";
|
||
|
$str .= $this->offset(2)."fields_mask = ~0L;\n";
|
||
|
$str .= $this->offset()."}\n\n";
|
||
|
|
||
|
$str .= $this->offset()."public void SetDirtyMaskDeep()\n";
|
||
|
$str .= $this->offset()."{\n";
|
||
|
$str .= $this->offset(2)."SetDirtyMask();\n";
|
||
|
foreach($fields as $field)
|
||
|
{
|
||
|
$type = $field->getType();
|
||
|
|
||
|
if($type instanceof mtgMetaStruct && $type->hasToken("bitfields"))
|
||
|
$str .= $this->offset(2)."{$field->getName()}.SetDirtyMaskDeep();\n";
|
||
|
else if($type instanceof mtgArrType && $type->getValue() instanceof mtgMetaStruct && $type->getValue()->hasToken("bitfields"))
|
||
|
{
|
||
|
$str .= $this->offset(2)."for(int i=0;i<{$field->getName()}.Count;++i) {\n";
|
||
|
$str .= $this->offset(2)."var __tmp = {$field->getName()}[i];\n";
|
||
|
$str .= $this->offset(2)."__tmp.SetDirtyMaskDeep();\n";
|
||
|
$str .= $this->offset(2)."{$field->getName()}[i] = __tmp;\n";
|
||
|
$str .= $this->offset(2)."}\n";
|
||
|
}
|
||
|
}
|
||
|
$str .= $this->offset()."}\n\n";
|
||
|
|
||
|
return $str;
|
||
|
}
|
||
|
|
||
|
}
|