1
0
mirror of https://github.com/Rogiel/star-replay synced 2025-12-06 06:32:46 +00:00

Initial commit

This commit is contained in:
2016-01-18 21:16:10 -02:00
commit 6c6a46e1cb
237 changed files with 48572 additions and 0 deletions

51
bin/Template/Event.php Normal file
View File

@@ -0,0 +1,51 @@
<?php
/**
* Copyright (c) 2016, Rogiel Sulzbach
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
namespace Rogiel\StarReplay\Event\{Type};
class {Name} extends Abstract{Type}Event {{
{Fields}
/**
* @return string the event name
*/
public function getEventName() {{
return "{FullName}";
}}
/**
* @return string a string representation of the event
*/
public function __toString() {{
return $this->getEventName()."{{ {ToString} }}";
}}
{Getters}
}}

122
bin/Template/Version.php Normal file
View File

@@ -0,0 +1,122 @@
<?php
/**
* Copyright (c) 2016, Rogiel Sulzbach
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
namespace Rogiel\StarReplay\Version;
use Rogiel\StarReplay\Parser\Serializer\Tree\Tree;
use Rogiel\StarReplay\Parser\Serializer\Tree\Node\ArrayNode;
use Rogiel\StarReplay\Parser\Serializer\Tree\Node\BitArrayNode;
use Rogiel\StarReplay\Parser\Serializer\Tree\Node\BlobNode;
use Rogiel\StarReplay\Parser\Serializer\Tree\Node\BooleanNode;
use Rogiel\StarReplay\Parser\Serializer\Tree\Node\ChoiceNode;
use Rogiel\StarReplay\Parser\Serializer\Tree\Node\IntegerNode;
use Rogiel\StarReplay\Parser\Serializer\Tree\Node\FourCCNode;
use Rogiel\StarReplay\Parser\Serializer\Tree\Node\NullNode;
use Rogiel\StarReplay\Parser\Serializer\Tree\Node\OptionalNode;
use Rogiel\StarReplay\Parser\Serializer\Tree\Node\StructNode;
class Version{Version} extends AbstractVersion {{
public static $TREE;
public static $GAME_EVENT_MAPPING;
public static $MESSAGE_EVENT_MAPPING;
public static $TRACKER_EVENT_MAPPING;
public function getVersion() {{
return {Version};
}}
public function getTree() {{
return self::$TREE;
}}
public function getGameEventMapping() {{
return self::$GAME_EVENT_MAPPING;
}}
public function getMessageEventMapping() {{
return self::$MESSAGE_EVENT_MAPPING;
}}
public function getTrackerEventMapping() {{
return self::$TRACKER_EVENT_MAPPING;
}}
public function getReplayHeaderNode() {{
return self::$TREE->getNode({HeaderNode});
}}
public function getReplayInitDataNode() {{
return self::$TREE->getNode({InitDataNode});
}}
public function getGameDetailsNode() {{
return self::$TREE->getNode({GameDetailsNode});
}}
public function getGameEventHeaderNode() {{
return new StructNode(
[
'timestamp' => ['type' => {TimestampNode}],
'user' => ['type' => {UserNode}],
'event' => ['type' => {GameEventNode}]
],
'Rogiel\StarReplay\Metadata\Event\Header',
true
);
}}
public function getMessageEventHeaderNode() {{
return new StructNode(
[
'timestamp' => ['type' => {TimestampNode}],
'user' => ['type' => {UserNode}],
'event' => ['type' => {MessageEventNode}]
],
'Rogiel\StarReplay\Metadata\Event\Header',
true
);
}}
public function getTrackerEventHeaderNode() {{
return new StructNode(
[
'timestamp' => ['type' => {TimestampNode}],
'event' => ['type' => {TrackerEventNode}]
],
'Rogiel\StarReplay\Metadata\Event\Header',
true
);
}}
}}
Version{Version}::$TREE = new Tree({Tree});
Version{Version}::$GAME_EVENT_MAPPING = {GameEvents};
Version{Version}::$MESSAGE_EVENT_MAPPING = {MessageEvents};
Version{Version}::$TRACKER_EVENT_MAPPING = {TrackerEvents};

37
bin/Template/Versions.php Normal file
View File

@@ -0,0 +1,37 @@
<?php
/**
* Copyright (c) 2016, Rogiel Sulzbach
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
namespace Rogiel\StarReplay\Version;
class Versions {{
public static function getVersions() {{
return {Versions};
}}
}}

148
bin/class_mapping.py Normal file
View File

@@ -0,0 +1,148 @@
def find_struct_field(protocol, struct, field_name):
for field in struct[1][0]:
if field[0] == field_name:
return field
return None
def set_class(mapping, protocol, field, class_name):
if field == None:
return
if protocol.typeinfos[field[1]][0] == '_optional':
mapping[protocol.typeinfos[field[1]][0][1]] = class_name
mapping[field[1]] = class_name
def detect_class_types(protocol):
mapping = {}
mapping[protocol.replay_header_typeid] = 'Rogiel\StarReplay\Metadata\Header\Header'
replay_header = protocol.typeinfos[protocol.replay_header_typeid]
for f in replay_header[1][0]:
if f[0] == "m_version":
mapping[f[1]] = 'Rogiel\StarReplay\Metadata\Header\Version'
if f[0] == "m_ngdpRootKey":
mapping[f[1]] = 'Rogiel\StarReplay\Metadata\Header\Hash'
mapping[protocol.game_details_typeid] = 'Rogiel\StarReplay\Metadata\Match\MatchInformation'
game_info = protocol.typeinfos[protocol.game_details_typeid]
for f in game_info[1][0]:
if f[0] == "m_playerList":
playerList = f[1]
playerList = protocol.typeinfos[playerList][1][0]
mapping[playerList] = 'Rogiel\StarReplay\Metadata\Match\PlayerList'
playerList = protocol.typeinfos[playerList][1][1]
mapping[playerList] = 'Rogiel\StarReplay\Entity\Player'
for t in protocol.typeinfos[playerList][1][0]:
if t[0] == "m_toon":
mapping[t[1]] = 'Rogiel\StarReplay\Entity\Toon'
if t[0] == "m_color":
mapping[t[1]] = 'Rogiel\StarReplay\Entity\Color'
if f[0] == "m_thumbnail":
mapping[f[1]] = 'Rogiel\StarReplay\Entity\Thumbnail'
mapping[protocol.replay_initdata_typeid] = 'Rogiel\StarReplay\Metadata\Init\InitData'
game_info = protocol.typeinfos[protocol.replay_initdata_typeid]
for f in game_info[1][0]:
if f[0] == "m_syncLobbyState":
mapping[f[1]] = 'Rogiel\StarReplay\Metadata\Init\SyncLobbyState'
for t in protocol.typeinfos[f[1]][1][0]:
if t[0] == "m_userInitialData":
mapping[t[1]] = 'Rogiel\StarReplay\Metadata\Init\UserInitialDataCollection'
mapping[protocol.typeinfos[t[1]][1][1]] = 'Rogiel\StarReplay\Metadata\Init\UserInitialData'
if t[0] == "m_gameDescription":
mapping[t[1]] = 'Rogiel\StarReplay\Metadata\Init\GameDescription'
for r in protocol.typeinfos[t[1]][1][0]:
if r[0] == "m_gameOptions":
mapping[r[1]] = 'Rogiel\StarReplay\Metadata\Init\GameOptions'
if t[0] == "m_lobbyState":
mapping[t[1]] = 'Rogiel\StarReplay\Metadata\Init\LobbyState'
for index, type in enumerate(protocol.typeinfos):
if type[0] == '_struct':
for field in type[1][0]:
if field[0] == 'x':
mapping[index] = 'Rogiel\StarReplay\Entity\Point'
for event in protocol.game_event_types.iteritems():
event_name = event[1][1][11:]
mapping[event[1][0]] = 'Rogiel\StarReplay\Event\Game\{0}'.format(event_name)
if event_name == 'TriggerSoundLengthSyncEvent':
sync_info = find_struct_field(protocol, protocol.typeinfos[event[1][0]], 'm_syncInfo')
mapping[sync_info[1]] = 'Rogiel\StarReplay\Event\Game\Entity\SoundLengthSync'
if event_name == 'BankSignatureEvent':
signature = find_struct_field(protocol, protocol.typeinfos[event[1][0]], 'm_signature')
mapping[signature[1]] = 'Rogiel\StarReplay\Event\Game\Entity\BankSignature'
if event_name == 'ResourceRequestEvent':
resources = find_struct_field(protocol, protocol.typeinfos[event[1][0]], 'm_resources')
mapping[resources[1]] = 'Rogiel\StarReplay\Event\Game\Entity\ResourceRequest'
if event_name == 'SelectionDeltaEvent':
delta = find_struct_field(protocol, protocol.typeinfos[event[1][0]], 'm_delta')
struct = protocol.typeinfos[delta[1]]
mapping[delta[1]] = 'Rogiel\StarReplay\Event\Game\Entity\SelectionDelta'
m_addSubgroups = find_struct_field(protocol, struct, 'm_addSubgroups')
if m_addSubgroups:
list = protocol.typeinfos[m_addSubgroups[1]]
mapping[list[1][1]] = 'Rogiel\StarReplay\Event\Game\Entity\SubgroupUnit'
if event_name == 'ControlGroupUpdateEvent':
mask = find_struct_field(protocol, protocol.typeinfos[event[1][0]], 'm_mask')
mask = protocol.typeinfos[mask[1]]
if mask[0] == '_choice':
for choice in mask[1][1].iteritems():
if choice[1][0] == 'Mask':
mapping[choice[1][1]] = 'Rogiel\StarReplay\Event\Game\Entity\ControlGroupUpdateMask'
if choice[1][0] == 'OneIndices':
mapping[choice[1][1]] = 'Rogiel\StarReplay\Event\Game\Entity\ControlGroupUpdateOneIndices'
if choice[1][0] == 'ZeroIndices':
mapping[choice[1][1]] = 'Rogiel\StarReplay\Event\Game\Entity\ControlGroupUpdateZeroIndices'
# print protocol.typeinfos[mask[1]][1][0]
# mask = protocol.typeinfos[protocol.typeinfos[mask[1]][1][0]]
# if mask[0] == '_optional':
# print mask
# exit()
# for key, option in protocol.typeinfos[mask[1]][2].iteritems():
# print option
# exit()
if event_name == 'CmdEvent':
abil = find_struct_field(protocol, protocol.typeinfos[event[1][0]], 'm_abil')
if abil:
mapping[protocol.typeinfos[abil[1]][1][0]] = 'Rogiel\StarReplay\Event\Game\Entity\Ability'
data = find_struct_field(protocol, protocol.typeinfos[event[1][0]], 'm_data')
if data:
for i, opt in protocol.typeinfos[data[1]][1][1].iteritems():
if opt[0] == 'TargetUnit':
mapping[opt[1]] = 'Rogiel\StarReplay\Event\Game\Entity\TargetUnit'
for event in protocol.message_event_types.iteritems():
event_name = event[1][1][11:]
mapping[event[1][0]] = 'Rogiel\StarReplay\Event\Message\{0}'.format(event_name)
if hasattr(protocol, 'tracker_event_types'):
for event in protocol.tracker_event_types.iteritems():
if event[1][1] == "NNet.Replay.Tracker.SPlayerStatsEvent":
for type in protocol.typeinfos[event[1][0]][1][0]:
if type[0] == "m_stats":
mapping[type[1]] = 'Rogiel\StarReplay\Event\Tracker\PlayerStats'
if event[1][1] == "NNet.Replay.Tracker.SUnitPositionsEvent":
for type in protocol.typeinfos[event[1][0]][1][0]:
if type[0] == "m_items":
mapping[type[1]] = 'Rogiel\StarReplay\Event\Tracker\UnitPositions'
event_name = event[1][1][21:]
mapping[event[1][0]] = 'Rogiel\StarReplay\Event\Tracker\{0}'.format(event_name)
return mapping

167
bin/generator.py Executable file
View File

@@ -0,0 +1,167 @@
import glob
import os
import sys
import logging
import tree as tree_generator
import template as template_generator
import class_mapping
sys.path.append('../s2protocol/')
current_path = os.path.dirname(os.path.realpath(__file__))
output_directory = current_path + "/../src/Version"
all_versions = []
protocols = glob.glob("../s2protocol/protocol*.py")
for protocolFile in protocols:
protocolBaseName = os.path.basename(protocolFile)
protocolName = protocolBaseName[:-3]
version = protocolBaseName[8:-3]
all_versions.append(version)
protocol = __import__(protocolName)
classes = class_mapping.detect_class_types(protocol)
events = template_generator.generate_game_event_template(protocol)
message_events = template_generator.generate_message_event_template(protocol)
tracker_events = template_generator.generate_tracker_event_template(protocol)
tree = tree_generator.generate_tree(protocol, classes)
if hasattr(protocol, 'replay_userid_typeid'):
useridNode = protocol.replay_userid_typeid
else:
useridNode = protocol.replay_playerid_typeid
if hasattr(protocol, 'tracker_eventid_typeid'):
tracker_eventid_typeid = protocol.tracker_eventid_typeid
else:
tracker_eventid_typeid = 'NULL'
template_vars = {
'Version': version,
'Tree': tree,
'TimestampNode': protocol.svaruint32_typeid,
'UserNode': useridNode,
'GameEventNode': protocol.game_eventid_typeid,
'MessageEventNode': protocol.message_eventid_typeid,
'TrackerEventNode': tracker_eventid_typeid,
'GameEvents': events,
'MessageEvents': message_events,
'TrackerEvents': tracker_events,
'HeaderNode': protocol.replay_header_typeid,
'GameDetailsNode': protocol.game_details_typeid,
'InitDataNode': protocol.replay_initdata_typeid
}
if not os.path.exists(output_directory):
os.makedirs(output_directory)
template_generator.parse_template(current_path + "/Template/Version.php",
"{0}/Version{1}.php".format(output_directory, version), template_vars)
all_versions_generated = "[\n"
for version in all_versions:
all_versions_generated += "\t\t\t{0} => 'Rogiel\StarReplay\Version\Version{0}',\n".format(version)
all_versions_generated = all_versions_generated[:-2] + "\n\t\t]"
template_vars = {
'Versions': all_versions_generated,
}
template_generator.parse_template(current_path + "/Template/Versions.php", "{0}/Versions.php".format(output_directory), template_vars)
def extract_field_type(field):
field_type = classes.get(field)
if field_type:
field_type = "\\"+field_type
else:
field_type_struct = protocol.typeinfos[field]
if(field_type_struct[0] == '_int'):
field_type = "integer"
elif(field_type_struct[0] == '_blob'):
field_type = "string"
elif(field_type_struct[0] == '_array'):
field_type = "array"
elif(field_type_struct[0] == '_null'):
field_type = "null"
elif(field_type_struct[0] == '_bool'):
field_type = "boolean"
elif(field_type_struct[0] == '_struct'):
logging.warn("Non mapped struct: %s. Falling back to array.", field_type_struct)
field_type = "struct"
elif(field_type_struct[0] == '_choice'):
field_type = ""
for choice in protocol.typeinfos[field][1][1].iteritems():
field_type += "{0}|".format(extract_field_type(choice[1][1]))
field_type = field_type[:-1]
elif(field_type_struct[0] == '_optional'):
field_type = "null|{0}".format(extract_field_type(protocol.typeinfos[field][1][0]))
elif(field_type_struct[0] == '_bitarray'):
field_type = "integer"
elif(field_type_struct[0] == '_fourcc'):
field_type = "integer"
else:
logging.error("Unknown type for field: %s. Ignoring type mapping.", field_type_struct)
return field_type
def parse_event_template(event, type, prefix, input, output_directory):
event_name = event["event"][1][1][len(prefix):]
full_name = event["event"][1][1]
fields = ""
to_string = ""
getters = ""
for field in event["type"][1][0]:
field_name = field[0][2:]
camel_field_name = template_generator.capital_first_letter(field_name)
field_type = extract_field_type(field[1])
if field_type:
fields += "\t/** @var {0} */\n".format(field_type)
fields += "\tpublic ${0};\n\n".format(field_name)
# if protocol.typeinfos[field[1]][0] == '_array':
# exit()
to_string += "{0} = $this->{0}, ".format(field_name)
if field_type:
getters += "\t/** @return {0} */\n".format(field_type)
getters += "\tpublic function get{0}() {{ return $this->{1}; }}\n\n".format(camel_field_name, field_name)
template_vars = {
'Name': event_name,
'FullName': full_name,
'Type': type,
'Fields': fields.rstrip('\n'),
'ToString': to_string[:-2],
'Getters': getters.rstrip('\n')
}
template_generator.parse_template(input, "{0}/{1}.php".format(output_directory, event_name), template_vars)
for name, event in template_generator.all_game_events.iteritems():
current_path = os.path.dirname(os.path.realpath(__file__))
output_directory = current_path + "/../src/Event/Game"
if not os.path.exists(output_directory):
os.makedirs(output_directory)
parse_event_template(event, 'Game', 'NNet.Game.S', current_path + "/Template/Event.php", output_directory)
for name, event in template_generator.all_message_events.iteritems():
current_path = os.path.dirname(os.path.realpath(__file__))
output_directory = current_path + "/../src/Event/Message"
if not os.path.exists(output_directory):
os.makedirs(output_directory)
parse_event_template(event, 'Message', 'NNet.Game.S', current_path + "/Template/Event.php", output_directory)
for name, event in template_generator.all_tracker_events.iteritems():
current_path = os.path.dirname(os.path.realpath(__file__))
output_directory = current_path + "/../src/Event/Tracker"
if not os.path.exists(output_directory):
os.makedirs(output_directory)
parse_event_template(event, 'Tracker', 'NNet.Replay.Tracker.S', current_path + "/Template/Event.php", output_directory)

