11# Fallback pure Python implementation of msgpack
22
3- #
4- # Easy imports
5- #
63import sys
74import array
85import struct
96
10- #
11- # Tricky imports
12- #
13- try :
14- from cStringIO import StringIO
15- except ImportError :
16- from StringIO import StringIO
17-
18- # We will use wStringIO for buffering the writes for packing.
19- # Normally, we will use cStringIO.StringIO.
20- # On PyPy we will use PyPy's own StringBuilder.
217if hasattr (sys , 'pypy_version_info' ):
8+ # cStringIO is slow on PyPy, StringIO is faster. However: PyPy's own
9+ # StringBuilder is fastest.
2210 from __pypy__ .builders import StringBuilder
2311 USING_STRINGBUILDER = True
24- class wStringIO (object ):
12+ class StringIO (object ):
2513 def __init__ (self , s = '' ):
2614 if s :
2715 self .builder = StringBuilder (len (s ))
@@ -34,18 +22,10 @@ def getvalue(self):
3422 return self .builder .build ()
3523else :
3624 USING_STRINGBUILDER = False
37- wStringIO = StringIO
38-
39- # We will use rStringIO for unpacking.
40- # Normally, this is a mmap. A normal StringIO is not a drop-in replacement ---
41- # it misses the __len__ operation.
42- # TODO add fallback for when mmap is unavailable
43- import mmap
44- def rStringIO (s ):
45- m = mmap .mmap (- 1 , len (s ))
46- m .write (s )
47- m .seek (0 )
48- return m
25+ try :
26+ from cStringIO import StringIO
27+ except ImportError :
28+ from StringIO import StringIO
4929
5030from msgpack .exceptions import (
5131 BufferFull ,
@@ -204,13 +184,13 @@ def feed(self, next_bytes):
204184 if self ._fb_buf_n + len (next_bytes ) > self .max_buffer_size :
205185 raise BufferFull
206186 self ._fb_buf_n += len (next_bytes )
207- self ._fb_buffers .append (rStringIO ( next_bytes ) )
187+ self ._fb_buffers .append (next_bytes )
208188
209189 def _fb_consume (self ):
210190 self ._fb_buffers = self ._fb_buffers [self ._fb_buf_i :]
211191 if self ._fb_buffers :
212- self ._fb_buffers [0 ] = rStringIO ( self ._fb_buffers [0 ][
213- self ._fb_buffers [ 0 ]. tell ():])
192+ self ._fb_buffers [0 ] = self ._fb_buffers [0 ][self . _fb_buf_o :]
193+ self ._fb_buf_o = 0
214194 self ._fb_buf_i = 0
215195 self ._fb_buf_n = sum (map (len , self ._fb_buffers ))
216196
@@ -232,20 +212,16 @@ def read_bytes(self, n):
232212 return self ._fb_read (n )
233213
234214 def _fb_rollback (self ):
235- for buf in self ._fb_buffers :
236- buf .seek (0 )
237215 self ._fb_buf_i = 0
216+ self ._fb_buf_o = 0
238217
239218 def _fb_get_extradata (self ):
240219 bufs = self ._fb_buffers [self ._fb_buf_i :]
241220 if bufs :
242- bufs [0 ] = rStringIO ( bufs [0 ][bufs [ 0 ]. tell ():])
243- return '' .join ([ buf [:] for buf in bufs ] )
221+ bufs [0 ] = bufs [0 ][self . _fb_buf_o :]
222+ return '' .join (bufs )
244223
245224 def _fb_read (self , n , write_bytes = None ):
246- if (write_bytes is None and self ._fb_buf_i < len (self ._fb_buffers )
247- and self ._fb_buffers [0 ].tell () + n < len (self ._fb_buffers [0 ])):
248- return self ._fb_buffers [0 ].read (n )
249225 ret = ''
250226 while len (ret ) != n :
251227 if self ._fb_buf_i == len (self ._fb_buffers ):
@@ -254,12 +230,14 @@ def _fb_read(self, n, write_bytes=None):
254230 tmp = self .file_like .read (self .read_size )
255231 if not tmp :
256232 break
257- self ._fb_buffers .append (rStringIO ( tmp ) )
233+ self ._fb_buffers .append (tmp )
258234 continue
259235 sliced = n - len (ret )
260- ret += self ._fb_buffers [self ._fb_buf_i ].read (sliced )
261- if (self ._fb_buffers [self ._fb_buf_i ].tell ()
262- == len (self ._fb_buffers [self ._fb_buf_i ])):
236+ ret += self ._fb_buffers [self ._fb_buf_i ][
237+ self ._fb_buf_o :self ._fb_buf_o + sliced ]
238+ self ._fb_buf_o += sliced
239+ if self ._fb_buf_o >= len (self ._fb_buffers [self ._fb_buf_i ]):
240+ self ._fb_buf_o = 0
263241 self ._fb_buf_i += 1
264242 if len (ret ) != n :
265243 self ._fb_rollback ()
@@ -416,7 +394,7 @@ def __init__(self, default=None, encoding='utf-8', unicode_errors='strict',
416394 self .autoreset = autoreset
417395 self .encoding = encoding
418396 self .unicode_errors = unicode_errors
419- self .buffer = wStringIO ()
397+ self .buffer = StringIO ()
420398 if default is not None :
421399 if not callable (default ):
422400 raise TypeError ("default must be callable" )
@@ -486,33 +464,33 @@ def pack(self, obj):
486464 self ._pack (obj )
487465 ret = self .buffer .getvalue ()
488466 if self .autoreset :
489- self .buffer = wStringIO ()
467+ self .buffer = StringIO ()
490468 elif USING_STRINGBUILDER :
491- self .buffer = wStringIO (ret )
469+ self .buffer = StringIO (ret )
492470 return ret
493471 def pack_map_pairs (self , pairs ):
494472 self ._fb_pack_map_pairs (len (pairs ), pairs )
495473 ret = self .buffer .getvalue ()
496474 if self .autoreset :
497- self .buffer = wStringIO ()
475+ self .buffer = StringIO ()
498476 elif USING_STRINGBUILDER :
499- self .buffer = wStringIO (ret )
477+ self .buffer = StringIO (ret )
500478 return ret
501479 def pack_array_header (self , n ):
502480 self ._fb_pack_array_header (n )
503481 ret = self .buffer .getvalue ()
504482 if self .autoreset :
505- self .buffer = wStringIO ()
483+ self .buffer = StringIO ()
506484 elif USING_STRINGBUILDER :
507- self .buffer = wStringIO (ret )
485+ self .buffer = StringIO (ret )
508486 return ret
509487 def pack_map_header (self , n ):
510488 self ._fb_pack_map_header (n )
511489 ret = self .buffer .getvalue ()
512490 if self .autoreset :
513- self .buffer = wStringIO ()
491+ self .buffer = StringIO ()
514492 elif USING_STRINGBUILDER :
515- self .buffer = wStringIO (ret )
493+ self .buffer = StringIO (ret )
516494 return ret
517495 def _fb_pack_array_header (self , n ):
518496 if n <= 0x0f :
@@ -538,4 +516,4 @@ def _fb_pack_map_pairs(self, n, pairs, nest_limit=DEFAULT_RECURSE_LIMIT):
538516 def bytes (self ):
539517 return self .buffer .getvalue ()
540518 def reset (self ):
541- self .buffer = wStringIO ()
519+ self .buffer = StringIO ()
0 commit comments