| # NamedType specification for constructed types |
| import sys |
| from pyasn1.type import tagmap |
| from pyasn1 import error |
| |
| class NamedType: |
| isOptional = 0 |
| isDefaulted = 0 |
| def __init__(self, name, t): |
| self.__name = name; self.__type = t |
| def __repr__(self): return '%s(%s, %s)' % ( |
| self.__class__.__name__, self.__name, self.__type |
| ) |
| def getType(self): return self.__type |
| def getName(self): return self.__name |
| def __getitem__(self, idx): |
| if idx == 0: return self.__name |
| if idx == 1: return self.__type |
| raise IndexError() |
| |
| class OptionalNamedType(NamedType): |
| isOptional = 1 |
| class DefaultedNamedType(NamedType): |
| isDefaulted = 1 |
| |
| class NamedTypes: |
| def __init__(self, *namedTypes): |
| self.__namedTypes = namedTypes |
| self.__namedTypesLen = len(self.__namedTypes) |
| self.__minTagSet = None |
| self.__tagToPosIdx = {}; self.__nameToPosIdx = {} |
| self.__tagMap = { False: None, True: None } |
| self.__ambigiousTypes = {} |
| |
| def __repr__(self): |
| r = '%s(' % self.__class__.__name__ |
| for n in self.__namedTypes: |
| r = r + '%r, ' % (n,) |
| return r + ')' |
| |
| def __getitem__(self, idx): return self.__namedTypes[idx] |
| |
| if sys.version_info[0] <= 2: |
| def __nonzero__(self): return bool(self.__namedTypesLen) |
| else: |
| def __bool__(self): return bool(self.__namedTypesLen) |
| def __len__(self): return self.__namedTypesLen |
| |
| def getTypeByPosition(self, idx): |
| if idx < 0 or idx >= self.__namedTypesLen: |
| raise error.PyAsn1Error('Type position out of range') |
| else: |
| return self.__namedTypes[idx].getType() |
| |
| def getPositionByType(self, tagSet): |
| if not self.__tagToPosIdx: |
| idx = self.__namedTypesLen |
| while idx > 0: |
| idx = idx - 1 |
| tagMap = self.__namedTypes[idx].getType().getTagMap() |
| for t in tagMap.getPosMap(): |
| if t in self.__tagToPosIdx: |
| raise error.PyAsn1Error('Duplicate type %s' % (t,)) |
| self.__tagToPosIdx[t] = idx |
| try: |
| return self.__tagToPosIdx[tagSet] |
| except KeyError: |
| raise error.PyAsn1Error('Type %s not found' % (tagSet,)) |
| |
| def getNameByPosition(self, idx): |
| try: |
| return self.__namedTypes[idx].getName() |
| except IndexError: |
| raise error.PyAsn1Error('Type position out of range') |
| def getPositionByName(self, name): |
| if not self.__nameToPosIdx: |
| idx = self.__namedTypesLen |
| while idx > 0: |
| idx = idx - 1 |
| n = self.__namedTypes[idx].getName() |
| if n in self.__nameToPosIdx: |
| raise error.PyAsn1Error('Duplicate name %s' % (n,)) |
| self.__nameToPosIdx[n] = idx |
| try: |
| return self.__nameToPosIdx[name] |
| except KeyError: |
| raise error.PyAsn1Error('Name %s not found' % (name,)) |
| |
| def __buildAmbigiousTagMap(self): |
| ambigiousTypes = () |
| idx = self.__namedTypesLen |
| while idx > 0: |
| idx = idx - 1 |
| t = self.__namedTypes[idx] |
| if t.isOptional or t.isDefaulted: |
| ambigiousTypes = (t, ) + ambigiousTypes |
| else: |
| ambigiousTypes = (t, ) |
| self.__ambigiousTypes[idx] = NamedTypes(*ambigiousTypes) |
| |
| def getTagMapNearPosition(self, idx): |
| if not self.__ambigiousTypes: self.__buildAmbigiousTagMap() |
| try: |
| return self.__ambigiousTypes[idx].getTagMap() |
| except KeyError: |
| raise error.PyAsn1Error('Type position out of range') |
| |
| def getPositionNearType(self, tagSet, idx): |
| if not self.__ambigiousTypes: self.__buildAmbigiousTagMap() |
| try: |
| return idx+self.__ambigiousTypes[idx].getPositionByType(tagSet) |
| except KeyError: |
| raise error.PyAsn1Error('Type position out of range') |
| |
| def genMinTagSet(self): |
| if self.__minTagSet is None: |
| for t in self.__namedTypes: |
| __type = t.getType() |
| tagSet = getattr(__type,'getMinTagSet',__type.getTagSet)() |
| if self.__minTagSet is None or tagSet < self.__minTagSet: |
| self.__minTagSet = tagSet |
| return self.__minTagSet |
| |
| def getTagMap(self, uniq=False): |
| if self.__tagMap[uniq] is None: |
| tagMap = tagmap.TagMap() |
| for nt in self.__namedTypes: |
| tagMap = tagMap.clone( |
| nt.getType(), nt.getType().getTagMap(), uniq |
| ) |
| self.__tagMap[uniq] = tagMap |
| return self.__tagMap[uniq] |