Fixed handling of null-termination in the string and unicode string readers.
[~jspiros/python-ebml.git] / ebml / schema / base.py
1 __all__ = ('INT', 'UINT', 'FLOAT', 'STRING', 'UNICODE', 'DATE', 'BINARY', 'CONTAINER', 'Element', 'EBML')
2
3
4 INT, UINT, FLOAT, STRING, UNICODE, DATE, BINARY, CONTAINER = range(0, 8)
5
6
7 class Element(object):
8         class_id = None
9         class_name = 'Unknown'
10         class_parents = ()
11         class_global = False
12         class_root = False
13         data_type = BINARY
14
15
16 class EBMLElement(Element):
17         class_id = 0x1A45DFA3
18         class_name = 'EBML'
19         class_root = True
20         data_type = CONTAINER
21
22
23 class EBMLVersionElement(Element):
24         class_id = 0x4286
25         class_name = 'EBMLVersion'
26         class_parents = (EBMLElement,)
27         data_type = UINT
28
29
30 class EBMLReadVersionElement(Element):
31         class_id = 0x42F7
32         class_name = 'EBMLReadVersion'
33         class_parents = (EBMLElement,)
34         data_type = UINT
35
36
37 class EBMLMaxIDLengthElement(Element):
38         class_id = 0x42F2
39         class_name = 'EBMLMaxIDLength'
40         class_parents = (EBMLElement,)
41         data_type = UINT
42
43
44 class EBMLMaxSizeLengthElement(Element):
45         class_id = 0x42F3
46         class_name = 'EBMLMaxSizeLength'
47         class_parents = (EBMLElement,)
48         data_type = UINT
49
50
51 class DocTypeElement(Element):
52         class_id = 0x4282
53         class_name = 'DocType'
54         class_parents = (EBMLElement,)
55         data_type = STRING
56
57
58 class DocTypeVersionElement(Element):
59         class_id = 0x4287
60         class_name = 'DocTypeVersion'
61         class_parents = (EBMLElement,)
62         data_type = UINT
63
64
65 class DocTypeReadVersionElement(Element):
66         class_id = 0x4285
67         class_name = 'DocTypeReadVersion'
68         class_parents = (EBMLElement,)
69         data_type = UINT
70
71
72 class CRC32Element(Element):
73         class_id = 0xBF
74         class_name = 'CRC-32'
75         class_global = True
76         data_type = BINARY
77
78
79 class VoidElement(Element):
80         class_id = 0xEC
81         class_name = 'Void'
82         class_global = True
83         data_type = BINARY
84
85
86 class SignatureSlotElement(Element):
87         class_id = 0x1B538667
88         class_name = 'SignatureSlot'
89         class_global = True
90         data_type = CONTAINER
91
92
93 class SignatureAlgoElement(Element):
94         class_id = 0x7E8A
95         class_name = 'SignatureAlgo'
96         class_parents = (SignatureSlotElement,)
97         data_type = UINT
98
99
100 class SignatureHashElement(Element):
101         class_id = 0x7E9A
102         class_name = 'SignatureHash'
103         class_parents = (SignatureSlotElement,)
104         data_type = UINT
105
106
107 class SignaturePublicKeyElement(Element):
108         class_id = 0x7EA5
109         class_name = 'SignaturePublicKey'
110         class_parents = (SignatureSlotElement,)
111         data_type = BINARY
112
113
114 class SignatureElement(Element):
115         class_id = 0x7EB5
116         class_name = 'Signature'
117         class_parents = (SignatureSlotElement,)
118         data_type = BINARY
119
120
121 class SignatureElementsElement(Element):
122         class_id = 0x7E5B
123         class_name = 'SignatureElements'
124         class_parents = (SignatureSlotElement,)
125         data_type = CONTAINER
126
127
128 class SignatureElementListElement(Element):
129         class_id = 0x7E7B
130         class_name = 'SignatureElementList'
131         class_parents = (SignatureElementsElement,)
132         data_type = CONTAINER
133
134
135 class SignedElementElement(Element):
136         class_id = 0x6532
137         class_name = 'SignedElement'
138         class_parents = (SignatureElementListElement,)
139         data_type = BINARY
140
141
142 class Schema(object):
143         doc_type = None
144         version = None
145         elements_by_class_id = None
146         
147         @classmethod
148         def element_with_class_id(cls, class_id):
149                 if cls.elements_by_class_id is None:
150                         cls.elements_by_class_id = {}
151                         for element in cls.elements:
152                                 cls.elements_by_class_id[element.class_id] = element
153                 return cls.elements_by_class_id[class_id]
154         
155         @classmethod
156         def global_elements(cls):
157                 return [element for element in cls.elements if element.class_global]
158         
159         @classmethod
160         def root_elements(cls):
161                 return [element for element in cls.elements if element.class_root]
162         
163         @classmethod
164         def child_elements_of_element(cls, parent):
165                 children = [element for element in cls.elements if parent in element.class_parents]
166                 children += cls.global_elements()
167                 if 'self' in parent.class_parents and parent not in children:
168                         children.append(parent)
169                 return children
170
171
172 class EBML(Schema):
173         elements = (
174                 EBMLElement,
175                 EBMLVersionElement,
176                 EBMLReadVersionElement,
177                 EBMLMaxIDLengthElement,
178                 EBMLMaxSizeLengthElement,
179                 DocTypeElement,
180                 DocTypeVersionElement,
181                 DocTypeReadVersionElement,
182                 CRC32Element,
183                 VoidElement,
184                 SignatureSlotElement,
185                 SignatureAlgoElement,
186                 SignatureHashElement,
187                 SignaturePublicKeyElement,
188                 SignatureElement,
189                 SignatureElementsElement,
190                 SignatureElementListElement,
191                 SignedElementElement
192         )