Created
August 11, 2009 18:45
-
-
Save magcius/166043 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import struct | |
from pypy.translator.avm.util import serialize_u32 as u32 | |
# ====================================== | |
# Constants | |
# ====================================== | |
# String types | |
TYPE_STRING_Utf8 = 0x01 | |
# Number types | |
TYPE_NUMBER_Int = 0x03 | |
TYPE_NUMBER_UInt = 0x04 | |
TYPE_NUMBER_DOUBLE = 0x06 | |
# Boolean types | |
TYPE_BOOLEAN_False = 0x0A | |
TYPE_BOOLEAN_True = 0x0B | |
# Object types | |
TYPE_OBJECT_Undefined = 0x00 | |
TYPE_OBJECT_Null = 0x0C | |
# Namespace types | |
TYPE_NAMESPACE_PrivateNamespace = 0x05 | |
TYPE_NAMESPACE_Namespace = 0x08 | |
TYPE_NAMESPACE_PackageNamespace = 0x16 | |
TYPE_NAMESPACE_PackageInternalNs = 0x17 | |
TYPE_NAMESPACE_ProtectedNamespace = 0x18 | |
TYPE_NAMESPACE_ExplicitNamespace = 0x19 | |
TYPE_NAMESPACE_StaticProtectedNs = 0x1A | |
# Namespace Set types | |
TYPE_NAMESPACE_SET_NamespaceSet = 0x15 | |
# Multiname types | |
TYPE_MULTINAME_QName = 0x07 | |
TYPE_MULTINAME_QNameA = 0x0D | |
TYPE_MULTINAME_Multiname = 0x09 | |
TYPE_MULTINAME_MultinameA = 0x0E | |
TYPE_MULTINAME_RtqName = 0x0F | |
TYPE_MULTINAME_RtqNameA = 0x10 | |
TYPE_MULTINAME_RtqNameL = 0x11 | |
TYPE_MULTINAME_RtqNameLA = 0x12 | |
TYPE_MULTINAME_NameL = 0x13 | |
TYPE_MULTINAME_NameLA = 0x14 | |
TYPE_MULTINAME_MultinameL = 0x1B | |
TYPE_MULTINAME_MultinameLA = 0x1C | |
# ====================================== | |
# Namespaces | |
# ====================================== | |
class Namespace(object): | |
def __init__(self, kind, name): | |
self.kind = kind | |
self.name = name | |
self._name_index = None | |
def __eq__(self, other): | |
return self.name == other.name and self.kind == other.kind | |
def __ne__(self, other): | |
return self.name != other.name or self.kind != other.kind | |
def write_to_pool(self, pool): | |
self._name_index = pool.utf8_index(name) | |
def serialize(self): | |
assert self._name_index is not None, "Please call write_to_pool before serializing" | |
return chr(self.kind) + u32(self._name_index) | |
class NamespaceSet(object): | |
def __init__(self, *namespaces): | |
self.namespaces = namespaces | |
self._namespace_indices = None | |
def __len__(self): | |
return len(self.namespaces) | |
def __eq__(self, other): | |
return len(self) == len(other) and all(n1 == n2 for n1, n2 in zip(self.namespaces, other.namespaces)) | |
def __ne__(self, other): | |
return len(self) != len(other) or any(n1 != n2 for n1, n2 in zip(self.namespaces, other.namespaces)) | |
def write_to_pool(self, pool): | |
self._namespace_indices = [pool.namespace_index(ns) for ns in self.namespaces] | |
def serialize(self): | |
assert self._namespace_indices is not None, "Please call write_to_pool before serializing" | |
return u32(len(self.namespaces)) + ''.join(u32(index) for index in self_namespace_indices) | |
NO_NAMESPACE = Namespace(TYPE_NAMESPACE_Namespace, "") | |
ANY_NAMESPACE = Namespace(TYPE_NAMESPACE_Namespace, "*") | |
NO_NAMESPACE_SET = NamespaceSet() | |
# ====================================== | |
# Multinames | |
# ====================================== | |
class MultinameL(object): | |
KIND = TYPE_MULTINAME_MultinameL | |
def __init__(self, ns_set): | |
self.ns_set = ns_set | |
self._ns_set_index = None | |
def write_to_pool(self, pool): | |
self._ns_set_index = pool.nsset_index(self.ns_set) | |
def serialize(self): | |
assert self._ns_set_index is not None, "Please call write_to_pool before serializing" | |
return chr(self.KIND) + u32(self._ns_set_index) | |
class MultinameLA(MultinameL): | |
KIND = TYPE_MULTINAME_MultinameLA | |
class Multiname(MultinameL): | |
KIND = TYPE_MULTINAME_Multiname | |
def __init__(self, name, ns_set): | |
super(Multiname, self).__init__(ns_set) | |
self.name = name | |
self._name_index = None | |
def write_to_pool(self, pool): | |
super(Multiname, self).write_to_pool(pool) | |
self._name_index = pool.utf8_index(self.name) | |
def serialize(self): | |
assert self._name_index is not None, "Please call write_to_pool before serializing" | |
assert self._ns_set_index is not None, "Please call write_to_pool before serializing" | |
return chr(self.kind) + u32(self._name_index) + u32(self._ns_set_index) | |
class MultinameA(Multiname): | |
KIND = TYPE_MULTINAME_MultinameA | |
class QName(object): | |
KIND = TYPE_MULTINAME_QName | |
def __init__(self, name, ns): | |
self.name = name | |
self.ns = ns | |
self._name_index = None | |
self._ns_index = None | |
def write_to_pool(self, pool): | |
self._name_index = pool.utf8_index(self.name) | |
self._ns_index = pool.namespace_index(self.ns) | |
def serialize(self): | |
assert self._name_index is not None, "Please call write_to_pool before serializing" | |
assert self._ns_index is not None, "Please call write_to_pool before serializing" | |
return chr(self.kind) + u32(self._ns_index) + u32(self._name_index) | |
class QNameA(QName): | |
KIND = TYPE_MULTINAME_QNameA | |
class RtqNameL(object): | |
KIND = TYPE_MULTINAME_RtqNameL | |
def serialize(self): | |
return chr(self.kind) | |
class RtqNameLA(RtqNameL): | |
KIND = TYPE_MULTINAME_RtqNameLA | |
class RtqName(object):: | |
KIND = TYPE_MULTINAME_RtqName | |
def __init__(self, name): | |
self.name = name | |
self._name_index = None | |
def write_to_pool(self, pool): | |
self._name_index = pool.utf8_index(name) | |
def serialize(self): | |
assert self._name_index is not None, "Please call write_to_pool before serializing" | |
# ====================================== | |
# Constant Pool | |
# ====================================== | |
def constant_index_base(default, pool_name): | |
def fn(self, value): | |
if value == default: | |
return 0 | |
pool = getattr(self, pool_name) | |
if value in pool: | |
return pool.index(value) + 1 | |
else: | |
pool.append(value) | |
return len(pool) | |
return fn | |
class AbcConstantPool(object): | |
def __init__(self): | |
self.int_pool = [] | |
self.uint_pool = [] | |
self.double_pool = [] | |
self.utf8_pool = [] | |
self.namespace_pool = [] | |
self.nsset_pool = [] | |
self.multiname_pool = [] | |
int_index = constant_index_base(0, "int_pool") | |
uint_index = constant_index_base(0, "uint_pool") | |
double_index = constant_index_base(float("nan"), "double_pool") | |
utf8_index = constant_index_base("", "utf8_pool") | |
namespace_index = constant_index_base(ANY_NAMESPACE, "namespace_pool") | |
nsset_index = constant_index_base(NO_NAMESPACE_SET, "nsset_pool") | |
def has_RTNS(self, index): | |
return self.multiname_pool[index].kind in (TYPE_MULTINAME_RtqName, TYPE_MULTINAME_RtqNameA, TYPE_MULTINAME_RtqNameL, TYPE_MULTINAME_RtqNameLA) | |
def has_RTName(self, index): | |
return self.multiname_pool[index].kind in (TYPE_MULTINAME_MultinameL, TYPE_MULTINAME_MultinameLA, TYPE_MULTINAME_RtqNameL, TYPE_MULTINAME_RtqNameLA) | |
def serialize(self): | |
def double(double): | |
return struct.pack("<d", double) | |
def utf8(string): | |
return u32(len(string)) + string | |
def serializable(item): | |
item.write_to_pool(self) | |
return item.serialize() | |
def write_pool(pool, fn): | |
return u32(len(pool)) + ''.join(fn(i) for i in pool) | |
buffer = "" | |
buffer += write_pool(self.int_pool, u32) | |
buffer += write_pool(self.uint_pool, u32) | |
buffer += write_pool(self.double_pool, double) | |
buffer += write_pool(self.utf8_pool, utf8) | |
buffer += write_pool(self.namespace_pool, serializable) | |
buffer += write_pool(self.nsset_pool, serializable) | |
buffer += write_pool(self.multiname_pool, serializable) | |
return buffer | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment