137 lines
No EOL
3.3 KiB
Python
Executable file
137 lines
No EOL
3.3 KiB
Python
Executable file
try:
|
|
from cStringIO import StringIO
|
|
except ImportError:
|
|
from StringIO import StringIO
|
|
|
|
|
|
|
|
class RingBuffer(object):
|
|
def __init__(self, size):
|
|
self.size = size
|
|
self.buffer = StringIO()
|
|
self.buffer_pos = 0
|
|
self.read_pos = 0
|
|
self.bytes_written = 0
|
|
self.first_read = True
|
|
self.fullclass = RingBufferFull
|
|
|
|
def write(self, data):
|
|
if self.buffer_pos + len(data) >= self.size:
|
|
self.__class__ = self.fullclass
|
|
split = self.size - self.buffer_pos
|
|
self.buffer.write(data[:split])
|
|
self.buffer.seek(0, 0)
|
|
self.buffer_pos = 0
|
|
self.bytes_written += split
|
|
self.write(data[split:])
|
|
else:
|
|
self.buffer.write(data)
|
|
self.buffer_pos += len(data)
|
|
self.bytes_written += len(data)
|
|
|
|
def read(self, bytes=0):
|
|
self.buffer.seek(self.read_pos, 0)
|
|
rb = self.buffer.read(bytes)
|
|
self.read_pos = self.buffer.tell()
|
|
self.buffer.seek(self.buffer_pos, 0)
|
|
return rb
|
|
|
|
|
|
class SplitRingBuffer(RingBuffer):
|
|
def __init__(self, size, split):
|
|
RingBuffer.__init__(self, size)
|
|
self.fullclass = SplitRingBufferFull
|
|
self.splitpos = split
|
|
self.read_pos = split
|
|
|
|
def read_head():
|
|
self.buffer.seek(0, 0)
|
|
rb = self.buffer.read()
|
|
self.buffer.seek(self.buffer_pos, 0)
|
|
return (True, rb)
|
|
|
|
|
|
class RingBufferFull(object):
|
|
def __init__(self, size):
|
|
raise NotImplementedError, "You should not create this class manually, use RingBuffer() instead"
|
|
|
|
def overflow_buffer():
|
|
self.buffer_pos = 0
|
|
self.seek_to_start()
|
|
|
|
def seek_to_start():
|
|
self.buffer.seek(0, 0)
|
|
|
|
|
|
def write(self, data):
|
|
di = 0
|
|
ld = len(data)
|
|
while (ld - di) + self.buffer_pos >= self.size:
|
|
self.buffer.write(data[di:di + (self.size - self.buffer_pos)])
|
|
if self.read_pos != None and self.read_pos > self.buffer_pos:
|
|
# our read pos has been overwritten, we've lost our place
|
|
self.read_pos = None
|
|
self.overflow_buffer()
|
|
di += (self.size - self.buffer_pos)
|
|
self.buffer.write(data[di:])
|
|
if self.read_pos != None and self.buffer_pos <= self.read_pos and (self.buffer_pos + ld - di) > self.read_pos:
|
|
self.read_pos = None
|
|
self.buffer_pos += ld - di
|
|
self.bytes_written += ld
|
|
|
|
def read(self, bytes=0):
|
|
pos = self.read_pos
|
|
fullread = False
|
|
if pos == None:
|
|
pos = self.buffer_pos
|
|
fullread = True
|
|
|
|
if pos == self.buffer_pos and fullread:
|
|
maxlen = self.size
|
|
elif pos == self.buffer_pos and not fullread:
|
|
maxlen = 0
|
|
else:
|
|
maxlen = self.buffer_pos - pos
|
|
if maxlen < 0:
|
|
maxlen += self.size
|
|
self.buffer.seek(pos, 0)
|
|
if bytes > 0 and maxlen > bytes:
|
|
maxlen = bytes
|
|
|
|
if maxlen == 0:
|
|
return ''
|
|
|
|
split = self.size - pos
|
|
if split >= maxlen:
|
|
self.buffer.seek(pos, 0)
|
|
rb = self.buffer.read(maxlen)
|
|
self.read_pos = self.buffer.tell()
|
|
self.buffer.seek(self.buffer_pos, 0)
|
|
else:
|
|
self.buffer.seek(pos, 0)
|
|
rb = self.buffer.read(split)
|
|
self.seek_to_start()
|
|
rb += self.buffer.read(maxlen - split)
|
|
self.read_pos = self.buffer.tell()
|
|
self.buffer.seek(self.buffer_pos, 0)
|
|
|
|
return rb
|
|
|
|
|
|
class SplitRingBufferFull(RingBufferFull):
|
|
def read(self, bytes=0):
|
|
pass
|
|
|
|
def overflow_buffer():
|
|
self.buffer_pos = self.split_pos
|
|
|
|
def seek_to_start():
|
|
self.buffer.seek(self.split_pos, 0)
|
|
|
|
def read_head():
|
|
self.buffer.seek(0, 0)
|
|
rb = self.buffer.read(self.split_pos)
|
|
self.buffer.seek(self.buffer_pos, 0)
|
|
return (False, rb)
|
|
|
|
|