[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