[pypy-svn] pypy default: Give the offset keyword argument to mmap().

arigo commits-noreply at bitbucket.org
Thu Feb 10 17:03:10 CET 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r41788:943e58cee14c
Date: 2011-02-10 17:02 +0100
http://bitbucket.org/pypy/pypy/changeset/943e58cee14c/

Log:	Give the offset keyword argument to mmap().

diff --git a/pypy/module/mmap/interp_mmap.py b/pypy/module/mmap/interp_mmap.py
--- a/pypy/module/mmap/interp_mmap.py
+++ b/pypy/module/mmap/interp_mmap.py
@@ -5,7 +5,7 @@
 from pypy.interpreter.typedef import TypeDef
 from pypy.interpreter.gateway import interp2app, NoneNotWrapped
 from pypy.rlib import rmmap
-from pypy.rlib.rmmap import RValueError, RTypeError
+from pypy.rlib.rmmap import RValueError, RTypeError, ROverflowError
 import sys
 import os
 import platform
@@ -207,36 +207,42 @@
 
     def mmap(space, w_subtype, fileno, length, flags=rmmap.MAP_SHARED,
              prot=rmmap.PROT_WRITE | rmmap.PROT_READ,
-             access=rmmap._ACCESS_DEFAULT):
+             access=rmmap._ACCESS_DEFAULT, offset=0):
         self = space.allocate_instance(W_MMap, w_subtype)
         try:
             W_MMap.__init__(self, space,
-                            rmmap.mmap(fileno, length, flags, prot, access))
+                            rmmap.mmap(fileno, length, flags, prot, access,
+                                       offset))
         except OSError, e:
             raise mmap_error(space, e)
         except RValueError, e:
             raise OperationError(space.w_ValueError, space.wrap(e.message))
         except RTypeError, e:
             raise OperationError(space.w_TypeError, space.wrap(e.message))
+        except ROverflowError, e:
+            raise OperationError(space.w_OverflowError, space.wrap(e.message))
         return space.wrap(self)
-    mmap.unwrap_spec = [ObjSpace, W_Root, int, 'index', int, int, int]
+    mmap.unwrap_spec = [ObjSpace, W_Root, int, 'index', int, int, int, 'index']
 
 elif rmmap._MS_WINDOWS:
 
     def mmap(space, w_subtype, fileno, length, tagname="",
-             access=rmmap._ACCESS_DEFAULT):
+             access=rmmap._ACCESS_DEFAULT, offset=0):
         self = space.allocate_instance(W_MMap, w_subtype)
         try:
             W_MMap.__init__(self, space,
-                            rmmap.mmap(fileno, length, tagname, access))
+                            rmmap.mmap(fileno, length, tagname, access,
+                                       offset))
         except OSError, e:
             raise mmap_error(space, e)
         except RValueError, e:
             raise OperationError(space.w_ValueError, space.wrap(e.message))
         except RTypeError, e:
             raise OperationError(space.w_TypeError, space.wrap(e.message))
+        except ROverflowError, e:
+            raise OperationError(space.w_OverflowError, space.wrap(e.message))
         return space.wrap(self)
-    mmap.unwrap_spec = [ObjSpace, W_Root, int, 'index', str, int]
+    mmap.unwrap_spec = [ObjSpace, W_Root, int, 'index', str, int, 'index']
 
 W_MMap.typedef = TypeDef("mmap",
     __new__ = interp2app(mmap),

diff --git a/pypy/module/mmap/test/test_mmap.py b/pypy/module/mmap/test/test_mmap.py
--- a/pypy/module/mmap/test/test_mmap.py
+++ b/pypy/module/mmap/test/test_mmap.py
@@ -518,6 +518,17 @@
         assert b[3] == "b"
         assert b[:] == "foobar"
 
+    def test_offset(self):
+        from mmap import mmap
+        f = open(self.tmpname + "y", "w+")
+        f.write("foobar" * 3000)
+        f.flush()
+        m = mmap(f.fileno(), 4, offset=8192)
+        assert m[:] == "obar"
+        assert len(m) == 4
+        m.close()
+        f.close()
+
     def test_all(self):
         # this is a global test, ported from test_mmap.py
         import mmap

diff --git a/pypy/rlib/rmmap.py b/pypy/rlib/rmmap.py
--- a/pypy/rlib/rmmap.py
+++ b/pypy/rlib/rmmap.py
@@ -21,7 +21,11 @@
 
 class RTypeError(Exception):
     def __init__(self, message):
-        self.message = message    
+        self.message = message
+
+class ROverflowError(Exception):
+    def __init__(self, message):
+        self.message = message
 
 includes = ["sys/types.h"]
 if _POSIX:
@@ -607,11 +611,11 @@
     if size < 0:
         raise RTypeError("memory mapped size must be positive")
     if rffi.cast(size_t, size) != size:
-        raise OverflowError("memory mapped size is too large (limited by C int)")
+        raise ROverflowError("memory mapped size is too large (limited by C int)")
 
 if _POSIX:
     def mmap(fileno, length, flags=MAP_SHARED,
-        prot=PROT_WRITE | PROT_READ, access=_ACCESS_DEFAULT):
+        prot=PROT_WRITE | PROT_READ, access=_ACCESS_DEFAULT, offset=0):
 
         fd = fileno
 
@@ -623,6 +627,8 @@
         # check size boundaries
         _check_map_size(length)
         map_size = length
+        if offset < 0:
+            raise RValueError("negative offset")
 
         if access == ACCESS_READ:
             flags = MAP_SHARED
@@ -649,6 +655,7 @@
         else:
             mode = st[stat.ST_MODE]
             size = st[stat.ST_SIZE]
+            size -= offset
             if size > sys.maxint:
                 size = sys.maxint
             else:
@@ -674,7 +681,7 @@
         # XXX if we use hintp below in alloc, the NonConstant
         #     is necessary since we want a general version of c_mmap
         #     to be annotated with a non-constant pointer.
-        res = c_mmap(NonConstant(NULL), map_size, prot, flags, fd, 0)
+        res = c_mmap(NonConstant(NULL), map_size, prot, flags, fd, offset)
         if res == rffi.cast(PTR, -1):
             errno = _get_error_no()
             raise OSError(errno, os.strerror(errno))
@@ -711,10 +718,12 @@
     free = c_munmap_safe
     
 elif _MS_WINDOWS:
-    def mmap(fileno, length, tagname="", access=_ACCESS_DEFAULT):
+    def mmap(fileno, length, tagname="", access=_ACCESS_DEFAULT, offset=0):
         # check size boundaries
         _check_map_size(length)
         map_size = length
+        if offset < 0:
+            raise RValueError("negative offset")
         
         flProtect = 0
         dwDesiredAccess = 0
@@ -785,16 +794,20 @@
         if _64BIT:
             size_hi = map_size >> 32
             size_lo = map_size & 0xFFFFFFFF
+            offset_hi = offset >> 32
+            offset_lo = offset & 0xFFFFFFFF
         else:
             size_hi = 0
             size_lo = map_size
+            offset_hi = 0
+            offset_lo = offset
 
         m.map_handle = CreateFileMapping(m.file_handle, NULL, flProtect,
                                          size_hi, size_lo, m.tagname)
 
         if m.map_handle:
             res = MapViewOfFile(m.map_handle, dwDesiredAccess,
-                                0, 0, 0)
+                                offset_hi, offset_lo, 0)
             if res:
                 # XXX we should have a real LPVOID which must always be casted
                 charp = rffi.cast(LPCSTR, res)


More information about the Pypy-commit mailing list