/* Vmapsmodule.c - Python Arrays on mmap() Copyright (c) 2002 Mark Lamb 1/12/02 - Version 1.0 1/22/02 - 1.1; errorcheck in atswap, add 2d colget() LICENSE: This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ------------------------------------ */ #include "Python.h" #include #include #include #include #ifdef HAVE_FTIME #include #endif /* HAVE_FTIME */ #include #include #define HEADALIGN (64) /* keep elements from misalignment by padding header out */ #define DFL_MM_FLAGS (MAP_ANON|MAP_PRIVATE) #define DFL_MM_PROT (PROT_READ|PROT_WRITE) /* whether to return tuple or lists SEE ALSO the CTOPY_ARRAY macros */ //#define NEWRSEQ PyTuple_New //#define SETRSEQ PyTuple_SET_ITEM #define NEWRSEQ PyList_New #define SETRSEQ PyList_SET_ITEM /* TYPE CODES */ #define VMT_RAW (0) /* Char array of bytes (a string) */ #define VMT_SA (1) /* FixChar array of 'fixed' len strings */ #define VMT_LLA (3) /* FixLong array of python longs ('fixed' size) */ #define VMT_IA (8) /* Int array of ints */ #define VMT_DA (9) /* Float array of floats (double) */ #define VMT_LL (10) /* Long array of python longs (long long) [speed over LLA] */ #define VMT_2IA (16) /* Int2d 2D array of ints */ #define VMT_2LA (17) /* Long2d 2D array of PyLong / c long long */ #define VMT_2FA (18) /* Float2d 2D array of PyFloat / c double */ /* Behavior / interpretation flags */ #define VM_AUTOPEN (1<< 1) /* try mmap() on access if not mapped already */ #define VM_STAYOPEN (1<< 2) /* do not munmap() after access */ #define VM_ADVOPEN (1<< 3) /* do madvise() on open */ #define VM_SYNCLOSE (1<< 4) /* do sync msync() on close/unmap */ #define VM_ASYNCLOSE (1<< 5) /* do async msync() on close/unmap */ #define VM_KEEPTS (1<< 6) /* update timestamps on access */ #define VM_DOFILL (1<< 8) /* (zero) fill bytes not set in assigned data */ #define VM_LLALE (1<< 9) /* LLA type data is little endian */ #define VM_LLASG (1<<10) /* LLA type data is signed */ #define VM_HEADER (1<<16) /* has a header, use it (lockit) */ #define VM_HDRLOCK (1<<17) /* do we try to lock header */ #define VM_HDRFAIL (1<<18) /* do we fail to open if we fail to load/lock header */ #define VM_HDRTYPE (1<<19) /* use type/elbytes from header */ #define VM_HDRLEN (1<<20) /* use elcount header (be a "list") */ #define DFL_VM_FLAGS (VM_STAYOPEN|VM_ASYNCLOSE|VM_DOFILL) #define DFL_VM_TYPE (0) /* but see also the swith in Vmap_setype */ #define VM_MAGIC ( 0x566d6170 ) /* */ #define VM_MAGIC_SWAP ( 0x6170566d ) /* */ /* ============================================================================================= sys/arch dependant */ #if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE) static int my_getpagesize(void) { return sysconf(_SC_PAGESIZE); } #else #define my_getpagesize getpagesize #endif #undef __HAVE_ATSWAP #if defined (ARCH_IA32) /* ------------------------------------------ */ #define __HAVE_ATSWAP 1 inline int at_swapw( void *wrd, int i ) { asm __volatile__ (" xchgl (%1), %0 " : "=&r" (i) :"r" (wrd), "0"(i) : "memory" ); return i; } #elif defined(ARCH_SPARC) /* ------------------------------------------ */ #define __HAVE_ATSWAP 1 inline int at_swapw( void *wrd, int i ) { asm __volatile__ (" swap [%1], %0 " : "=&r" (i) :"r" (wrd), "0"(i) : "memory"); return i; } #else /* ------------------------------------------ */ #undef __HAVE_ATSWAP #warning "=========================== No atomic swap" static int at_swapw( void *byte, int newv ) { return newv; } /* ------------------------------------------ */ #endif /* __HAVE_ATSWAP */ /* ===================================================================================== Vmap */ static PyObject *ErrorObject; /* Vmap Header */ typedef struct { long magic; /* id and lock */ long hsize; /* offset at which user data starts */ long type; /* VMT_something */ long elbytes; /* Vmap->elbytes */ long elcount; /* "length" with VM_HDRLEN */ } SharedHead; /* Vmap Python object */ typedef struct { PyObject_HEAD /* general behavior */ long flags; int fill; /* mmap() */ void *mm_data; int fd; int mm_flags; int mm_prot; size_t mm_size; size_t start; /* madvise() */ int mm_advflags; /* data access */ void *data; /* ptr to data */ size_t size; /* size of data */ int headsize; /* offset of data start */ int eltype; /* what access methods to use */ int elsize; /* size in elements */ int elbytes; /* how large is an element */ /* timestamps */ double rts; /* read */ double wts; /* write */ double sts; /* sync */ double ots; /* open */ double cts; /* close */ /* locking */ long hspins; /* header lock spins */ long husec; /* header lock usleep() */ /* type func ptr */ /* seq access */ PyObject *(*f_item)( PyObject *s , int i); int (*f_aitem)(PyObject *s , int i, PyObject *v); PyObject *(*f_slice)(PyObject *s , int il, int ih ); int (*f_aslice)(PyObject *s , int il, int ih, PyObject *v); /* for sort */ int (*f_elcmp)(const void *p1, const void *p2); /* for find and contains */ int (*f_search)(PyObject *s ,PyObject *v ); /* funcs that must error check */ void *f_meth; /* other methods */ } VmapObject; staticforward PyTypeObject Vmaptype; #define is_VmapObject(v) ((v)->ob_type == &Vmaptype) /* ---------------------------------------------------------------------------- lower level */ static VmapObject * newVmapObject(PyObject *arg) { VmapObject *map; map = PyObject_NEW(VmapObject, &Vmaptype); if (map == NULL) return NULL; return map; } static void Vmap_dealloc(VmapObject *vmap) { if(vmap->data!=NULL) { /* msync(self->mm_data, self->mm_size, MS_SYNC); */ munmap(vmap->mm_data, vmap->mm_size); vmap->mm_data=NULL; } PyObject_DEL(vmap); } /* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */ /* example seen in timemodule.c */ inline double vm_timestamp(void) { double now; #if defined(HAVE_FTIME) struct timeb t; ftime(&t); now= (double)t.time + (double)t.millitm * (double)0.001; #else /* !HAVE_FTIME */ time_t x; time(&x); now = (double)x; #endif /* !HAVE_FTIME */ return now; } /* keep a counter? */ inline void vm_lockwait(VmapObject * self) { // give up timeslice (void) sched_yield( ); //usleep(0); return; } /* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */ static int vm_initheader(VmapObject *self, long bytes) { int hsize=0, wc=0; SharedHead *hdr= self->mm_data; hdr->type = self->eltype; hdr->elbytes = self->elbytes; hdr->elcount=0; hsize= sizeof(SharedHead); /* do some roundoff */ hsize += bytes; wc = (hsize / HEADALIGN); if (hsize % HEADALIGN) wc +=1; hsize = wc * HEADALIGN; hdr->hsize = hsize ; hdr->magic = VM_MAGIC; /* "unlock" */ return 1; } static void vm_swapheader(VmapObject *self ) { void *iptr; char *p; long sz=0,i=0; SharedHead *hdr= self->mm_data; iptr= self->mm_data + sizeof(long); sz=sizeof(SharedHead)-sizeof(long); for (p=iptr; imagic = VM_MAGIC; /* unlock */ return ; } /* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */ #ifdef __HAVE_ATSWAP #define HEADER_LOCK() \ do { \ if (self->flags & VM_HDRLOCK) { while (lspins--) { \ hmagic = at_swapw( &hdr->magic, -1 ); \ if (hmagic != -1) break; \ if (lusec >0) vm_lockwait(self); \ }} else { hmagic = VM_MAGIC; } \ } while (0) #else /* ! __HAVE_ATSWAP */ #define HEADER_LOCK() \ do { \ if (self->flags & VM_HDRLOCK){ hmagic=VM_MAGIC; lusec=lspins=0; }\ }while (0) #endif /* HEADER_LOCK */ static int Vmap_setype(VmapObject *self, int tp, int size); /* defined after types */ inline int vm_getypehdr(VmapObject *self) { SharedHead *hdr= self->mm_data; long hmagic=0,lspins=self->hspins,lusec=self->husec; HEADER_LOCK(); if (hmagic != VM_MAGIC) { /* uninitialized/locked */ self->headsize=0; self->data = self->mm_data; self->size = self->mm_size; self->elsize= (int) self->size / self->elbytes; return 0; } self->headsize = hdr->hsize; self->data = self->mm_data + hdr->hsize; self->size = self->mm_size - (size_t) hdr->hsize; if (self->flags & VM_HDRTYPE ) { /* (hdr overrrides self) */ hdr->type = Vmap_setype( self, hdr->type, hdr->elbytes ); if (self->flags & VM_HDRLEN) { /* use the count */ self->elsize= hdr->elcount; } else { /* all data addressable */ self->elsize= (int) self->size / self->elbytes; } } /* if type */ if (self->flags & VM_HDRLOCK) hdr->magic = VM_MAGIC; /* unlock */ return 1; } inline int vm_setypehdr(VmapObject *self) { SharedHead *hdr= self->mm_data; long hmagic=0,lspins=self->hspins,lusec=self->husec; HEADER_LOCK(); if (hmagic != VM_MAGIC) /* lock fail */ return 0; hdr->type = self->eltype; hdr->elbytes = self->elbytes; /* if (self->flags & VM_HDRLEN) ... we dont care */ if (self->flags & VM_HDRLOCK) hdr->magic = VM_MAGIC; /* unlock */ return 1; } /* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */ inline int vm_hdrcntget(VmapObject *self ) { SharedHead *hdr= self->mm_data; long hmagic=0,lspins=self->hspins,lusec=self->husec; long oldc; HEADER_LOCK(); if (hmagic != VM_MAGIC) /* lock fail */ return -1; oldc = hdr->elcount; if (self->flags & VM_HDRLOCK) hdr->magic = VM_MAGIC; /* unlock */ return oldc; } inline int vm_hdrcntinc(VmapObject *self, int toadd ) { SharedHead *hdr= self->mm_data; long hmagic=0,lspins=self->hspins,lusec=self->husec; long oldc,max; HEADER_LOCK(); if (hmagic != VM_MAGIC) /* lock fail */ return -1; oldc = hdr->elcount; max= (long) self->size / self->elbytes; if ((oldc + toadd) > max) toadd= (max - oldc); hdr->elcount += toadd; if (self->flags & VM_HDRLOCK) hdr->magic = VM_MAGIC; /* unlock */ return toadd; } inline int vm_hdrcntdec(VmapObject *self, int tosub ) { SharedHead *hdr= self->mm_data; long hmagic=0,lspins=self->hspins,lusec=self->husec; long oldc; HEADER_LOCK(); if (hmagic != VM_MAGIC) /* lock fail */ return -1; oldc = hdr->elcount; if ((oldc - tosub) <0 ) tosub=oldc; hdr->elcount -= tosub; if (self->flags & VM_HDRLOCK) hdr->magic = VM_MAGIC; /* unlock */ return tosub; } /* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */ inline PyObject * vm_getuserhdr(VmapObject *self) { PyObject *rt; long size=0,ofs=0; SharedHead *hdr= self->mm_data; long hmagic=0,lspins=self->hspins,lusec=self->husec; HEADER_LOCK(); if (hmagic != VM_MAGIC) /* lock fail */ return NULL; ofs = (sizeof(SharedHead)); size = hdr->hsize - ofs; rt= PyString_FromStringAndSize( self->mm_data + ofs, size); if (self->flags & VM_HDRLOCK) hdr->magic = VM_MAGIC; /* unlock */ return rt; } inline int vm_setuserhdr(VmapObject *self, char *in, int insz) { long size=0,ofs=0; SharedHead *hdr= self->mm_data; long hmagic=0,lspins=self->hspins,lusec=self->husec; HEADER_LOCK(); if (hmagic != VM_MAGIC) /* lock fail */ return -1; ofs = (sizeof(SharedHead)); size = hdr->hsize - ofs; if (insz < size) size=insz; memcpy( self->mm_data+ofs, in, size); if (self->flags & VM_HDRLOCK) hdr->magic = VM_MAGIC; /* unlock */ return size; } /* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */ inline int vm_map(VmapObject *self) { if ( (self->mm_data==NULL) ) { if (self->flags & VM_AUTOPEN) { self->mm_data= mmap(NULL, self->mm_size, self->mm_prot, self->mm_flags, self->fd, self->start); if ( (self->mm_data==NULL) || (self->mm_data==MAP_FAILED) ) { self->mm_data=NULL; return 0; } } else { return 0; } /* endif autoopen */ if (self->flags & VM_ADVOPEN) { if (-1 == madvise(self->mm_data, self->mm_size, self->mm_advflags)) { ;/* oops, but who cares */ } } if (self->flags & VM_KEEPTS) self->ots = vm_timestamp(); } /* endif map was closed */ if (self->flags & VM_HEADER) { if ( (!vm_getypehdr( self )) && (self->flags &VM_HDRFAIL) ) return 0; } else { // XXXX ?? self->headsize=0; self->data = self->mm_data; self->size = self->mm_size; self->elsize= (int) self->size / self->elbytes; } /* endif header */ return 1; } #define CHECK_VALID(err)\ do {\ if ( vm_map(self)==0 ) { \ PyErr_SetString(PyExc_IOError, "Vmap closed"); \ return err; \ } \ } while (0) /* CHECK_VALID */ static PyObject * Vmap_open(VmapObject *self, PyObject *args) { int x=0; long extra=0; if (!PyArg_ParseTuple(args, "|ll:open", &x, &extra)) return NULL; if ( (self->mm_data==NULL) ) { self->mm_data= mmap(NULL, self->mm_size, self->mm_prot, self->mm_flags, self->fd, self->start); } if ( (self->mm_data==NULL) || (self->mm_data==MAP_FAILED) ) { PyErr_SetString(PyExc_IOError, "Vmap not open, mmap () failed"); return NULL; } if (self->flags & VM_ADVOPEN) { if (-1 == madvise(self->mm_data, self->mm_size, self->mm_advflags)) { ;/* oops, but who cares */ } } /* is open */ if (x != 0) vm_initheader(self, extra); if (self->flags & VM_HEADER) { if ( (!vm_getypehdr( self )) && (self->flags &VM_HDRFAIL) ) { PyErr_SetString(PyExc_IOError, "Vmap read header failed"); return NULL; } } else { self->eltype = Vmap_setype( self, self->eltype, self->elbytes ); self->headsize=0; self->data = self->mm_data; self->size = self->mm_size; self->elsize= (int) self->size / self->elbytes; } /* endif header */ if (self->flags & VM_KEEPTS) self->ots = vm_timestamp(); Py_INCREF (Py_None); return (Py_None); } /* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */ inline void vm_unmap(VmapObject *self) { if (self->flags & VM_STAYOPEN) { return; } else if (self->flags & VM_ASYNCLOSE) { msync(self->mm_data, self->mm_size, MS_ASYNC) ; if (self->flags & VM_KEEPTS) self->sts = vm_timestamp(); } else if (self->flags & VM_SYNCLOSE) { msync(self->mm_data, self->mm_size, MS_SYNC) ; if (self->flags & VM_KEEPTS) self->sts = vm_timestamp(); } munmap(self->mm_data, self->mm_size); if (self->flags & VM_KEEPTS) self->cts = vm_timestamp(); self->mm_data = NULL; return; } static PyObject * Vmap_close(VmapObject *self, PyObject *args) { if (!PyArg_ParseTuple(args, ":close")) return NULL; if ( (self->mm_data==NULL) ) { /* already closed */; } else { if (self->flags & VM_ASYNCLOSE) { msync(self->mm_data, self->mm_size, MS_ASYNC) ; if (self->flags & VM_KEEPTS) self->sts = vm_timestamp(); } else if (self->flags & VM_SYNCLOSE) { msync(self->mm_data, self->mm_size, MS_SYNC) ; if (self->flags & VM_KEEPTS) self->sts = vm_timestamp(); } munmap(self->mm_data, self->mm_size); self->mm_data = NULL; self->data = NULL; } if (self->flags & VM_KEEPTS) self->cts = vm_timestamp(); Py_INCREF (Py_None); return (Py_None); } /* ---------------------------------------------------------------------------- data types */ /* ------------------------------------------------------------------------ NUMERICS *************************************************** CTOPY macro ASTAG - asInt, asLL, etc CTYPE - int, double, long long CTOPY - PyInt_FromLong, etc PYARG - "i", "L", etc PYTOC - PyLong_AsLongLong etc PTCHK - PyLong_Check SEARCHCMP - (iptr[i] == x) RSEQ - List or Tuple */ #define CTOPY_ARRAY( ASTAG, CTYPE, CTOPY, PYARG, PYTOC, PTCHK, SEARCHCMP, RSEQ ) \ static int Vmap_ ## ASTAG ## _elcmp( const void *p1, const void *p2 ) { \ CTYPE a = *((CTYPE *) p1);\ CTYPE x = *((CTYPE *) p2);\ if ( SEARCHCMP ) return 0;\ if (a > x) return (1);\ if (a < x) return (-1);\ return (0);\ }\ static PyObject * Vmap_ ## ASTAG ## _item(VmapObject *self, int i) {\ CTYPE *iptr;\ iptr = self->data;\ return CTOPY ( iptr[i] );\ }\ static int Vmap_ ## ASTAG ## _ass_item(VmapObject *self, int i, PyObject *v) {\ CTYPE *iptr;\ CTYPE x;\ if (!PyArg_Parse(v, #PYARG ";Vmap item wrong type", &x))\ return -1;\ iptr = self->data;\ iptr[i]=x;\ return 0;\ }\ static PyObject * Vmap_ ## ASTAG ## _slice(VmapObject *self, int ilow, int ihigh) {\ CTYPE *iptr;\ int i, ri=0;\ PyObject *rt;\ rt = Py ## RSEQ ## _New(ihigh - ilow);\ if (rt == NULL ) return NULL;\ iptr = self->data;\ for (i=ilow ; idata;\ for (i=ilow ; ielsize;\ iptr=self->data;\ if ( (v == NULL) || (v == Py_None) ) return -1;\ else if ( PTCHK (v) ) {\ x= PYTOC (v);\ for (i=start ; i< end ; i++ ) {\ a=iptr[i];\ if ( SEARCHCMP ) return i;\ }\ return -1;\ }\ if (!PyArg_ParseTuple (v, #PYARG "|ll:find", &x, &start, &end )) {\ PyErr_Clear();\ return -1;\ }\ if (start<0) start=0;\ if (end>self->elsize) end=self->elsize;\ for (i=start ; i< end ; i++ ) {\ a=iptr[i];\ if ( SEARCHCMP ) return i;\ }\ return -1;\ }\ static PyObject *Vmap_ ## ASTAG ## _setrange(VmapObject *self, PyObject *args) {\ CTYPE *iptr;\ CTYPE x;\ int i, ilow=0, ihigh=-1;\ if (!PyArg_ParseTuple (args, #PYARG "|ll:setrange", &x, &ilow, &ihigh )) return NULL;\ if ( vm_map(self)==0 ) { \ PyErr_SetString(PyExc_IOError, "Vmap closed"); \ return NULL; \ } \ if (ihigh ==-1) ihigh=self->elsize;\ iptr = self->data; \ for (i=ilow ; iflags & VM_KEEPTS) self->wts = vm_timestamp();\ vm_unmap(self);\ Py_INCREF (Py_None);\ return (Py_None);\ }\ static PyObject *Vmap_ ## ASTAG ## _minmax(VmapObject *self, PyObject *args) {\ CTYPE *iptr;\ CTYPE fmin=0,fmax=0;\ PyObject *rt;\ int i, maxi=-1,mini=-1, ilow=0, ihigh=-1;\ rt = Py ## RSEQ ## _New(2);\ if (rt == NULL ) return NULL;\ if (!PyArg_ParseTuple (args, "|" #PYARG #PYARG "ll:minmax", &fmin, &fmax, &ilow, &ihigh ))\ return NULL;\ if ( vm_map(self)==0 ) { \ PyErr_SetString(PyExc_IOError, "Vmap closed"); \ return NULL; \ } \ if (ihigh ==-1) ihigh=self->elsize;\ iptr = self->data; \ for (i=ilow ; i fmax) {\ fmax = iptr[i];\ maxi=i;\ }\ }\ if (self->flags & VM_KEEPTS) self->rts = vm_timestamp();\ vm_unmap(self);\ Py ## RSEQ ## _SET_ITEM( rt, 0, PyInt_FromLong( mini ) );\ Py ## RSEQ ## _SET_ITEM( rt, 1, PyInt_FromLong( maxi ) );\ return rt;\ }\ static PyObject *Vmap_ ## ASTAG ## _sumrange(VmapObject *self, PyObject *args) {\ CTYPE *iptr;\ CTYPE x=0;\ int i, ilow=0, ihigh=-1;\ if (!PyArg_ParseTuple (args, "|ll:sumrange", &ilow, &ihigh )) return NULL;\ if ( vm_map(self)==0 ) { \ PyErr_SetString(PyExc_IOError, "Vmap closed"); \ return NULL; \ } \ if (ihigh ==-1) ihigh=self->elsize;\ iptr = self->data; \ for (i=ilow ; iflags & VM_KEEPTS) self->rts = vm_timestamp();\ vm_unmap(self);\ return CTOPY ( x );\ }\ static PyObject *Vmap_ ## ASTAG ## _cntbndrange(VmapObject *self, PyObject *args) {\ CTYPE *iptr;\ CTYPE vlo=-1,vhi=1;\ unsigned long cnt=0;\ int i, ilow=0, ihigh=-1;\ if (!PyArg_ParseTuple (args, "|" #PYARG #PYARG "ll:cntbndrange",&vlo, &vhi, &ilow, &ihigh )) return NULL;\ if ( vm_map(self)==0 ) { \ PyErr_SetString(PyExc_IOError, "Vmap closed"); \ return NULL; \ } \ if (ihigh ==-1) ihigh=self->elsize;\ iptr = self->data; \ for (i=ilow ; i vlo) && (iptr[i] < vhi) ) cnt++;\ }\ if (self->flags & VM_KEEPTS) self->rts = vm_timestamp();\ vm_unmap(self);\ return PyInt_FromLong ( cnt );\ }\ /* ******************************* end macro */ /* ------------------------------------------------------------------------ Int */ CTOPY_ARRAY( asInt, long, PyInt_FromLong, l, PyInt_AS_LONG, PyInt_Check, (a == x), List ); /* ------------------------------- */ #ifdef __HAVE_ATSWAP static PyObject *Vmap_asInt_atswap(VmapObject *self, PyObject *args) { long *iptr; long x,r, el=0; if (!PyArg_ParseTuple(args, "ll:atswap", &el, &x )) return NULL; CHECK_VALID(NULL); if (el < 0 || el >= self->elsize) { PyErr_SetString(PyExc_IndexError, "Vmap index out of range"); vm_unmap(self); return NULL; } iptr = self->data; r=at_swapw( &iptr[el], x ); if (self->flags & VM_KEEPTS) self->rts = self->wts = vm_timestamp(); vm_unmap(self); return PyInt_FromLong( r ); } #endif /* ------------------------------- */ static PyMethodDef Vmap_asInt_methods[] = { {"setrange", (PyCFunction)Vmap_asInt_setrange, METH_VARARGS}, {"sumrange", (PyCFunction)Vmap_asInt_sumrange, METH_VARARGS}, {"cntbndrange", (PyCFunction)Vmap_asInt_cntbndrange, METH_VARARGS}, {"minmax", (PyCFunction)Vmap_asInt_minmax, METH_VARARGS}, #ifdef __HAVE_ATSWAP {"atswap", (PyCFunction)Vmap_asInt_atswap, METH_VARARGS}, #endif // {"", (PyCFunction)Vmap_asInt_, METH_VARARGS}, {NULL,NULL} }; /* ------------------------------------------------------------------------ LongLong */ CTOPY_ARRAY( asLL, long long, PyLong_FromLongLong, L, PyLong_AsLongLong, PyLong_Check, (a == x), List ); /* ------------------------------- */ static PyMethodDef Vmap_asLL_methods[] = { {"setrange", (PyCFunction)Vmap_asLL_setrange, METH_VARARGS}, {"sumrange", (PyCFunction)Vmap_asLL_sumrange, METH_VARARGS}, {"cntbndrange", (PyCFunction)Vmap_asLL_cntbndrange, METH_VARARGS}, {"minmax", (PyCFunction)Vmap_asLL_minmax, METH_VARARGS}, // {"", (PyCFunction)Vmap_asLL_, METH_VARARGS}, {NULL,NULL} }; /* ------------------------------------------------------------------------ Float */ CTOPY_ARRAY( asFlt, double, PyFloat_FromDouble, d, PyFloat_AS_DOUBLE, PyFloat_Check, ( (abs(a - x) < 0.0000001 )), List ); /* ------------------------------- */ static PyMethodDef Vmap_asFlt_methods[] = { {"setrange", (PyCFunction)Vmap_asFlt_setrange, METH_VARARGS}, {"sumrange", (PyCFunction)Vmap_asFlt_sumrange, METH_VARARGS}, {"cntbndrange", (PyCFunction)Vmap_asFlt_cntbndrange, METH_VARARGS}, {"minmax", (PyCFunction)Vmap_asFlt_minmax, METH_VARARGS}, // {"", (PyCFunction)Vmap_asFlt_, METH_VARARGS}, {NULL,NULL} }; /* *************************************************** CTOPY_2D macro ASTAG - asInt, asLL, etc CTYPE - int, double, long long CTOPY - PyInt_FromLong, etc PYARG - "i", "L", etc PYTOC - PyLong_AsLongLong etc PTCHK - PyLong_Check SEARCHCMP - (iptr[i] == x) RSEQ - List or Tuple */ #define CTOPY_ARRAY_2D( ASTAG, CTYPE, CTOPY, PYARG, PYTOC, PTCHK, SEARCHCMP, RSEQ ) \ static int Vmap_ ## ASTAG ## _elcmp( const void *p1, const void *p2 ) { \ CTYPE a = *((CTYPE *) p1);\ CTYPE x = *((CTYPE *) p2);\ if ( SEARCHCMP ) return 0;\ if (a > x) return (1);\ if (a < x) return (-1);\ return (0);\ }\ static PyObject * Vmap_ ## ASTAG ## _item(VmapObject *self, int i) {\ CTYPE *iptr;\ PyObject *rt;\ long ri, al;\ al=(self->elbytes / sizeof(CTYPE));\ rt= Py ## RSEQ ## _New( al );\ if (rt == NULL) return NULL;\ iptr = self->data + (i * self->elbytes);\ for (ri=0 ; rielbytes / sizeof(CTYPE));\ if (!PySequence_Check(v)) return -1;\ tpl = PySequence_Fast( v, "Vmap item assign must be sequence" );\ tsz = PySequence_Size(tpl);\ if (tsz != al) {\ PyErr_SetString(PyExc_IndexError, "Vmap assignment is wrong size");\ Py_DECREF(tpl);\ return -1;\ }\ iptr = self->data + (i * self->elbytes);\ for (ri=0 ; rielbytes / sizeof(CTYPE));\ rt = Py ## RSEQ ## _New(ihigh - ilow);\ if (rt == NULL ) return NULL;\ for (i=ilow ; idata + (i * self->elbytes);\ for (ii=0 ; iielbytes / sizeof(CTYPE));\ PyObject *tpl, *itpl, *iv, *ix;\ tpl = PySequence_Fast( v, "Vmap slice assign must be sequence" );\ csz= PySequence_Size(tpl);\ if (csz != (ihigh - ilow) ) {\ PyErr_SetString(PyExc_IndexError, "Vmap slice assignment is wrong size");\ Py_DECREF(tpl);\ return -1;\ }\ for (i=ilow ; idata + (i * self->elbytes);\ for (ii=0 ; iielbytes / sizeof(CTYPE)), end=(self->elsize * al) ;\ iptr=self->data;\ if ( (v == NULL) || (v == Py_None) ) return -1;\ else if ( PTCHK (v) ) {\ x= PYTOC (v);\ for (i=start ; i< end ; i++ ) {\ a=iptr[i];\ if ( SEARCHCMP ) return (i / al );\ }\ return -1;\ }\ if (!PyArg_ParseTuple (v, #PYARG "|ll:find", &x, &start, &end )) {\ PyErr_Clear();\ return -1;\ }\ if (start<0) start=0;\ if (end>self->elsize) end=self->elsize;\ end = end * al;\ for (i=start ; i< end ; i++ ) {\ a=iptr[i];\ if ( SEARCHCMP ) return (i / al);\ }\ return -1;\ }\ static PyObject *Vmap_ ## ASTAG ## _colxchg(VmapObject *self, PyObject *args) {\ CTYPE *iptr;\ CTYPE x;\ int i, cols=0, ca=0,cb=0, ilow=0, ihigh=-1;\ if (!PyArg_ParseTuple (args, "ll|ll:swapcol", &ca, &cb, &ilow, &ihigh )) return NULL;\ if (ca == cb) {\ Py_INCREF (Py_None);\ return (Py_None);\ }\ if ( vm_map(self)==0 ) { \ PyErr_SetString(PyExc_IOError, "Vmap closed"); \ return NULL; \ } \ if (ihigh ==-1) ihigh=self->elsize;\ cols=(self->elbytes / sizeof(CTYPE));\ if ( (ca>cols) && (cb>cols) ) {\ PyErr_SetString(PyExc_IndexError, "Vmap columns out of range"); \ return NULL; \ }\ for (i=ilow ; idata + (i * self->elbytes);\ x = iptr[cb];\ iptr[cb] = iptr[ca];\ iptr[ca] = x;\ }\ if (self->flags & VM_KEEPTS) self->rts = self->wts = vm_timestamp();\ vm_unmap(self);\ Py_INCREF (Py_None);\ return (Py_None);\ }\ static PyObject *Vmap_ ## ASTAG ## _colget(VmapObject *self, PyObject *args) {\ CTYPE *iptr;\ CTYPE x;\ int el=0, col=0, cols=0;\ if (!PyArg_ParseTuple (args, "ll:colget", &el, &col )) return NULL;\ if ( vm_map(self)==0 ) { \ PyErr_SetString(PyExc_IOError, "Vmap closed"); \ return NULL; \ } \ if (el < 0 || el >= self->elsize) {\ PyErr_SetString(PyExc_IndexError, "Vmap index out of range");\ vm_unmap(self);\ return NULL;\ }\ cols=(self->elbytes / sizeof(long));\ if ( (col>cols) ) {\ PyErr_SetString(PyExc_IndexError, "Vmap column out of range"); \ return NULL; \ }\ iptr = self->data + (el * self->elbytes);\ x=iptr[col];\ if (self->flags & VM_KEEPTS) self->rts = vm_timestamp();\ vm_unmap(self);\ return PyInt_FromLong( x );\ }\ /* ******************************* end macro */ /* ------------------------------------------------------------------------ INT 2D */ CTOPY_ARRAY_2D( as2I, long, PyInt_FromLong, l, PyInt_AS_LONG, PyInt_Check, (a == x), List ); /* ------------------------------- */ #ifdef __HAVE_ATSWAP static PyObject *Vmap_as2I_atswap(VmapObject *self, PyObject *args) { long *iptr; long cols,x=0, el=0, col=0; if (!PyArg_ParseTuple(args, "lll:atswap", &el, &col, &x )) return NULL; CHECK_VALID(NULL); if (el < 0 || el >= self->elsize) { PyErr_SetString(PyExc_IndexError, "Vmap index out of range"); vm_unmap(self); return NULL; } cols=(self->elbytes / sizeof(long)); if ( (col>cols) ) { PyErr_SetString(PyExc_IndexError, "Vmap column out of range"); return NULL; } iptr = self->data + (el * self->elbytes); x=at_swapw( &iptr[col], x ); if (self->flags & VM_KEEPTS) self->rts = self->wts = vm_timestamp(); vm_unmap(self); return PyInt_FromLong( x ); } #endif /* ------------------------------- */ static PyMethodDef Vmap_as2I_methods[] = { {"colxchg", (PyCFunction)Vmap_as2I_colxchg, METH_VARARGS}, {"colget", (PyCFunction)Vmap_as2I_colget, METH_VARARGS}, #ifdef __HAVE_ATSWAP {"atswap", (PyCFunction)Vmap_as2I_atswap, METH_VARARGS}, #endif // {"", (PyCFunction)Vmap_as2I_, METH_VARARGS}, {NULL,NULL} }; /* ------------------------------------------------------------------------ LongLong 2D */ CTOPY_ARRAY_2D( as2LL, long long, PyLong_FromLongLong, L, PyLong_AsLongLong, PyLong_Check, (a == x), List ); /* ------------------------------- */ static PyMethodDef Vmap_as2LL_methods[] = { {"colxchg", (PyCFunction)Vmap_as2LL_colxchg, METH_VARARGS}, {"colget", (PyCFunction)Vmap_as2LL_colget, METH_VARARGS}, // {"", (PyCFunction)Vmap_as2LL_, METH_VARARGS}, {NULL,NULL} }; /* ------------------------------------------------------------------------ Float 2D */ CTOPY_ARRAY_2D( as2Flt, double, PyFloat_FromDouble, d, PyFloat_AS_DOUBLE, PyFloat_Check, ( (abs(a - x) < 0.0000001 )), List ); /* ------------------------------- */ static PyMethodDef Vmap_as2Flt_methods[] = { {"colxchg", (PyCFunction)Vmap_as2Flt_colxchg, METH_VARARGS}, {"colget", (PyCFunction)Vmap_as2Flt_colget, METH_VARARGS}, // {"", (PyCFunction)Vmap_as2Flt_, METH_VARARGS}, {NULL,NULL} }; /* ------------------------------------------------------------------------ "varlen" */ /* Copid from Python 2.2 stringobject.c */ static int mymemfind(const char *mem, int len, const char *pat, int pat_len) { register int ii; /* pattern can not occur in the last pat_len-1 chars */ len -= pat_len; for (ii = 0; ii <= len; ii++) { if (mem[ii] == pat[0] && memcmp(&mem[ii], pat, pat_len) == 0) return ii; } return -1; } /* ------------------------------------------------------------------------ Raw */ static int Vmap_asRaw_elcmp( const void *p1, const void *p2 ) { char i = *((char *)p1); char j = *((char *)p2); if (i > j) return (1); if (i < j) return (-1); return (0); } /* ------------------------------- */ static PyObject * Vmap_asRaw_item(VmapObject *self, int i) { char *iptr; PyObject *rt; iptr=self->data+i; rt=PyString_FromStringAndSize( iptr, 1); return rt; } static int Vmap_asRaw_ass_item(VmapObject *self, int i, PyObject *v) { int insize; char *iptr; char *buf; iptr=self->data; if ( (v == NULL) || (v == Py_None) ) { if (self->flags & VM_DOFILL) iptr[i] = (char)self->fill; return 0; } if (!PyString_Check(v) ) { PyErr_SetString(PyExc_ValueError, "Vmap assignment expected string"); return -1; } insize = PyString_Size(v); if (insize == 0) { if (self->flags & VM_DOFILL) iptr[i] = (char)self->fill; } else { buf = PyString_AsString(v); iptr[i] = buf[0]; } return 0; } /* ------------------------------- */ static PyObject * Vmap_asRaw_slice(VmapObject *self, int ilow, int ihigh) { PyObject *rt; rt=PyString_FromStringAndSize(self->data + ilow, ihigh-ilow); return rt; } static int Vmap_asRaw_ass_slice(VmapObject *self, int ilow, int ihigh, PyObject *v) { int insize; char *buf; void *iptr; if ( (v == NULL) || (v == Py_None) ) insize = 0; else if (!PyString_Check(v) ) { PyErr_SetString(PyExc_ValueError, "Vmap assignment expected string"); return -1; } else insize = PyString_Size(v); if (insize > (ihigh-ilow)) insize=ihigh-ilow; if (insize > self->elsize) insize=self->elsize; iptr = self->data + ilow; if (insize == 0) { if (self->flags & VM_DOFILL) memset(iptr, self->fill, (ihigh-ilow)); } else { buf = PyString_AsString(v); memcpy(iptr, buf, insize); } return 0; } /* ------------------------------- */ static int Vmap_asRaw_dosearch(VmapObject *self, PyObject *v) { char *buf; int insize=0,start=0,end=self->size; if ( (v == NULL) || (v == Py_None) ) return -1; else if (PyString_Check(v) ) { return mymemfind( self->data, self->size, PyString_AsString(v), PyString_Size(v) ); } if (!PyArg_ParseTuple (v, "z#|ll:find", &buf, &insize, &start, &end )) { PyErr_Clear(); return -1; } if (insize==0) return -1; if (start<0) start=0; if (end>self->size) end=self->size; return mymemfind( (self->data +start), end, buf, insize ); } /* ---------------------------------------------------------- */ // .stripped(lo,hi) ? // .replace() static PyMethodDef Vmap_asRaw_methods[] = { // {"", (PyCFunction)Vmap_as_, METH_VARARGS}, {NULL,NULL} }; /* ------------------------------------------------------------------------ StrA */ static int Vmap_asSA_elcmp( const void *p1, const void *p2 ) { // XXX needs elbytes char i = *((char *)p1); char j = *((char *)p2); if (i > j) return (1); if (i < j) return (-1); return (0); } /* ------------------------------- */ static PyObject * Vmap_asSA_item(VmapObject *self, int i) { char *iptr; iptr = self->data + (i * self->elbytes); return PyString_FromStringAndSize(iptr, self->elbytes); } static int Vmap_asSA_ass_item(VmapObject *self, int i, PyObject *v) { void *iptr; int insize; char * buf; if ( (v == NULL) || (v == Py_None) ) insize = 0; else if (!PyString_Check(v) ) { PyErr_SetString(PyExc_ValueError, "Vmap assignment expected string"); return -1; } else insize = PyString_Size(v); if (insize > self->elbytes) insize=self->elbytes; iptr = self->data + (i * self->elbytes); if (insize == 0) memset(iptr, self->fill, self->elbytes); else { buf = PyString_AsString(v); memcpy(iptr, buf, insize); if ( (self->flags & VM_DOFILL) && (insize< self->elbytes) ) { memset(iptr+insize, self->fill, self->elbytes - insize ); } } return 0; } /* ------------------------------- */ static PyObject * Vmap_asSA_slice(VmapObject *self, int ilow, int ihigh) { int i, ri=0; PyObject *rt; rt = NEWRSEQ (ihigh - ilow); if (rt == NULL ) return NULL; for (i=ilow ; idata + (i * self->elbytes), self->elbytes) ); } if (PyErr_Occurred()) { Py_DECREF(rt); return NULL; } return rt; } static int Vmap_asSA_ass_slice(VmapObject *self, int ilow, int ihigh, PyObject *v) { char *buf, *iptr; int csz, insize, i, ri=0; PyObject *tpl, *iv; if (!PySequence_Check(v)) { PyErr_SetString(PyExc_ValueError, "Vmap assignment expected sequence"); return -1; } tpl = PySequence_Fast( v, "Vmap slice assign must be sequence" ); csz= PySequence_Size(tpl); if (csz != (ihigh - ilow) ) { PyErr_SetString(PyExc_IndexError, "Vmap slice assignment is wrong size"); Py_DECREF(tpl); return -1; } for (i=ilow ; i self->elbytes) insize=self->elbytes; iptr = self->data + (i * self->elbytes); if (insize == 0) memset(iptr, self->fill, self->elbytes); else { buf = PyString_AsString(iv); memcpy(iptr, buf, insize); if ( (self->flags & VM_DOFILL) && (insize< self->elbytes) ) { memset(iptr+insize, self->fill, self->elbytes - insize ); } } } if (PyErr_Occurred()) PyErr_Clear(); Py_DECREF(tpl); return 0; } /* ------------------------------- */ static int Vmap_asSA_dosearch(VmapObject *self, PyObject *v) { char *buf; int i=0, insize=0,start=0,end=self->elsize; if ( (v == NULL) || (v == Py_None) ) return -1; else if (PyString_Check(v) ) { buf=PyString_AsString(v); insize=PyString_Size(v); for (i=start ; i< self->elsize ; i++ ) { if (mymemfind( self->data + (i * self->elbytes), self->elbytes, buf, insize ) != -1) return i; } return -1; } if (!PyArg_ParseTuple (v, "z#|ll:find", &buf, &insize, &start, &end )) { PyErr_Clear(); return -1; } if (insize==0) return -1; if (start<0) start=0; if (end>self->elsize) end=self->elsize; for (i=start ; i< self->elsize ; i++ ) { if (mymemfind( self->data + (i * self->elbytes), self->elbytes, buf, insize ) != -1) return i; } return -1; } /* ---------------------------------------------------------- */ static PyObject *Vmap_asSA_size(VmapObject *self, PyObject *v) { int newsz=self->elbytes; if (!PyArg_ParseTuple (v, "|l:size", &newsz )) return NULL; CHECK_VALID(NULL); if ((newsz<1) || (newsz>self->size)) return NULL; if (newsz!=self->elbytes) { self->elbytes=newsz; if (!(self->flags & VM_HDRLEN) ) self->elsize= self->size / newsz; if (self->flags & (VM_HEADER | VM_HDRTYPE)) { if ( (!vm_setypehdr(self)) && (self->flags & VM_HDRFAIL) ) { vm_unmap( self ); PyErr_SetString(PyExc_IOError, "Vmaps header lock failed"); return NULL; } } /* endif header */ } vm_unmap(self); return PyInt_FromLong( self->elbytes ); } /* ------------------------------- */ // Return stripped mode? static PyMethodDef Vmap_asSA_methods[] = { {"resize", (PyCFunction)Vmap_asSA_size, METH_VARARGS}, //{"", (PyCFunction)Vmap_, METH_VARARGS}, {NULL,NULL} }; /* ------------------------------------------------------------------------ PyLongArray */ static int Vmap_asLLA_elcmp( const void *p1, const void *p2 ) { // XXX needs elbytes char i = *((char *)p1); char j = *((char *)p2); if (i > j) return (1); if (i < j) return (-1); return (0); } /* ------------------------------- */ static PyObject * Vmap_asLLA_item(VmapObject *self, int i) { char *iptr; iptr = self->data + (i * self->elbytes); return _PyLong_FromByteArray(iptr, self->elbytes, ((self->flags & VM_LLALE)!=0),((self->flags & VM_LLASG)!=0) ); } static int Vmap_asLLA_ass_item(VmapObject *self, int i, PyObject *v) { void *iptr; if (!PyLong_Check(v) ) { PyErr_SetString(PyExc_ValueError, "Vmap assignment expected long"); return -1; } iptr = self->data + (i * self->elbytes); return _PyLong_AsByteArray((PyLongObject *)v, iptr, self->elbytes, ((self->flags & VM_LLALE)!=0),((self->flags & VM_LLASG)!=0) ); } /* ------------------------------- */ static PyObject * Vmap_asLLA_slice(VmapObject *self, int ilow, int ihigh) { int i, ri=0; PyObject *rt; rt = NEWRSEQ (ihigh - ilow); if (rt == NULL ) return NULL; for (i=ilow ; idata + (i * self->elbytes), self->elbytes, ((self->flags & VM_LLALE)!=0),((self->flags & VM_LLASG)!=0) ) ); } if (PyErr_Occurred()) { Py_DECREF(rt); return NULL; } return rt; } static int Vmap_asLLA_ass_slice(VmapObject *self, int ilow, int ihigh, PyObject *v) { char *iptr; int csz, i, ri=0; PyObject *tpl, *iv; if (!PySequence_Check(v)) { PyErr_SetString(PyExc_ValueError, "Vmap assignment expected sequence"); return -1; } tpl = PySequence_Fast( v, "Vmap slice assign must be sequence" ); csz= PySequence_Size(tpl); if (csz != (ihigh - ilow) ) { PyErr_SetString(PyExc_IndexError, "Vmap slice assignment is wrong size"); Py_DECREF(tpl); return -1; } for (i=ilow ; idata + (i * self->elbytes); (void) _PyLong_AsByteArray((PyLongObject*) iv, iptr, self->elbytes, ((self->flags & VM_LLALE)!=0),((self->flags & VM_LLASG)!=0) ); } if (PyErr_Occurred()) PyErr_Clear(); Py_DECREF(tpl); return 0; } /* ------------------------------- */ static int Vmap_asLLA_dosearch(VmapObject *self, PyObject *v) { // whooo return -1; } /* ---------------------------------------------------------- */ static PyObject *Vmap_asLLA_size(VmapObject *self, PyObject *v) { int newsz=self->elbytes; if (!PyArg_ParseTuple (v, "|l:size", &newsz )) return NULL; CHECK_VALID(NULL); if ((newsz<1) || (newsz>self->size)) return NULL; if (newsz!=self->elbytes) { self->elbytes=newsz; if (!(self->flags & VM_HDRLEN) ) self->elsize= self->size / newsz; if (self->flags & (VM_HEADER | VM_HDRTYPE)) { if ( (!vm_setypehdr(self)) && (self->flags & VM_HDRFAIL) ) { vm_unmap( self ); PyErr_SetString(PyExc_IOError, "Vmaps header lock failed"); return NULL; } } /* endif header */ } vm_unmap(self); return PyInt_FromLong( self->elbytes ); } /* ------------------------------- */ static PyMethodDef Vmap_asLLA_methods[] = { {"resize", (PyCFunction)Vmap_asLLA_size, METH_VARARGS}, //{"", (PyCFunction)Vmap_, METH_VARARGS}, {NULL,NULL} }; /* ---------------------------------------------------------------------------- type switch */ #define _SET_TYPE_FUNCS(ASTAG)\ do{\ self->f_elcmp = (void *)&Vmap_ ## ASTAG ## _elcmp;\ self->f_item = (void *)&Vmap_ ## ASTAG ## _item;\ self->f_aitem = (void *)&Vmap_ ## ASTAG ## _ass_item;\ self->f_slice = (void *)&Vmap_ ## ASTAG ## _slice;\ self->f_aslice = (void *)&Vmap_ ## ASTAG ## _ass_slice;\ self->f_search = (void *)&Vmap_ ## ASTAG ## _dosearch;\ self->f_meth = &Vmap_ ## ASTAG ## _methods;\ } while (0) /* _SET_TYPE_FUNCS */ static int Vmap_setype(VmapObject *self, int tp, int size) { /* no shared data here */ switch (tp) { default: /* FALLTHRU */ case VMT_RAW: self->eltype=VMT_RAW; self->elbytes=1; self->f_elcmp = (void *)&Vmap_asRaw_elcmp; _SET_TYPE_FUNCS( asRaw ); break; case VMT_SA: self->eltype=tp; self->elbytes=size; _SET_TYPE_FUNCS( asSA ); self->f_elcmp = NULL; /* (void *)&Vmap_asSA_elcmp; // it dont work */ break; case VMT_LLA: self->eltype=tp; self->elbytes=size; _SET_TYPE_FUNCS( asLLA ); self->f_elcmp = NULL; /* (void *)&Vmap_asLLA_elcmp; // it dont work */ break; case VMT_IA: self->eltype=tp; self->elbytes=sizeof(long); _SET_TYPE_FUNCS( asInt ); break; case VMT_DA: self->eltype=tp; self->elbytes=sizeof(double); _SET_TYPE_FUNCS( asFlt ); break; case VMT_LL: self->eltype=tp; self->elbytes=sizeof(long long); _SET_TYPE_FUNCS( asLL ); break; case VMT_2IA: self->eltype=tp; self->elbytes=(size * sizeof(long)); _SET_TYPE_FUNCS( as2I ); break; case VMT_2LA: self->eltype=tp; self->elbytes=(size * sizeof(long long)); _SET_TYPE_FUNCS( as2LL ); break; case VMT_2FA: self->eltype=tp; self->elbytes=(size * sizeof(double)); _SET_TYPE_FUNCS( as2Flt ); break; } // XXXXXXXXXXXX ? self->elsize=(int)self->size/self->elbytes; return tp; } /* ---------------------------------------------------------------------------- generic methods ---------------------------------------------------------------------------- (all types) */ /* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */ static PyObject * Vmap_type(VmapObject *self, PyObject *args) { long tp=self->eltype, size=self->elbytes; if (!PyArg_ParseTuple (args, "|ll:type", &tp, &size )) return NULL; CHECK_VALID(NULL); if ( (tp!=self->eltype) || (size != self->elbytes) ) { Vmap_setype( self, tp, size ); if (self->flags & (VM_HEADER | VM_HDRTYPE)) { if ( !vm_setypehdr(self) ) { vm_unmap( self ); PyErr_SetString(PyExc_IOError, "Vmaps header lock failed"); return NULL; } } /* endif header */ } /*endif chtype */ vm_unmap(self); return PyInt_FromLong( self->eltype ); } /* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */ //XXXX push, pop (slice access wrap); insert, remove (w/memmove); static PyObject * Vmap_count_get(VmapObject *self, PyObject *args) { long x=0,r=0; if (!PyArg_ParseTuple (args, "|l:count_get", &x )) return NULL; if ( ! (self->flags & VM_HEADER) ) { PyErr_SetString(PyExc_ValueError, "Vmap has no count in header"); return NULL; } CHECK_VALID(NULL); r = vm_hdrcntget(self); vm_unmap(self); return PyInt_FromLong(r); } static PyObject * Vmap_count_add(VmapObject *self, PyObject *args) { long x=0,r=0; if (!PyArg_ParseTuple (args, "|l:count_add", &x )) return NULL; if ( ! (self->flags & VM_HEADER) ) { PyErr_SetString(PyExc_ValueError, "Vmap has no count in header"); return NULL; } if (x<1) return PyInt_FromLong(0); CHECK_VALID(NULL); r = vm_hdrcntinc(self, x); vm_unmap(self); return PyInt_FromLong(r); } static PyObject * Vmap_count_sub(VmapObject *self, PyObject *args) { long x=0,r=0; if (!PyArg_ParseTuple (args, "|l:count_sub", &x )) return NULL; if ( ! (self->flags & VM_HEADER) ) { PyErr_SetString(PyExc_ValueError, "Vmap has no count in header"); return NULL; } if (x<1) return PyInt_FromLong(0); CHECK_VALID(NULL); r = vm_hdrcntdec(self, x); vm_unmap(self); return PyInt_FromLong(r); } /* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */ static PyObject *Vmap_swapheader(VmapObject *self, PyObject *v) { if (!PyArg_ParseTuple (v, ":swapheader" )) return NULL; if ( !(self->flags & VM_HEADER) ) { PyErr_SetString(PyExc_ValueError, "Vmap has no header"); return NULL; } CHECK_VALID(NULL); vm_swapheader(self); vm_unmap(self); return PyInt_FromLong( 0 ); } static PyObject * Vmap_getheader(VmapObject *self, PyObject *args) { PyObject *rt; long x; if (!PyArg_ParseTuple (args, "|l:getheader", &x )) return NULL; if ( !(self->flags & VM_HEADER) ) { PyErr_SetString(PyExc_ValueError, "Vmap has no header"); return NULL; } CHECK_VALID(NULL); rt = vm_getuserhdr(self); vm_unmap(self); return rt; } static PyObject * Vmap_setheader(VmapObject *self, PyObject *args) { PyObject *v; char *buf; int rt=0,insz=0; if (!PyArg_ParseTuple (args, "O:setheader", &v )) return NULL; if ( !(self->flags & VM_HEADER) ) { PyErr_SetString(PyExc_ValueError, "Vmap has no header"); return NULL; } insz = PyString_Size(v); buf = PyString_AsString(v); CHECK_VALID(NULL); rt = vm_setuserhdr(self,buf,insz); vm_unmap(self); return PyInt_FromLong(rt); } /* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */ static PyObject *Vmap_copyfrom(VmapObject *self, PyObject *args) { VmapObject *v; size_t bytes=-1,ilow=0, vlow=0; if (!PyArg_ParseTuple (args, "O!|lll:copyfrom", &Vmaptype, &v, &bytes, &ilow, &vlow )) { return NULL; } CHECK_VALID(NULL); if ( vm_map(v)==0 ) { PyErr_SetString(PyExc_IOError, "Vmap closed"); vm_unmap(self); return NULL; } if (bytes == -1) { if ( (self->size - ilow) < (v->size - vlow) ) bytes = (self->size - ilow); else bytes=(v->size - vlow); } if ( (ilow+bytes> self->size) || (vlow+bytes > v->size) ) { PyErr_SetString (PyExc_ValueError, "copy offsets out of range"); vm_unmap(v); vm_unmap(self); return NULL; } memmove( v->data+vlow, self->data+ilow, bytes ); if (v->flags & VM_KEEPTS) v->rts = vm_timestamp(); if (self->flags & VM_KEEPTS) self->wts = vm_timestamp(); vm_unmap(v); vm_unmap(self); return PyInt_FromLong( bytes ); } /* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */ #define CHECK_OPENANDSIZE()\ do{\ if ( (self->mm_data==NULL) || (self->mm_data==MAP_FAILED) ) {\ PyErr_SetString(PyExc_IOError, "Vmaps must be open for that");\ return NULL;\ }\ if (size ==0)\ size=self->mm_size;\ if ((offset + size) > self->mm_size) {\ PyErr_SetString (PyExc_ValueError, "values out of range");\ return NULL;\ }\ } while (0)\ /* CHECK_OPENANDSIZE */ static PyObject * Vmap_raw_msync(VmapObject *self, PyObject *args) { size_t offset = 0; size_t size = self->mm_size; int flags = MS_SYNC; CHECK_OPENANDSIZE(); if (!PyArg_ParseTuple (args, "|lll:raw_msync", &flags, &offset, &size)) return NULL; if (-1 == msync(self->mm_data + offset, size, flags)) { PyErr_SetFromErrno(ErrorObject); return NULL; } if (self->flags & VM_KEEPTS) self->sts = vm_timestamp(); Py_INCREF (Py_None); return (Py_None); } static PyObject * Vmap_raw_madvise(VmapObject *self, PyObject *args) { size_t offset = 0; size_t size = self->mm_size; int flags = self->mm_advflags; CHECK_OPENANDSIZE(); if (!PyArg_ParseTuple (args, "|lll:raw_madvise", &flags, &offset, &size)) return NULL; if (-1 == madvise(self->mm_data + offset, size, flags)) { PyErr_SetFromErrno(ErrorObject); return NULL; } Py_INCREF (Py_None); return (Py_None); } static PyObject * Vmap_raw_mlock(VmapObject *self, PyObject *args) { size_t offset = 0; size_t size = self->mm_size; CHECK_OPENANDSIZE(); if (!PyArg_ParseTuple (args, "|ll:raw_mlock", &offset, &size)) return NULL; if (-1 == mlock(self->mm_data + offset, size )) { PyErr_SetFromErrno(ErrorObject); return NULL; } Py_INCREF (Py_None); return (Py_None); } static PyObject * Vmap_raw_munlock(VmapObject *self, PyObject *args) { size_t offset = 0; size_t size = self->mm_size; CHECK_OPENANDSIZE(); if (!PyArg_ParseTuple (args, "|ll:raw_munlock", &offset, &size)) return NULL; if (-1 == munlock(self->mm_data + offset, size )) { PyErr_SetFromErrno(ErrorObject); return NULL; } Py_INCREF (Py_None); return (Py_None); } /* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */ static PyObject * Vmap_raw_string(VmapObject *self, PyObject *args) { size_t ilow = 0; size_t ihigh = self->mm_size; PyObject *r; if (!PyArg_ParseTuple (args, "|ll:raw_string", &ilow, &ihigh )) return NULL; else if ((ilow + ihigh) > self->mm_size) { PyErr_SetString (PyExc_ValueError, "values out of range"); return NULL; } if (ilow <0) ilow=0; else if (ilow > self->mm_size) ilow=self->mm_size; if (ihigh self->mm_size) ihigh=self->mm_size; CHECK_VALID(NULL); r=PyString_FromStringAndSize(self->mm_data + ilow, ihigh-ilow); if (self->flags & VM_KEEPTS) self->rts = vm_timestamp(); vm_unmap(self); return r; } /* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */ static PyObject *Vmap_sort(VmapObject *self, PyObject *args) { void *iptr, *cmpfunc; size_t size, wide; long ofs=0,cnt=-1; if (!PyArg_ParseTuple (args, "|ll:sort", &ofs, &cnt )) return NULL; CHECK_VALID(NULL); cmpfunc=self->f_elcmp; if (cmpfunc == NULL) { vm_unmap(self); return NULL; } if (cnt<0) cnt = self->elsize -ofs; if (cnt+ofs > self->elsize) { PyErr_SetString (PyExc_ValueError, "sort offsets out of range"); vm_unmap(self); return NULL; } iptr=self->data + (ofs * self->elbytes); size=cnt; wide=self->elbytes; qsort( iptr, size, wide, cmpfunc ); if (self->flags & VM_KEEPTS) self->rts = self->wts = vm_timestamp(); vm_unmap(self); Py_INCREF (Py_None); return (Py_None); } static PyObject *Vmap_byteswap(VmapObject *self, PyObject *args) { void *iptr; char *p; long ofs=0,cnt=-1,sz=0,i=0; if (!PyArg_ParseTuple (args, "|ll:byteswap", &ofs, &cnt )) return NULL; CHECK_VALID(NULL); if (cnt<0) cnt = self->elsize -ofs; if (cnt+ofs > self->elsize) { PyErr_SetString (PyExc_ValueError, "byteswap offsets out of range"); vm_unmap(self); return NULL; } iptr= self->data + (ofs * self->elbytes); sz=(cnt*self->elbytes); switch (self->eltype) { /* 4 bytes */ case VMT_IA: /* FALLTHRU */ case VMT_2IA: for (p=iptr; iflags & VM_KEEPTS) self->rts = self->wts = vm_timestamp(); vm_unmap(self); return PyInt_FromLong( sz); Py_INCREF (Py_None); return (Py_None); } /* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */ static PyObject *Vmap_find(VmapObject *self, PyObject *args) { int (*sfunc)(PyObject *s ,PyObject *v ); long r; CHECK_VALID(NULL); sfunc= (void*) self->f_search; if (sfunc == NULL) { vm_unmap(self); return NULL; } r=(int) sfunc((PyObject *)self, args); if (self->flags & VM_KEEPTS) self->rts = vm_timestamp(); vm_unmap( self ); return PyInt_FromLong( r ); } /* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */ static PyObject *Vmap_schyield(VmapObject *self, PyObject *v) { if (!PyArg_ParseTuple (v, ":schyield" )) return NULL; vm_lockwait(self); return PyInt_FromLong( 0 ); } static PyObject *Vmap_getflag(VmapObject *self, PyObject *v) { long x; if (!PyArg_ParseTuple (v, "|l:getflag", &x )) return NULL; return PyInt_FromLong( ((self->flags & x)!=0) ); } static PyObject *Vmap_setflag(VmapObject *self, PyObject *v) { long x; if (!PyArg_ParseTuple (v, "|l:setflag", &x )) return NULL; self->flags = (self->flags | x ); return PyInt_FromLong( (self->flags) ); } static PyObject *Vmap_clearflag(VmapObject *self, PyObject *v) { long x; if (!PyArg_ParseTuple (v, "|l:clearflag", &x )) return NULL; self->flags = (self->flags & (~x) ); return PyInt_FromLong( (self->flags) ); } static PyObject *Vmap_times(VmapObject *self, PyObject *args) { long reset=0; PyObject *rt; if (!PyArg_ParseTuple (args, "|l:times", &reset )) return NULL; rt = PyTuple_New(5); if (rt == NULL ) return NULL; PyTuple_SET_ITEM( rt, 0, PyFloat_FromDouble( self->rts )); PyTuple_SET_ITEM( rt, 1, PyFloat_FromDouble( self->wts )); PyTuple_SET_ITEM( rt, 2, PyFloat_FromDouble( self->sts )); PyTuple_SET_ITEM( rt, 3, PyFloat_FromDouble( self->ots )); PyTuple_SET_ITEM( rt, 4, PyFloat_FromDouble( self->cts )); if (reset !=0) self->rts = self->wts = self->sts = self->ots = self->cts = 0.0; return rt; } static PyObject *Vmap_elsize(VmapObject *self, PyObject *v) { if (!PyArg_ParseTuple (v, ":size" )) return NULL; return PyInt_FromLong( self->elbytes ); } static PyObject *Vmap_elpage(VmapObject *self, PyObject *v) { long eofs=0, x=0,pg=0; if (!PyArg_ParseTuple (v, "l:elpage", &x )) return NULL; if (self->flags & VM_HEADER) { /* Actually lets just say it has to have been opened if ( vm_map(self)==0 ) { PyErr_SetString(PyExc_IOError, "Vmap closed"); return err; } vm_unmap(self); */ eofs += self->headsize; } eofs += (x * self->elbytes); pg = eofs / my_getpagesize(); return PyInt_FromLong( pg ); } /* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */ static char xx_doc[] = "noneyet"; static PyMethodDef Vmap_methods[] = { {"schyield", (PyCFunction)Vmap_schyield, METH_VARARGS, xx_doc}, {"elsize", (PyCFunction)Vmap_elsize, METH_VARARGS, xx_doc}, {"elpage", (PyCFunction)Vmap_elpage, METH_VARARGS, xx_doc}, {"find", (PyCFunction)Vmap_find, METH_VARARGS, xx_doc}, {"count_get", (PyCFunction)Vmap_count_get, METH_VARARGS, xx_doc}, {"count_add", (PyCFunction)Vmap_count_add, METH_VARARGS, xx_doc}, {"count_sub", (PyCFunction)Vmap_count_sub, METH_VARARGS, xx_doc}, {"getheader", (PyCFunction)Vmap_getheader, METH_VARARGS, xx_doc}, {"setheader", (PyCFunction)Vmap_setheader, METH_VARARGS, xx_doc}, {"swapheader",(PyCFunction)Vmap_swapheader, METH_VARARGS, xx_doc}, {"raw_msync", (PyCFunction)Vmap_raw_msync, METH_VARARGS, xx_doc}, {"raw_madvise",(PyCFunction)Vmap_raw_madvise, METH_VARARGS, xx_doc}, {"raw_mlock", (PyCFunction)Vmap_raw_mlock, METH_VARARGS, xx_doc}, {"raw_munlock",(PyCFunction)Vmap_raw_munlock, METH_VARARGS, xx_doc}, {"raw_string",(PyCFunction)Vmap_raw_string, METH_VARARGS, xx_doc}, {"copyfrom", (PyCFunction)Vmap_copyfrom, METH_VARARGS, xx_doc}, {"times", (PyCFunction)Vmap_times, METH_VARARGS, xx_doc}, {"sort", (PyCFunction)Vmap_sort, METH_VARARGS, xx_doc}, {"open", (PyCFunction)Vmap_open, METH_VARARGS, xx_doc}, {"close", (PyCFunction)Vmap_close, METH_VARARGS, xx_doc}, {"astype", (PyCFunction)Vmap_type, METH_VARARGS, xx_doc}, {"getflag", (PyCFunction)Vmap_getflag, METH_VARARGS, xx_doc}, {"setflag", (PyCFunction)Vmap_setflag, METH_VARARGS, xx_doc}, {"clearflag", (PyCFunction)Vmap_clearflag, METH_VARARGS, xx_doc}, {"byteswap", (PyCFunction)Vmap_byteswap, METH_VARARGS, xx_doc}, //{"", (PyCFunction)Vmap_, METH_VARARGS, xx_doc}, {NULL, NULL} /* sentinel */ }; /* ------------------------------------------------------------------------- builtin */ static PyObject * Vmap_getattr(VmapObject *self, char *name) { PyObject *meth; /* speed */ meth = Py_FindMethod(self->f_meth, (PyObject *)self, name); if (meth != NULL) return meth; PyErr_Clear(); meth= Py_FindMethod(Vmap_methods, (PyObject *)self, name); if (meth != NULL) return meth; PyErr_Clear(); if (strcmp(name, "isopen") == 0) return PyInt_FromLong( (long) ( !((self->mm_data==NULL) || (self->mm_data==MAP_FAILED)) ) ); if (strcmp(name, "vm_flags") == 0) return PyInt_FromLong( (long) self->flags); if (strcmp(name, "vm_type") == 0) return PyInt_FromLong( (long) self->eltype); if (strcmp(name, "len") == 0) return PyInt_FromLong( (long) self->elsize); if (strcmp(name, "databytes") == 0) return PyInt_FromLong( (long) self->size); if (strcmp(name, "headerbytes") == 0) return PyInt_FromLong( (long) self->headsize); if (strcmp(name, "overheadbytes") == 0) return PyInt_FromLong( (long) sizeof(SharedHead) ); if (strcmp(name, "fileno") == 0) return PyInt_FromLong( (long) self->fd); if (strcmp(name, "size") == 0) return PyInt_FromLong( (long) self->mm_size); if (strcmp(name, "start") == 0) return PyInt_FromLong( (long) self->start); if (strcmp(name, "mm_flags") == 0) return PyInt_FromLong( (long) self->mm_flags); if (strcmp(name, "mm_prot") == 0) return PyInt_FromLong( (long) self->mm_prot); if (strcmp(name, "mm_advflags") == 0) return PyInt_FromLong( (long) self->mm_advflags); if (strcmp(name, "fillwith") == 0) return PyInt_FromLong( (long) self->fill); if (strcmp(name, "hlckspins") == 0) return PyInt_FromLong( (long) self->hspins); if (strcmp(name, "hlkyield") == 0) return PyInt_FromLong( (long) self->husec); if (strcmp(name, "__members__") == 0) { PyObject *list = PyList_New(14); if (list) { PyList_SetItem(list, 0, PyString_FromString("isopen")); PyList_SetItem(list, 1, PyString_FromString("vm_flags")); PyList_SetItem(list, 2, PyString_FromString("vm_type")); PyList_SetItem(list, 3, PyString_FromString("databytes")); PyList_SetItem(list, 4, PyString_FromString("headerbytes")); PyList_SetItem(list, 5, PyString_FromString("overheadbytes")); PyList_SetItem(list, 6, PyString_FromString("fileno")); PyList_SetItem(list, 7, PyString_FromString("size")); PyList_SetItem(list, 8, PyString_FromString("start")); PyList_SetItem(list, 9, PyString_FromString("mm_flags")); PyList_SetItem(list, 10, PyString_FromString("mm_prot")); PyList_SetItem(list, 11, PyString_FromString("mm_advflags")); PyList_SetItem(list, 12, PyString_FromString("hlckspins")); PyList_SetItem(list, 13, PyString_FromString("hlckyield")); if (PyErr_Occurred()) { Py_DECREF(list); list = NULL; } } return list; } return NULL; } /* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */ static int Vmap_setattr(VmapObject *self, char *name, PyObject *v) { int x=0; if (strcmp(name, "fillwith") == 0) { if (!PyArg_Parse(v, "i;Vmap wanted int", &x)) x=0; self->fill = x; } else if (strcmp(name, "mm_advflags") == 0) { if (!PyArg_Parse(v, "i;Vmap wanted int", &x)) x=0; self->mm_advflags= x; } else if (strcmp(name, "hlkyield") == 0) { if (!PyArg_Parse(v, "i;Vmap wanted int", &x)) x=0; self->husec= x; } else if (strcmp(name, "hlkspins") == 0) { if (!PyArg_Parse(v, "i;Vmap wanted int", &x)) x=0; self->hspins= x; } else if ( ((self->mm_data==NULL) || (self->mm_data==MAP_FAILED)) ) { if (strcmp(name, "mm_flags") == 0) { if (!PyArg_Parse(v, "i;Vmap wanted int", &x)) x=DFL_MM_FLAGS; self->mm_flags= x; } else if (strcmp(name, "mm_prot") == 0) { if (!PyArg_Parse(v, "i;Vmap wanted int", &x)) x=DFL_MM_PROT; self->mm_prot= x; } else if (strcmp(name, "start") == 0) { if (!PyArg_Parse(v, "i;Vmap wanted int", &x)) x=0; self->start= x; } else if (strcmp(name, "size") == 0) { if (!PyArg_Parse(v, "i;Vmap wanted int", &x)) x=0; self->mm_size= x; } else if (strcmp(name, "fileno") == 0) { if (!PyArg_Parse(v, "i;Vmap wanted int", &x)) x=-1; self->fd = x; } } /* it closed */ return 0; } /* ----------------------------------------------------------- SEQUENCE */ static int Vmap_length(VmapObject *self) { int r; CHECK_VALID(-1); r = self->elsize; vm_unmap(self); return r; } /* ------------------------------- */ static PyObject * Vmap_item(VmapObject *self, int i) { PyObject *r; CHECK_VALID(NULL); if (i < 0 || i >= self->elsize) { vm_unmap(self); PyErr_SetString(PyExc_IndexError, "Vmap index out of range"); return NULL; } r= self->f_item((PyObject *)self, i); if (self->flags & VM_KEEPTS) self->rts = vm_timestamp(); vm_unmap(self); return r; } static int Vmap_ass_item(VmapObject *self, int i, PyObject *v) { int r; CHECK_VALID(-1); if (i < 0 || i >= self->elsize) { PyErr_SetString(PyExc_IndexError, "Vmap index out of range"); vm_unmap(self); return -1; } r=(int) self->f_aitem((PyObject *)self, i, v); if (self->flags & VM_KEEPTS) self->rts = self->wts = vm_timestamp(); vm_unmap(self); return r; } /* ------------------------------- */ static PyObject * Vmap_slice(VmapObject *self, int ilow, int ihigh) { PyObject *r; CHECK_VALID(NULL); if (ilow <0) ilow=0; else if (ilow > self->elsize) ilow=self->elsize; if (ihigh self->elsize) ihigh=self->elsize; r= self->f_slice((PyObject *)self, ilow, ihigh); if (self->flags & VM_KEEPTS) self->rts = vm_timestamp(); vm_unmap(self); return r; } static int Vmap_ass_slice(VmapObject *self, int ilow, int ihigh, PyObject *v) { int r; CHECK_VALID(-1); if (ilow <0) ilow=0; else if (ilow > self->elsize) ilow=self->elsize; if (ihigh self->elsize) ihigh=self->elsize; r=(int) self->f_aslice((PyObject *)self, ilow, ihigh, v); if (self->flags & VM_KEEPTS) self->rts = self->wts = vm_timestamp(); vm_unmap(self); return r; } /* ------------------------------- */ static int Vmap_contains(VmapObject *self, PyObject *v) { /* 0 = does not contain, 1=does contain */ int (*sfunc)(PyObject *s ,PyObject *v ); int r; CHECK_VALID(-1); sfunc=(void*) self->f_search; if (sfunc == NULL) { vm_unmap(self); return -1; } r=(int) sfunc((PyObject *)self, v); if (self->flags & VM_KEEPTS) self->rts = vm_timestamp(); vm_unmap( self ); return (r != -1); } /* ------------------------------- */ static PyObject * Vmap_concat(VmapObject *self, PyObject *bb) { PyErr_SetString(PyExc_SystemError, "Vmaps don't support concatenation"); return NULL; } static PyObject * Vmap_inplace_concat(VmapObject *self, PyObject *bb) { // XXXX be nice to do push()? PyErr_SetString(PyExc_SystemError, "Vmaps don't support concatenation"); return NULL; } static PyObject * Vmap_repeat(VmapObject *self, int n) { PyErr_SetString(PyExc_SystemError, "Vmaps don't support repeating"); return NULL; } static PyObject * Vmap_inplace_repeat(VmapObject *self, int n) { PyErr_SetString(PyExc_SystemError, "Vmaps don't support repeating"); return NULL; } /* ------------------------------- */ static PySequenceMethods Vmap_as_sequence = { (inquiry)Vmap_length, /*sq_length*/ (binaryfunc)Vmap_concat, /*sq_concat*/ (intargfunc)Vmap_repeat, /*sq_repeat*/ (intargfunc)Vmap_item, /*sq_item*/ (intintargfunc)Vmap_slice, /*sq_slice*/ (intobjargproc)Vmap_ass_item, /*sq_ass_item*/ (intintobjargproc)Vmap_ass_slice, /*sq_ass_slice*/ (objobjproc)Vmap_contains, /* sq_contains */ (binaryfunc)Vmap_inplace_concat, /* sq_inplace_concat */ (intargfunc)Vmap_inplace_repeat, /* sq_inplace_repeat */ }; /* ----------------------------------------------------------- BUFFER */ /* XXXX these are prolly borked (might work in STAYOPEN) Functions for treating an mmap'ed file as a buffer */ static int Vmap_buffer_getreadbuf(VmapObject *self, int index, const void **ptr) { CHECK_VALID(-1); if ( index != 0 ) { PyErr_SetString(PyExc_SystemError,"Accessing non-existent Vmap segment"); return -1; } *ptr = self->data; return self->size; } static int Vmap_buffer_getwritebuf(VmapObject *self, int index, const void **ptr) { CHECK_VALID(-1); if ( index != 0 ) { PyErr_SetString(PyExc_SystemError, "Accessing non-existent Vmap segment"); return -1; } *ptr = self->data; return self->size; } static int Vmap_buffer_getsegcount(VmapObject *self, int *lenp) { CHECK_VALID(-1); if (lenp) *lenp = self->size; return 1; } static int Vmap_buffer_getcharbuffer(VmapObject *self, int index, const void **ptr) { CHECK_VALID(-1); if ( index != 0 ) { PyErr_SetString(PyExc_SystemError,"accessing non-existent buffer segment"); return -1; } *ptr = (const char *)self->data; return self->size; } /* ------------------------------- */ static PyBufferProcs Vmap_as_buffer = { (getreadbufferproc)Vmap_buffer_getreadbuf, (getwritebufferproc)Vmap_buffer_getwritebuf, (getsegcountproc)Vmap_buffer_getsegcount, (getcharbufferproc)Vmap_buffer_getcharbuffer, }; /* -------------------------------------------------------------------------- Object def */ static PyTypeObject Vmaptype = { PyObject_HEAD_INIT(&PyType_Type) 0, /*ob_size*/ "Vmap", /*tp_name*/ sizeof(VmapObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ /* methods */ (destructor)Vmap_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ (getattrfunc)Vmap_getattr, /*tp_getattr*/ (setattrfunc)Vmap_setattr, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ &Vmap_as_sequence, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash*/ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ &Vmap_as_buffer, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT, /*tp_flags*/ 0, /*tp_doc*/ 0, /*tp_traverse*/ 0, /*tp_clear*/ 0, /*tp_richcompare*/ 0, /*tp_weaklistoffset*/ 0, /*tp_iter*/ 0, /*tp_iternext*/ Vmap_methods, /*tp_methods*/ 0, /*tp_members*/ 0, /*tp_getset*/ 0, /*tp_base*/ 0, /*tp_dict*/ 0, /*tp_descr_get*/ 0, /*tp_descr_set*/ 0, /*tp_dictoffset*/ 0, /*tp_init*/ 0, /*tp_alloc*/ 0, /*tp_new*/ 0, /*tp_free*/ 0, /*tp_is_gc*/ }; /* ============================================================================================= MODULE ============================================================================================= */ /* I copied this whole from mmapmodule.c ------------------------------- extract the map size from the given PyObject The map size is restricted to [0, INT_MAX] because this is the current Python limitation on object sizes. Although the mmap object *could* handle a larger map size, there is no point because all the useful operations (len(), slicing(), sequence indexing) are limited by a C int. Returns -1 on error, with an appropriate Python exception raised. On success, the map size is returned. */ static int _GetMapSize(PyObject *o) { if (PyInt_Check(o)) { long i = PyInt_AsLong(o); if (PyErr_Occurred()) return -1; if (i < 0) goto onnegoverflow; if (i > INT_MAX) goto onposoverflow; return (int)i; } else if (PyLong_Check(o)) { long i = PyLong_AsLong(o); if (PyErr_Occurred()) { /* yes negative overflow is mistaken for positive overflow but not worth the trouble to check sign of 'i' */ if (PyErr_ExceptionMatches(PyExc_OverflowError)) goto onposoverflow; else return -1; } if (i < 0) goto onnegoverflow; if (i > INT_MAX) goto onposoverflow; return (int)i; } else { PyErr_SetString(PyExc_TypeError, "map size must be an integral value"); return -1; } onnegoverflow: PyErr_SetString(PyExc_OverflowError, "memory mapped size must be positive"); return -1; onposoverflow: PyErr_SetString(PyExc_OverflowError, "memory mapped size is too large (limited by C int)"); return -1; } /* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */ static PyObject * Vmaps_new(PyObject *self, PyObject *args, PyObject *kwdict) { VmapObject *map; PyObject *map_size_obj = NULL; PyObject *start_obj = PyInt_FromLong(0); int map_size, start; int fd, mm_flags = DFL_MM_FLAGS, prot = DFL_MM_PROT; int flags = DFL_VM_FLAGS; int otype=DFL_VM_TYPE, osize=1; char *keywords[] = {"fileno", "size", "start", "mm_flags", "mm_prot", "vm_flags", "vm_type", "elsize", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iO|Oiiiii", keywords, &fd, &map_size_obj, &start_obj, &mm_flags, &prot, &flags, &otype, &osize) ) return NULL; map_size = _GetMapSize(map_size_obj); if (map_size < 0) return NULL; start = _GetMapSize(start_obj); if (start < 0) start=0; /* could do more error checking */ map = PyObject_NEW(VmapObject, &Vmaptype); if ( map == NULL ) return NULL; map->flags = flags; /* mmap call */ map->mm_data=NULL; map->data = NULL; map->fd = fd; map->mm_flags = mm_flags; map->mm_prot = prot; map->mm_size = map->size = (size_t) map_size - start; map->start = (size_t) start; #ifdef MADV_NORMAL map->mm_advflags=MADV_NORMAL; #else map->mm_advflags=0; #endif /* data type */ Vmap_setype( map, otype, osize ); map->fill=0; /* timestamps */ map->rts = map->wts = map->sts = map->ots = map->cts = 0.0; /* locking */ map->hspins=32; map->husec=1; return (PyObject *)map; } /* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */ /* List of functions defined in the module */ static char xxmod_doc[] = "noneyet"; static PyMethodDef Vmaps_methods[] = { /* gcc complains but works? */ {"newmap", (PyCFunction) Vmaps_new, METH_VARARGS|METH_KEYWORDS, xxmod_doc}, {NULL, NULL} /* sentinel */ }; /* ======================================================================================== */ #define MDEXPORT( DCT, CVAL ) PyDict_SetItemString ( DCT , #CVAL , PyInt_FromLong( CVAL ) ) /* Initialization function for the module (*must* be called initVmaps) */ DL_EXPORT(void) initVmaps(void) { PyObject *m, *d; /* Initialize the type of the new type object here; doing it here * is required for portability to Windows without requiring C++. wh00 -ml */ Vmaptype.ob_type = &PyType_Type; /* Create the module and add the functions */ m = Py_InitModule("Vmaps", Vmaps_methods); /* Add some symbolic constants to the module */ d = PyModule_GetDict(m); ErrorObject = PyErr_NewException("Vmaps.error", NULL, NULL); PyDict_SetItemString(d, "error", ErrorObject); /* defaults */ MDEXPORT( d, DFL_MM_FLAGS ); MDEXPORT( d, DFL_MM_PROT ); MDEXPORT( d, DFL_VM_FLAGS ); MDEXPORT( d, DFL_VM_TYPE ); MDEXPORT( d, HEADALIGN ); /* VM_ flags */ MDEXPORT( d, VM_AUTOPEN ); MDEXPORT( d, VM_STAYOPEN ); MDEXPORT( d, VM_ADVOPEN ); MDEXPORT( d, VM_SYNCLOSE ); MDEXPORT( d, VM_ASYNCLOSE ); MDEXPORT( d, VM_KEEPTS ); MDEXPORT( d, VM_DOFILL ); MDEXPORT( d, VM_LLALE ); MDEXPORT( d, VM_LLASG ); MDEXPORT( d, VM_HEADER ); MDEXPORT( d, VM_HDRLOCK ); MDEXPORT( d, VM_HDRFAIL ); MDEXPORT( d, VM_HDRTYPE ); MDEXPORT( d, VM_HDRLEN ); /* TYPES */ PyDict_SetItemString (d, "Int", PyInt_FromLong(VMT_IA) ); PyDict_SetItemString (d, "Float", PyInt_FromLong(VMT_DA) ); PyDict_SetItemString (d, "Long", PyInt_FromLong(VMT_LL) ); PyDict_SetItemString (d, "Int2d", PyInt_FromLong(VMT_2IA) ); PyDict_SetItemString (d, "Long2d", PyInt_FromLong(VMT_2LA) ); PyDict_SetItemString (d, "Float2d", PyInt_FromLong(VMT_2FA) ); PyDict_SetItemString (d, "Char", PyInt_FromLong(VMT_RAW) ); PyDict_SetItemString (d, "FixChar", PyInt_FromLong(VMT_SA) ); PyDict_SetItemString (d, "FixLong", PyInt_FromLong(VMT_LLA) ); //PyDict_SetItemString (d, "", PyInt_FromLong(VMT_) ); PyDict_SetItemString (d, "PAGESIZE", PyInt_FromLong( (long)my_getpagesize() ) ); #ifdef PROT_EXEC MDEXPORT( d, PROT_EXEC ); #endif #ifdef PROT_READ MDEXPORT( d, PROT_READ ); #endif #ifdef PROT_WRITE MDEXPORT( d, PROT_WRITE ); #endif #ifdef MAP_SHARED MDEXPORT( d, MAP_SHARED ); #endif #ifdef MAP_PRIVATE MDEXPORT( d, MAP_PRIVATE ); #endif #ifdef MAP_ANON MDEXPORT( d, MAP_ANON ); #endif #ifdef MAP_NORESERVE MDEXPORT( d, MAP_NORESERVE ); #endif #ifdef MS_ASYNC MDEXPORT( d, MS_ASYNC ); #endif #ifdef MS_SYNC MDEXPORT( d, MS_SYNC ); #endif #ifdef MS_INVALIDATE MDEXPORT( d, MS_INVALIDATE ); #endif #ifdef MADV_NORMAL MDEXPORT( d, MADV_NORMAL ); #endif #ifdef MADV_RANDOM MDEXPORT( d, MADV_RANDOM ); #endif #ifdef MADV_SEQUENTIAL MDEXPORT( d, MADV_SEQUENTIAL ); #endif #ifdef MADV_WILLNEED MDEXPORT( d, MADV_WILLNEED ); #endif #ifdef MADV_DONTNEED MDEXPORT( d, MADV_DONTNEED ); #endif #ifdef MADV_FREE MDEXPORT( d, MADV_FREE ); #endif }