xenu_nntp/lib/nntp/tiny/buffer.py

116 lines
2.9 KiB
Python
Raw Normal View History

2024-11-17 22:55:28 -05:00
import socket
2024-11-17 22:47:30 -05:00
class BufferOverflow(Exception):
def __init__(self):
super().__init__("Buffer overflow")
2024-11-26 18:43:08 -05:00
class OutputBuffer():
__slots__ = 'buf', 'size', 'sock', 'offset',
BUFFER_SIZE = 20480
def __init__(self, sock: socket.socket, size: int=BUFFER_SIZE):
self.buf: bytearray = bytearray(size)
self.size: int = size
self.sock: socket.socket = sock
self.offset: int = 0
2024-11-26 22:21:06 -05:00
def write(self, data: bytes):
count = len(data)
remaining = count
2024-11-26 18:43:08 -05:00
2024-11-26 22:21:06 -05:00
while remaining > 0:
if self.offset >= self.size:
self.offset = 0
2024-11-26 18:43:08 -05:00
2024-11-26 22:21:06 -05:00
needed = self.size - self.offset
copy = min(needed, remaining)
2024-11-26 18:43:08 -05:00
2024-11-26 22:21:06 -05:00
self.buf[self.offset:self.offset+copy] = data[0:copy]
2024-11-26 18:43:08 -05:00
2024-11-26 22:21:06 -05:00
remaining -= copy
self.offset += copy
2024-11-26 18:43:08 -05:00
2024-11-26 22:21:06 -05:00
if self.offset >= self.size:
self.sock.send(self.buf)
self.offset = 0
2024-11-26 18:43:08 -05:00
2024-11-26 22:21:06 -05:00
def print(self, text: str, end: str="\r\n"):
return self.write(bytes(text + end, 'utf-8'))
2024-11-26 18:43:08 -05:00
def flush(self):
self.sock.send(self.buf[0:self.offset])
self.offset = 0
2024-11-17 22:47:30 -05:00
class LineBuffer():
2024-11-19 14:29:51 -05:00
__slots__ = 'buf', 'size', 'offset_i', 'offset_o', 'eof', 'done',
2024-11-17 22:47:30 -05:00
BUFFER_SIZE = 4096
def __init__(self, size: int=BUFFER_SIZE):
2024-11-19 14:29:51 -05:00
self.buf: bytearray = bytearray(size)
self.size: int = size
self.offset_i: int = 0
self.offset_o: int = 0
self.eof: bool = False
self.done: bool = False
2024-11-17 22:47:30 -05:00
2024-11-18 21:40:10 -05:00
def _shift(self):
2024-11-19 14:29:51 -05:00
count = self.offset_i - self.offset_o
2024-11-18 21:40:10 -05:00
2024-11-19 14:29:51 -05:00
self.buf[0:count] = self.buf[self.offset_o:self.offset_i]
self.offset_i = count
self.offset_o = 0
2024-11-18 21:40:10 -05:00
def _is_full(self):
2024-11-19 14:29:51 -05:00
return self.offset_i >= self.size
2024-11-18 21:40:10 -05:00
def _fill(self, sock: socket.socket):
if self.eof:
return
2024-11-19 14:29:51 -05:00
data = sock.recv(self.size - self.offset_i)
2024-11-18 21:40:10 -05:00
if data == b'':
self.eof = True
return
readlen = len(data)
2024-11-19 14:29:51 -05:00
self.buf[self.offset_i:self.size] = data
self.offset_i += readlen
def _drain(self, end=None):
if end is None:
end = self.offset_i + 1
2024-11-18 21:40:10 -05:00
2024-11-19 14:29:51 -05:00
ret = self.buf[self.offset_o:end+1]
2024-11-18 21:40:10 -05:00
2024-11-19 14:29:51 -05:00
self.offset_o = end + 1
2024-11-18 21:40:10 -05:00
2024-11-25 15:57:20 -05:00
return str(ret, 'utf-8')
2024-11-18 21:40:10 -05:00
def readline(self, sock: socket.socket) -> str:
2024-11-19 14:29:51 -05:00
if self.done:
return ''
2024-11-19 14:31:48 -05:00
2024-11-17 22:47:30 -05:00
while True:
2024-11-19 14:29:51 -05:00
index = self.buf.find(b'\n', self.offset_o, self.offset_i)
2024-11-18 21:40:10 -05:00
if index < 0:
if self._is_full():
2024-11-19 14:29:51 -05:00
if self.offset_o == 0:
2024-11-18 21:40:10 -05:00
raise BufferOverflow()
2024-11-19 14:31:48 -05:00
2024-11-19 14:29:51 -05:00
self._shift()
elif self.eof:
self.done = True
return self._drain()
2024-11-18 21:40:10 -05:00
else:
self._fill(sock)
2024-11-17 22:47:30 -05:00
else:
2024-11-19 14:29:51 -05:00
return self._drain(index)