Home | History | Annotate | Download | only in type
      1 # NamedType specification for constructed types
      2 import sys
      3 from pyasn1.type import tagmap
      4 from pyasn1 import error
      5 
      6 class 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     
     21 class OptionalNamedType(NamedType):
     22     isOptional = 1
     23 class DefaultedNamedType(NamedType):
     24     isDefaulted = 1
     25     
     26 class 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