summaryrefslogtreecommitdiff
path: root/pyasn1/type/base.py
diff options
context:
space:
mode:
authorelie <elie>2005-06-14 06:59:38 +0000
committerelie <elie>2005-06-14 06:59:38 +0000
commit3dfa1b281dfd1f1d8a8d955f56042be9b093a912 (patch)
treeda5b6711a73ca89caa0e7dd93cbecdacf4b0d831 /pyasn1/type/base.py
downloadpyasn1-3dfa1b281dfd1f1d8a8d955f56042be9b093a912.tar.gz
Initial revision
Diffstat (limited to 'pyasn1/type/base.py')
-rw-r--r--pyasn1/type/base.py210
1 files changed, 210 insertions, 0 deletions
diff --git a/pyasn1/type/base.py b/pyasn1/type/base.py
new file mode 100644
index 0000000..da5790e
--- /dev/null
+++ b/pyasn1/type/base.py
@@ -0,0 +1,210 @@
+# Base classes for ASN.1 types
+try:
+ from sys import version_info
+except ImportError:
+ version_info = (0, 0) # a really early version
+from operator import getslice, setslice, delslice
+from string import join
+from types import SliceType
+from pyasn1.type import constraint
+from pyasn1 import error
+
+class Asn1Item: pass
+
+class Asn1ItemBase(Asn1Item):
+ # Set of tags for this ASN.1 type
+ tagSet = ()
+
+ # A list of constraint.Constraint instances for checking values
+ subtypeSpec = constraint.ConstraintsIntersection()
+
+ def __init__(self, tagSet=None, subtypeSpec=None):
+ if tagSet is None:
+ self._tagSet = self.tagSet
+ else:
+ self._tagSet = tagSet
+ if subtypeSpec is None:
+ self._subtypeSpec = self.subtypeSpec
+ else:
+ self._subtypeSpec = subtypeSpec
+
+ def _verifySubtypeSpec(self, value, idx=None):
+ self._subtypeSpec(value, idx)
+
+ def getSubtypeSpec(self): return self._subtypeSpec
+
+ def getTagSet(self): return self._tagSet
+ def getTypeMap(self): return { self._tagSet: self }
+
+ def isSameTypeWith(self, other):
+ return self is other or \
+ self._tagSet == other.getTagSet() and \
+ self._subtypeSpec == other.getSubtypeSpec()
+ def isSuperTypeOf(self, other):
+ """Returns true if argument is a ASN1 subtype of ourselves"""
+ return self._tagSet.isSuperTagSetOf(other.getTagSet()) and \
+ self._subtypeSpec.isSuperTypeOf(other.getSubtypeSpec())
+
+# Base class for "simple" ASN.1 objects. These are immutable.
+class AbstractSimpleAsn1Item(Asn1ItemBase):
+ defaultValue = None
+ def __init__(self, value=None, tagSet=None, subtypeSpec=None):
+ Asn1ItemBase.__init__(self, tagSet, subtypeSpec)
+ if value is None:
+ self._value = self.defaultValue
+ else:
+ value = self._prettyIn(value)
+ self._verifySubtypeSpec(value)
+ self._value = value
+ self.__hashedValue = hash(
+ (self._value, self._tagSet, self._subtypeSpec)
+ )
+
+ def __repr__(self):
+ return self.__class__.__name__ + '(' + repr(
+ self._prettyOut(self._value)
+ ) +')'
+ def __str__(self): return str(self._value)
+ def __cmp__(self, value): return cmp(self._value, value)
+ def __hash__(self): return self.__hashedValue
+
+ def __nonzero__(self): return bool(self._value)
+
+ def clone(self, value=None, tagSet=None, subtypeSpec=None):
+ if value is None and tagSet is None and subtypeSpec is None:
+ return self
+ if value is None and self._value is not self.defaultValue:
+ value = self._value
+ if tagSet is None:
+ tagSet = self._tagSet
+ if subtypeSpec is None:
+ subtypeSpec = self._subtypeSpec
+ return self.__class__(value, tagSet, subtypeSpec)
+
+ def subtype(self, value=None, implicitTag=None, explicitTag=None,
+ subtypeSpec=None):
+ if value is None and self._value is not self.defaultValue:
+ value = self._value
+ if implicitTag is not None:
+ tagSet = self._tagSet.tagImplicitly(implicitTag)
+ elif explicitTag is not None:
+ tagSet = self._tagSet.tagExplicitly(explicitTag)
+ else:
+ tagSet = self._tagSet
+ if subtypeSpec is None:
+ subtypeSpec = self._subtypeSpec
+ else:
+ subtypeSpec = subtypeSpec + self._subtypeSpec
+ return self.__class__(value, tagSet, subtypeSpec)
+
+ def _prettyIn(self, value): return value
+ def _prettyOut(self, value): return value
+
+ def prettyPrinter(self, scope=0): return self._prettyOut(self._value)
+
+#
+# Constructed types:
+# * There are five of them: Sequence, SequenceOf/SetOf, Set and Choice
+# * ASN1 types and values are represened by Python class instances
+# * Value initialization is made for defaulted components only
+# * Primary method of component addressing is by-position. Data model for base
+# type is Python sequence. Additional type-specific addressing methods
+# may be implemented for particular types.
+# * SequenceOf and SetOf types do not implement any additional methods
+# * Sequence, Set and Choice types also implement by-identifier addressing
+# * Sequence, Set and Choice types also implement by-asn1-type (tag) addressing
+# * Sequence and Set types may include optional and defaulted
+# components
+# * Constructed types hold a reference to component types used for value
+# verification and ordering.
+# * Component type is a scalar type for SequenceOf/SetOf types and a list
+# of types for Sequence/Set/Choice.
+#
+
+class AbstractConstructedAsn1Item(Asn1ItemBase):
+ componentType = None
+ sizeSpec = constraint.ConstraintsIntersection()
+ def __init__(self, componentType=None, tagSet=None,
+ subtypeSpec=None, sizeSpec=None):
+ Asn1ItemBase.__init__(self, tagSet, subtypeSpec)
+ if componentType is None:
+ self._componentType = self.componentType
+ else:
+ self._componentType = componentType
+ if sizeSpec is None:
+ self._sizeSpec = self.sizeSpec
+ else:
+ self._sizeSpec = sizeSpec
+ self._componentValues = []
+
+ def __repr__(self):
+ r = self.__class__.__name__ + '()'
+ for idx in range(len(self)):
+ if self._componentValues[idx] is None:
+ continue
+ r = r + '.setComponentByPosition(%s, %s)' % (
+ idx, repr(self._componentValues[idx])
+ )
+ return r
+
+ def __cmp__(self, other): return cmp(self._componentValues, other)
+
+ def getComponentTypeMap(self):
+ raise error.PyAsn1Error('Method not implemented')
+
+ def clone(self, componentType=None, tagSet=None, subtypeSpec=None,
+ sizeSpec=None):
+ if componentType is None:
+ componentType = self._componentType
+ if tagSet is None:
+ tagSet = self._tagSet
+ if subtypeSpec is None:
+ subtypeSpec = self._subtypeSpec
+ if sizeSpec is None:
+ sizeSpec = self._sizeSpec
+ r = self.__class__(componentType, tagSet, subtypeSpec, sizeSpec)
+ if componentType is self._componentType and \
+ self.getComponentType() is not None:
+ self._cloneComponentValues(r) # XXX when do we clone inner vals?
+ return r
+
+ def subtype(self, componentType=None, implicitTag=None, explicitTag=None,
+ subtypeSpec=None, sizeSpec=None):
+ if componentType is None:
+ componentType = self._componentType
+ if implicitTag is not None:
+ tagSet = self._tagSet.tagImplicitly(implicitTag)
+ elif explicitTag is not None:
+ tagSet = self._tagSet.tagExplicitly(explicitTag)
+ else:
+ tagSet = self._tagSet
+ if subtypeSpec is None:
+ subtypeSpec = self._subtypeSpec
+ else:
+ subtypeSpec = subtypeSpec + self._subtypeSpec
+ if sizeSpec is None:
+ sizeSpec = self._sizeSpec
+ else:
+ sizeSpec = sizeSpec + self._sizeSpec
+ r = self.__class__(componentType, tagSet, subtypeSpec, sizeSpec)
+ if componentType is self._componentType and \
+ self.getComponentType() is not None:
+ self._cloneComponentValues(r) # XXX when do we clone inner vals?
+ return r
+
+ def _verifyComponent(self, idx, value): pass
+
+ def verifySizeSpec(self): self._sizeSpec(self)
+
+ def getComponentByPosition(self, idx):
+ raise error.PyAsn1Error('Method not implemented')
+ def setComponentByPosition(self, idx, value):
+ raise error.PyAsn1Error('Method not implemented')
+
+ def getComponentType(self): return self._componentType
+
+ def __getitem__(self, idx): return self._componentValues[idx]
+
+ def __len__(self): return len(self._componentValues)
+
+ def clear(self): self._componentValues = []