Hacked for Win32 by Mark Hammond.
Reformatted for 8-space tabs and fitted into 80-char lines by GvR. Mark writes: * the Win32 version now accepts the same args as the Unix version. The win32 specific "tag" param is now optional. The end result is that the exact same test suite runs on Windows (definately a worthy goal!). * I changed the error object. All occurences of the error, except for 1, corresponds to an underlying OS error. This one was changed to a ValueError (a better error for that condition), and the module error object is now simply EnvironmentError. All win32 error routines now call the new Windows specific error handler.
This commit is contained in:
parent
767e775a98
commit
09fdf07315
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: C++; tab-width: 4 -*-
|
||||
/*
|
||||
/ Author: Sam Rushing <rushing@nightmare.com>
|
||||
/ Hacked for Unix by A.M. Kuchling <amk1@bigfoot.com>
|
||||
/ $Id$
|
||||
|
@ -16,6 +16,8 @@
|
|||
/ ftp://squirl.nightmare.com/pub/python/python-ext.
|
||||
*/
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
#ifndef MS_WIN32
|
||||
#define UNIX
|
||||
#endif
|
||||
|
@ -29,8 +31,6 @@
|
|||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
|
@ -95,7 +95,7 @@ mmap_close_method (mmap_object * self, PyObject * args)
|
|||
#define CHECK_VALID(err) \
|
||||
do { \
|
||||
if (!self->map_handle) { \
|
||||
PyErr_SetString (PyExc_ValueError, "mmap closed or invalid");\
|
||||
PyErr_SetString (PyExc_ValueError, "mmap closed or invalid"); \
|
||||
return err; \
|
||||
} \
|
||||
} while (0)
|
||||
|
@ -191,7 +191,9 @@ mmap_find_method (mmap_object *self,
|
|||
s++, n++;
|
||||
}
|
||||
if (!*n) {
|
||||
return Py_BuildValue ("l", (long) (p - (self->data + start)));
|
||||
return Py_BuildValue (
|
||||
"l",
|
||||
(long) (p - (self->data + start)));
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
@ -211,7 +213,7 @@ mmap_write_method (mmap_object * self,
|
|||
return(NULL);
|
||||
|
||||
if ((self->pos + length) > self->size) {
|
||||
PyErr_SetString (mmap_module_error, "data out of range");
|
||||
PyErr_SetString (PyExc_ValueError, "data out of range");
|
||||
return NULL;
|
||||
}
|
||||
memcpy (self->data+self->pos, data, length);
|
||||
|
@ -244,7 +246,9 @@ mmap_size_method (mmap_object * self,
|
|||
|
||||
#ifdef MS_WIN32
|
||||
if (self->file_handle != (HFILE) 0xFFFFFFFF) {
|
||||
return (Py_BuildValue ("l", GetFileSize ((HANDLE)self->file_handle, NULL)));
|
||||
return (Py_BuildValue (
|
||||
"l",
|
||||
GetFileSize ((HANDLE)self->file_handle, NULL)));
|
||||
} else {
|
||||
return (Py_BuildValue ("l", self->size) );
|
||||
}
|
||||
|
@ -274,22 +278,24 @@ mmap_resize_method (mmap_object * self,
|
|||
return NULL;
|
||||
#ifdef MS_WIN32
|
||||
} else {
|
||||
DWORD dwErrCode = 0;
|
||||
/* First, unmap the file view */
|
||||
UnmapViewOfFile (self->data);
|
||||
/* Close the mapping object */
|
||||
CloseHandle ((HANDLE)self->map_handle);
|
||||
/* Move to the desired EOF position */
|
||||
SetFilePointer ((HANDLE)self->file_handle, new_size, NULL, FILE_BEGIN);
|
||||
SetFilePointer ((HANDLE)self->file_handle,
|
||||
new_size, NULL, FILE_BEGIN);
|
||||
/* Change the size of the file */
|
||||
SetEndOfFile ((HANDLE)self->file_handle);
|
||||
/* Create another mapping object and remap the file view */
|
||||
self->map_handle = CreateFileMapping ((HANDLE) self->file_handle,
|
||||
self->map_handle = CreateFileMapping (
|
||||
(HANDLE) self->file_handle,
|
||||
NULL,
|
||||
PAGE_READWRITE,
|
||||
0,
|
||||
new_size,
|
||||
self->tagname);
|
||||
char complaint[256];
|
||||
if (self->map_handle != NULL) {
|
||||
self->data = (char *) MapViewOfFile (self->map_handle,
|
||||
FILE_MAP_WRITE,
|
||||
|
@ -301,20 +307,20 @@ mmap_resize_method (mmap_object * self,
|
|||
Py_INCREF (Py_None);
|
||||
return Py_None;
|
||||
} else {
|
||||
sprintf (complaint, "MapViewOfFile failed: %ld", GetLastError());
|
||||
dwErrCode = GetLastError();
|
||||
}
|
||||
} else {
|
||||
sprintf (complaint, "CreateFileMapping failed: %ld", GetLastError());
|
||||
dwErrCode = GetLastError();
|
||||
}
|
||||
PyErr_SetString (mmap_module_error, complaint);
|
||||
PyErr_SetFromWindowsErr(dwErrCode);
|
||||
return (NULL);
|
||||
}
|
||||
#endif /* MS_WIN32 */
|
||||
|
||||
#ifdef UNIX
|
||||
#ifndef MREMAP_MAYMOVE
|
||||
} else {
|
||||
PyErr_SetString(PyExc_SystemError, "mmap: resizing not available--no mremap()");
|
||||
PyErr_SetString(PyExc_SystemError,
|
||||
"mmap: resizing not available--no mremap()");
|
||||
return NULL;
|
||||
#else
|
||||
} else {
|
||||
|
@ -351,16 +357,19 @@ mmap_flush_method (mmap_object * self, PyObject * args)
|
|||
if (!PyArg_ParseTuple (args, "|ll", &offset, &size)) {
|
||||
return NULL;
|
||||
} else if ((offset + size) > self->size) {
|
||||
PyErr_SetString (PyExc_ValueError, "flush values out of range");
|
||||
PyErr_SetString (PyExc_ValueError,
|
||||
"flush values out of range");
|
||||
return NULL;
|
||||
} else {
|
||||
#ifdef MS_WIN32
|
||||
return (Py_BuildValue ("l", FlushViewOfFile (self->data+offset, size)));
|
||||
return (Py_BuildValue (
|
||||
"l", FlushViewOfFile (self->data+offset, size)));
|
||||
#endif /* MS_WIN32 */
|
||||
#ifdef UNIX
|
||||
/* XXX semantics of return value? */
|
||||
/* XXX flags for msync? */
|
||||
if (-1 == msync(self->data + offset, size, MS_SYNC | MS_INVALIDATE))
|
||||
if (-1 == msync(self->data + offset, size,
|
||||
MS_SYNC | MS_INVALIDATE))
|
||||
{
|
||||
PyErr_SetFromErrno(mmap_module_error);
|
||||
return NULL;
|
||||
|
@ -392,7 +401,8 @@ mmap_seek_method (mmap_object * self, PyObject * args)
|
|||
where = self->size - dist;
|
||||
break;
|
||||
default:
|
||||
PyErr_SetString (PyExc_ValueError, "unknown seek type");
|
||||
PyErr_SetString (PyExc_ValueError,
|
||||
"unknown seek type");
|
||||
return NULL;
|
||||
}
|
||||
if ((where >= 0) && (where < (self->size))) {
|
||||
|
@ -400,7 +410,8 @@ mmap_seek_method (mmap_object * self, PyObject * args)
|
|||
Py_INCREF (Py_None);
|
||||
return (Py_None);
|
||||
} else {
|
||||
PyErr_SetString (PyExc_ValueError, "seek out of range");
|
||||
PyErr_SetString (PyExc_ValueError,
|
||||
"seek out of range");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -443,7 +454,7 @@ static struct PyMethodDef mmap_object_methods[] = {
|
|||
{"size", (PyCFunction) mmap_size_method, 1},
|
||||
{"tell", (PyCFunction) mmap_tell_method, 1},
|
||||
{"write", (PyCFunction) mmap_write_method, 1},
|
||||
{"write_byte",(PyCFunction) mmap_write_byte_method, 1},
|
||||
{"write_byte", (PyCFunction) mmap_write_byte_method, 1},
|
||||
{NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
|
@ -457,7 +468,8 @@ const void **ptr;
|
|||
{
|
||||
CHECK_VALID(-1);
|
||||
if ( index != 0 ) {
|
||||
PyErr_SetString(PyExc_SystemError, "Accessing non-existent mmap segment");
|
||||
PyErr_SetString(PyExc_SystemError,
|
||||
"Accessing non-existent mmap segment");
|
||||
return -1;
|
||||
}
|
||||
*ptr = self->data;
|
||||
|
@ -467,12 +479,13 @@ const void **ptr;
|
|||
static int
|
||||
mmap_buffer_getwritebuf(self, index, ptr)
|
||||
mmap_object *self;
|
||||
int index;
|
||||
const void **ptr;
|
||||
int index;
|
||||
const void **ptr;
|
||||
{
|
||||
CHECK_VALID(-1);
|
||||
if ( index != 0 ) {
|
||||
PyErr_SetString(PyExc_SystemError, "Accessing non-existent mmap segment");
|
||||
PyErr_SetString(PyExc_SystemError,
|
||||
"Accessing non-existent mmap segment");
|
||||
return -1;
|
||||
}
|
||||
*ptr = self->data;
|
||||
|
@ -482,7 +495,7 @@ const void **ptr;
|
|||
static int
|
||||
mmap_buffer_getsegcount(self, lenp)
|
||||
mmap_object *self;
|
||||
int *lenp;
|
||||
int *lenp;
|
||||
{
|
||||
CHECK_VALID(-1);
|
||||
if (lenp)
|
||||
|
@ -493,8 +506,8 @@ int *lenp;
|
|||
static int
|
||||
mmap_buffer_getcharbuffer(self, index, ptr)
|
||||
mmap_object *self;
|
||||
int index;
|
||||
const void **ptr;
|
||||
int index;
|
||||
const void **ptr;
|
||||
{
|
||||
if ( index != 0 ) {
|
||||
PyErr_SetString(PyExc_SystemError,
|
||||
|
@ -522,7 +535,7 @@ mmap_length(self)
|
|||
static PyObject *
|
||||
mmap_item(self, i)
|
||||
mmap_object *self;
|
||||
int i;
|
||||
int i;
|
||||
{
|
||||
CHECK_VALID(NULL);
|
||||
if (i < 0 || i >= self->size) {
|
||||
|
@ -535,7 +548,7 @@ int i;
|
|||
static PyObject *
|
||||
mmap_slice(self, ilow, ihigh)
|
||||
mmap_object *self;
|
||||
int ilow, ihigh;
|
||||
int ilow, ihigh;
|
||||
{
|
||||
CHECK_VALID(NULL);
|
||||
if (ilow < 0)
|
||||
|
@ -555,28 +568,30 @@ int ilow, ihigh;
|
|||
static PyObject *
|
||||
mmap_concat(self, bb)
|
||||
mmap_object *self;
|
||||
PyObject *bb;
|
||||
PyObject *bb;
|
||||
{
|
||||
CHECK_VALID(NULL);
|
||||
PyErr_SetString(PyExc_SystemError, "mmaps don't support concatenation");
|
||||
PyErr_SetString(PyExc_SystemError,
|
||||
"mmaps don't support concatenation");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
mmap_repeat(self, n)
|
||||
mmap_object *self;
|
||||
int n;
|
||||
int n;
|
||||
{
|
||||
CHECK_VALID(NULL);
|
||||
PyErr_SetString(PyExc_SystemError, "mmaps don't support repeat operation");
|
||||
PyErr_SetString(PyExc_SystemError,
|
||||
"mmaps don't support repeat operation");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
mmap_ass_slice(self, ilow, ihigh, v)
|
||||
mmap_object *self;
|
||||
int ilow, ihigh;
|
||||
PyObject *v;
|
||||
int ilow, ihigh;
|
||||
PyObject *v;
|
||||
{
|
||||
unsigned char *buf;
|
||||
|
||||
|
@ -610,8 +625,8 @@ PyObject *v;
|
|||
static int
|
||||
mmap_ass_item(self, i, v)
|
||||
mmap_object *self;
|
||||
int i;
|
||||
PyObject *v;
|
||||
int i;
|
||||
PyObject *v;
|
||||
{
|
||||
unsigned char *buf;
|
||||
|
||||
|
@ -648,7 +663,7 @@ static PyBufferProcs mmap_as_buffer = {
|
|||
};
|
||||
|
||||
static PyTypeObject mmap_object_type = {
|
||||
PyObject_HEAD_INIT(&PyType_Type)
|
||||
PyObject_HEAD_INIT(0) /* patched in module init */
|
||||
0, /* ob_size */
|
||||
"mmap", /* tp_name */
|
||||
sizeof(mmap_object), /* tp_size */
|
||||
|
@ -656,7 +671,7 @@ static PyTypeObject mmap_object_type = {
|
|||
/* methods */
|
||||
(destructor) mmap_object_dealloc, /* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
(getattrfunc) mmap_object_getattr,/* tp_getattr */
|
||||
(getattrfunc) mmap_object_getattr, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
0, /* tp_compare */
|
||||
0, /* tp_repr */
|
||||
|
@ -715,29 +730,37 @@ new_mmap_object (PyObject * self, PyObject * args)
|
|||
unsigned long map_size;
|
||||
char * filename;
|
||||
int namelen;
|
||||
char * tagname;
|
||||
char * tagname = "";
|
||||
|
||||
char complaint[256];
|
||||
DWORD dwErr = 0;
|
||||
int fileno;
|
||||
HFILE fh = 0;
|
||||
OFSTRUCT file_info;
|
||||
|
||||
if (!PyArg_Parse (args,
|
||||
"(s#zl)",
|
||||
&filename,
|
||||
&namelen,
|
||||
&tagname,
|
||||
&map_size)
|
||||
/* Patch the object type */
|
||||
mmap_object_type.ob_type = &PyType_Type;
|
||||
|
||||
if (!PyArg_ParseTuple(args,
|
||||
"il|z",
|
||||
&fileno,
|
||||
&map_size,
|
||||
&tagname)
|
||||
)
|
||||
return NULL;
|
||||
|
||||
/* if an actual filename has been specified */
|
||||
if (namelen != 0) {
|
||||
fh = OpenFile (filename, &file_info, OF_READWRITE);
|
||||
if (fh == HFILE_ERROR) {
|
||||
sprintf (complaint, "OpenFile failed: %ld", GetLastError());
|
||||
PyErr_SetString(mmap_module_error, complaint);
|
||||
if (fileno != 0) {
|
||||
fh = _get_osfhandle(fileno);
|
||||
if (fh==-1) {
|
||||
PyErr_SetFromErrno(mmap_module_error);
|
||||
return NULL;
|
||||
}
|
||||
//
|
||||
// fh = OpenFile (filename, &file_info, OF_READWRITE);
|
||||
// if (fh == HFILE_ERROR) {
|
||||
// PyErr_SetFromWindowsErr(GetLastError());
|
||||
// return NULL;
|
||||
// }
|
||||
}
|
||||
|
||||
m_obj = PyObject_NEW (mmap_object, &mmap_object_type);
|
||||
|
@ -773,31 +796,25 @@ new_mmap_object (PyObject * self, PyObject * args)
|
|||
if (m_obj->data != NULL) {
|
||||
return ((PyObject *) m_obj);
|
||||
} else {
|
||||
sprintf (complaint, "MapViewOfFile failed: %ld", GetLastError());
|
||||
dwErr = GetLastError();
|
||||
}
|
||||
} else {
|
||||
sprintf (complaint, "CreateFileMapping failed: %ld", GetLastError());
|
||||
dwErr = GetLastError();
|
||||
}
|
||||
PyErr_SetString (mmap_module_error, complaint);
|
||||
PyErr_SetFromWindowsErr(dwErr);
|
||||
return (NULL);
|
||||
}
|
||||
#endif /* MS_WIN32 */
|
||||
|
||||
/* List of functions exported by this module */
|
||||
static struct PyMethodDef mmap_functions[] = {
|
||||
#ifdef MS_WIN32
|
||||
{"mmap", (PyCFunction) new_mmap_object},
|
||||
#endif /* MS_WIN32 */
|
||||
|
||||
#ifdef UNIX
|
||||
{"mmap", (PyCFunction) new_mmap_object,
|
||||
METH_VARARGS|METH_KEYWORDS},
|
||||
#endif /* UNIX */
|
||||
{NULL, NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
#ifdef MS_WIN32
|
||||
extern"C" __declspec(dllexport) void
|
||||
__declspec(dllexport) void
|
||||
#endif /* MS_WIN32 */
|
||||
#ifdef UNIX
|
||||
extern void
|
||||
|
@ -808,9 +825,9 @@ initmmap(void)
|
|||
PyObject *dict, *module;
|
||||
module = Py_InitModule ("mmap", mmap_functions);
|
||||
dict = PyModule_GetDict (module);
|
||||
mmap_module_error = PyString_FromString ("mmap error");
|
||||
mmap_module_error = PyExc_EnvironmentError;
|
||||
Py_INCREF(mmap_module_error);
|
||||
PyDict_SetItemString (dict, "error", mmap_module_error);
|
||||
|
||||
#ifdef PROT_EXEC
|
||||
PyDict_SetItemString (dict, "PROT_EXEC", PyInt_FromLong(PROT_EXEC) );
|
||||
#endif
|
||||
|
@ -825,24 +842,34 @@ initmmap(void)
|
|||
PyDict_SetItemString (dict, "MAP_SHARED", PyInt_FromLong(MAP_SHARED) );
|
||||
#endif
|
||||
#ifdef MAP_PRIVATE
|
||||
PyDict_SetItemString (dict, "MAP_PRIVATE", PyInt_FromLong(MAP_PRIVATE) );
|
||||
PyDict_SetItemString (dict, "MAP_PRIVATE",
|
||||
PyInt_FromLong(MAP_PRIVATE) );
|
||||
#endif
|
||||
#ifdef MAP_DENYWRITE
|
||||
PyDict_SetItemString (dict, "MAP_DENYWRITE", PyInt_FromLong(MAP_DENYWRITE) );
|
||||
PyDict_SetItemString (dict, "MAP_DENYWRITE",
|
||||
PyInt_FromLong(MAP_DENYWRITE) );
|
||||
#endif
|
||||
#ifdef MAP_EXECUTABLE
|
||||
PyDict_SetItemString (dict, "MAP_EXECUTABLE", PyInt_FromLong(MAP_EXECUTABLE) );
|
||||
PyDict_SetItemString (dict, "MAP_EXECUTABLE",
|
||||
PyInt_FromLong(MAP_EXECUTABLE) );
|
||||
#endif
|
||||
#ifdef MAP_ANON
|
||||
PyDict_SetItemString (dict, "MAP_ANON", PyInt_FromLong(MAP_ANON) );
|
||||
PyDict_SetItemString (dict, "MAP_ANONYMOUS", PyInt_FromLong(MAP_ANON) );
|
||||
PyDict_SetItemString (dict, "MAP_ANONYMOUS",
|
||||
PyInt_FromLong(MAP_ANON) );
|
||||
#endif
|
||||
|
||||
#ifdef UNIX
|
||||
PyDict_SetItemString (dict, "PAGESIZE", PyInt_FromLong( (long)getpagesize() ) );
|
||||
PyDict_SetItemString (dict, "PAGESIZE",
|
||||
PyInt_FromLong( (long)getpagesize() ) );
|
||||
#endif
|
||||
#ifdef MS_WIN32
|
||||
{
|
||||
SYSTEM_INFO si;
|
||||
GetSystemInfo(&si);
|
||||
PyDict_SetItemString (dict, "PAGESIZE",
|
||||
PyInt_FromLong( si.dwPageSize ) );
|
||||
}
|
||||
#endif /* MS_WIN32 */
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue