1111process.
1212"""
1313import select
14- from .exceptions import ConnectionResetError
14+ from .exceptions import ConnectionResetError , LineTooLongError
1515
1616class BufferedSocket (object ):
1717 """
@@ -76,6 +76,25 @@ def can_read(self):
7676
7777 return False
7878
79+ def new_buffer (self ):
80+ """
81+ This method moves all the data in the backing buffer to the start of
82+ a new, fresh buffer. This gives the ability to read much more data.
83+ """
84+ def read_all_from_buffer ():
85+ end = self ._index + self ._bytes_in_buffer
86+ return self ._buffer_view [self ._index :end ]
87+
88+ new_buffer = bytearray (self ._buffer_size )
89+ new_buffer_view = memoryview (new_buffer )
90+ new_buffer_view [0 :self ._bytes_in_buffer ] = read_all_from_buffer ()
91+
92+ self ._index = 0
93+ self ._backing_buffer = new_buffer
94+ self ._buffer_view = new_buffer_view
95+
96+ return
97+
7998 def recv (self , amt ):
8099 """
81100 Read some data from the socket.
@@ -85,26 +104,16 @@ def recv(self, amt):
85104 bytes. The data *must* be copied out by the caller before the next
86105 call to this function.
87106 """
88- def read_all_from_buffer ():
89- end = self ._index + self ._bytes_in_buffer
90- return self ._buffer_view [self ._index :end ]
91-
92107 # In this implementation you can never read more than the number of
93108 # bytes in the buffer.
94109 if amt > self ._buffer_size :
95110 amt = self ._buffer_size
96111
97112 # If the amount of data we've been asked to read is less than the
98113 # remaining space in the buffer, we need to clear out the buffer and
99- # start over. Copy the data into the new array.
114+ # start over.
100115 if amt > self ._remaining_capacity :
101- new_buffer = bytearray (self ._buffer_size )
102- new_buffer_view = memoryview (new_buffer )
103- new_buffer_view [0 :self ._bytes_in_buffer ] = read_all_from_buffer ()
104-
105- self ._index = 0
106- self ._backing_buffer = new_buffer
107- self ._buffer_view = new_buffer_view
116+ self .new_buffer ()
108117
109118 # If there's still some room in the buffer, opportunistically attempt
110119 # to read into it.
@@ -136,5 +145,66 @@ def read_all_from_buffer():
136145
137146 return data
138147
148+ def readline (self ):
149+ """
150+ Read up to a newline from the network and returns it. The implicit
151+ maximum line length is the buffer size of the buffered socket.
152+
153+ :returns: A ``memoryview`` object containing the appropriate number of
154+ bytes. The data *must* be copied out by the caller before the next
155+ call to this function.
156+ """
157+ # First, check if there's anything in the buffer. This is one of those
158+ # rare circumstances where this will work correctly on all platforms.
159+ index = self ._backing_buffer .find (
160+ b'\n ' ,
161+ self ._index ,
162+ self ._index + self ._bytes_in_buffer
163+ )
164+
165+ if index != - 1 :
166+ length = index + 1 - self ._index
167+ data = self ._buffer_view [self ._index :self ._index + length ]
168+ self ._index += length
169+ self ._bytes_in_buffer -= length
170+ return data
171+
172+ # In this case, we didn't find a newline in the buffer. To fix that,
173+ # read some data into the buffer. To do our best to satisfy the read,
174+ # we should shunt the data down in the buffer so that it's right at
175+ # the start. We don't bother if we're already at the start of the
176+ # buffer.
177+ if self ._index != 0 :
178+ self .new_buffer ()
179+
180+ while self ._bytes_in_buffer < self ._buffer_size :
181+ count = self ._sck .recv_into (self ._buffer_view [self ._buffer_end :])
182+ if not count :
183+ raise ConnectionResetError ()
184+
185+ # We have some more data. Again, look for a newline in that gap.
186+ first_new_byte = self ._buffer_end
187+ self ._bytes_in_buffer += count
188+ index = self ._backing_buffer .find (
189+ b'\n ' ,
190+ first_new_byte ,
191+ first_new_byte + count ,
192+ )
193+
194+ if index != - 1 :
195+ # The length of the buffer is the index into the
196+ # buffer at which we found the newline plus 1, minus the start
197+ # index of the buffer, which really should be zero.
198+ assert not self ._index
199+ length = index + 1
200+ data = self ._buffer_view [:length ]
201+ self ._index += length
202+ self ._bytes_in_buffer -= length
203+ return data
204+
205+ # If we got here, it means we filled the buffer without ever getting
206+ # a newline. Time to throw an exception.
207+ raise LineTooLongError ()
208+
139209 def __getattr__ (self , name ):
140210 return getattr (self ._sck , name )
0 commit comments