Added a distutils script.
[pycfml.git] / classfile / file.py
CommitLineData
964561d6
FT
1import collections
2from . import binfmt
3
4ACC_PUBLIC = 0x0001
5ACC_PRIVATE = 0x0002
6ACC_PROTECTED = 0x0004
7ACC_STATIC = 0x0008
8ACC_FINAL = 0x0010
9ACC_SUPER = 0x0020
10ACC_SYNCHRONIZED = 0x0020
11ACC_VOLATILE = 0x0040
12ACC_BRIDGE = 0x0040
13ACC_TRANSIENT = 0x0080
14ACC_VARARGS = 0x0080
15ACC_NATIVE = 0x0100
16ACC_INTERFACE = 0x0200
17ACC_ABSTRACT = 0x0400
18ACC_STRICT = 0x0800
19ACC_SYNTHETIC = 0x1000
20ACC_ANNOTATION = 0x2000
21ACC_ENUM = 0x4000
22
23CONSTANT_Class = 7
24CONSTANT_Fieldref = 9
25CONSTANT_Methodref = 10
26CONSTANT_InterfaceMethodref = 11
27CONSTANT_String = 8
28CONSTANT_Integer = 3
29CONSTANT_Float = 4
30CONSTANT_Long = 5
31CONSTANT_Double = 6
32CONSTANT_NameAndType = 12
33CONSTANT_Utf8 = 1
34CONSTANT_MethodHandle = 15
35CONSTANT_MethodType = 16
36CONSTANT_InvokeDynamic = 18
37
38version = collections.namedtuple("version", ["major", "minor"])
39version.__eq__ = lambda s, o: s.major == o.major and s.minor == o.minor
40version.__ne__ = lambda s, o: s.major != o.major or s.minor != o.minor
41version.__lt__ = lambda s, o: (s.major < o.major) or (s.major == o.major and s.minor < o.minor)
42version.__gt__ = lambda s, o: (s.major > o.major) or (s.major == o.major and s.minor > o.minor)
43version.__le__ = lambda s, o: (s.major < o.major) or (s.major == o.major and s.minor <= o.minor)
44version.__ge__ = lambda s, o: (s.major > o.major) or (s.major == o.major and s.minor >= o.minor)
45version.J5 = version(49, 0)
46version.J6 = version(50, 0)
47version.J7 = version(51, 0)
48version.J8 = version(52, 0)
49
50class constint(object):
51 def __init__(self, val):
52 self.val = val
53 def __hash__(self):
54 return hash(constint) + self.val
55 def __eq__(s, o):
56 return isinstance(o, constint) and o.val == s.val
57class constfloat(object):
58 def __init__(self, val):
59 self.val = val
60 def __hash__(self):
61 return hash(constfloat) + self.val
62 def __eq__(s, o):
63 return isinstance(o, constfloat) and o.val == s.val
64class constlong(object):
65 def __init__(self, val):
66 self.val = val
67 def __hash__(self):
68 return hash(constlong) + self.val
69 def __eq__(s, o):
70 return isinstance(o, constlong) and o.val == s.val
71class constdouble(object):
72 def __init__(self, val):
73 self.val = val
74 def __hash__(self):
75 return hash(constdouble) + self.val
76 def __eq__(s, o):
77 return isinstance(o, constdouble) and o.val == s.val
78
79class conststr(object):
80 def __init__(self, idx):
81 self.idx = idx
82 def __hash__(self):
83 return hash(conststr) + self.idx
84 def __eq__(s, o):
85 return isinstance(o, conststr) and o.idx == s.idx
86
87class classref(object):
88 def __init__(self, nm):
89 self.nm = nm
90 def __hash__(self):
91 return hash(classref) + self.nm
92 def __eq__(s, o):
93 return isinstance(o, classref) and o.nm == s.nm
94
95class sig(object):
96 def __init__(self, nm, tp):
97 self.nm = nm
98 self.tp = tp
99 def __hash__(self):
100 return hash(sig) + self.nm * 31 + self.tp
101 def __eq__(s, o):
102 return isinstance(o, sig) and o.nm == s.nm and o.tp == s.tp
103
104class fieldref(object):
105 def __init__(self, cls, sig):
106 self.cls = cls
107 self.sig = sig
108 def __hash__(self):
109 return hash(fieldref) + self.cls * 31 + self.sig
110 def __eq__(s, o):
111 return isinstance(o, fieldref) and o.cls == s.cls and o.sig == s.sig
112
113class methodref(object):
114 def __init__(self, cls, sig):
115 self.cls = cls
116 self.sig = sig
117 def __hash__(self):
118 return hash(methodref) + self.cls * 31 + self.sig
119 def __eq__(s, o):
120 return isinstance(o, methodref) and o.cls == s.cls and o.sig == s.sig
121
122class imethodref(object):
123 def __init__(self, cls, sig):
124 self.cls = cls
125 self.sig = sig
126 def __hash__(self):
127 return hash(imethodref) + self.cls * 31 + self.sig
128 def __eq__(s, o):
129 return isinstance(o, imethodref) and o.cls == s.cls and o.sig == s.sig
130
131class field(object):
132 def __init__(self, acc, nm, descr):
133 self.acc = acc
134 self.nm = nm
135 self.descr = descr
136 self.const = None
137 self.syn = False
138 self.sig = None
139 self.deprecated = False
140 self.rtann = []
141 self.cpann = []
142 self.attrs = []
143
144class localdef(object):
145 def __init__(self, start, end, nm, descr, reg):
146 self.start = start
147 self.end = end
148 self.nm = nm
149 self.descr = descr
150 self.reg = reg
151
152class code(object):
153 def __init__(self):
154 self.maxstack = 0
155 self.maxlocals = 0
156 self.code = b""
157 self.exctab = []
158 self.lintab = None
159 self.locals = None
160 self.tlocals = None
161 self.attrs = []
162
163class method(object):
164 def __init__(self, acc, nm, descr):
165 self.acc = acc
166 self.nm = nm
167 self.descr = descr
168 self.code = None
169 self.throws = []
170 self.syn = False
171 self.sig = None
172 self.deprecated = False
173 self.rtann = []
174 self.cpann = []
175 self.prtann = None
176 self.pcpann = None
177 self.anndef = None
178 self.attrs = []
179
180class annotation(object):
181 def __init__(self, tp):
182 self.tp = tp
183 self.vals = {}
184
185class innerclass(object):
186 def __init__(self, cls, outer, nm, acc):
187 self.cls = cls
188 self.outer = outer
189 self.nm = nm
190 self.acc = acc
191
192class classfile(object):
193 MAGIC = 0xCAFEBABE
194
195 def __init__(self, ver, access=None):
196 self.ver = ver
197 self.cp = []
198 self.access = access
199 self.this = None
200 self.super = None
201 self.ifaces = []
202 self.fields = []
203 self.methods = []
204 self.srcfile = None
205 self.innerclasses = []
206 self.enclosingmethod = None
207 self.syn = False
208 self.sig = None
209 self.deprecated = False
210 self.rtann = []
211 self.cpann = []
212 self.attrs = []
213
214 def loadconstant(self, buf):
215 t = buf.uint8()
216 if t == CONSTANT_Utf8:
217 return binfmt.mutf8dec(buf.splice(buf.uint16())), False
218 elif t == CONSTANT_Class:
219 return classref(buf.uint16()), False
220 elif t == CONSTANT_String:
221 return conststr(buf.uint16()), False
222 elif t == CONSTANT_Integer:
223 return constint(buf.int32()), False
224 elif t == CONSTANT_Float:
225 return constfloat(buf.float32()), False
226 elif t == CONSTANT_Long:
227 return constlong(buf.int64()), True
228 elif t == CONSTANT_Double:
229 return constdouble(buf.float64()), True
230 elif t == CONSTANT_Fieldref:
231 return fieldref(buf.uint16(), buf.uint16()), False
232 elif t == CONSTANT_Methodref:
233 return methodref(buf.uint16(), buf.uint16()), False
234 elif t == CONSTANT_InterfaceMethodref:
235 return imethodref(buf.uint16(), buf.uint16()), False
236 elif t == CONSTANT_NameAndType:
237 return sig(buf.uint16(), buf.uint16()), False
238 else:
239 raise binfmt.fmterror("unknown constant tag: " + str(t))
240
241 def saveconstant(self, buf, const):
242 if isinstance(const, str):
31eb7672
FT
243 enc = binfmt.mutf8enc(const)
244 buf.uint8(CONSTANT_Utf8).uint16(len(enc)).extend(enc)
964561d6
FT
245 elif isinstance(const, classref):
246 buf.uint8(CONSTANT_Class).uint16(const.nm)
247 elif isinstance(const, conststr):
248 buf.uint8(CONSTANT_String).uint16(const.idx)
249 elif isinstance(const, constint):
250 buf.uint8(CONSTANT_Integer).int32(const.val)
251 elif isinstance(const, constfloat):
252 buf.uint8(CONSTANT_Float).float32(const.val)
253 elif isinstance(const, constlong):
254 buf.uint8(CONSTANT_Long).int64(const.val)
255 elif isinstance(const, constdouble):
256 buf.uint8(CONSTANT_Double).float64(const.val)
257 elif isinstance(const, fieldref):
258 buf.uint8(CONSTANT_Fieldref).uint16(const.cls).uint16(const.sig)
259 elif isinstance(const, methodref):
260 buf.uint8(CONSTANT_Methodref).uint16(const.cls).uint16(const.sig)
261 elif isinstance(const, imethodref):
262 buf.uint8(CONSTANT_InterfaceMethodref).uint16(const.cls).uint16(const.sig)
263 elif isinstance(const, sig):
264 buf.uint8(CONSTANT_NameAndType).uint16(const.nm).uint16(const.tp)
265 else:
266 raise Exception("unexpected object type in constant pool: " + const)
267
268 def checkcp(self, idx, tp):
269 return 0 <= idx < len(self.cp) and isinstance(self.cp[idx], tp)
270
271 def intern(self, const, new=Exception):
272 for i, cur in enumerate(self.cp):
273 if cur == const:
274 return i
275 if new == Exception:
276 raise Exception("constant not present in pool: " + const)
277 if new:
278 self.cp.append(const)
279 return len(self.cp) - 1
280 else:
281 return None
282
283 def loadattr(self, buf):
284 nm = buf.uint16()
285 if not self.checkcp(nm, str):
286 raise binfmt.fmterror("invalid attribute name reference")
287 return nm, binfmt.decbuf(buf.splice(buf.uint32()))
288
289 def saveattrs(self, buf, attrs):
290 buf.uint16(len(attrs))
291 for nm, data in attrs:
292 buf.uint16(nm).uint32(len(data)).extend(data)
293
294 def loadannval(self, buf):
295 t = chr(buf.uint8())
296 if t in "BCDFIJSZs":
297 return buf.uint16()
298 elif t == "e":
299 return (buf.uint16(), buf.uint16())
300 elif t == "c":
301 return classref(buf.uint16()) # XXX, but meh
302 elif t == "@":
303 return loadannotation(buf)
304 elif t == "[":
305 return [self.loadannval(buf) for i in range(buf.uint16())]
306 else:
307 raise binfmt.fmterror("unknown annotation-value type tag: " + t)
308
309 def saveannval(self, buf, val):
310 if isinstance(val, int):
311 const = self.cp[val]
312 if isinstance(const, str):
313 buf.uint8(ord('s')).uint16(val)
314 else:
315 raise Exception("unexpected constant type in annotation value: " + const)
316 elif isinstance(val, tuple) and len(val) == 2:
317 buf.uint8(ord('e')).uint16(val[0]).uint16(val[1])
318 elif isinstance(val, classref):
319 buf.uint8(ord('c')).uint16(val.nm)
320 elif isinstance(val, annotation):
321 buf.uint8(ord('@'))
322 saveannotation(buf, val)
323 elif isinstance(val, list):
324 buf.uint8(ord('['))
325 for sval in val: self.saveannval(buf, sval)
326 else:
327 raise Exception("unexpected annotation value type: " + val)
328
329 def loadannotation(self, buf):
330 tp = buf.uint16()
331 if not self.checkcp(tp, str):
332 raise binfmt.fmterror("invalid annotation type reference")
333 ret = annotation(tp)
334 nval = buf.uint16()
335 for i in range(nval):
336 nm = buf.uint16()
337 if not self.checkcp(nm, str):
338 raise binfmt.fmterror("invalid annotation-value name reference")
339 ret.vals[nm] = self.loadannval(buf)
340 return ret
341
342 def saveannotation(self, buf, ann):
343 buf.uint16(ann.tp)
344 buf.uint16(len(ann.vals))
345 for key, val in ann.vals.items():
346 buf.uint16(key)
347 self.saveannval(buf, val)
348
349 def loadfield(self, buf):
350 acc = buf.uint16()
351 nm = buf.uint16()
352 if not self.checkcp(nm, str):
353 raise binfmt.fmterror("invalid field name reference")
354 descr = buf.uint16()
355 if not self.checkcp(descr, str):
356 raise binfmt.fmterror("invalid field descriptor reference")
357 ret = field(acc, nm, descr)
358 nattr = buf.uint16()
359 for i in range(nattr):
360 nm, data = self.loadattr(buf)
361 pnm = self.cp[nm]
362 if pnm == "ConstantValue":
363 ret.const = data.uint16()
364 elif pnm == "Synthetic":
365 ret.syn = True
366 elif pnm == "Signature":
367 ret.sig = data.uint16()
368 elif pnm == "Deprecated":
369 ret.deprecated = True
370 elif pnm == "RuntimeVisibleAnnotations":
371 for o in range(data.uint16()):
372 ret.rtann.append(self.loadannotation(data))
373 elif pnm == "RuntimeInvisibleAnnotations":
374 for o in range(data.uint16()):
375 ret.cpann.append(self.loadannotation(data))
376 else:
377 ret.attrs.append((nm, data.splice()))
378 return ret
379
380 def savefield(self, buf, field):
381 buf.uint16(field.acc)
382 buf.uint16(field.nm).uint16(field.descr)
383 attrs = list(field.attrs)
384 enc = binfmt.encbuf
385 if field.const is not None:
386 attrs.append((self.intern("ConstantValue"), enc().uint16(field.const)))
387 if field.syn:
388 attrs.append((self.intern("Synthetic"), b""))
389 if field.sig is not None:
390 attrs.append((self.intern("Signature"), enc().uint16(field.sig)))
391 if field.deprecated:
392 attrs.append((self.intern("Deprecated"), b""))
393 if len(field.rtann) > 0:
394 data = enc()
395 data.uint16(len(field.rtann))
396 for ann in field.rtann: self.saveannotation(data, ann)
397 attrs.append((self.intern("RuntimeVisibleAnnotations"), data))
398 if len(field.cpann) > 0:
399 data = enc()
400 data.uint16(len(field.cpann))
401 for ann in field.cpann: self.saveannotation(data, ann)
402 attrs.append((self.intern("RuntimeInvisibleAnnotations"), data))
403 self.saveattrs(buf, attrs)
404
405 def loadcode(self, buf):
406 ret = code()
407 ret.maxstack = buf.uint16()
408 ret.maxlocals = buf.uint16()
409 ret.code = buf.splice(buf.uint32())
410 for i in range(buf.uint16()):
411 estart = buf.uint16()
412 eend = buf.uint16()
413 ehnd = buf.uint16()
414 ctp = buf.uint16()
415 if not (ctp == 0 or self.checkcp(ctp, classref)):
416 raise binfmt.fmterror("invalid exception-catch reference")
417 ret.exctab.append((estart, eend, ehnd, ctp))
418 nattr = buf.uint16()
419 for i in range(nattr):
420 nm, data = self.loadattr(buf)
421 pnm = self.cp[nm]
422 if pnm == "LineNumberTable":
423 lintab = []
424 for o in range(data.uint16()):
425 pc = data.uint16()
426 ln = data.uint16()
427 lintab.append((pc, ln))
428 ret.lintab = lintab
429 elif pnm in ("LocalVariableTable", "LocalVariableTypeTable"):
430 locals = []
431 for o in range(data.uint16()):
432 start = data.uint16()
433 ln = data.uint16()
434 nm = data.uint16()
435 descr = data.uint16()
436 reg = data.uint16()
437 if not self.checkcp(nm, str):
438 raise binfmt.fmterror("invalid local variable name reference")
439 if not self.checkcp(descr, str):
440 raise binfmt.fmterror("invalid local variable descriptor reference")
441 locals.append(localdef(start, start + ln, nm, descr, reg))
442 if nm == "LocalVariableTypeTable":
443 ret.tlocals = locals
444 else:
445 ret.locals = locals
446 else:
447 ret.attrs.append((nm, data.splice()))
448 return ret
449
450 def savecode(self, buf, code):
451 buf.uint16(code.maxstack).uint16(code.maxlocals)
452 buf.uint32(len(code.code)).extend(code.code)
453 buf.uint16(len(code.exctab))
454 for estart, eend, ehnd, ctp in code.exctab:
455 buf.uint16(estart).uint16(eend).uint16(ehnd).uint16(ctp)
456 attrs = list(code.attrs)
457 enc = binfmt.encbuf
458 if code.lintab is not None:
459 data = enc()
460 data.uint16(len(code.lintab))
461 for pc, ln in code.lintab:
462 data.uint16(pc).uint16(ln)
463 attrs.append((self.intern("LineNumberTable"), data))
464 def savelocals(ltab):
465 data = enc()
466 data.uint16(len(ltab))
467 for local in ltab:
468 data.uint16(local.start).uint16(local.end - local.start).uint16(local.nm).uint16(local.descr).uint16(local.reg)
469 return data
470 if code.locals is not None:
471 attrs.append((self.intern("LocalVariableTable"), savelocals(code.locals)))
472 if code.tlocals is not None:
473 attrs.append((self.intern("LocalVariableTypeTable"), savelocals(code.tlocals)))
474 self.saveattrs(buf, attrs)
475
476 def loadmethod(self, buf):
477 acc = buf.uint16()
478 nm = buf.uint16()
479 if not self.checkcp(nm, str):
480 raise binfmt.fmterror("invalid field name reference")
481 descr = buf.uint16()
482 if not self.checkcp(descr, str):
483 raise binfmt.fmterror("invalid field descriptor reference")
484 ret = method(acc, nm, descr)
485 nattr = buf.uint16()
486 for i in range(nattr):
487 nm, data = self.loadattr(buf)
488 pnm = self.cp[nm]
489 if pnm == "Code":
490 ret.code = self.loadcode(data)
491 elif pnm == "Exceptions":
492 for o in range(data.uint16()):
493 eref = data.uint16()
494 if not self.checkcp(eref, classref):
495 raise binfmt.fmterror("invalid exception reference")
496 ret.throws.append(eref)
497 elif pnm == "Synthetic":
498 ret.syn = True
499 elif pnm == "Signature":
500 ret.sig = data.uint16()
501 elif pnm == "Deprecated":
502 ret.deprecated = True
503 elif pnm == "RuntimeVisibleAnnotations":
504 for o in range(data.uint16()):
505 ret.rtann.append(self.loadannotation(data))
506 elif pnm == "RuntimeInvisibleAnnotations":
507 for o in range(data.uint16()):
508 ret.cpann.append(self.loadannotation(data))
509 elif pnm == "RuntimeVisibleParameterAnnotations":
510 ret.prtann = []
511 for o in range(data.uint8()):
512 abuf = []
513 for u in range(data.uint16()):
514 abuf.append(self.loadannotation(data))
515 ret.prtann.append(abuf)
516 elif pnm == "RuntimeInvisibleParameterAnnotations":
517 ret.pcpann = []
518 for o in range(data.uint8()):
519 abuf = []
520 for u in range(data.uint16()):
521 abuf.append(self.loadannotation(data))
522 ret.pcpann.append(abuf)
523 elif pnm == "AnnotationDefault":
524 ret.anndef = self.loadannval(data)
525 else:
526 ret.attrs.append((nm, data.splice()))
527 return ret
528
529 def savemethod(self, buf, method):
530 buf.uint16(method.acc)
531 buf.uint16(method.nm).uint16(method.descr)
532 attrs = list(method.attrs)
533 enc = binfmt.encbuf
534 if method.code:
535 data = enc()
536 self.savecode(data, method.code)
537 attrs.append((self.intern("Code"), data))
538 if len(method.throws) > 0:
539 data = enc()
540 data.uint16(len(method.throws))
541 for eref in method.throws: data.uint16(eref)
542 attrs.append((self.intern("Exceptions"), data))
543 if method.syn:
544 attrs.append((self.intern("Synthetic"), b""))
545 if method.sig is not None:
546 attrs.append((self.intern("Signature"), enc().uint16(method.sig)))
547 if method.deprecated:
548 attrs.append((self.intern("Deprecated"), b""))
549 if len(method.rtann) > 0:
550 data = enc()
551 data.uint16(len(method.rtann))
552 for ann in method.rtann: self.saveannotation(data, ann)
553 attrs.append((self.intern("RuntimeVisibleAnnotations"), data))
554 if len(method.cpann) > 0:
555 data = enc()
556 data.uint16(len(method.cpann))
557 for ann in method.cpann: self.saveannotation(data, ann)
558 attrs.append((self.intern("RuntimeInvisibleAnnotations"), data))
559 if method.prtann is not None:
560 data = enc()
561 data.uint8(len(method.prtann))
562 for par in method.prtann:
563 buf.uint16(len(par))
564 for ann in par: self.saveannotation(data, ann)
565 attrs.append((self.intern("RuntimeVisibleParameterAnnotations"), data))
566 if method.pcpann is not None:
567 data = enc()
568 data.uint8(len(method.pcpann))
569 for par in method.pcpann:
570 buf.uint16(len(par))
571 for ann in par: self.saveannotation(data, ann)
572 attrs.append((self.intern("RuntimeInvisibleParameterAnnotations"), data))
573 if method.anndef is not None:
574 data = enc()
575 self.saveannval(data, method.anndef)
576 attrs.append((self.intern("AnnotationDefault"), data))
577 self.saveattrs(buf, attrs)
578
579 @classmethod
580 def load(cls, fp):
581 buf = binfmt.decstream(fp)
582 if buf.uint32() != cls.MAGIC:
583 raise binfmt.fmterror("invalid magic number")
584 minor, major = buf.uint16(), buf.uint16()
585 self = cls(version(major, minor))
586
587 cplen = buf.uint16()
588 if cplen < 1:
589 raise binfmt.fmterror("invalid constant-pool length")
590 self.cp.append(None)
591 while len(self.cp) < cplen:
592 loaded, dbl = self.loadconstant(buf)
593 self.cp.append(loaded)
594 if dbl:
595 self.cp.append(None)
596
597 self.acc = buf.uint16()
598 self.this = buf.uint16()
599 self.super = buf.uint16()
600 if not self.checkcp(self.this, classref):
601 raise binfmt.fmterror("invalid class name reference")
602 if not self.checkcp(self.super, classref):
603 raise binfmt.fmterror("invalid super-class reference")
604 iflen = buf.uint16()
605 while len(self.ifaces) < iflen:
606 iref = buf.uint16()
607 if not self.checkcp(iref, classref):
608 raise binfmt.fmterror("invalid interface reference")
609 self.ifaces.append(iref)
610
611 nfields = buf.uint16()
612 while len(self.fields) < nfields:
613 self.fields.append(self.loadfield(buf))
614 nmethods = buf.uint16()
615 while len(self.methods) < nmethods:
616 self.methods.append(self.loadmethod(buf))
617
618 nattrs = buf.uint16()
619 for i in range(nattrs):
620 nm, data = self.loadattr(buf)
621 pnm = self.cp[nm]
622 if pnm == "SourceFile":
623 self.srcfile = data.uint16()
624 elif pnm == "Signature":
625 self.sig = data.uint16()
626 elif pnm == "Synthetic":
627 self.syn = True
628 elif pnm == "Deprecated":
629 self.deprecated = True
630 elif pnm == "InnerClasses":
631 for o in range(data.uint16()):
632 cref = data.uint16()
633 outer = data.uint16()
634 cnm = data.uint16()
635 acc = data.uint16()
636 if not self.checkcp(cref, classref):
637 raise binfmt.fmterror("invalid inner-class reference")
638 if not (outer == 0 or self.checkcp(outer, classref)):
639 raise binfmt.fmterror("invalid inner-class outer reference")
640 if not (cnm == 0 or self.checkcp(cnm, str)):
641 raise binfmt.fmterror("invalid inner-class name reference")
642 self.innerclasses.append(innerclass(cref, outer, cnm, acc))
643 elif pnm == "EnclosingMethod":
644 self.enclosingmethod = (data.uint16(), data.uint16())
645 if not self.checkcp(self.enclosingmethod[0], classref):
646 raise binfmt.fmterror("invalid enclosing-method class reference")
647 if not (self.enclosingmethod[1] == 0 or self.checkcp(self.enclosingmethod[1], sig)):
648 raise binfmt.fmterror("invalid enclosing-method method reference")
649 elif pnm == "RuntimeVisibleAnnotations":
650 for o in range(data.uint16()):
651 self.rtann.append(self.loadannotation(data))
652 elif pnm == "RuntimeInvisibleAnnotations":
653 for o in range(data.uint16()):
654 self.cpann.append(self.loadannotation(data))
655 else:
656 self.attrs.append((nm, data.splice()))
657
658 return self
659
660 def _save(self, buf):
661 buf.uint32(self.MAGIC)
662 buf.uint16(self.ver.minor).uint16(self.ver.major)
663
31eb7672 664 buf.uint16(len(self.cp))
964561d6
FT
665 for const in self.cp:
666 if const is not None:
667 self.saveconstant(buf, const)
668
669 buf.uint16(self.acc)
670 buf.uint16(self.this).uint16(self.super)
671 buf.uint16(len(self.ifaces))
672 for iref in self.ifaces: buf.uint16(iref)
673
674 buf.uint16(len(self.fields))
675 for field in self.fields:
676 self.savefield(buf, field)
677
678 buf.uint16(len(self.methods))
679 for method in self.methods:
680 self.savemethod(buf, method)
681
682 enc = binfmt.encbuf
683 attrs = list(self.attrs)
684 if self.srcfile is not None:
685 attrs.append((self.intern("SourceFile"), enc().uint16(self.srcfile)))
686 if self.syn:
687 attrs.append((self.intern("Synthetic"), b""))
688 if self.deprecated:
689 attrs.append((self.intern("Deprecated"), b""))
690 if self.sig is not None:
691 attrs.append((self.intern("Signature"), enc().uint16(self.sig)))
692 if len(self.innerclasses) > 0:
693 data = enc()
694 data.uint16(len(self.innerclasses))
695 for inner in self.innerclasses: data.uint16(inner.cls).uint16(inner.outer).uint16(inner.nm).uint16(inner.acc)
696 attrs.append((self.intern("InnerClasses"), data))
697 if self.enclosingmethod is not None:
31eb7672 698 attrs.append((self.intern("EnclosingMethod"), enc().uint16(self.enclosingmethod[0]).uint16(self.enclosingmethod[1])))
964561d6
FT
699 if len(self.rtann) > 0:
700 data = enc()
701 data.uint16(len(self.rtann))
702 for ann in self.rtann: self.saveannotation(data, ann)
703 attrs.append((self.intern("RuntimeVisibleAnnotations"), data))
704 if len(self.cpann) > 0:
705 data = enc()
706 data.uint16(len(self.cpann))
707 for ann in self.cpann: self.saveannotation(data, ann)
708 attrs.append((self.intern("RuntimeInvisibleAnnotations"), data))
709 self.saveattrs(buf, attrs)
710
711 def save(self, fp):
712 return self._save(binfmt.encstream(fp))
713
714 @classmethod
715 def fromfile(cls, fn):
716 with open(fn, "rb") as fp:
717 return cls.load(fp)
718
719 def tofile(self, fn):
720 with open(fn, "wb") as fp:
721 return self.save(fp)