[pypy-svn] r32257 - pypy/dist/pypy/module/mmap

arigo at codespeak.net arigo at codespeak.net
Wed Sep 13 14:11:17 CEST 2006


Author: arigo
Date: Wed Sep 13 14:11:16 2006
New Revision: 32257

Modified:
   pypy/dist/pypy/module/mmap/interp_mmap.py
Log:
In-progress: various clean-ups of the mmap module.


Modified: pypy/dist/pypy/module/mmap/interp_mmap.py
==============================================================================
--- pypy/dist/pypy/module/mmap/interp_mmap.py	(original)
+++ pypy/dist/pypy/module/mmap/interp_mmap.py	Wed Sep 13 14:11:16 2006
@@ -19,15 +19,13 @@
 
 
 class CConfig:
-    _header_ = "#include <sys/types.h>"
+    _includes_ = ("sys/types.h",)
     size_t = ctypes_platform.SimpleType("size_t", c_long)
     off_t = ctypes_platform.SimpleType("off_t", c_long)
 
 constants = {}
 if _POSIX:
-    CConfig._header_ = """
-    %s
-    #include <sys/mman.h>""" % CConfig._header_
+    CConfig._includes_ += ("sys/mman.h",)
     # constants, look in sys/mman.h and platform docs for the meaning
     # some constants are linux only so they will be correctly exposed outside 
     # depending on the OS
@@ -37,9 +35,7 @@
     for name in constant_names:
         setattr(CConfig, name, ctypes_platform.DefinedConstantInteger(name))
 elif _MS_WINDOWS:
-    CConfig._header_ = """
-    %s
-    #include <windows.h>""" % CConfig._header_
+    CConfig._includes_ += ("windows.h",)
     constant_names = ['PAGE_READONLY', 'PAGE_READWRITE', 'PAGE_WRITECOPY',
                       'FILE_MAP_READ', 'FILE_MAP_WRITE', 'FILE_MAP_COPY',
                       'DUPLICATE_SAME_ACCESS']
@@ -68,39 +64,31 @@
 
 _ACCESS_DEFAULT, ACCESS_READ, ACCESS_WRITE, ACCESS_COPY = range(4)
 
+PTR = POINTER(c_char)    # cannot use c_void_p as return value of functions :-(
+
 size_t = cConfig.size_t
 off_t = cConfig.off_t
 libc.strerror.restype = c_char_p
 libc.strerror.argtypes = [c_int]
-libc.memcpy.argtypes = [POINTER(c_char), c_char_p, c_int]
-libc.memcpy.restype = c_void_p
-libc.memmove.argtypes = [c_char_p, c_char_p, size_t]
-libc.memmove.restype = c_void_p
 
 if _POSIX:
-    libc.mmap.argtypes = [c_void_p, size_t, c_int, c_int, c_int, off_t]
-    libc.mmap.restype = c_void_p
+    libc.mmap.argtypes = [PTR, size_t, c_int, c_int, c_int, off_t]
+    libc.mmap.restype = PTR
+    libc.mmap.includes = ("sys/mman.h",)
     libc.close.argtypes = [c_int]
     libc.close.restype = c_int
-    libc.munmap.argtypes = [c_void_p, size_t]
+    libc.munmap.argtypes = [PTR, size_t]
     libc.munmap.restype = c_int
-    libc.msync.argtypes = [c_char_p, size_t, c_int]
+    libc.munmap.includes = ("sys/mman.h",)
+    libc.msync.argtypes = [PTR, size_t, c_int]
     libc.msync.restype = c_int
-
-    ## LINUX msync syscall helper stuff
-    # you don't have addressof() in rctypes so I looked up the implementation
-    # of addressof in ctypes source and come up with this.
-    pythonapi.PyLong_FromVoidPtr.argtypes = [c_char_p]
-    pythonapi.PyLong_FromVoidPtr.restype = c_int
-    # we also need to alias msync to take a c_void_p instead of c_char_p
-    linux_msync = libc["msync"]
-    linux_msync.argtypes = [c_void_p, size_t, c_int]
-    linux_msync.restype = c_int
+    libc.msync.includes = ("sys/mman.h",)
     
     has_mremap = False
     if hasattr(libc, "mremap"):
-        libc.mremap.argtypes = [POINTER(c_char), size_t, size_t, c_ulong]
-        libc.mremap.restype = c_void_p
+        libc.mremap.argtypes = [PTR, size_t, size_t, c_ulong]
+        libc.mremap.restype = PTR
+        libc.mremap.includes = ("sys/mman.h",)
         has_mremap = True
     libc.ftruncate.argtypes = [c_int, off_t]
     libc.ftruncate.restype = c_int
@@ -118,7 +106,7 @@
     DWORD = wintypes.DWORD
     BOOL = wintypes.BOOL
     LONG = wintypes.LONG
-    LPVOID = c_void_p
+    LPVOID = PTR
     LPCVOID = LPVOID
     DWORD_PTR = DWORD
     c_int = wintypes.c_int
@@ -155,12 +143,12 @@
                                 BOOL, DWORD]
     DuplicateHandle.restype = BOOL
     CreateFileMapping = windll.kernel32.CreateFileMappingA
-    CreateFileMapping.argtypes = [c_int, c_void_p, c_int, c_int, c_int,
+    CreateFileMapping.argtypes = [c_int, PTR, c_int, c_int, c_int,
                                   c_char_p]
     CreateFileMapping.restype = c_int
     MapViewOfFile = windll.kernel32.MapViewOfFile
     MapViewOfFile.argtypes = [c_int, DWORD,  DWORD, DWORD, DWORD]
-    MapViewOfFile.restype = c_void_p
+    MapViewOfFile.restype = PTR
     CloseHandle = windll.kernel32.CloseHandle
     CloseHandle.argtypes = [c_int]
     CloseHandle.restype = BOOL
@@ -168,7 +156,7 @@
     UnmapViewOfFile.argtypes = [LPCVOID]
     UnmapViewOfFile.restype = BOOL
     FlushViewOfFile = windll.kernel32.FlushViewOfFile
-    FlushViewOfFile.argtypes = [c_char_p, c_int]
+    FlushViewOfFile.argtypes = [LPCVOID, c_int]
     FlushViewOfFile.restype = BOOL
     SetFilePointer = windll.kernel32.SetFilePointer
     SetFilePointer.argtypes = [c_int, c_int, POINTER(c_int), c_int]
@@ -187,6 +175,7 @@
         return int(si.dwPageSize)
     
     def _get_file_size(space, handle):
+        # XXX use native Windows types like WORD
         high = c_int(0)
         low = c_int(windll.kernel32.GetFileSize(c_int(handle.value), byref(high)))
         # low might just happen to have the value INVALID_FILE_SIZE
@@ -205,80 +194,86 @@
         return libc.strerror(errno)
 
 PAGESIZE = _get_page_size()
+NULL = PTR()
+
+# ____________________________________________________________
 
-class _mmap(Wrappable):
-    def __init__(self, space):
+class W_MMap(Wrappable):
+    def __init__(self, space, access):
         self.space = space
-        self._size = 0
-        self._pos = 0
-        self._access = _ACCESS_DEFAULT
+        self.size = 0
+        self.pos = 0
+        self.access = access
 
         if _MS_WINDOWS:
-            self._map_handle = wintypes.c_int()
-            self._file_handle = wintypes.c_int()
-            self._tagname = ""
+            self.map_handle = wintypes.c_int()
+            self.file_handle = wintypes.c_int()
+            self.tagname = ""
         elif _POSIX:
-            self._fd = 0
-            self._closed = False
+            self.fd = -1
+            self.closed = False
     
-    def _to_str(self):
-        data = "".join([self._data[i] for i in range(self._size)])
-        return self.space.wrap(data)
-    _to_str.unwrap_spec = ['self']
+##    def to_str(self):
+##        return "".join([self.data[i] for i in range(self.size)])
     
-    def _check_valid(self):
+    def check_valid(self):
         if _MS_WINDOWS:
-            to_close = self._map_handle.value == INVALID_c_int_VALUE
+            to_close = self.map_handle.value == INVALID_c_int_VALUE
         elif _POSIX:
-            to_close = self._closed
+            to_close = self.closed
 
         if to_close:
             raise OperationError(self.space.w_ValueError, 
                     self.space.wrap("map closed or invalid"))
-    _check_valid.unwrap_spec = ['self']
     
-    def _check_writeable(self):
-        if not (self._access != ACCESS_READ):
+    def check_writeable(self):
+        if not (self.access != ACCESS_READ):
             raise OperationError(self.space.w_TypeError,
                 self.space.wrap("mmap can't modify a readonly memory map."))
-    _check_writeable.unwrap_spec = ['self']
     
-    def _check_resizeable(self):
-        if not (self._access == ACCESS_WRITE or self._access == _ACCESS_DEFAULT):
+    def check_resizeable(self):
+        if not (self.access == ACCESS_WRITE or self.access == _ACCESS_DEFAULT):
             raise OperationError(self.space.w_TypeError,
                 self.space.wrap(
                     "mmap can't resize a readonly or copy-on-write memory map."))
-    _check_resizeable.unwrap_spec = ['self']
+
+    def setdata(self, data, size):
+        """Set the internal data and map size from a PTR."""
+        arraytype = c_char * size
+        self.data = cast(data, POINTER(arraytype))
+        self.size = size
     
     def close(self):
         if _MS_WINDOWS:
-            if self._data:
-                self._unmapview()
-                self._data = POINTER(c_char)()
-            if self._map_handle.value != INVALID_c_int_VALUE:
-                CloseHandle(self._map_handle)
-                self._map_handle.value = INVALID_c_int_VALUE
-            if self._file_handle.value != INVALID_c_int_VALUE:
-                CloseHandle(self._file_handle)
-                self._file_handle.value = INVALID_c_int_VALUE
+            if self.data:
+                self.unmapview()
+                self.setdata(NULL, 0)
+            if self.map_handle.value != INVALID_c_int_VALUE:
+                CloseHandle(self.map_handle)
+                self.map_handle.value = INVALID_c_int_VALUE
+            if self.file_handle.value != INVALID_c_int_VALUE:
+                CloseHandle(self.file_handle)
+                self.file_handle.value = INVALID_c_int_VALUE
         elif _POSIX:
-            self._closed = True
-            libc.close(self._fd)
-            self._fd = -1
-            if self._data:
-                libc.munmap(self._data, self._size)
+            self.closed = True
+            if self.fd != -1:
+                libc.close(self.fd)
+                self.fd = -1
+            if self.data:
+                libc.munmap(self.data, self.size)
+                self.setdata(NULL, 0)
     close.unwrap_spec = ['self']
     
-    def _unmapview(self):
-        data = cast(self._data, c_void_p)
+    def unmapview(self):
+        data = cast(self.data, PTR)
         UnmapViewOfFile(data)
     
     def read_byte(self):
-        self._check_valid()
+        self.check_valid()
 
-        if self._pos < self._size:
-            value = self._data[self._pos]
-            self._pos += 1
+        if self.pos < self.size:
+            value = self.data[self.pos]
+            self.pos += 1
             return self.space.wrap(value)
         else:
             raise OperationError(self.space.w_ValueError,
@@ -286,174 +281,157 @@
     read_byte.unwrap_spec = ['self']
     
     def readline(self):
-        self._check_valid()
+        self.check_valid()
 
-        found = False
-        for pos in range(self._pos, self._size):
-            if self._data[pos] == '\n':
-                found = True
+        for pos in xrange(self.pos, self.size):
+            if self.data[pos] == '\n':
+                eol = pos + 1 # we're interested in the position after new line
                 break
+        else: # no '\n' found
+            eol = self.size
 
-        if not found:
-            eol = self._size
-        else:
-            eol = pos + 1 # we're interested in the position after new line
-
-        # res = self._data[self._pos:eol-self._pos] XXX: can't use this slicing
-        # in translation step
-        res = "".join([self._data[i] for i in range(self._pos, eol-self._pos)])
-        self._pos += eol - self._pos
+        res = self.data[self.pos:eol]
+        self.pos += len(res)
         return self.space.wrap(res)
     readline.unwrap_spec = ['self']
     
-    def read(self, num):
-        self._check_valid()
-        
-        num_bytes = num
-        
-        # silently adjust out of range requests
-        assert self._pos >= 0; assert num_bytes >= 0; assert self._size >= 0
-        if self._pos + num_bytes > self._size:
-            num_bytes -= (self._pos + num_bytes) - self._size
-        
-        # due to slicing of python, the last char is not always returned
-        if num_bytes < self._size - 1:
-            res = "".join([self._data[i] for i in range(self._pos, num_bytes)])
-        else:
-            res = "".join([self._data[i] for i in range(self._pos, self._size)])
-        self._pos += num_bytes
+    def read(self, num=-1):
+        self.check_valid()
+
+        if num < 0:
+            # read all
+            eol = self.size
+        else:
+            eol = self.pos + num
+            # silently adjust out of range requests
+            if eol > self.size:
+                eol = self.size
+
+        res = self.data[self.pos:eol]
+        self.pos += len(res)
         return self.space.wrap(res)
     read.unwrap_spec = ['self', int]
 
     def find(self, tofind, start=0):
-        self._check_valid()
-        
-        # since we don't have to update positions we
-        # gain advantage of python strings :-)
-        w_str_data = self._to_str()
-        str_data = self.space.str_w(w_str_data)
-        assert start >= 0
-        return self.space.wrap(str_data.find(tofind, start))
+        self.check_valid()
+
+        # XXX naive! how can we reuse the rstr algorithm?
+        if start < 0:
+            start += self.size
+            if start < 0:
+                start = 0
+        data = self.data
+        for p in xrange(start, self.size):
+            for q in range(len(tofind)):
+                if data[p+q] != tofind[q]:
+                    break     # position 'p' is not a match
+            else:
+                # full match
+                return self.space.wrap(p)
+        # failure
+        return self.space.wrap(-1)
     find.unwrap_spec = ['self', str, int]
 
     def seek(self, pos, whence=0):
-        self._check_valid()
+        self.check_valid()
         
         dist = pos
         how = whence
         
         if how == 0: # relative to start
-            if dist < 0:
-                raise OperationError(self.space.w_ValueError,
-                    self.space.wrap("seek out of range"))
             where = dist
         elif how == 1: # relative to current position
-            if self._pos + dist < 0:
-                raise OperationError(self.space.w_ValueError,
-                    self.space.wrap("seek out of range"))
-            where = self._pos + dist
+            where = self.pos + dist
         elif how == 2: # relative to the end
-            if self._size + dist < 0:
-                raise OperationError(self.space.w_ValueError,
-                    self.space.wrap("seek out of range"))
-            where = self._size + dist
+            where = self.size + dist
         else:
             raise OperationError(self.space.w_ValueError,
                     self.space.wrap("unknown seek type"))
-        
-        assert where >= 0 
-        if where > self._size:
+
+        if not (0 <= where <= self.size):
             raise OperationError(self.space.w_ValueError,
-                    self.space.wrap("seek out of range"))
+                self.space.wrap("seek out of range"))
         
-        self._pos = where
+        self.pos = where
     seek.unwrap_spec = ['self', int, int]
     
     def tell(self):
-        self._check_valid()
+        self.check_valid()
         
-        return self.space.wrap(self._pos)
+        return self.space.wrap(self.pos)
     tell.unwrap_spec = ['self']
     
     def size(self):
-        self._check_valid()
+        self.check_valid()
         
+        size = self.size
         if _MS_WINDOWS:
-            if self._file_handle.value != INVALID_c_int_VALUE:
-                low, high = _get_file_size(self.space, self._file_handle)
-                if not high and low < sys.maxint:
+            if self.file_handle.value != INVALID_c_int_VALUE:
+                low, high = _get_file_size(self.space, self.file_handle)
+                if not high and low <= sys.maxint:
                     return self.space.wrap(low)
                 size = c_int((high << 32) + low).value
-                return self.space.wrap(size)
-            else:
-                return self.space.wrap(self._size)
         elif _POSIX:
-            st = os.fstat(self._fd)
-            SIZE_BIT = 6
-            return self.space.wrap(st[SIZE_BIT])
+            st = os.fstat(self.fd)
+            size = st[stat.ST_SIZE]
+        return self.space.wrap(size)
     size.unwrap_spec = ['self']
     
     def write(self, data):
-        self._check_valid()        
-        self._check_writeable()
+        self.check_valid()        
+        self.check_writeable()
         
         data_len = len(data)
-        if self._pos + data_len > self._size:
+        if self.pos + data_len > self.size:
             raise OperationError(self.space.w_ValueError,
                 self.space.wrap("data out of range"))
-        
-        p = c_char_p(data)
-        libc.memcpy(self._data, p, data_len)
-        self._pos += data_len
+
+        internaldata = self.data
+        start = self.pos
+        for i in range(data_len):
+            internaldata[start+i] = data[i]
+        self.pos = start + data_len
     write.unwrap_spec = ['self', str]
     
     def write_byte(self, byte):
-        self._check_valid()
+        self.check_valid()
         
         if len(byte) > 1:
             raise OperationError(self.space.w_TypeError,
                 self.space.wrap("write_byte() argument must be char"))
         
-        self._check_writeable()
-        
-        str_data = self.space.str_w(self._to_str())
-        str_data_lst = [i for i in str_data] 
-        str_data_lst[self._pos] = byte
-        str_data = "".join(str_data_lst)
-        
-        p = c_char_p(str_data)
-        libc.memcpy(self._data, p, len(str_data))
-        self._pos += 1
+        self.check_writeable()
+        self.data[self.pos] = byte
+        self.pos += 1
     write_byte.unwrap_spec = ['self', str]
     
     def flush(self, offset=0, size=0):
-        self._check_valid()
-        
+        self.check_valid()
+
         if size == 0:
-            size = self._size
-        
-        assert offset >= 0
-        assert size >= 0
-        if offset + size > self._size:
+            size = self.size
+        if offset < 0 or size < 0 or offset + size > self.size:
             raise OperationError(self.space.w_ValueError,
                 self.space.wrap("flush values out of range"))
         else:
-            data = c_char_p("".join([self._data[i] for i in range(offset, size)]))
-            
+            # XXX 64-bit support for pointer arithmetic!
+            start = cast(self.data, c_void_p)
+            if offset > 0:
+                start = c_void_p(start.value + offset)
+            start = cast(start, PTR)
             if _MS_WINDOWS:
-                res = FlushViewOfFile(data, size)
+                res = FlushViewOfFile(start, size)
                 return self.space.wrap(res)
             elif _POSIX:
-                if _LINUX:
-                    # alignment of the address
-                    value = pythonapi.PyLong_FromVoidPtr(data)
-                    aligned_value = value & ~(PAGESIZE - 1)
-                    # the size should be increased too. otherwise the final
-                    # part is not "msynced"
-                    new_size = size + value & (PAGESIZE - 1)
-                    res = linux_msync(c_void_p(aligned_value), new_size, MS_SYNC)
-                else:
-                    res = libc.msync(data, size, MS_SYNC)
+##                XXX why is this code here?  There is no equivalent in CPython
+##                if _LINUX:
+##                    # alignment of the address
+##                    value = cast(self.data, c_void_p).value
+##                    aligned_value = value & ~(PAGESIZE - 1)
+##                    # the size should be increased too. otherwise the final
+##                    # part is not "msynced"
+##                    new_size = size + value & (PAGESIZE - 1)
+                res = libc.msync(start, size, MS_SYNC)
                 if res == -1:
                     raise OperationError(self.space.w_EnvironmentError,
                         self.space.wrap(_get_error_msg()))
@@ -462,32 +440,33 @@
     flush.unwrap_spec = ['self', int, int]
     
     def move(self, dest, src, count):
-        self._check_valid()
+        self.check_valid()
         
-        self._check_writeable()
+        self.check_writeable()
         
         # check boundings
-        assert src >= 0; assert dest >= 0; assert count >= 0; assert self._size >= 0
-        if (src + count > self._size) or (dest + count > self._size):
+        assert src >= 0; assert dest >= 0; assert count >= 0; assert self.size >= 0
+        if (src + count > self.size) or (dest + count > self.size):
             raise OperationError(self.space.w_ValueError,
                 self.space.wrap("source or destination out of range"))
-        
-        data_dest = c_char_p("".join([self._data[i] for i in range(dest, self._size)]))
-        data_src = c_char_p("".join([self._data[i] for i in range(src, src+count)]))
-        libc.memmove(data_dest, data_src, size_t(count))
+
+        XXXXXXX
+        data_dest = c_char_p("".join([self.data[i] for i in range(dest, self.size)]))
+        data_src = c_char_p("".join([self.data[i] for i in range(src, src+count)]))
+        libc.memmove XXX (data_dest, data_src, size_t(count))
         
         assert dest >= 0
-        str_left = self.space.str_w(self._to_str())[0:dest]
+        str_left = self.space.str_w(self.to_str())[0:dest]
         final_str = "%s%s" % (str_left, data_dest.value)
         
         p = c_char_p(final_str)
-        libc.memcpy(self._data, p, len(final_str))
+        libc.memcpy(self.data, p, len(final_str))
     move.unwrap_spec = ['self', int, int, int]
     
     def resize(self, newsize):
-        self._check_valid()
+        self.check_valid()
         
-        self._check_resizeable()
+        self.check_resizeable()
         
         if _POSIX:
             if not has_mremap:
@@ -496,19 +475,19 @@
                     self.space.wrap(msg))
             
             # resize the underlying file first
