summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Pipek <jan.pipek@gmail.com>2019-09-13 12:17:40 +0200
committerJan Pipek <jan.pipek@gmail.com>2019-09-13 12:17:40 +0200
commitec49b521106ac9cfa6b3099f8579e69276234103 (patch)
treed1a0d18c6593d3f6c1e545213eb2d8cab15e7ccf
parent0fbc60eba7270f2b30f67b2e3dfbd74b0123340f (diff)
downloadpyasn1-git-ec49b521106ac9cfa6b3099f8579e69276234103.tar.gz
Simplify _CachingStreamWrapper
-rw-r--r--pyasn1/codec/ber/decoder.py25
1 files changed, 17 insertions, 8 deletions
diff --git a/pyasn1/codec/ber/decoder.py b/pyasn1/codec/ber/decoder.py
index 396b04b..cfdea7a 100644
--- a/pyasn1/codec/ber/decoder.py
+++ b/pyasn1/codec/ber/decoder.py
@@ -38,6 +38,9 @@ class _CachingStreamWrapper(IOBase):
Note that the implementation is tied to the decoder,
not checking for dangerous arguments for the sake
of performance.
+
+ The read bytes are kept in an internal cache until
+ setting _markedPosition which may reset the cache.
"""
def __init__(self, raw):
self._raw = raw
@@ -53,36 +56,42 @@ class _CachingStreamWrapper(IOBase):
return True
def seek(self, n=-1, whence=os.SEEK_SET):
+ # Note that this not safe for seeking forward.
return self._cache.seek(n, whence)
def read(self, n=-1):
read_from_cache = self._cache.read(n)
if n != -1:
n -= len(read_from_cache)
+ if n <= 0:
+ return read_from_cache
+
read_from_raw = self._raw.read(n)
self._cache.write(read_from_raw)
return read_from_cache + read_from_raw
@property
def _markedPosition(self):
- # This closely corresponds with how _marked_position attribute
- # is manipulated with in Decoder.__call__ and (indefLen)ValueDecoder's
+ """Position where the currently processed element starts.
+
+ This is used for back-tracking in Decoder.__call__
+ and (indefLen)ValueDecoder and should not be used for other purposes.
+ The client is not supposed to ever seek before this position.
+ """
return self._markedPosition_
@_markedPosition.setter
def _markedPosition(self, value):
+ # By setting the value, we ensure we won't seek back before it.
+ # `value` should be the same as the current position
+ # We don't check for this for performance reasons.
self._markedPosition_ = value
- self.seek(value)
# Whenever we set _marked_position, we know for sure
# that we will not return back, and thus it is
# safe to drop all cached data.
if self._cache.tell() > DEFAULT_BUFFER_SIZE:
- current = self._cache.read()
- self._cache.seek(0, os.SEEK_SET)
- self._cache.truncate()
- self._cache.write(current)
- self._cache.seek(0, os.SEEK_SET)
+ self._cache = BytesIO(self._cache.read())
self._markedPosition_ = 0
def tell(self):