1# NamedType specification for constructed types 2import sys 3from pyasn1.type import tagmap 4from pyasn1 import error 5 6class NamedType: 7 isOptional = 0 8 isDefaulted = 0 9 def __init__(self, name, t): 10 self.__name = name; self.__type = t 11 def __repr__(self): return '%s(%s, %s)' % ( 12 self.__class__.__name__, self.__name, self.__type 13 ) 14 def getType(self): return self.__type 15 def getName(self): return self.__name 16 def __getitem__(self, idx): 17 if idx == 0: return self.__name 18 if idx == 1: return self.__type 19 raise IndexError() 20 21class OptionalNamedType(NamedType): 22 isOptional = 1 23class DefaultedNamedType(NamedType): 24 isDefaulted = 1 25 26class NamedTypes: 27 def __init__(self, *namedTypes): 28 self.__namedTypes = namedTypes 29 self.__namedTypesLen = len(self.__namedTypes) 30 self.__minTagSet = None 31 self.__tagToPosIdx = {}; self.__nameToPosIdx = {} 32 self.__tagMap = { False: None, True: None } 33 self.__ambigiousTypes = {} 34 35 def __repr__(self): 36 r = '%s(' % self.__class__.__name__ 37 for n in self.__namedTypes: 38 r = r + '%r, ' % (n,) 39 return r + ')' 40 41 def __getitem__(self, idx): return self.__namedTypes[idx] 42 43 if sys.version_info[0] <= 2: 44 def __nonzero__(self): return bool(self.__namedTypesLen) 45 else: 46 def __bool__(self): return bool(self.__namedTypesLen) 47 def __len__(self): return self.__namedTypesLen 48 49 def getTypeByPosition(self, idx): 50 if idx < 0 or idx >= self.__namedTypesLen: 51 raise error.PyAsn1Error('Type position out of range') 52 else: 53 return self.__namedTypes[idx].getType() 54 55 def getPositionByType(self, tagSet): 56 if not self.__tagToPosIdx: 57 idx = self.__namedTypesLen 58 while idx > 0: 59 idx = idx - 1 60 tagMap = self.__namedTypes[idx].getType().getTagMap() 61 for t in tagMap.getPosMap(): 62 if t in self.__tagToPosIdx: 63 raise error.PyAsn1Error('Duplicate type %s' % (t,)) 64 self.__tagToPosIdx[t] = idx 65 try: 66 return self.__tagToPosIdx[tagSet] 67 except KeyError: 68 raise error.PyAsn1Error('Type %s not found' % (tagSet,)) 69 70 def getNameByPosition(self, idx): 71 try: 72 return self.__namedTypes[idx].getName() 73 except IndexError: 74 raise error.PyAsn1Error('Type position out of range') 75 def getPositionByName(self, name): 76 if not self.__nameToPosIdx: 77 idx = self.__namedTypesLen 78 while idx > 0: 79 idx = idx - 1 80 n = self.__namedTypes[idx].getName() 81 if n in self.__nameToPosIdx: 82 raise error.PyAsn1Error('Duplicate name %s' % (n,)) 83 self.__nameToPosIdx[n] = idx 84 try: 85 return self.__nameToPosIdx[name] 86 except KeyError: 87 raise error.PyAsn1Error('Name %s not found' % (name,)) 88 89 def __buildAmbigiousTagMap(self): 90 ambigiousTypes = () 91 idx = self.__namedTypesLen 92 while idx > 0: 93 idx = idx - 1 94 t = self.__namedTypes[idx] 95 if t.isOptional or t.isDefaulted: 96 ambigiousTypes = (t, ) + ambigiousTypes 97 else: 98 ambigiousTypes = (t, ) 99 self.__ambigiousTypes[idx] = NamedTypes(*ambigiousTypes) 100 101 def getTagMapNearPosition(self, idx): 102 if not self.__ambigiousTypes: self.__buildAmbigiousTagMap() 103 try: 104 return self.__ambigiousTypes[idx].getTagMap() 105 except KeyError: 106 raise error.PyAsn1Error('Type position out of range') 107 108 def getPositionNearType(self, tagSet, idx): 109 if not self.__ambigiousTypes: self.__buildAmbigiousTagMap() 110 try: 111 return idx+self.__ambigiousTypes[idx].getPositionByType(tagSet) 112 except KeyError: 113 raise error.PyAsn1Error('Type position out of range') 114 115 def genMinTagSet(self): 116 if self.__minTagSet is None: 117 for t in self.__namedTypes: 118 __type = t.getType() 119 tagSet = getattr(__type,'getMinTagSet',__type.getTagSet)() 120 if self.__minTagSet is None or tagSet < self.__minTagSet: 121 self.__minTagSet = tagSet 122 return self.__minTagSet 123 124 def getTagMap(self, uniq=False): 125 if self.__tagMap[uniq] is None: 126 tagMap = tagmap.TagMap() 127 for nt in self.__namedTypes: 128 tagMap = tagMap.clone( 129 nt.getType(), nt.getType().getTagMap(), uniq 130 ) 131 self.__tagMap[uniq] = tagMap 132 return self.__tagMap[uniq] 133