ddnet/datasrc/datatypes.py
2008-09-01 17:30:20 +00:00

299 lines
8 KiB
Python

GlobalIdCounter = 0
def GetID():
global GlobalIdCounter
GlobalIdCounter += 1
return GlobalIdCounter
def GetUID():
return "x%d"%GetID()
class BaseType:
def __init__(self, type_name):
self._type_name = type_name
self._target_name = "INVALID"
self._id = GetID() # this is used to remeber what order the members have in structures etc
def Identifyer(self): return "x"+str(self._id)
def TargetName(self): return self._target_name
def TypeName(self): return self._type_name
def ID(self): return self._id;
def EmitDeclaration(self, name):
return ["%s %s;"%(self.TypeName(), name)]
def EmitPreDefinition(self, target_name):
self._target_name = target_name
return []
def EmitDefinition(self, name):
return []
class MemberType:
def __init__(self, name, var):
self.name = name
self.var = var
class Struct(BaseType):
def __init__(self, type_name):
BaseType.__init__(self, type_name)
def Members(self):
def sorter(a,b):
return a.var.ID()-b.var.ID()
m = []
for name in self.__dict__:
if name[0] == "_":
continue
m += [MemberType(name, self.__dict__[name])]
try:
m.sort(sorter)
except:
for v in m:
print v.name, v.var
sys.exit(-1)
return m
def EmitTypeDeclaration(self, name):
lines = []
lines += ["struct " + self.TypeName()]
lines += ["{"]
for member in self.Members():
lines += ["\t"+l for l in member.var.EmitDeclaration(member.name)]
lines += ["};"]
return lines
def EmitPreDefinition(self, target_name):
BaseType.EmitPreDefinition(self, target_name)
lines = []
for member in self.Members():
lines += member.var.EmitPreDefinition(target_name+"."+member.name)
return lines
def EmitDefinition(self, name):
lines = ["/* %s */ {" % self.TargetName()]
for member in self.Members():
lines += ["\t" + " ".join(member.var.EmitDefinition("")) + ","]
lines += ["}"]
return lines
class Array(BaseType):
def __init__(self, type):
BaseType.__init__(self, type.TypeName())
self.type = type
self.items = []
def Add(self, instance):
if instance.TypeName() != self.type.TypeName():
error("bah")
self.items += [instance]
def EmitDeclaration(self, name):
return ["int num_%s;"%(name),
"%s *%s;"%(self.TypeName(), name)]
def EmitPreDefinition(self, target_name):
BaseType.EmitPreDefinition(self, target_name)
lines = []
i = 0
for item in self.items:
lines += item.EmitPreDefinition("%s[%d]"%(self.Identifyer(), i))
i += 1
if len(self.items):
lines += ["static %s %s[] = {"%(self.TypeName(), self.Identifyer())]
for item in self.items:
itemlines = item.EmitDefinition("")
lines += ["\t" + " ".join(itemlines).replace("\t", " ") + ","]
lines += ["};"]
else:
lines += ["static %s *%s = 0;"%(self.TypeName(), self.Identifyer())]
return lines
def EmitDefinition(self, name):
return [str(len(self.items))+","+self.Identifyer()]
# Basic Types
class Int(BaseType):
def __init__(self, value):
BaseType.__init__(self, "int")
self.value = value
def Set(self, value):
self.value = value
def EmitDefinition(self, name):
return ["%d"%self.value]
#return ["%d /* %s */"%(self.value, self._target_name)]
class Float(BaseType):
def __init__(self, value):
BaseType.__init__(self, "float")
self.value = value
def Set(self, value):
self.value = value
def EmitDefinition(self, name):
return ["%f"%self.value]
#return ["%d /* %s */"%(self.value, self._target_name)]
class String(BaseType):
def __init__(self, value):
BaseType.__init__(self, "const char*")
self.value = value
def Set(self, value):
self.value = value
def EmitDefinition(self, name):
return ['"'+self.value+'"']
class Pointer(BaseType):
def __init__(self, type, target):
BaseType.__init__(self, "%s*"%type().TypeName())
self.target = target
def Set(self, target):
self.target = target
def EmitDefinition(self, name):
return ["&"+self.target.TargetName()]
# helper functions
def EmitTypeDeclaration(root):
for l in root().EmitTypeDeclaration(""):
print l
def EmitDefinition(root, name):
for l in root.EmitPreDefinition(name):
print l
print "%s %s = " % (root.TypeName(), name)
for l in root.EmitDefinition(name):
print l
print ";"
# Network stuff after this
class Object:
pass
class Enum():
def __init__(self, name, values):
self.name = name
self.values = values
class Flags():
def __init__(self, name, values):
self.name = name
self.values = values
class NetObject:
def __init__(self, name, variables):
l = name.split(":")
self.name = l[0].lower()
self.base = ""
if len(l) > 1:
self.base = l[1]
self.base_struct_name = "NETOBJ_%s" % self.base.upper()
self.struct_name = "NETOBJ_%s" % self.name.upper()
self.enum_name = "NETOBJTYPE_%s" % self.name.upper()
self.variables = variables
def emit_declaration(self):
if self.base:
lines = ["struct %s : public %s"%(self.struct_name,self.base_struct_name), "{"]
else:
lines = ["struct %s"%self.struct_name, "{"]
for v in self.variables:
lines += ["\t"+line for line in v.emit_declaration()]
lines += ["};"]
return lines
def emit_validate(self):
lines = ["static int validate_%s(void *data, int size)" % self.name]
lines += ["{"]
lines += ["\t%s *obj = (%s *)data;"%(self.struct_name, self.struct_name)]
lines += ["\tif(sizeof(*obj) != size) return -1;"]
for v in self.variables:
lines += ["\t"+line for line in v.emit_validate()]
lines += ["\treturn 0;"]
lines += ["}"]
return lines
class NetEvent(NetObject):
def __init__(self, name, variables):
NetObject.__init__(self, name, variables)
self.base_struct_name = "NETEVENT_%s" % self.base.upper()
self.struct_name = "NETEVENT_%s" % self.name.upper()
self.enum_name = "NETEVENTTYPE_%s" % self.name.upper()
class NetMessage(NetObject):
def __init__(self, name, variables):
NetObject.__init__(self, name, variables)
self.base_struct_name = "NETMSG_%s" % self.base.upper()
self.struct_name = "NETMSG_%s" % self.name.upper()
self.enum_name = "NETMSGTYPE_%s" % self.name.upper()
def emit_unpack(self):
lines = []
lines += ["static void *secure_unpack_%s()" % self.name]
lines += ["{"]
lines += ["\tstatic %s msg;" % self.struct_name]
for v in self.variables:
lines += ["\t"+line for line in v.emit_unpack()]
for v in self.variables:
lines += ["\t"+line for line in v.emit_unpack_check()]
lines += ["\treturn &msg;"]
lines += ["}"]
return lines
def emit_declaration(self):
extra = []
extra += ["\tvoid pack(int flags)"]
extra += ["\t{"]
extra += ["\t\tmsg_pack_start(%s, flags);"%self.enum_name]
for v in self.variables:
extra += ["\t\t"+line for line in v.emit_pack()]
extra += ["\t\tmsg_pack_end();"]
extra += ["\t}"]
lines = NetObject.emit_declaration(self)
lines = lines[:-1] + extra + lines[-1:]
return lines
class NetVariable:
def __init__(self, name):
self.name = name
def emit_declaration(self):
return []
def emit_validate(self):
return []
def emit_pack(self):
return []
def emit_unpack(self):
return []
def emit_unpack_check(self):
return []
class NetString(NetVariable):
def emit_declaration(self):
return ["const char *%s;"%self.name]
def emit_unpack(self):
return ["msg.%s = msg_unpack_string();" % self.name]
def emit_pack(self):
return ["msg_pack_string(%s, -1);" % self.name]
class NetIntAny(NetVariable):
def emit_declaration(self):
return ["int %s;"%self.name]
def emit_unpack(self):
return ["msg.%s = msg_unpack_int();" % self.name]
def emit_pack(self):
return ["msg_pack_int(%s);" % self.name]
class NetIntRange(NetIntAny):
def __init__(self, name, min, max):
NetIntAny.__init__(self,name)
self.min = str(min)
self.max = str(max)
def emit_validate(self):
return ["netobj_clamp_int(\"%s\", obj->%s, %s, %s);"%(self.name,self.name, self.min, self.max)]
def emit_unpack_check(self):
return ["if(msg.%s < %s || msg.%s > %s) { msg_failed_on = \"%s\"; return 0; }" % (self.name, self.min, self.name, self.max, self.name)]
class NetBool(NetIntRange):
def __init__(self, name):
NetIntRange.__init__(self,name,0,1)
class NetTick(NetIntRange):
def __init__(self, name):
NetIntRange.__init__(self,name,0,'max_int')