67
bin/template.py Normal file
View File

@@ -0,0 +1,67 @@
all_game_events = {}
def generate_game_event_template(protocol):
generated = "[\n"
for event in protocol.game_event_types.iteritems():
name = event[1][1][11:]
all_game_events[name] = {}
all_game_events[name]["event"] = event
all_game_events[name]["type"] = protocol.typeinfos[event[1][0]]
template_vars = {
'ID': event[0],
'Name': name,
'Node': event[1][0],
}
generated += "\t{ID} => {Node},\n".format(**template_vars)
generated += "]"
return generated
all_message_events = {}
def generate_message_event_template(protocol):
generated = "[\n"
for event in protocol.message_event_types.iteritems():
name = event[1][1][11:]
all_message_events[name] = {}
all_message_events[name]["event"] = event
all_message_events[name]["type"] = protocol.typeinfos[event[1][0]]
template_vars = {
'ID': event[0],
'Name': name,
'Node': event[1][0],
}
generated += "\t{ID} => {Node},\n".format(**template_vars)
generated += "]"
return generated
all_tracker_events = {}
def generate_tracker_event_template(protocol):
if hasattr(protocol, 'tracker_event_types'):
generated = "[\n"
for event in protocol.tracker_event_types.iteritems():
name = event[1][1][11:]
all_tracker_events[name] = {}
all_tracker_events[name]["event"] = event
all_tracker_events[name]["type"] = protocol.typeinfos[event[1][0]]
template_vars = {
'ID': event[0],
'Name': name,
'Node': event[1][0],
}
generated += "\t{ID} => {Node},\n".format(**template_vars)
generated += "]"
return generated
else:
return "NULL"
def parse_template(input_file, output_file, vars):
print(output_file)
with open(input_file, 'r') as ftemp:
templateString = ftemp.read()
with open(output_file, 'w') as f:
f.write(templateString.format(**vars))
def capital_first_letter(s):
return s[0].upper() + s[1:]

