-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutil.pyx
105 lines (86 loc) · 3.21 KB
/
util.pyx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
cimport numpy
from libc.string cimport memcpy
import mmap
import numpy
cdef extern from "Python.h":
ctypedef Py_ssize_t (*readbufferproc)(object, Py_ssize_t, void **)
ctypedef Py_ssize_t (*writebufferproc)(object, Py_ssize_t, void **)
ctypedef struct PyBufferProcs:
readbufferproc bf_getreadbuffer
writebufferproc bf_getwritebuffer
ctypedef struct PyTypeObject:
PyBufferProcs * tp_as_buffer
# the "object[...] m" syntax means m supports the buffer protocol
# which gives efficient access to the underlying data.
# (see http://docs.python.org/c-api/buffer.html for the python side of things)
# (and http://wiki.cython.org/enhancements/buffer for the cython side)
def mmap_read_offsets(m, numpy.ndarray[numpy.int_t, ndim=1] begin, numpy.ndarray[numpy.int_t, ndim=1] end):
"""
res = mmap_read_offets(m, begin, end)
If m supports the buffer interface, then this function will return a
memory-mapped file containing the concatenation of the data byte sequences
m[begin[i]:end[i]] for all i in range.
Inputs:
* m: python object that implements the buffer interface
* begin: list of start offsets
* end: list of end offsets
Output:
* res: a memory-mapped file
"""
cdef int i
cdef int n = len(begin)
cdef int sz = numpy.sum(end - begin)
cdef PyTypeObject * m_t = <PyTypeObject*> m.__class__
cdef void * src_v
cdef PyBufferProcs * m_buf = <PyBufferProcs *> m_t.tp_as_buffer
cdef readbufferproc read_b = m_buf.bf_getreadbuffer
read_b(m, 0, & src_v)
cdef char * src = <char*> src_v
cdef res = mmap.mmap(-1, sz)
cdef PyTypeObject * res_t = <PyTypeObject*> res.__class__
cdef void * dst_v
cdef PyBufferProcs * res_buf = <PyBufferProcs *> res_t.tp_as_buffer
cdef writebufferproc write_b = m_buf.bf_getwritebuffer
write_b(res, 0, & dst_v)
cdef char * dst = <char*> dst_v
cdef size_t off = 0
cdef size_t i1
cdef size_t i2
cdef size_t k
cdef size_t j
for i in xrange(n):
i1 = begin[i]
i2 = end[i]
k = i2 - i1
memcpy(dst + off, src + i1, k)
off += k
return res
def has_old_buffer_interface(x):
"""
Python supports a so-called "Buffer Interface" that allows efficient
access to the C implementation of an object that is implemented in C and
implements the interface.
Furthermore as is often the case in Python there are 2 competing versions
of the buffer interface, the "old-style interface" and the "new-style"
interface. A python object can presumably implement either, none or both
of these.
This function returns True iff the argument supports the old-style buffer
interface.
"""
cdef PyTypeObject * t = <PyTypeObject*> x.__class__
cdef PyBufferProcs * buf = <PyBufferProcs *> t.tp_as_buffer
return buf != <PyBufferProcs*>0
def has_new_buffer_interface(x):
"""
Python supports a so-called "Buffer Interface" that allows efficient
access to the C implementation of an object that is implemented in C and
implements the interface.
Furthermore as is often the case in Python there are 2 competing versions
of the buffer interface, the "old-style interface" and the "new-style"
interface. A python object can presumably implement either, none or both
of these.
This function returns True iff the argument supports the new-style buffer
interface.
"""
cdef object[char] y
y = x