""" Input buffering code for AsyncThreadedAppServer. This module creates a file interface to data being received through an asynconous socket. Based entirely on code contributed by Vladimir Kralik. Tweaked by Jay Love. """ import string class ATASStreamIn: # methods to simulating read file-access to ayncore.dispatcher, # idea from StringIO def __init__(self, dispatcher, buffersize=8192): self._dispatcher=dispatcher self._buffersize=buffersize self.reset() def reset(self): self.len = 0 self.buflist = [] self.closed = 0 self.softspace = 0 self._hasMore=1 # in socket self._notQueued=1 # in request queue def dataAvailable(self): return not self._hasMore def canRecv(self): return self._hasMore and self._notQueued def recv(self): assert self._hasMore and self._notQueued data = self._dispatcher.recv(8192) lendata=len(data) self.len=self.len+lendata if lendata > 0: self.buflist.append(data) else: self.buflist.append(data) self._hasMore=0 # all is readed if self._hasMore and self.len < self._buffersize: pass else: self._notQueued=0 self._dispatcher.server.requestQueue.put(self._dispatcher) # file access def close(self): if not self.closed: self.closed = 1 del self.buflist, self.len def isatty(self): if self.closed: raise ValueError, "I/O operation on closed file" return 0 def read(self, n = -1): assert not self._notQueued if self.closed: raise ValueError, "I/O operation on closed file" if n==0: return '' elif n < 0: # read all data if self._hasMore: # has more data in socket, read it sock=self._dispatcher.socket try : sock.setblocking(1) while 1: data=sock.recv(8192) if not data: break self.buflist.append(data) finally: sock.setblocking(0) self._hasMore=0 return string.joinfields(self.buflist,'') elif self.buflist: outlist=[] outlen=0 while self.buflist: data=self.buflist.pop(0) lendata=len(data) outlen=outlen+lendata if outlen>n: break outlist.append(data) if outlen>n: diff=n-outlen+lendata outlist.append(data[:diff]) self.buflist.insert(0, data[diff:]) elif self._hasMore and outlen<n: outlist.append(self.read(n-outlen)) return string.joinfields(outlist,'') elif self._hasMore: sock=self._dispatcher.socket try : sock.setblocking(1) data=sock.recv(n) finally: sock.setblocking(0) self._hasMore=0 return data else: return '' def _readlinedata(self,data,length,outlist): i = string.find(data, '\n') if i<0: # not found if length and len(data)>=length: i=length else: outlist.append(data) return (0,length and length-len(data)) elif length and i>=length: i=length else: i=i+1 dd=data[:i] outlist.append(dd) self.buflist.insert(0,data[i:]) return (1,length and length-len(data)) # read all def readline(self, length=None): assert not self._notQueued if self.closed: raise ValueError, "I/O operation on closed file" if length==0: return '' elif self.buflist: outlist=[] while self.buflist: data=self.buflist.pop(0) con,length = self._readlinedata( data,length,outlist) if con: break if self._hasMore and not con: outlist.append(self.readline(length)) return string.joinfields(outlist,'') elif self._hasMore: sock=self._dispatcher.socket try : outlist=[] sock.setblocking(1) while 1: if self.buflist:data=self.buflist.pop(0) else: data=sock.recv(8192) if not data: self._hasMore=0 break con,length = self._readlinedata( data,length,outlist) if con: break return string.joinfields(outlist,'') finally: sock.setblocking(0) else: return '' def readlines(self): lines = [] line = self.readline() while line: lines.append(line) line = self.readline() return lines def flush(self): if self.closed: raise ValueError, "I/O operation on closed file"