From 1e2e6da7875e0fc431ab9ac680fd12582eacc104 Mon Sep 17 00:00:00 2001 From: DankParrot Date: Wed, 19 Aug 2020 16:06:38 -0700 Subject: [PATCH] [protocol] Implement object arrays --- src/protocol/generate_protocol.py | 71 ++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 16 deletions(-) diff --git a/src/protocol/generate_protocol.py b/src/protocol/generate_protocol.py index 0bb8fd1..20f534d 100644 --- a/src/protocol/generate_protocol.py +++ b/src/protocol/generate_protocol.py @@ -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)