[protocol] Implement object arrays

This commit is contained in:
DankParrot 2020-08-19 16:06:38 -07:00
parent 8a6fdb67ef
commit 1e2e6da787
1 changed files with 55 additions and 16 deletions

View File

@ -33,9 +33,32 @@ def extract_array_type(type):
return type[:type.rfind('[')]
return type
def extract_array_count(type):
if '[' in type and ']' in type:
count = type[type.find('[')+1:type.rfind(']')]
def extract_array_count(value, name=''):
if isinstance(value, dict):
if name == '' or name == None:
raise Exception('extract_array_count called with dict value but name not provided')
idx = name.find('(')
if idx > 0:
idxend = name.find(')')
if idxend > idx:
attribute = name[idx+1:idxend]
name = name[:idx]
# array of objects key(#count): {...}
if attribute.startswith('#'):
count = attribute[1:]
if count.isdigit():
return int(count)
else:
return count
else:
warn('WARNING: Var name "{}" has unterminated () brackets', name)
return None
else:
return None
if '[' in value and ']' in value:
count = value[value.find('[')+1:value.rfind(']')]
if count.isdigit():
return int(count)
else:
@ -69,13 +92,8 @@ def get_type_info(types, typename):
return tp
def resolve_name(types, name, value, decl=False):
if isinstance(value, dict):
return name
typename = value
tp = get_type_info(types, typename)
fullname = name
idx = name.find('(')
if idx > 0:
@ -84,9 +102,10 @@ def resolve_name(types, name, value, decl=False):
warn('ERROR: Invalid variable name "{}"'.format(name))
exit(1)
# standard array syntax key: type[count]
if decl:
if is_type_array(types, typename):
count = extract_array_count(typename)
if is_type_array(types, fullname, value):
count = extract_array_count(value, fullname)
if type(count) is int:
# array of fixed size
name += '[' + str(count) + ']'
@ -109,20 +128,33 @@ def resolve_type(types, value):
else:
return typename
def is_type_array(types, typename):
def is_type_array(types, name, value):
if isinstance(value, dict):
return extract_array_count(value, name) != None
typename = value
tp = get_type_info(types, typename)
if 'size' in tp and tp['size'] == 'count':
return False
else:
return extract_array_count(typename) != None
def get_type_size(types, value):
def get_type_size(types, value, name=''):
global varint_max_size
if isinstance(value, dict):
if name == '' or name == None:
raise Exception('get_type_size called on dict value with no name')
size = 0
for k, v in value.items():
size += get_type_size(types, v)
if is_type_array(types, name, value):
count = extract_array_count(value, name)
if type(count) is int:
return size * count
else:
# TODO: handling size for variable arrays...
return size
return size
typename = value
@ -178,10 +210,17 @@ def print_rw_logic(types, value, name, read):
resolved_name = resolve_name(types, name, value)
if isinstance(value, dict):
is_array = is_type_array(types, name, value)
if is_array:
count = extract_array_count(value, name)
add_text(f'for (int i = 0; i < {count}; i++)')
add_text('{{')
indent()
for k, v in value.items():
scoped_name = f'{resolved_name}.{resolve_name(types, k, v)}'
scoped_name = resolved_name
if is_array:
scoped_name += '[i]'
scoped_name += f'.{resolve_name(types, k, v)}'
print_rw_logic(types, v, scoped_name, read)
unindent()
add_text('}}')
@ -204,7 +243,7 @@ def print_rw_logic(types, value, name, read):
rw_func = get_rw_func(types, typename, read)
if is_type_array(types, typename):
if is_type_array(types, name, typename):
# arrays
count = extract_array_count(typename)
arrtype = extract_array_type(typename)
@ -310,7 +349,7 @@ def print_messages(list, globalTypes):
size = varint_max_size # Packet Length
size += varint_max_size # Packet Id
for name, typename in message['vars'].items():
size += get_type_size(types, typename)
size += get_type_size(types, typename, name)
struct_name = '{}{}'.format(direction.capitalize(), message_name)
add_text('struct {}', struct_name)