111
bin/tree.py Normal file
View File

@@ -0,0 +1,111 @@
def generate_integer(bounds, className):
generated = "new IntegerNode({0}, {1}".format(bounds[0][1], bounds[0][0])
if className:
generated += ", '{0}'".format(className)
return generated + ")"
def generate_choice(tagger, choices, className):
generated = "new ChoiceNode(new IntegerNode({0}), [\n".format(tagger[1])
for index, choice in choices.iteritems():
generated += "\t{tag} => {index},\n".format(tag = index, index = choice[1])
generated += "]"
if className:
generated += ", '{0}'".format(className)
return generated + ")"
def generate_struct(members, className):
generated = "new StructNode([\n"
for member in members[0]:
if member:
member_name = member[0]
if member_name.startswith('m_'):
member_name = member[0][2:]
generated += "\t\"{name}\" => array('type' => {index}, 'tag' => {tag}),\n".format(name = member_name, index = member[1], tag = member[2])
generated += "]"
if className:
generated += ",\n\t'{0}'\n".format(className)
generated += ")"
return generated
def generate_optional(bounds, className):
generated = "new OptionalNode({0}".format(bounds[0])
if className:
generated += ", '{0}'".format(className)
return generated + ")"
def generate_blob(bounds, className):
generated = "new BlobNode(new IntegerNode({0}, {1})".format(bounds[0][1], bounds[0][0])
if className:
generated += ", '{0}'".format(className)
return generated + ")"
def generate_bool(className):
generated = "new BooleanNode("
if className:
generated += ", '{0}'".format(className)
return generated + ")"
def generate_array(bounds, className):
generated = "new ArrayNode(\n"
generated += "\tnew IntegerNode({size}, {constant}),\n".format(size=bounds[0][1], constant=bounds[0][0])
generated += "\t{0}".format(bounds[1])
if className:
generated += ",\n\t'{0}'\n".format(className)
generated += "\n)"
return generated
def generate_bitarray(bounds, className):
generated = "new BitArrayNode(\n"
generated += "\tnew IntegerNode({size}, {constant})\n".format(size=bounds[0][1], constant=bounds[0][0])
if className:
generated += ",\n\t'{0}'".format(className)
generated += ")"
return generated
def generate_null(className):
return "new NullNode()"
def generate_fourcc(className):
generated = "new FourCCNode("
if className:
generated += ", '{0}'".format(className)
generated += ")"
return generated
def generate_tree(protocol, classes):
nodes = []
for index, typeinfo in enumerate(protocol.typeinfos):
if typeinfo[0] == "_int":
generated = generate_integer(typeinfo[1], classes.get(index))
elif typeinfo[0] == "_choice":
generated = generate_choice(typeinfo[1][0], typeinfo[1][1], classes.get(index))
elif typeinfo[0] == "_struct":
generated = generate_struct(typeinfo[1], classes.get(index))
elif typeinfo[0] == "_optional":
generated = generate_optional(typeinfo[1], classes.get(index))
elif typeinfo[0] == "_blob":
generated = generate_blob(typeinfo[1], classes.get(index))
elif typeinfo[0] == "_bool":
generated = generate_bool(classes.get(index))
elif typeinfo[0] == "_array":
generated = generate_array(typeinfo[1], classes.get(index))
elif typeinfo[0] == "_bitarray":
generated = generate_bitarray(typeinfo[1], classes.get(index))
elif typeinfo[0] == "_fourcc":
generated = generate_fourcc(classes.get(index))
elif typeinfo[0] == "_null":
generated = generate_null(classes.get(index))
else:
print "Node %s unknown!" % typeinfo[0]
exit()
nodes.append(generated)
tree = "[\n"
for index, node in enumerate(nodes):
tree += "{index} => {code},\n".format(index=index, code = node)
tree += "]\n"
return tree