-            res = libc.ftruncate(self._fd, newsize)
+            res = libc.ftruncate(self.fd, newsize)
             if res == -1:
                 raise OperationError(self.space.w_EnvironmentError,
                     self.space.wrap(_get_error_msg()))
                 
             # now resize the mmap
             MREMAP_MAYMOVE = 1
-            libc.mremap(self._data, self._size, newsize, MREMAP_MAYMOVE)
-            self._size = newsize
+            libc.mremap(self.data, self.size, newsize, MREMAP_MAYMOVE)
+            self.size = newsize
         elif _MS_WINDOWS:
             # disconnect the mapping
-            self._unmapview()
-            CloseHandle(self._map_handle)
+            self.unmapview()
+            CloseHandle(self.map_handle)
 
             # move to the desired EOF position
             if _64BIT:
@@ -519,22 +498,21 @@
                 newsize_low = c_int(newsize)
 
             FILE_BEGIN = c_int(0)
-            SetFilePointer(self._file_handle, newsize_low, byref(newsize_high),
+            SetFilePointer(self.file_handle, newsize_low, byref(newsize_high),
                            FILE_BEGIN)
             # resize the file
-            SetEndOfFile(self._file_handle)
+            SetEndOfFile(self.file_handle)
             # create another mapping object and remap the file view
-            res = CreateFileMapping(self._file_handle, c_void_p(0), PAGE_READWRITE,
-                                 newsize_high, newsize_low, self._tagname)
-            self._map_handle = c_int(res)
+            res = CreateFileMapping(self.file_handle, NULL, PAGE_READWRITE,
+                                 newsize_high, newsize_low, self.tagname)
+            self.map_handle = c_int(res)
 
             dwErrCode = DWORD(0)
-            if self._map_handle:
-                data = MapViewOfFile(self._map_handle, FILE_MAP_WRITE,
+            if self.map_handle:
+                data = MapViewOfFile(self.map_handle, FILE_MAP_WRITE,
                     0, 0, 0)
                 if data:
-                    self._data = cast(data, POINTER(c_char))
-                    self._size = newsize
+                    self.setdata(data, newsize)
                     return
                 else:
                     dwErrCode = GetLastError()
@@ -546,26 +524,26 @@
     resize.unwrap_spec = ['self', int]
     
     def __len__(self):
-        self._check_valid()
+        self.check_valid()
         
-        return self.space.wrap(self._size)
+        return self.space.wrap(self.size)
     __len__.unwrap_spec = ['self']
     
     def __getitem__(self, index):
-        self._check_valid()
+        self.check_valid()
 
         # XXX this does not support slice() instances
 
         try:
-            return self.space.wrap(self.space.str_w(self._to_str())[index])
+            return self.space.wrap(self.space.str_w(self.to_str())[index])
         except IndexError:
             raise OperationError(self.space.w_IndexError,
                 self.space.wrap("mmap index out of range"))
     __getitem__.unwrap_spec = ['self', int]
     
     def __setitem__(self, index, value):
-        self._check_valid()
-        self._check_writeable()
+        self.check_valid()
+        self.check_writeable()
         
         # XXX this does not support slice() instances
         
@@ -575,20 +553,21 @@
 
         str_data = ""
         try:
-            str_data = self.space.str_w(self._to_str())
+            str_data = self.space.str_w(self.to_str())
             str_data_lst = [i for i in str_data] 
             str_data_lst[index] = value
             str_data = "".join(str_data_lst)
         except IndexError:
             raise OperationError(self.space.w_IndexError,
                 self.space.wrap("mmap index out of range"))
-        
+
+        XXXXXXXXXX
         p = c_char_p(str_data)
-        libc.memcpy(self._data, p, len(str_data))
+        libc.memcpy(self.data, p, len(str_data))
     __setitem__.unwrap_spec = ['self', int, str]
     
     def __delitem__(self, index):
-        self._check_valid()
+        self.check_valid()
         
         # XXX this does not support slice() instances (does it matter?)
         
@@ -597,61 +576,48 @@
     __delitem__.unwrap_spec = ['self', int]
     
     def __add__(self, w_other):
-        self._check_valid()
+        self.check_valid()
         
         raise OperationError(self.space.w_SystemError,
             self.space.wrap("mmaps don't support concatenation"))
     __add__.unwrap_spec = ['self', W_Root]
     
     def __mul__(self, w_other):
-        self._check_valid()
+        self.check_valid()
         
         raise OperationError(self.space.w_SystemError,
             self.space.wrap("mmaps don't support repeat operation"))
     __mul__.unwrap_spec = ['self', W_Root]
 
 
-_mmap.typedef = TypeDef("_mmap",
-    _to_str = interp2app(_mmap._to_str, unwrap_spec=_mmap._to_str.unwrap_spec),
-    _check_valid = interp2app(_mmap._check_valid,
-        unwrap_spec=_mmap._check_valid.unwrap_spec),
-    _check_writeable = interp2app(_mmap._check_writeable,
-        unwrap_spec=_mmap._check_writeable.unwrap_spec),
-    _check_resizeable = interp2app(_mmap._check_resizeable,
-        unwrap_spec=_mmap._check_resizeable.unwrap_spec),
-    close = interp2app(_mmap.close, unwrap_spec=_mmap.close.unwrap_spec),
-    read_byte = interp2app(_mmap.read_byte,
-        unwrap_spec=_mmap.read_byte.unwrap_spec),
-    readline = interp2app(_mmap.readline,
-        unwrap_spec=_mmap.readline.unwrap_spec),
-    read = interp2app(_mmap.read, unwrap_spec=_mmap.read.unwrap_spec),
-    find = interp2app(_mmap.find, unwrap_spec=_mmap.find.unwrap_spec),
-    seek = interp2app(_mmap.seek, unwrap_spec=_mmap.seek.unwrap_spec),
-    tell = interp2app(_mmap.tell, unwrap_spec=_mmap.tell.unwrap_spec),
-    size = interp2app(_mmap.size, unwrap_spec=_mmap.size.unwrap_spec),
-    write = interp2app(_mmap.write, unwrap_spec=_mmap.write.unwrap_spec),
-    write_byte = interp2app(_mmap.write_byte,
-        unwrap_spec=_mmap.write_byte.unwrap_spec),
-    flush = interp2app(_mmap.flush, unwrap_spec=_mmap.flush.unwrap_spec),
-    move = interp2app(_mmap.move, unwrap_spec=_mmap.move.unwrap_spec),
-    resize = interp2app(_mmap.resize, unwrap_spec=_mmap.resize.unwrap_spec),
-
-    __len__ = interp2app(_mmap.__len__, unwrap_spec=_mmap.__len__.unwrap_spec),
-    __getitem__ = interp2app(_mmap.__getitem__,
-        unwrap_spec=_mmap.__getitem__.unwrap_spec),
-    __setitem__ = interp2app(_mmap.__setitem__,
-        unwrap_spec=_mmap.__setitem__.unwrap_spec),
-    __delitem__ = interp2app(_mmap.__delitem__,
-        unwrap_spec=_mmap.__delitem__.unwrap_spec),
-    __add__ = interp2app(_mmap.__add__, unwrap_spec=_mmap.__add__.unwrap_spec),
-    __mul__ = interp2app(_mmap.__mul__, unwrap_spec=_mmap.__mul__.unwrap_spec),   
+W_MMap.typedef = TypeDef("mmap",
+    close = interp2app(W_MMap.close),
+    read_byte = interp2app(W_MMap.read_byte),
+    readline = interp2app(W_MMap.readline),
+    read = interp2app(W_MMap.read),
+    find = interp2app(W_MMap.find),
+    seek = interp2app(W_MMap.seek),
+    tell = interp2app(W_MMap.tell),
+    size = interp2app(W_MMap.size),
+    write = interp2app(W_MMap.write),
+    write_byte = interp2app(W_MMap.write_byte),
+    flush = interp2app(W_MMap.flush),
+    move = interp2app(W_MMap.move),
+    resize = interp2app(W_MMap.resize),
+
+    __len__ = interp2app(W_MMap.__len__),
+    __getitem__ = interp2app(W_MMap.__getitem__),
+    __setitem__ = interp2app(W_MMap.__setitem__),
+    __delitem__ = interp2app(W_MMap.__delitem__),
+    __add__ = interp2app(W_MMap.__add__),
+    __mul__ = interp2app(W_MMap.__mul__),   
 )
 
 def _check_map_size(space, size):
     if size < 0:
         raise OperationError(space.w_TypeError,
             space.wrap("memory mapped size must be positive"))
-    if size == sys.maxint:
+    if size_t(size).value != size:
         raise OperationError(space.w_OverflowError,
             space.wrap("memory mapped size is too large (limited by C int)"))
 
@@ -690,40 +656,35 @@
         try:
             st = os.fstat(fd)
         except OSError:
-            raise OperationError(space.w_EnvironmentError,
-                space.wrap("bad file descriptor"))
-        MODE_BIT, SIZE_BIT = 0, 6 # cannot use st.st_mode and st.st_size
-        mode = st[MODE_BIT]
-        size = st[SIZE_BIT]
-        if stat.S_ISREG(mode):
-            if map_size == 0:
-                map_size = size
-            elif map_size > size:
-                raise OperationError(space.w_ValueError,
-                    space.wrap("mmap length is greater than file size"))
+            pass     # ignore errors and trust map_size
+        else:
+            mode = st[stat.ST_MODE]
+            size = st[stat.ST_SIZE]
+            if stat.S_ISREG(mode):
+                if map_size == 0:
+                    map_size = size
+                elif map_size > size:
+                    raise OperationError(space.w_ValueError,
+                        space.wrap("mmap length is greater than file size"))
 
-        m = _mmap(space)
-        m._size = map_size
+        m = W_MMap(space, access)
         if fd == -1:
             # Assume the caller wants to map anonymous memory.
             # This is the same behaviour as Windows.  mmap.mmap(-1, size)
             # on both Windows and Unix map anonymous memory.
-            m._fd = -1
+            m.fd = -1
 
             flags |= MAP_ANONYMOUS
 
         else:
-            m._fd = os.dup(fd)
-            if m._fd == -1:
-                raise OperationError(space.w_EnvironmentError,
-                    space.wrap(_get_error_msg()))
+            m.fd = os.dup(fd)
 
-        res = libc.mmap(c_void_p(0), map_size, prot, flags, fd, 0)
-        if not res:
+        res = libc.mmap(NULL, map_size, prot, flags, fd, 0)
+        if cast(res, c_void_p).value == -1:
             raise OperationError(space.w_EnvironmentError,
                 space.wrap(_get_error_msg()))
-        m._data = cast(res, POINTER(c_char))
-        m._access = access
+        
+        m.setdata(res, map_size)
 
         return space.wrap(m)
     mmap.unwrap_spec = [ObjSpace, int, int, int, int, int]
@@ -733,19 +694,19 @@
         _check_map_size(space, length)
         map_size = length
         
-        flProtect = c_int()
-        dwDesiredAccess = WORD()
+        flProtect = 0
+        dwDesiredAccess = 0
         fh = 0
         
         if access == ACCESS_READ:
-            flProtect = c_int(PAGE_READONLY)
-            dwDesiredAccess = DWORD(FILE_MAP_READ)
+            flProtect = PAGE_READONLY
+            dwDesiredAccess = FILE_MAP_READ
         elif access == _ACCESS_DEFAULT or access == ACCESS_WRITE:
-            flProtect = c_int(PAGE_READWRITE)
-            dwDesiredAccess = DWORD(FILE_MAP_WRITE)
+            flProtect = PAGE_READWRITE
+            dwDesiredAccess = FILE_MAP_WRITE
         elif access == ACCESS_COPY:
-            flProtect = c_int(PAGE_WRITECOPY)
-            dwDesiredAccess = DWORD(FILE_MAP_COPY)
+            flProtect = PAGE_WRITECOPY
+            dwDesiredAccess = FILE_MAP_COPY
         else:
             raise OperationError(space.w_ValueError,
                                  space.wrap("mmap invalid access parameter."))
@@ -761,20 +722,20 @@
             # SEEK_SET = 0
             # libc._lseek(fileno, 0, SEEK_SET)
         
-        m = _mmap(space)
-        m._file_handle = c_int(INVALID_c_int_VALUE)
-        m._map_handle = c_int(INVALID_c_int_VALUE)
+        m = W_MMap(space, access)
+        # XXX the following two attributes should be plain RPython ints
+        m.file_handle = c_int(INVALID_c_int_VALUE)
+        m.map_handle = c_int(INVALID_c_int_VALUE)
         
         if fh:
-            res = BOOL()
             # it is necessary to duplicate the handle, so the
             # Python code can close it on us        
             res = DuplicateHandle(GetCurrentProcess(), # source process handle
                                   fh, # handle to be duplicated
                                   GetCurrentProcess(), # target process handle
-                                  byref(m._file_handle), # result
+                                  byref(m.file_handle), # result
                                   0, # access - ignored due to options value
-                                  wintypes.BOOL(False), # inherited by child procs?
+                                  False, # inherited by child procs?
                                   DUPLICATE_SAME_ACCESS) # options
             if not res:
                 raise OperationError(space.w_EnvironmentError,
@@ -783,38 +744,33 @@
             if not map_size:
                 low, high = _get_file_size(space, c_int(fh))
                 if _64BIT:
-                    m._size = c_int((low << 32) + 1).value
+                    map_size = c_int((low << 32) + 1).value
                 else:
                     if high:
                         # file is too large to map completely
-                        m._size = -1
+                        map_size = -1
                     else:
-                        m._size = low
-            else:
-                m._size = map_size
-        else:
-            m._size = map_size
+                        map_size = low
 
         if tagname:
-            m._tagname = tagname
-        m._access = access
+            m.tagname = tagname
         
         # DWORD is a 4-byte int. If int > 4-byte it must be divided
         if _64BIT:
-            size_hi = DWORD(m._size >> 32)
-            size_lo = DWORD(m._size & 0xFFFFFFFF)
+            size_hi = DWORD(map_size >> 32)
+            size_lo = DWORD(map_size & 0xFFFFFFFF)
         else:
             size_hi = c_int(0)
-            size_lo = c_int(m._size)
+            size_lo = c_int(map_size)
 
-        m._map_handle = c_int(CreateFileMapping(m._file_handle, c_void_p(0), flProtect,
-                                                 size_hi, size_lo, m._tagname))
+        m.map_handle = c_int(CreateFileMapping(m.file_handle, NULL, flProtect,
+                                               size_hi, size_lo, m.tagname))
 
-        if m._map_handle:
-            res = MapViewOfFile(m._map_handle, dwDesiredAccess,
+        if m.map_handle:
+            res = MapViewOfFile(m.map_handle, dwDesiredAccess,
                                 0, 0, 0)
             if res:
-                m._data = cast(res, POINTER(c_char))
+                m.setdata(res, map_size)
                 return space.wrap(m)
             else:
                 dwErr = GetLastError()



More information about the Pypy-commit mailing list