mirror of
https://github.com/python/cpython.git
synced 2025-10-19 16:03:42 +00:00
gh-116738: make mmap
module thread-safe (#139237)
This commit is contained in:
parent
e7e3d1d4a8
commit
7f155f9c46
5 changed files with 1568 additions and 207 deletions
315
Lib/test/test_free_threading/test_mmap.py
Normal file
315
Lib/test/test_free_threading/test_mmap.py
Normal file
|
@ -0,0 +1,315 @@
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from test.support import import_helper, threading_helper
|
||||||
|
from test.support.threading_helper import run_concurrently
|
||||||
|
|
||||||
|
import os
|
||||||
|
import string
|
||||||
|
import tempfile
|
||||||
|
import threading
|
||||||
|
|
||||||
|
from collections import Counter
|
||||||
|
|
||||||
|
mmap = import_helper.import_module("mmap")
|
||||||
|
|
||||||
|
NTHREADS = 10
|
||||||
|
ANONYMOUS_MEM = -1
|
||||||
|
|
||||||
|
|
||||||
|
@threading_helper.requires_working_threading()
|
||||||
|
class MmapTests(unittest.TestCase):
|
||||||
|
def test_read_and_read_byte(self):
|
||||||
|
ascii_uppercase = string.ascii_uppercase.encode()
|
||||||
|
# Choose a total mmap size that evenly divides across threads and the
|
||||||
|
# read pattern (3 bytes per loop).
|
||||||
|
mmap_size = 3 * NTHREADS * len(ascii_uppercase)
|
||||||
|
num_bytes_to_read_per_thread = mmap_size // NTHREADS
|
||||||
|
bytes_read_from_mmap = []
|
||||||
|
|
||||||
|
def read(mm_obj):
|
||||||
|
nread = 0
|
||||||
|
while nread < num_bytes_to_read_per_thread:
|
||||||
|
b = mm_obj.read_byte()
|
||||||
|
bytes_read_from_mmap.append(b)
|
||||||
|
b = mm_obj.read(2)
|
||||||
|
bytes_read_from_mmap.extend(b)
|
||||||
|
nread += 3
|
||||||
|
|
||||||
|
with mmap.mmap(ANONYMOUS_MEM, mmap_size) as mm_obj:
|
||||||
|
for i in range(mmap_size // len(ascii_uppercase)):
|
||||||
|
mm_obj.write(ascii_uppercase)
|
||||||
|
|
||||||
|
mm_obj.seek(0)
|
||||||
|
run_concurrently(
|
||||||
|
worker_func=read,
|
||||||
|
args=(mm_obj,),
|
||||||
|
nthreads=NTHREADS,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(len(bytes_read_from_mmap), mmap_size)
|
||||||
|
# Count each letter/byte to verify read correctness
|
||||||
|
counter = Counter(bytes_read_from_mmap)
|
||||||
|
self.assertEqual(len(counter), len(ascii_uppercase))
|
||||||
|
# Each letter/byte should be read (3 * NTHREADS) times
|
||||||
|
for letter in ascii_uppercase:
|
||||||
|
self.assertEqual(counter[letter], 3 * NTHREADS)
|
||||||
|
|
||||||
|
def test_readline(self):
|
||||||
|
num_lines = 1000
|
||||||
|
lines_read_from_mmap = []
|
||||||
|
expected_lines = []
|
||||||
|
|
||||||
|
def readline(mm_obj):
|
||||||
|
for i in range(num_lines // NTHREADS):
|
||||||
|
line = mm_obj.readline()
|
||||||
|
lines_read_from_mmap.append(line)
|
||||||
|
|
||||||
|
# Allocate mmap enough for num_lines (max line 5 bytes including NL)
|
||||||
|
with mmap.mmap(ANONYMOUS_MEM, num_lines * 5) as mm_obj:
|
||||||
|
for i in range(num_lines):
|
||||||
|
line = b"%d\n" % i
|
||||||
|
mm_obj.write(line)
|
||||||
|
expected_lines.append(line)
|
||||||
|
|
||||||
|
mm_obj.seek(0)
|
||||||
|
run_concurrently(
|
||||||
|
worker_func=readline,
|
||||||
|
args=(mm_obj,),
|
||||||
|
nthreads=NTHREADS,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(len(lines_read_from_mmap), num_lines)
|
||||||
|
# Every line should be read once by threads; order is non-deterministic
|
||||||
|
# Sort numerically by integer value
|
||||||
|
lines_read_from_mmap.sort(key=lambda x: int(x))
|
||||||
|
self.assertEqual(lines_read_from_mmap, expected_lines)
|
||||||
|
|
||||||
|
def test_write_and_write_byte(self):
|
||||||
|
thread_letters = list(string.ascii_uppercase)
|
||||||
|
self.assertLessEqual(NTHREADS, len(thread_letters))
|
||||||
|
per_thread_write_loop = 100
|
||||||
|
|
||||||
|
def write(mm_obj):
|
||||||
|
# Each thread picks a unique letter to write
|
||||||
|
thread_letter = thread_letters.pop(0)
|
||||||
|
thread_bytes = (thread_letter * 2).encode()
|
||||||
|
for _ in range(per_thread_write_loop):
|
||||||
|
mm_obj.write_byte(thread_bytes[0])
|
||||||
|
mm_obj.write(thread_bytes)
|
||||||
|
|
||||||
|
with mmap.mmap(
|
||||||
|
ANONYMOUS_MEM, per_thread_write_loop * 3 * NTHREADS
|
||||||
|
) as mm_obj:
|
||||||
|
run_concurrently(
|
||||||
|
worker_func=write,
|
||||||
|
args=(mm_obj,),
|
||||||
|
nthreads=NTHREADS,
|
||||||
|
)
|
||||||
|
mm_obj.seek(0)
|
||||||
|
data = mm_obj.read()
|
||||||
|
self.assertEqual(len(data), NTHREADS * per_thread_write_loop * 3)
|
||||||
|
counter = Counter(data)
|
||||||
|
self.assertEqual(len(counter), NTHREADS)
|
||||||
|
# Each thread letter should be written `per_thread_write_loop` * 3
|
||||||
|
for letter in counter:
|
||||||
|
self.assertEqual(counter[letter], per_thread_write_loop * 3)
|
||||||
|
|
||||||
|
def test_move(self):
|
||||||
|
ascii_uppercase = string.ascii_uppercase.encode()
|
||||||
|
num_letters = len(ascii_uppercase)
|
||||||
|
|
||||||
|
def move(mm_obj):
|
||||||
|
for i in range(num_letters):
|
||||||
|
# Move 1 byte from the first half to the second half
|
||||||
|
mm_obj.move(0 + i, num_letters + i, 1)
|
||||||
|
|
||||||
|
with mmap.mmap(ANONYMOUS_MEM, 2 * num_letters) as mm_obj:
|
||||||
|
mm_obj.write(ascii_uppercase)
|
||||||
|
run_concurrently(
|
||||||
|
worker_func=move,
|
||||||
|
args=(mm_obj,),
|
||||||
|
nthreads=NTHREADS,
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_seek_and_tell(self):
|
||||||
|
seek_per_thread = 10
|
||||||
|
|
||||||
|
def seek(mm_obj):
|
||||||
|
self.assertTrue(mm_obj.seekable())
|
||||||
|
for _ in range(seek_per_thread):
|
||||||
|
before_seek = mm_obj.tell()
|
||||||
|
mm_obj.seek(1, os.SEEK_CUR)
|
||||||
|
self.assertLess(before_seek, mm_obj.tell())
|
||||||
|
|
||||||
|
with mmap.mmap(ANONYMOUS_MEM, 1024) as mm_obj:
|
||||||
|
run_concurrently(
|
||||||
|
worker_func=seek,
|
||||||
|
args=(mm_obj,),
|
||||||
|
nthreads=NTHREADS,
|
||||||
|
)
|
||||||
|
# Each thread seeks from current position, the end position should
|
||||||
|
# be the sum of all seeks from all threads.
|
||||||
|
self.assertEqual(mm_obj.tell(), NTHREADS * seek_per_thread)
|
||||||
|
|
||||||
|
def test_slice_update_and_slice_read(self):
|
||||||
|
thread_letters = list(string.ascii_uppercase)
|
||||||
|
self.assertLessEqual(NTHREADS, len(thread_letters))
|
||||||
|
|
||||||
|
def slice_update_and_slice_read(mm_obj):
|
||||||
|
# Each thread picks a unique letter to write
|
||||||
|
thread_letter = thread_letters.pop(0)
|
||||||
|
thread_bytes = (thread_letter * 1024).encode()
|
||||||
|
for _ in range(100):
|
||||||
|
mm_obj[:] = thread_bytes
|
||||||
|
read_bytes = mm_obj[:]
|
||||||
|
# Read bytes should be all the same letter, showing no
|
||||||
|
# interleaving
|
||||||
|
self.assertTrue(all_same(read_bytes))
|
||||||
|
|
||||||
|
with mmap.mmap(ANONYMOUS_MEM, 1024) as mm_obj:
|
||||||
|
run_concurrently(
|
||||||
|
worker_func=slice_update_and_slice_read,
|
||||||
|
args=(mm_obj,),
|
||||||
|
nthreads=NTHREADS,
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_item_update_and_item_read(self):
|
||||||
|
thread_indexes = [i for i in range(NTHREADS)]
|
||||||
|
|
||||||
|
def item_update_and_item_read(mm_obj):
|
||||||
|
# Each thread picks a unique index to write
|
||||||
|
thread_index = thread_indexes.pop()
|
||||||
|
for i in range(100):
|
||||||
|
mm_obj[thread_index] = i
|
||||||
|
self.assertEqual(mm_obj[thread_index], i)
|
||||||
|
|
||||||
|
# Read values set by other threads, all values
|
||||||
|
# should be less than '100'
|
||||||
|
for val in mm_obj:
|
||||||
|
self.assertLess(int.from_bytes(val), 100)
|
||||||
|
|
||||||
|
with mmap.mmap(ANONYMOUS_MEM, NTHREADS + 1) as mm_obj:
|
||||||
|
run_concurrently(
|
||||||
|
worker_func=item_update_and_item_read,
|
||||||
|
args=(mm_obj,),
|
||||||
|
nthreads=NTHREADS,
|
||||||
|
)
|
||||||
|
|
||||||
|
@unittest.skipUnless(os.name == "posix", "requires Posix")
|
||||||
|
@unittest.skipUnless(hasattr(mmap.mmap, "resize"), "requires mmap.resize")
|
||||||
|
def test_resize_and_size(self):
|
||||||
|
thread_indexes = [i for i in range(NTHREADS)]
|
||||||
|
|
||||||
|
def resize_and_item_update(mm_obj):
|
||||||
|
# Each thread picks a unique index to write
|
||||||
|
thread_index = thread_indexes.pop()
|
||||||
|
mm_obj.resize(2048)
|
||||||
|
self.assertEqual(mm_obj.size(), 2048)
|
||||||
|
for i in range(100):
|
||||||
|
mm_obj[thread_index] = i
|
||||||
|
self.assertEqual(mm_obj[thread_index], i)
|
||||||
|
|
||||||
|
with mmap.mmap(ANONYMOUS_MEM, 1024, flags=mmap.MAP_PRIVATE) as mm_obj:
|
||||||
|
run_concurrently(
|
||||||
|
worker_func=resize_and_item_update,
|
||||||
|
args=(mm_obj,),
|
||||||
|
nthreads=NTHREADS,
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_close_and_closed(self):
|
||||||
|
def close_mmap(mm_obj):
|
||||||
|
mm_obj.close()
|
||||||
|
self.assertTrue(mm_obj.closed)
|
||||||
|
|
||||||
|
with mmap.mmap(ANONYMOUS_MEM, 1) as mm_obj:
|
||||||
|
run_concurrently(
|
||||||
|
worker_func=close_mmap,
|
||||||
|
args=(mm_obj,),
|
||||||
|
nthreads=NTHREADS,
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_find_and_rfind(self):
|
||||||
|
per_thread_loop = 10
|
||||||
|
|
||||||
|
def find_and_rfind(mm_obj):
|
||||||
|
pattern = b'Thread-Ident:"%d"' % threading.get_ident()
|
||||||
|
mm_obj.write(pattern)
|
||||||
|
for _ in range(per_thread_loop):
|
||||||
|
found_at = mm_obj.find(pattern, 0)
|
||||||
|
self.assertNotEqual(found_at, -1)
|
||||||
|
# Should not find it after the `found_at`
|
||||||
|
self.assertEqual(mm_obj.find(pattern, found_at + 1), -1)
|
||||||
|
found_at_rev = mm_obj.rfind(pattern, 0)
|
||||||
|
self.assertEqual(found_at, found_at_rev)
|
||||||
|
# Should not find it after the `found_at`
|
||||||
|
self.assertEqual(mm_obj.rfind(pattern, found_at + 1), -1)
|
||||||
|
|
||||||
|
with mmap.mmap(ANONYMOUS_MEM, 1024) as mm_obj:
|
||||||
|
run_concurrently(
|
||||||
|
worker_func=find_and_rfind,
|
||||||
|
args=(mm_obj,),
|
||||||
|
nthreads=NTHREADS,
|
||||||
|
)
|
||||||
|
|
||||||
|
@unittest.skipUnless(os.name == "posix", "requires Posix")
|
||||||
|
@unittest.skipUnless(hasattr(mmap.mmap, "resize"), "requires mmap.resize")
|
||||||
|
def test_flush(self):
|
||||||
|
mmap_filename = "test_mmap_file"
|
||||||
|
resize_to = 1024
|
||||||
|
|
||||||
|
def resize_and_flush(mm_obj):
|
||||||
|
mm_obj.resize(resize_to)
|
||||||
|
mm_obj.flush()
|
||||||
|
|
||||||
|
with tempfile.TemporaryDirectory() as tmpdirname:
|
||||||
|
file_path = f"{tmpdirname}/{mmap_filename}"
|
||||||
|
with open(file_path, "wb+") as file:
|
||||||
|
file.write(b"CPython")
|
||||||
|
file.flush()
|
||||||
|
with mmap.mmap(file.fileno(), 1) as mm_obj:
|
||||||
|
run_concurrently(
|
||||||
|
worker_func=resize_and_flush,
|
||||||
|
args=(mm_obj,),
|
||||||
|
nthreads=NTHREADS,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(os.path.getsize(file_path), resize_to)
|
||||||
|
|
||||||
|
def test_mmap_export_as_memoryview(self):
|
||||||
|
"""
|
||||||
|
Each thread creates a memoryview and updates the internal state of the
|
||||||
|
mmap object.
|
||||||
|
"""
|
||||||
|
buffer_size = 42
|
||||||
|
|
||||||
|
def create_memoryview_from_mmap(mm_obj):
|
||||||
|
memoryviews = []
|
||||||
|
for _ in range(100):
|
||||||
|
mv = memoryview(mm_obj)
|
||||||
|
memoryviews.append(mv)
|
||||||
|
self.assertEqual(len(mv), buffer_size)
|
||||||
|
self.assertEqual(mv[:7], b"CPython")
|
||||||
|
|
||||||
|
# Cannot close the mmap while it is exported as buffers
|
||||||
|
with self.assertRaisesRegex(
|
||||||
|
BufferError, "cannot close exported pointers exist"
|
||||||
|
):
|
||||||
|
mm_obj.close()
|
||||||
|
|
||||||
|
with mmap.mmap(ANONYMOUS_MEM, 42) as mm_obj:
|
||||||
|
mm_obj.write(b"CPython")
|
||||||
|
run_concurrently(
|
||||||
|
worker_func=create_memoryview_from_mmap,
|
||||||
|
args=(mm_obj,),
|
||||||
|
nthreads=NTHREADS,
|
||||||
|
)
|
||||||
|
# Implicit mm_obj.close() verifies all exports (memoryviews) are
|
||||||
|
# properly freed.
|
||||||
|
|
||||||
|
|
||||||
|
def all_same(lst):
|
||||||
|
return all(item == lst[0] for item in lst)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
|
@ -871,6 +871,10 @@ def test_madvise(self):
|
||||||
size = 2 * PAGESIZE
|
size = 2 * PAGESIZE
|
||||||
m = mmap.mmap(-1, size)
|
m = mmap.mmap(-1, size)
|
||||||
|
|
||||||
|
class Number:
|
||||||
|
def __index__(self):
|
||||||
|
return 2
|
||||||
|
|
||||||
with self.assertRaisesRegex(ValueError, "madvise start out of bounds"):
|
with self.assertRaisesRegex(ValueError, "madvise start out of bounds"):
|
||||||
m.madvise(mmap.MADV_NORMAL, size)
|
m.madvise(mmap.MADV_NORMAL, size)
|
||||||
with self.assertRaisesRegex(ValueError, "madvise start out of bounds"):
|
with self.assertRaisesRegex(ValueError, "madvise start out of bounds"):
|
||||||
|
@ -879,10 +883,14 @@ def test_madvise(self):
|
||||||
m.madvise(mmap.MADV_NORMAL, 0, -1)
|
m.madvise(mmap.MADV_NORMAL, 0, -1)
|
||||||
with self.assertRaisesRegex(OverflowError, "madvise length too large"):
|
with self.assertRaisesRegex(OverflowError, "madvise length too large"):
|
||||||
m.madvise(mmap.MADV_NORMAL, PAGESIZE, sys.maxsize)
|
m.madvise(mmap.MADV_NORMAL, PAGESIZE, sys.maxsize)
|
||||||
|
with self.assertRaisesRegex(
|
||||||
|
TypeError, "'str' object cannot be interpreted as an integer"):
|
||||||
|
m.madvise(mmap.MADV_NORMAL, PAGESIZE, "Not a Number")
|
||||||
self.assertEqual(m.madvise(mmap.MADV_NORMAL), None)
|
self.assertEqual(m.madvise(mmap.MADV_NORMAL), None)
|
||||||
self.assertEqual(m.madvise(mmap.MADV_NORMAL, PAGESIZE), None)
|
self.assertEqual(m.madvise(mmap.MADV_NORMAL, PAGESIZE), None)
|
||||||
self.assertEqual(m.madvise(mmap.MADV_NORMAL, PAGESIZE, size), None)
|
self.assertEqual(m.madvise(mmap.MADV_NORMAL, PAGESIZE, size), None)
|
||||||
self.assertEqual(m.madvise(mmap.MADV_NORMAL, 0, 2), None)
|
self.assertEqual(m.madvise(mmap.MADV_NORMAL, 0, 2), None)
|
||||||
|
self.assertEqual(m.madvise(mmap.MADV_NORMAL, 0, Number()), None)
|
||||||
self.assertEqual(m.madvise(mmap.MADV_NORMAL, 0, size), None)
|
self.assertEqual(m.madvise(mmap.MADV_NORMAL, 0, size), None)
|
||||||
|
|
||||||
@unittest.skipUnless(hasattr(mmap.mmap, 'resize'), 'requires mmap.resize')
|
@unittest.skipUnless(hasattr(mmap.mmap, 'resize'), 'requires mmap.resize')
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Make :mod:`mmap` thread-safe on the :term:`free threaded <free threading>`
|
||||||
|
build.
|
799
Modules/clinic/mmapmodule.c.h
generated
Normal file
799
Modules/clinic/mmapmodule.c.h
generated
Normal file
|
@ -0,0 +1,799 @@
|
||||||
|
/*[clinic input]
|
||||||
|
preserve
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
|
#include "pycore_abstract.h" // _PyNumber_Index()
|
||||||
|
#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION()
|
||||||
|
#include "pycore_modsupport.h" // _PyArg_CheckPositional()
|
||||||
|
|
||||||
|
PyDoc_STRVAR(mmap_mmap_close__doc__,
|
||||||
|
"close($self, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
#define MMAP_MMAP_CLOSE_METHODDEF \
|
||||||
|
{"close", (PyCFunction)mmap_mmap_close, METH_NOARGS, mmap_mmap_close__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap_close_impl(mmap_object *self);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap_close(PyObject *self, PyObject *Py_UNUSED(ignored))
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(self);
|
||||||
|
return_value = mmap_mmap_close_impl((mmap_object *)self);
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
|
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(mmap_mmap_read_byte__doc__,
|
||||||
|
"read_byte($self, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
#define MMAP_MMAP_READ_BYTE_METHODDEF \
|
||||||
|
{"read_byte", (PyCFunction)mmap_mmap_read_byte, METH_NOARGS, mmap_mmap_read_byte__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap_read_byte_impl(mmap_object *self);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap_read_byte(PyObject *self, PyObject *Py_UNUSED(ignored))
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(self);
|
||||||
|
return_value = mmap_mmap_read_byte_impl((mmap_object *)self);
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
|
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(mmap_mmap_readline__doc__,
|
||||||
|
"readline($self, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
#define MMAP_MMAP_READLINE_METHODDEF \
|
||||||
|
{"readline", (PyCFunction)mmap_mmap_readline, METH_NOARGS, mmap_mmap_readline__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap_readline_impl(mmap_object *self);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap_readline(PyObject *self, PyObject *Py_UNUSED(ignored))
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(self);
|
||||||
|
return_value = mmap_mmap_readline_impl((mmap_object *)self);
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
|
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(mmap_mmap_read__doc__,
|
||||||
|
"read($self, n=None, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
#define MMAP_MMAP_READ_METHODDEF \
|
||||||
|
{"read", _PyCFunction_CAST(mmap_mmap_read), METH_FASTCALL, mmap_mmap_read__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap_read_impl(mmap_object *self, Py_ssize_t num_bytes);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap_read(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
Py_ssize_t num_bytes = PY_SSIZE_T_MAX;
|
||||||
|
|
||||||
|
if (!_PyArg_CheckPositional("read", nargs, 0, 1)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (nargs < 1) {
|
||||||
|
goto skip_optional;
|
||||||
|
}
|
||||||
|
if (!_Py_convert_optional_to_ssize_t(args[0], &num_bytes)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
skip_optional:
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(self);
|
||||||
|
return_value = mmap_mmap_read_impl((mmap_object *)self, num_bytes);
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(mmap_mmap_find__doc__,
|
||||||
|
"find($self, view, start=None, end=None, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
#define MMAP_MMAP_FIND_METHODDEF \
|
||||||
|
{"find", _PyCFunction_CAST(mmap_mmap_find), METH_FASTCALL, mmap_mmap_find__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap_find_impl(mmap_object *self, Py_buffer *view, PyObject *start,
|
||||||
|
PyObject *end);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap_find(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
Py_buffer view = {NULL, NULL};
|
||||||
|
PyObject *start = Py_None;
|
||||||
|
PyObject *end = Py_None;
|
||||||
|
|
||||||
|
if (!_PyArg_CheckPositional("find", nargs, 1, 3)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (PyObject_GetBuffer(args[0], &view, PyBUF_SIMPLE) != 0) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (nargs < 2) {
|
||||||
|
goto skip_optional;
|
||||||
|
}
|
||||||
|
start = args[1];
|
||||||
|
if (nargs < 3) {
|
||||||
|
goto skip_optional;
|
||||||
|
}
|
||||||
|
end = args[2];
|
||||||
|
skip_optional:
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(self);
|
||||||
|
return_value = mmap_mmap_find_impl((mmap_object *)self, &view, start, end);
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
|
|
||||||
|
exit:
|
||||||
|
/* Cleanup for view */
|
||||||
|
if (view.obj) {
|
||||||
|
PyBuffer_Release(&view);
|
||||||
|
}
|
||||||
|
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(mmap_mmap_rfind__doc__,
|
||||||
|
"rfind($self, view, start=None, end=None, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
#define MMAP_MMAP_RFIND_METHODDEF \
|
||||||
|
{"rfind", _PyCFunction_CAST(mmap_mmap_rfind), METH_FASTCALL, mmap_mmap_rfind__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap_rfind_impl(mmap_object *self, Py_buffer *view, PyObject *start,
|
||||||
|
PyObject *end);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap_rfind(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
Py_buffer view = {NULL, NULL};
|
||||||
|
PyObject *start = Py_None;
|
||||||
|
PyObject *end = Py_None;
|
||||||
|
|
||||||
|
if (!_PyArg_CheckPositional("rfind", nargs, 1, 3)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (PyObject_GetBuffer(args[0], &view, PyBUF_SIMPLE) != 0) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (nargs < 2) {
|
||||||
|
goto skip_optional;
|
||||||
|
}
|
||||||
|
start = args[1];
|
||||||
|
if (nargs < 3) {
|
||||||
|
goto skip_optional;
|
||||||
|
}
|
||||||
|
end = args[2];
|
||||||
|
skip_optional:
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(self);
|
||||||
|
return_value = mmap_mmap_rfind_impl((mmap_object *)self, &view, start, end);
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
|
|
||||||
|
exit:
|
||||||
|
/* Cleanup for view */
|
||||||
|
if (view.obj) {
|
||||||
|
PyBuffer_Release(&view);
|
||||||
|
}
|
||||||
|
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(mmap_mmap_write__doc__,
|
||||||
|
"write($self, bytes, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
#define MMAP_MMAP_WRITE_METHODDEF \
|
||||||
|
{"write", (PyCFunction)mmap_mmap_write, METH_O, mmap_mmap_write__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap_write_impl(mmap_object *self, Py_buffer *data);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap_write(PyObject *self, PyObject *arg)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
Py_buffer data = {NULL, NULL};
|
||||||
|
|
||||||
|
if (PyObject_GetBuffer(arg, &data, PyBUF_SIMPLE) != 0) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(self);
|
||||||
|
return_value = mmap_mmap_write_impl((mmap_object *)self, &data);
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
|
|
||||||
|
exit:
|
||||||
|
/* Cleanup for data */
|
||||||
|
if (data.obj) {
|
||||||
|
PyBuffer_Release(&data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(mmap_mmap_write_byte__doc__,
|
||||||
|
"write_byte($self, byte, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
#define MMAP_MMAP_WRITE_BYTE_METHODDEF \
|
||||||
|
{"write_byte", (PyCFunction)mmap_mmap_write_byte, METH_O, mmap_mmap_write_byte__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap_write_byte_impl(mmap_object *self, unsigned char value);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap_write_byte(PyObject *self, PyObject *arg)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
unsigned char value;
|
||||||
|
|
||||||
|
{
|
||||||
|
long ival = PyLong_AsLong(arg);
|
||||||
|
if (ival == -1 && PyErr_Occurred()) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
else if (ival < 0) {
|
||||||
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
|
"unsigned byte integer is less than minimum");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
else if (ival > UCHAR_MAX) {
|
||||||
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
|
"unsigned byte integer is greater than maximum");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
value = (unsigned char) ival;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(self);
|
||||||
|
return_value = mmap_mmap_write_byte_impl((mmap_object *)self, value);
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(mmap_mmap_size__doc__,
|
||||||
|
"size($self, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
#define MMAP_MMAP_SIZE_METHODDEF \
|
||||||
|
{"size", (PyCFunction)mmap_mmap_size, METH_NOARGS, mmap_mmap_size__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap_size_impl(mmap_object *self);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap_size(PyObject *self, PyObject *Py_UNUSED(ignored))
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(self);
|
||||||
|
return_value = mmap_mmap_size_impl((mmap_object *)self);
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
|
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (defined(MS_WINDOWS) || defined(HAVE_MREMAP))
|
||||||
|
|
||||||
|
PyDoc_STRVAR(mmap_mmap_resize__doc__,
|
||||||
|
"resize($self, newsize, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
#define MMAP_MMAP_RESIZE_METHODDEF \
|
||||||
|
{"resize", (PyCFunction)mmap_mmap_resize, METH_O, mmap_mmap_resize__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap_resize_impl(mmap_object *self, Py_ssize_t new_size);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap_resize(PyObject *self, PyObject *arg)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
Py_ssize_t new_size;
|
||||||
|
|
||||||
|
{
|
||||||
|
Py_ssize_t ival = -1;
|
||||||
|
PyObject *iobj = _PyNumber_Index(arg);
|
||||||
|
if (iobj != NULL) {
|
||||||
|
ival = PyLong_AsSsize_t(iobj);
|
||||||
|
Py_DECREF(iobj);
|
||||||
|
}
|
||||||
|
if (ival == -1 && PyErr_Occurred()) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
new_size = ival;
|
||||||
|
}
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(self);
|
||||||
|
return_value = mmap_mmap_resize_impl((mmap_object *)self, new_size);
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* (defined(MS_WINDOWS) || defined(HAVE_MREMAP)) */
|
||||||
|
|
||||||
|
PyDoc_STRVAR(mmap_mmap_tell__doc__,
|
||||||
|
"tell($self, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
#define MMAP_MMAP_TELL_METHODDEF \
|
||||||
|
{"tell", (PyCFunction)mmap_mmap_tell, METH_NOARGS, mmap_mmap_tell__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap_tell_impl(mmap_object *self);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap_tell(PyObject *self, PyObject *Py_UNUSED(ignored))
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(self);
|
||||||
|
return_value = mmap_mmap_tell_impl((mmap_object *)self);
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
|
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(mmap_mmap_flush__doc__,
|
||||||
|
"flush($self, offset=0, size=-1, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
#define MMAP_MMAP_FLUSH_METHODDEF \
|
||||||
|
{"flush", _PyCFunction_CAST(mmap_mmap_flush), METH_FASTCALL, mmap_mmap_flush__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap_flush_impl(mmap_object *self, Py_ssize_t offset, Py_ssize_t size);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap_flush(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
Py_ssize_t offset = 0;
|
||||||
|
Py_ssize_t size = -1;
|
||||||
|
|
||||||
|
if (!_PyArg_CheckPositional("flush", nargs, 0, 2)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (nargs < 1) {
|
||||||
|
goto skip_optional;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Py_ssize_t ival = -1;
|
||||||
|
PyObject *iobj = _PyNumber_Index(args[0]);
|
||||||
|
if (iobj != NULL) {
|
||||||
|
ival = PyLong_AsSsize_t(iobj);
|
||||||
|
Py_DECREF(iobj);
|
||||||
|
}
|
||||||
|
if (ival == -1 && PyErr_Occurred()) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
offset = ival;
|
||||||
|
}
|
||||||
|
if (nargs < 2) {
|
||||||
|
goto skip_optional;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Py_ssize_t ival = -1;
|
||||||
|
PyObject *iobj = _PyNumber_Index(args[1]);
|
||||||
|
if (iobj != NULL) {
|
||||||
|
ival = PyLong_AsSsize_t(iobj);
|
||||||
|
Py_DECREF(iobj);
|
||||||
|
}
|
||||||
|
if (ival == -1 && PyErr_Occurred()) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
size = ival;
|
||||||
|
}
|
||||||
|
skip_optional:
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(self);
|
||||||
|
return_value = mmap_mmap_flush_impl((mmap_object *)self, offset, size);
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(mmap_mmap_seek__doc__,
|
||||||
|
"seek($self, pos, whence=0, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
#define MMAP_MMAP_SEEK_METHODDEF \
|
||||||
|
{"seek", _PyCFunction_CAST(mmap_mmap_seek), METH_FASTCALL, mmap_mmap_seek__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap_seek_impl(mmap_object *self, Py_ssize_t dist, int how);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap_seek(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
Py_ssize_t dist;
|
||||||
|
int how = 0;
|
||||||
|
|
||||||
|
if (!_PyArg_CheckPositional("seek", nargs, 1, 2)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Py_ssize_t ival = -1;
|
||||||
|
PyObject *iobj = _PyNumber_Index(args[0]);
|
||||||
|
if (iobj != NULL) {
|
||||||
|
ival = PyLong_AsSsize_t(iobj);
|
||||||
|
Py_DECREF(iobj);
|
||||||
|
}
|
||||||
|
if (ival == -1 && PyErr_Occurred()) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
dist = ival;
|
||||||
|
}
|
||||||
|
if (nargs < 2) {
|
||||||
|
goto skip_optional;
|
||||||
|
}
|
||||||
|
how = PyLong_AsInt(args[1]);
|
||||||
|
if (how == -1 && PyErr_Occurred()) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
skip_optional:
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(self);
|
||||||
|
return_value = mmap_mmap_seek_impl((mmap_object *)self, dist, how);
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(mmap_mmap_seekable__doc__,
|
||||||
|
"seekable($self, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
#define MMAP_MMAP_SEEKABLE_METHODDEF \
|
||||||
|
{"seekable", (PyCFunction)mmap_mmap_seekable, METH_NOARGS, mmap_mmap_seekable__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap_seekable_impl(mmap_object *self);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap_seekable(PyObject *self, PyObject *Py_UNUSED(ignored))
|
||||||
|
{
|
||||||
|
return mmap_mmap_seekable_impl((mmap_object *)self);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(mmap_mmap_move__doc__,
|
||||||
|
"move($self, dest, src, count, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
#define MMAP_MMAP_MOVE_METHODDEF \
|
||||||
|
{"move", _PyCFunction_CAST(mmap_mmap_move), METH_FASTCALL, mmap_mmap_move__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap_move_impl(mmap_object *self, Py_ssize_t dest, Py_ssize_t src,
|
||||||
|
Py_ssize_t cnt);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap_move(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
Py_ssize_t dest;
|
||||||
|
Py_ssize_t src;
|
||||||
|
Py_ssize_t cnt;
|
||||||
|
|
||||||
|
if (!_PyArg_CheckPositional("move", nargs, 3, 3)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Py_ssize_t ival = -1;
|
||||||
|
PyObject *iobj = _PyNumber_Index(args[0]);
|
||||||
|
if (iobj != NULL) {
|
||||||
|
ival = PyLong_AsSsize_t(iobj);
|
||||||
|
Py_DECREF(iobj);
|
||||||
|
}
|
||||||
|
if (ival == -1 && PyErr_Occurred()) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
dest = ival;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Py_ssize_t ival = -1;
|
||||||
|
PyObject *iobj = _PyNumber_Index(args[1]);
|
||||||
|
if (iobj != NULL) {
|
||||||
|
ival = PyLong_AsSsize_t(iobj);
|
||||||
|
Py_DECREF(iobj);
|
||||||
|
}
|
||||||
|
if (ival == -1 && PyErr_Occurred()) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
src = ival;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Py_ssize_t ival = -1;
|
||||||
|
PyObject *iobj = _PyNumber_Index(args[2]);
|
||||||
|
if (iobj != NULL) {
|
||||||
|
ival = PyLong_AsSsize_t(iobj);
|
||||||
|
Py_DECREF(iobj);
|
||||||
|
}
|
||||||
|
if (ival == -1 && PyErr_Occurred()) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
cnt = ival;
|
||||||
|
}
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(self);
|
||||||
|
return_value = mmap_mmap_move_impl((mmap_object *)self, dest, src, cnt);
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(mmap_mmap___enter____doc__,
|
||||||
|
"__enter__($self, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
#define MMAP_MMAP___ENTER___METHODDEF \
|
||||||
|
{"__enter__", (PyCFunction)mmap_mmap___enter__, METH_NOARGS, mmap_mmap___enter____doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap___enter___impl(mmap_object *self);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap___enter__(PyObject *self, PyObject *Py_UNUSED(ignored))
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(self);
|
||||||
|
return_value = mmap_mmap___enter___impl((mmap_object *)self);
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
|
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(mmap_mmap___exit____doc__,
|
||||||
|
"__exit__($self, exc_type, exc_value, traceback, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
#define MMAP_MMAP___EXIT___METHODDEF \
|
||||||
|
{"__exit__", _PyCFunction_CAST(mmap_mmap___exit__), METH_FASTCALL, mmap_mmap___exit____doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap___exit___impl(mmap_object *self, PyObject *exc_type,
|
||||||
|
PyObject *exc_value, PyObject *traceback);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap___exit__(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
PyObject *exc_type;
|
||||||
|
PyObject *exc_value;
|
||||||
|
PyObject *traceback;
|
||||||
|
|
||||||
|
if (!_PyArg_CheckPositional("__exit__", nargs, 3, 3)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
exc_type = args[0];
|
||||||
|
exc_value = args[1];
|
||||||
|
traceback = args[2];
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(self);
|
||||||
|
return_value = mmap_mmap___exit___impl((mmap_object *)self, exc_type, exc_value, traceback);
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(MS_WINDOWS)
|
||||||
|
|
||||||
|
PyDoc_STRVAR(mmap_mmap___sizeof____doc__,
|
||||||
|
"__sizeof__($self, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
#define MMAP_MMAP___SIZEOF___METHODDEF \
|
||||||
|
{"__sizeof__", (PyCFunction)mmap_mmap___sizeof__, METH_NOARGS, mmap_mmap___sizeof____doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap___sizeof___impl(mmap_object *self);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap___sizeof__(PyObject *self, PyObject *Py_UNUSED(ignored))
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(self);
|
||||||
|
return_value = mmap_mmap___sizeof___impl((mmap_object *)self);
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
|
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* defined(MS_WINDOWS) */
|
||||||
|
|
||||||
|
#if (defined(MS_WINDOWS) && defined(Py_DEBUG))
|
||||||
|
|
||||||
|
PyDoc_STRVAR(mmap_mmap__protect__doc__,
|
||||||
|
"_protect($self, flNewProtect, start, length, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
#define MMAP_MMAP__PROTECT_METHODDEF \
|
||||||
|
{"_protect", _PyCFunction_CAST(mmap_mmap__protect), METH_FASTCALL, mmap_mmap__protect__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap__protect_impl(mmap_object *self, unsigned int flNewProtect,
|
||||||
|
Py_ssize_t start, Py_ssize_t length);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap__protect(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
unsigned int flNewProtect;
|
||||||
|
Py_ssize_t start;
|
||||||
|
Py_ssize_t length;
|
||||||
|
|
||||||
|
if (!_PyArg_CheckPositional("_protect", nargs, 3, 3)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Py_ssize_t _bytes = PyLong_AsNativeBytes(args[0], &flNewProtect, sizeof(unsigned int),
|
||||||
|
Py_ASNATIVEBYTES_NATIVE_ENDIAN |
|
||||||
|
Py_ASNATIVEBYTES_ALLOW_INDEX |
|
||||||
|
Py_ASNATIVEBYTES_UNSIGNED_BUFFER);
|
||||||
|
if (_bytes < 0) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if ((size_t)_bytes > sizeof(unsigned int)) {
|
||||||
|
if (PyErr_WarnEx(PyExc_DeprecationWarning,
|
||||||
|
"integer value out of range", 1) < 0)
|
||||||
|
{
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Py_ssize_t ival = -1;
|
||||||
|
PyObject *iobj = _PyNumber_Index(args[1]);
|
||||||
|
if (iobj != NULL) {
|
||||||
|
ival = PyLong_AsSsize_t(iobj);
|
||||||
|
Py_DECREF(iobj);
|
||||||
|
}
|
||||||
|
if (ival == -1 && PyErr_Occurred()) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
start = ival;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Py_ssize_t ival = -1;
|
||||||
|
PyObject *iobj = _PyNumber_Index(args[2]);
|
||||||
|
if (iobj != NULL) {
|
||||||
|
ival = PyLong_AsSsize_t(iobj);
|
||||||
|
Py_DECREF(iobj);
|
||||||
|
}
|
||||||
|
if (ival == -1 && PyErr_Occurred()) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
length = ival;
|
||||||
|
}
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(self);
|
||||||
|
return_value = mmap_mmap__protect_impl((mmap_object *)self, flNewProtect, start, length);
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* (defined(MS_WINDOWS) && defined(Py_DEBUG)) */
|
||||||
|
|
||||||
|
#if defined(HAVE_MADVISE)
|
||||||
|
|
||||||
|
PyDoc_STRVAR(mmap_mmap_madvise__doc__,
|
||||||
|
"madvise($self, option, start=0, length=None, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
#define MMAP_MMAP_MADVISE_METHODDEF \
|
||||||
|
{"madvise", _PyCFunction_CAST(mmap_mmap_madvise), METH_FASTCALL, mmap_mmap_madvise__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap_madvise_impl(mmap_object *self, int option, Py_ssize_t start,
|
||||||
|
PyObject *length_obj);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap_madvise(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
int option;
|
||||||
|
Py_ssize_t start = 0;
|
||||||
|
PyObject *length_obj = Py_None;
|
||||||
|
|
||||||
|
if (!_PyArg_CheckPositional("madvise", nargs, 1, 3)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
option = PyLong_AsInt(args[0]);
|
||||||
|
if (option == -1 && PyErr_Occurred()) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (nargs < 2) {
|
||||||
|
goto skip_optional;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Py_ssize_t ival = -1;
|
||||||
|
PyObject *iobj = _PyNumber_Index(args[1]);
|
||||||
|
if (iobj != NULL) {
|
||||||
|
ival = PyLong_AsSsize_t(iobj);
|
||||||
|
Py_DECREF(iobj);
|
||||||
|
}
|
||||||
|
if (ival == -1 && PyErr_Occurred()) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
start = ival;
|
||||||
|
}
|
||||||
|
if (nargs < 3) {
|
||||||
|
goto skip_optional;
|
||||||
|
}
|
||||||
|
length_obj = args[2];
|
||||||
|
skip_optional:
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(self);
|
||||||
|
return_value = mmap_mmap_madvise_impl((mmap_object *)self, option, start, length_obj);
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* defined(HAVE_MADVISE) */
|
||||||
|
|
||||||
|
#ifndef MMAP_MMAP_RESIZE_METHODDEF
|
||||||
|
#define MMAP_MMAP_RESIZE_METHODDEF
|
||||||
|
#endif /* !defined(MMAP_MMAP_RESIZE_METHODDEF) */
|
||||||
|
|
||||||
|
#ifndef MMAP_MMAP___SIZEOF___METHODDEF
|
||||||
|
#define MMAP_MMAP___SIZEOF___METHODDEF
|
||||||
|
#endif /* !defined(MMAP_MMAP___SIZEOF___METHODDEF) */
|
||||||
|
|
||||||
|
#ifndef MMAP_MMAP__PROTECT_METHODDEF
|
||||||
|
#define MMAP_MMAP__PROTECT_METHODDEF
|
||||||
|
#endif /* !defined(MMAP_MMAP__PROTECT_METHODDEF) */
|
||||||
|
|
||||||
|
#ifndef MMAP_MMAP_MADVISE_METHODDEF
|
||||||
|
#define MMAP_MMAP_MADVISE_METHODDEF
|
||||||
|
#endif /* !defined(MMAP_MMAP_MADVISE_METHODDEF) */
|
||||||
|
/*[clinic end generated code: output=381f6cf4986ac867 input=a9049054013a1b77]*/
|
|
@ -91,6 +91,12 @@ my_getpagesize(void)
|
||||||
# define MAP_ANONYMOUS MAP_ANON
|
# define MAP_ANONYMOUS MAP_ANON
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
module mmap
|
||||||
|
class mmap.mmap "mmap_object *" ""
|
||||||
|
[clinic start generated code]*/
|
||||||
|
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=82a9f8a529905b9b]*/
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
ACCESS_DEFAULT,
|
ACCESS_DEFAULT,
|
||||||
|
@ -129,6 +135,26 @@ typedef struct {
|
||||||
|
|
||||||
#define mmap_object_CAST(op) ((mmap_object *)(op))
|
#define mmap_object_CAST(op) ((mmap_object *)(op))
|
||||||
|
|
||||||
|
#include "clinic/mmapmodule.c.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Return a Py_ssize_t from the object arg. This conversion logic is similar
|
||||||
|
to what AC uses for `Py_ssize_t` arguments.
|
||||||
|
|
||||||
|
Returns -1 on error. Use PyErr_Occurred() to disambiguate.
|
||||||
|
*/
|
||||||
|
static Py_ssize_t
|
||||||
|
_As_Py_ssize_t(PyObject *arg) {
|
||||||
|
assert(arg != NULL);
|
||||||
|
Py_ssize_t ival = -1;
|
||||||
|
PyObject *iobj = _PyNumber_Index(arg);
|
||||||
|
if (iobj != NULL) {
|
||||||
|
ival = PyLong_AsSsize_t(iobj);
|
||||||
|
Py_DECREF(iobj);
|
||||||
|
}
|
||||||
|
return ival;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mmap_object_dealloc(PyObject *op)
|
mmap_object_dealloc(PyObject *op)
|
||||||
{
|
{
|
||||||
|
@ -165,10 +191,16 @@ mmap_object_dealloc(PyObject *op)
|
||||||
Py_DECREF(tp);
|
Py_DECREF(tp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
@critical_section
|
||||||
|
mmap.mmap.close
|
||||||
|
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
mmap_close_method(PyObject *op, PyObject *Py_UNUSED(ignored))
|
mmap_mmap_close_impl(mmap_object *self)
|
||||||
|
/*[clinic end generated code: output=a1ae0c727546f78d input=25020035f047eae1]*/
|
||||||
{
|
{
|
||||||
mmap_object *self = mmap_object_CAST(op);
|
|
||||||
if (self->exports > 0) {
|
if (self->exports > 0) {
|
||||||
PyErr_SetString(PyExc_BufferError, "cannot close "\
|
PyErr_SetString(PyExc_BufferError, "cannot close "\
|
||||||
"exported pointers exist");
|
"exported pointers exist");
|
||||||
|
@ -472,10 +504,16 @@ _safe_PyBytes_FromStringAndSize(char *start, size_t num_bytes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
@critical_section
|
||||||
|
mmap.mmap.read_byte
|
||||||
|
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
mmap_read_byte_method(PyObject *op, PyObject *Py_UNUSED(ignored))
|
mmap_mmap_read_byte_impl(mmap_object *self)
|
||||||
|
/*[clinic end generated code: output=d931da1319f3869b input=5b8c6a904bdddda9]*/
|
||||||
{
|
{
|
||||||
mmap_object *self = mmap_object_CAST(op);
|
|
||||||
CHECK_VALID(NULL);
|
CHECK_VALID(NULL);
|
||||||
if (self->pos >= self->size) {
|
if (self->pos >= self->size) {
|
||||||
PyErr_SetString(PyExc_ValueError, "read byte out of range");
|
PyErr_SetString(PyExc_ValueError, "read byte out of range");
|
||||||
|
@ -489,12 +527,18 @@ mmap_read_byte_method(PyObject *op, PyObject *Py_UNUSED(ignored))
|
||||||
return PyLong_FromLong((unsigned char) dest);
|
return PyLong_FromLong((unsigned char) dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
@critical_section
|
||||||
|
mmap.mmap.readline
|
||||||
|
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
mmap_read_line_method(PyObject *op, PyObject *Py_UNUSED(ignored))
|
mmap_mmap_readline_impl(mmap_object *self)
|
||||||
|
/*[clinic end generated code: output=b9d2bf9999283311 input=2c4efd1d06e1cdd1]*/
|
||||||
{
|
{
|
||||||
Py_ssize_t remaining;
|
Py_ssize_t remaining;
|
||||||
char *start, *eol;
|
char *start, *eol;
|
||||||
mmap_object *self = mmap_object_CAST(op);
|
|
||||||
|
|
||||||
CHECK_VALID(NULL);
|
CHECK_VALID(NULL);
|
||||||
|
|
||||||
|
@ -519,15 +563,21 @@ mmap_read_line_method(PyObject *op, PyObject *Py_UNUSED(ignored))
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
/*[clinic input]
|
||||||
mmap_read_method(PyObject *op, PyObject *args)
|
@critical_section
|
||||||
{
|
mmap.mmap.read
|
||||||
Py_ssize_t num_bytes = PY_SSIZE_T_MAX, remaining;
|
|
||||||
mmap_object *self = mmap_object_CAST(op);
|
n as num_bytes: object(converter='_Py_convert_optional_to_ssize_t', type='Py_ssize_t', c_default='PY_SSIZE_T_MAX') = None
|
||||||
|
/
|
||||||
|
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap_read_impl(mmap_object *self, Py_ssize_t num_bytes)
|
||||||
|
/*[clinic end generated code: output=3b4d4f3704ed0969 input=8f97f361d435e357]*/
|
||||||
|
{
|
||||||
|
Py_ssize_t remaining;
|
||||||
|
|
||||||
CHECK_VALID(NULL);
|
|
||||||
if (!PyArg_ParseTuple(args, "|O&:read", _Py_convert_optional_to_ssize_t, &num_bytes))
|
|
||||||
return NULL;
|
|
||||||
CHECK_VALID(NULL);
|
CHECK_VALID(NULL);
|
||||||
|
|
||||||
/* silently 'adjust' out-of-range requests */
|
/* silently 'adjust' out-of-range requests */
|
||||||
|
@ -544,81 +594,105 @@ mmap_read_method(PyObject *op, PyObject *args)
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
mmap_gfind(mmap_object *self,
|
mmap_gfind_lock_held(mmap_object *self, Py_buffer *view, PyObject *start_obj,
|
||||||
PyObject *args,
|
PyObject *end_obj, int reverse)
|
||||||
int reverse)
|
|
||||||
{
|
{
|
||||||
Py_ssize_t start = self->pos;
|
Py_ssize_t start = self->pos;
|
||||||
Py_ssize_t end = self->size;
|
Py_ssize_t end = self->size;
|
||||||
Py_buffer view;
|
|
||||||
|
|
||||||
CHECK_VALID(NULL);
|
CHECK_VALID(NULL);
|
||||||
if (!PyArg_ParseTuple(args, reverse ? "y*|nn:rfind" : "y*|nn:find",
|
if (start_obj != Py_None) {
|
||||||
&view, &start, &end)) {
|
start = _As_Py_ssize_t(start_obj);
|
||||||
return NULL;
|
if (start == -1 && PyErr_Occurred()) {
|
||||||
}
|
return NULL;
|
||||||
else {
|
|
||||||
if (start < 0)
|
|
||||||
start += self->size;
|
|
||||||
if (start < 0)
|
|
||||||
start = 0;
|
|
||||||
else if (start > self->size)
|
|
||||||
start = self->size;
|
|
||||||
|
|
||||||
if (end < 0)
|
|
||||||
end += self->size;
|
|
||||||
if (end < 0)
|
|
||||||
end = 0;
|
|
||||||
else if (end > self->size)
|
|
||||||
end = self->size;
|
|
||||||
|
|
||||||
Py_ssize_t index;
|
|
||||||
PyObject *result;
|
|
||||||
CHECK_VALID_OR_RELEASE(NULL, view);
|
|
||||||
if (end < start) {
|
|
||||||
result = PyLong_FromSsize_t(-1);
|
|
||||||
}
|
}
|
||||||
else if (reverse) {
|
|
||||||
assert(0 <= start && start <= end && end <= self->size);
|
if (end_obj != Py_None) {
|
||||||
if (_safe_PyBytes_ReverseFind(&index, self,
|
end = _As_Py_ssize_t(end_obj);
|
||||||
self->data + start, end - start,
|
if (end == -1 && PyErr_Occurred()) {
|
||||||
view.buf, view.len, start) < 0)
|
return NULL;
|
||||||
{
|
|
||||||
result = NULL;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
result = PyLong_FromSsize_t(index);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start < 0)
|
||||||
|
start += self->size;
|
||||||
|
if (start < 0)
|
||||||
|
start = 0;
|
||||||
|
else if (start > self->size)
|
||||||
|
start = self->size;
|
||||||
|
|
||||||
|
if (end < 0)
|
||||||
|
end += self->size;
|
||||||
|
if (end < 0)
|
||||||
|
end = 0;
|
||||||
|
else if (end > self->size)
|
||||||
|
end = self->size;
|
||||||
|
|
||||||
|
Py_ssize_t index;
|
||||||
|
PyObject *result;
|
||||||
|
CHECK_VALID(NULL);
|
||||||
|
if (end < start) {
|
||||||
|
result = PyLong_FromSsize_t(-1);
|
||||||
|
}
|
||||||
|
else if (reverse) {
|
||||||
|
assert(0 <= start && start <= end && end <= self->size);
|
||||||
|
if (_safe_PyBytes_ReverseFind(&index, self,
|
||||||
|
self->data + start, end - start,
|
||||||
|
view->buf, view->len, start) < 0)
|
||||||
|
{
|
||||||
|
result = NULL;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
assert(0 <= start && start <= end && end <= self->size);
|
result = PyLong_FromSsize_t(index);
|
||||||
if (_safe_PyBytes_Find(&index, self,
|
|
||||||
self->data + start, end - start,
|
|
||||||
view.buf, view.len, start) < 0)
|
|
||||||
{
|
|
||||||
result = NULL;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
result = PyLong_FromSsize_t(index);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
PyBuffer_Release(&view);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
assert(0 <= start && start <= end && end <= self->size);
|
||||||
|
if (_safe_PyBytes_Find(&index, self,
|
||||||
|
self->data + start, end - start,
|
||||||
|
view->buf, view->len, start) < 0)
|
||||||
|
{
|
||||||
|
result = NULL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result = PyLong_FromSsize_t(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
/*[clinic input]
|
||||||
mmap_find_method(PyObject *op, PyObject *args)
|
@critical_section
|
||||||
{
|
mmap.mmap.find
|
||||||
mmap_object *self = mmap_object_CAST(op);
|
|
||||||
return mmap_gfind(self, args, 0);
|
view: Py_buffer
|
||||||
}
|
start: object = None
|
||||||
|
end: object = None
|
||||||
|
/
|
||||||
|
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
mmap_rfind_method(PyObject *op, PyObject *args)
|
mmap_mmap_find_impl(mmap_object *self, Py_buffer *view, PyObject *start,
|
||||||
|
PyObject *end)
|
||||||
|
/*[clinic end generated code: output=ef8878a322f00192 input=0135504494b52c2b]*/
|
||||||
{
|
{
|
||||||
mmap_object *self = mmap_object_CAST(op);
|
return mmap_gfind_lock_held(self, view, start, end, 0);
|
||||||
return mmap_gfind(self, args, 1);
|
}
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
@critical_section
|
||||||
|
mmap.mmap.rfind = mmap.mmap.find
|
||||||
|
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap_rfind_impl(mmap_object *self, Py_buffer *view, PyObject *start,
|
||||||
|
PyObject *end)
|
||||||
|
/*[clinic end generated code: output=73b918940d67c2b8 input=8aecdd1f70c06c62]*/
|
||||||
|
{
|
||||||
|
return mmap_gfind_lock_held(self, view, start, end, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -654,50 +728,55 @@ is_resizeable(mmap_object *self)
|
||||||
#endif /* MS_WINDOWS || HAVE_MREMAP */
|
#endif /* MS_WINDOWS || HAVE_MREMAP */
|
||||||
|
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
@critical_section
|
||||||
|
mmap.mmap.write
|
||||||
|
|
||||||
|
bytes as data: Py_buffer
|
||||||
|
/
|
||||||
|
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
mmap_write_method(PyObject *op, PyObject *args)
|
mmap_mmap_write_impl(mmap_object *self, Py_buffer *data)
|
||||||
|
/*[clinic end generated code: output=9e97063efb6fb27b input=3f16fa79aa89d6f7]*/
|
||||||
{
|
{
|
||||||
Py_buffer data;
|
|
||||||
mmap_object *self = mmap_object_CAST(op);
|
|
||||||
|
|
||||||
CHECK_VALID(NULL);
|
CHECK_VALID(NULL);
|
||||||
if (!PyArg_ParseTuple(args, "y*:write", &data))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (!is_writable(self)) {
|
if (!is_writable(self)) {
|
||||||
PyBuffer_Release(&data);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self->pos > self->size || self->size - self->pos < data.len) {
|
if (self->pos > self->size || self->size - self->pos < data->len) {
|
||||||
PyBuffer_Release(&data);
|
|
||||||
PyErr_SetString(PyExc_ValueError, "data out of range");
|
PyErr_SetString(PyExc_ValueError, "data out of range");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK_VALID_OR_RELEASE(NULL, data);
|
CHECK_VALID(NULL);
|
||||||
PyObject *result;
|
PyObject *result;
|
||||||
if (safe_memcpy(self->data + self->pos, data.buf, data.len) < 0) {
|
if (safe_memcpy(self->data + self->pos, data->buf, data->len) < 0) {
|
||||||
result = NULL;
|
result = NULL;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
self->pos += data.len;
|
self->pos += data->len;
|
||||||
result = PyLong_FromSsize_t(data.len);
|
result = PyLong_FromSsize_t(data->len);
|
||||||
}
|
}
|
||||||
PyBuffer_Release(&data);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
@critical_section
|
||||||
|
mmap.mmap.write_byte
|
||||||
|
|
||||||
|
byte as value: unsigned_char
|
||||||
|
/
|
||||||
|
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
mmap_write_byte_method(PyObject *op, PyObject *args)
|
mmap_mmap_write_byte_impl(mmap_object *self, unsigned char value)
|
||||||
|
/*[clinic end generated code: output=aa11adada9b17510 input=32740bfa174f0991]*/
|
||||||
{
|
{
|
||||||
char value;
|
|
||||||
mmap_object *self = mmap_object_CAST(op);
|
|
||||||
|
|
||||||
CHECK_VALID(NULL);
|
CHECK_VALID(NULL);
|
||||||
if (!PyArg_ParseTuple(args, "b:write_byte", &value))
|
|
||||||
return(NULL);
|
|
||||||
|
|
||||||
if (!is_writable(self))
|
if (!is_writable(self))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -707,17 +786,23 @@ mmap_write_byte_method(PyObject *op, PyObject *args)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (safe_byte_copy(self->data + self->pos, &value) < 0) {
|
if (safe_byte_copy(self->data + self->pos, (const char*)&value) < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
self->pos++;
|
self->pos++;
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
@critical_section
|
||||||
|
mmap.mmap.size
|
||||||
|
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
mmap_size_method(PyObject *op, PyObject *Py_UNUSED(ignored))
|
mmap_mmap_size_impl(mmap_object *self)
|
||||||
|
/*[clinic end generated code: output=c177e65e83a648ff input=f69c072efd2e1595]*/
|
||||||
{
|
{
|
||||||
mmap_object *self = mmap_object_CAST(op);
|
|
||||||
CHECK_VALID(NULL);
|
CHECK_VALID(NULL);
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
|
@ -771,14 +856,21 @@ mmap_size_method(PyObject *op, PyObject *Py_UNUSED(ignored))
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(MS_WINDOWS) || defined(HAVE_MREMAP)
|
#if defined(MS_WINDOWS) || defined(HAVE_MREMAP)
|
||||||
|
/*[clinic input]
|
||||||
|
@critical_section
|
||||||
|
mmap.mmap.resize
|
||||||
|
|
||||||
|
newsize as new_size: Py_ssize_t
|
||||||
|
/
|
||||||
|
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
mmap_resize_method(PyObject *op, PyObject *args)
|
mmap_mmap_resize_impl(mmap_object *self, Py_ssize_t new_size)
|
||||||
|
/*[clinic end generated code: output=6f262537ce9c2dcc input=b6b5dee52a41b79f]*/
|
||||||
{
|
{
|
||||||
Py_ssize_t new_size;
|
|
||||||
mmap_object *self = mmap_object_CAST(op);
|
|
||||||
CHECK_VALID(NULL);
|
CHECK_VALID(NULL);
|
||||||
if (!PyArg_ParseTuple(args, "n:resize", &new_size) ||
|
if (!is_resizeable(self)) {
|
||||||
!is_resizeable(self)) {
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (new_size < 0 || PY_SSIZE_T_MAX - new_size < self->offset) {
|
if (new_size < 0 || PY_SSIZE_T_MAX - new_size < self->offset) {
|
||||||
|
@ -921,24 +1013,35 @@ mmap_resize_method(PyObject *op, PyObject *args)
|
||||||
}
|
}
|
||||||
#endif /* MS_WINDOWS || HAVE_MREMAP */
|
#endif /* MS_WINDOWS || HAVE_MREMAP */
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
@critical_section
|
||||||
|
mmap.mmap.tell
|
||||||
|
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
mmap_tell_method(PyObject *op, PyObject *Py_UNUSED(ignored))
|
mmap_mmap_tell_impl(mmap_object *self)
|
||||||
|
/*[clinic end generated code: output=6034958630e1b1d1 input=fd163acacf45c3a5]*/
|
||||||
{
|
{
|
||||||
mmap_object *self = mmap_object_CAST(op);
|
|
||||||
CHECK_VALID(NULL);
|
CHECK_VALID(NULL);
|
||||||
return PyLong_FromSize_t(self->pos);
|
return PyLong_FromSize_t(self->pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
@critical_section
|
||||||
|
mmap.mmap.flush
|
||||||
|
|
||||||
|
offset: Py_ssize_t = 0
|
||||||
|
size: Py_ssize_t = -1
|
||||||
|
/
|
||||||
|
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
mmap_flush_method(PyObject *op, PyObject *args)
|
mmap_mmap_flush_impl(mmap_object *self, Py_ssize_t offset, Py_ssize_t size)
|
||||||
|
/*[clinic end generated code: output=956ced67466149cf input=c50b893bc69520ec]*/
|
||||||
{
|
{
|
||||||
Py_ssize_t offset = 0;
|
|
||||||
Py_ssize_t size = -1;
|
|
||||||
mmap_object *self = mmap_object_CAST(op);
|
|
||||||
CHECK_VALID(NULL);
|
CHECK_VALID(NULL);
|
||||||
if (!PyArg_ParseTuple(args, "|nn:flush", &offset, &size)) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (size == -1) {
|
if (size == -1) {
|
||||||
size = self->size - offset;
|
size = self->size - offset;
|
||||||
}
|
}
|
||||||
|
@ -969,60 +1072,80 @@ mmap_flush_method(PyObject *op, PyObject *args)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
@critical_section
|
||||||
|
mmap.mmap.seek
|
||||||
|
|
||||||
|
pos as dist: Py_ssize_t
|
||||||
|
whence as how: int = 0
|
||||||
|
/
|
||||||
|
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
mmap_seek_method(PyObject *op, PyObject *args)
|
mmap_mmap_seek_impl(mmap_object *self, Py_ssize_t dist, int how)
|
||||||
|
/*[clinic end generated code: output=00310494e8b8c592 input=e2fda5d081c3db22]*/
|
||||||
{
|
{
|
||||||
Py_ssize_t dist;
|
|
||||||
mmap_object *self = mmap_object_CAST(op);
|
|
||||||
int how=0;
|
|
||||||
CHECK_VALID(NULL);
|
CHECK_VALID(NULL);
|
||||||
if (!PyArg_ParseTuple(args, "n|i:seek", &dist, &how))
|
Py_ssize_t where;
|
||||||
return NULL;
|
switch (how) {
|
||||||
else {
|
case 0: /* relative to start */
|
||||||
Py_ssize_t where;
|
where = dist;
|
||||||
switch (how) {
|
break;
|
||||||
case 0: /* relative to start */
|
case 1: /* relative to current position */
|
||||||
where = dist;
|
if (PY_SSIZE_T_MAX - self->pos < dist)
|
||||||
break;
|
|
||||||
case 1: /* relative to current position */
|
|
||||||
if (PY_SSIZE_T_MAX - self->pos < dist)
|
|
||||||
goto onoutofrange;
|
|
||||||
where = self->pos + dist;
|
|
||||||
break;
|
|
||||||
case 2: /* relative to end */
|
|
||||||
if (PY_SSIZE_T_MAX - self->size < dist)
|
|
||||||
goto onoutofrange;
|
|
||||||
where = self->size + dist;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PyErr_SetString(PyExc_ValueError, "unknown seek type");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (where > self->size || where < 0)
|
|
||||||
goto onoutofrange;
|
goto onoutofrange;
|
||||||
self->pos = where;
|
where = self->pos + dist;
|
||||||
return PyLong_FromSsize_t(self->pos);
|
break;
|
||||||
|
case 2: /* relative to end */
|
||||||
|
if (PY_SSIZE_T_MAX - self->size < dist)
|
||||||
|
goto onoutofrange;
|
||||||
|
where = self->size + dist;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PyErr_SetString(PyExc_ValueError, "unknown seek type");
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (where > self->size || where < 0)
|
||||||
|
goto onoutofrange;
|
||||||
|
self->pos = where;
|
||||||
|
return PyLong_FromSsize_t(self->pos);
|
||||||
|
|
||||||
onoutofrange:
|
onoutofrange:
|
||||||
PyErr_SetString(PyExc_ValueError, "seek out of range");
|
PyErr_SetString(PyExc_ValueError, "seek out of range");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
mmap.mmap.seekable
|
||||||
|
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
mmap_seekable_method(PyObject *op, PyObject *Py_UNUSED(ignored))
|
mmap_mmap_seekable_impl(mmap_object *self)
|
||||||
|
/*[clinic end generated code: output=6311dc3ea300fa38 input=5132505f6e259001]*/
|
||||||
{
|
{
|
||||||
Py_RETURN_TRUE;
|
Py_RETURN_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
@critical_section
|
||||||
|
mmap.mmap.move
|
||||||
|
|
||||||
|
dest: Py_ssize_t
|
||||||
|
src: Py_ssize_t
|
||||||
|
count as cnt: Py_ssize_t
|
||||||
|
/
|
||||||
|
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
mmap_move_method(PyObject *op, PyObject *args)
|
mmap_mmap_move_impl(mmap_object *self, Py_ssize_t dest, Py_ssize_t src,
|
||||||
|
Py_ssize_t cnt)
|
||||||
|
/*[clinic end generated code: output=391f549a44181793 input=cf8cfe10d9f6b448]*/
|
||||||
{
|
{
|
||||||
Py_ssize_t dest, src, cnt;
|
|
||||||
mmap_object *self = mmap_object_CAST(op);
|
|
||||||
CHECK_VALID(NULL);
|
CHECK_VALID(NULL);
|
||||||
if (!PyArg_ParseTuple(args, "nnn:move", &dest, &src, &cnt) ||
|
if (!is_writable(self)) {
|
||||||
!is_writable(self)) {
|
|
||||||
return NULL;
|
return NULL;
|
||||||
} else {
|
} else {
|
||||||
/* bounds check the values */
|
/* bounds check the values */
|
||||||
|
@ -1048,30 +1171,53 @@ static PyObject *
|
||||||
mmap_closed_get(PyObject *op, void *Py_UNUSED(closure))
|
mmap_closed_get(PyObject *op, void *Py_UNUSED(closure))
|
||||||
{
|
{
|
||||||
mmap_object *self = mmap_object_CAST(op);
|
mmap_object *self = mmap_object_CAST(op);
|
||||||
|
PyObject *result;
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(op);
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
return PyBool_FromLong(self->map_handle == NULL ? 1 : 0);
|
result = PyBool_FromLong(self->map_handle == NULL ? 1 : 0);
|
||||||
#elif defined(UNIX)
|
#elif defined(UNIX)
|
||||||
return PyBool_FromLong(self->data == NULL ? 1 : 0);
|
result = PyBool_FromLong(self->data == NULL ? 1 : 0);
|
||||||
#endif
|
#endif
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
@critical_section
|
||||||
|
mmap.mmap.__enter__
|
||||||
|
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
mmap__enter__method(PyObject *op, PyObject *Py_UNUSED(ignored))
|
mmap_mmap___enter___impl(mmap_object *self)
|
||||||
|
/*[clinic end generated code: output=92cfc59f4c4e2d26 input=a446541fbfe0b890]*/
|
||||||
{
|
{
|
||||||
mmap_object *self = mmap_object_CAST(op);
|
|
||||||
CHECK_VALID(NULL);
|
CHECK_VALID(NULL);
|
||||||
|
|
||||||
return Py_NewRef(self);
|
return Py_NewRef(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
@critical_section
|
||||||
|
mmap.mmap.__exit__
|
||||||
|
|
||||||
|
exc_type: object
|
||||||
|
exc_value: object
|
||||||
|
traceback: object
|
||||||
|
/
|
||||||
|
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
mmap__exit__method(PyObject *op, PyObject *Py_UNUSED(args))
|
mmap_mmap___exit___impl(mmap_object *self, PyObject *exc_type,
|
||||||
|
PyObject *exc_value, PyObject *traceback)
|
||||||
|
/*[clinic end generated code: output=bec7e3e319c1f07e input=5f28e91cf752bc64]*/
|
||||||
{
|
{
|
||||||
return mmap_close_method(op, NULL);
|
return mmap_mmap_close_impl(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
mmap__repr__method(PyObject *op)
|
mmap__repr__method_lock_held(PyObject *op)
|
||||||
{
|
{
|
||||||
mmap_object *mobj = mmap_object_CAST(op);
|
mmap_object *mobj = mmap_object_CAST(op);
|
||||||
|
|
||||||
|
@ -1115,11 +1261,27 @@ mmap__repr__method(PyObject *op)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
mmap__sizeof__method(PyObject *op, PyObject *Py_UNUSED(dummy))
|
mmap__repr__method(PyObject *op)
|
||||||
|
{
|
||||||
|
PyObject *result;
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(op);
|
||||||
|
result = mmap__repr__method_lock_held(op);
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef MS_WINDOWS
|
||||||
|
/*[clinic input]
|
||||||
|
@critical_section
|
||||||
|
mmap.mmap.__sizeof__
|
||||||
|
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_mmap___sizeof___impl(mmap_object *self)
|
||||||
|
/*[clinic end generated code: output=1aed30daff807d09 input=8a648868a089553c]*/
|
||||||
{
|
{
|
||||||
mmap_object *self = mmap_object_CAST(op);
|
|
||||||
size_t res = _PyObject_SIZE(Py_TYPE(self));
|
size_t res = _PyObject_SIZE(Py_TYPE(self));
|
||||||
if (self->tagname) {
|
if (self->tagname) {
|
||||||
res += (wcslen(self->tagname) + 1) * sizeof(self->tagname[0]);
|
res += (wcslen(self->tagname) + 1) * sizeof(self->tagname[0]);
|
||||||
|
@ -1129,18 +1291,26 @@ mmap__sizeof__method(PyObject *op, PyObject *Py_UNUSED(dummy))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(MS_WINDOWS) && defined(Py_DEBUG)
|
#if defined(MS_WINDOWS) && defined(Py_DEBUG)
|
||||||
|
/*[clinic input]
|
||||||
|
@critical_section
|
||||||
|
mmap.mmap._protect
|
||||||
|
|
||||||
|
flNewProtect: unsigned_int(bitwise=True)
|
||||||
|
start: Py_ssize_t
|
||||||
|
length: Py_ssize_t
|
||||||
|
/
|
||||||
|
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
mmap_protect_method(PyObject *op, PyObject *args) {
|
mmap_mmap__protect_impl(mmap_object *self, unsigned int flNewProtect,
|
||||||
DWORD flNewProtect, flOldProtect;
|
Py_ssize_t start, Py_ssize_t length)
|
||||||
Py_ssize_t start, length;
|
/*[clinic end generated code: output=a87271a34d1ad6cf input=9170498c5e1482da]*/
|
||||||
mmap_object *self = mmap_object_CAST(op);
|
{
|
||||||
|
DWORD flOldProtect;
|
||||||
|
|
||||||
CHECK_VALID(NULL);
|
CHECK_VALID(NULL);
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "Inn:protect", &flNewProtect, &start, &length)) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!VirtualProtect((void *) (self->data + start), length, flNewProtect,
|
if (!VirtualProtect((void *) (self->data + start), length, flNewProtect,
|
||||||
&flOldProtect))
|
&flOldProtect))
|
||||||
{
|
{
|
||||||
|
@ -1153,18 +1323,32 @@ mmap_protect_method(PyObject *op, PyObject *args) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_MADVISE
|
#ifdef HAVE_MADVISE
|
||||||
|
/*[clinic input]
|
||||||
|
@critical_section
|
||||||
|
mmap.mmap.madvise
|
||||||
|
|
||||||
|
option: int
|
||||||
|
start: Py_ssize_t = 0
|
||||||
|
length as length_obj: object = None
|
||||||
|
/
|
||||||
|
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
mmap_madvise_method(PyObject *op, PyObject *args)
|
mmap_mmap_madvise_impl(mmap_object *self, int option, Py_ssize_t start,
|
||||||
|
PyObject *length_obj)
|
||||||
|
/*[clinic end generated code: output=816be656f08c0e3c input=2d37f7a4c87f1053]*/
|
||||||
{
|
{
|
||||||
int option;
|
Py_ssize_t length;
|
||||||
Py_ssize_t start = 0, length;
|
|
||||||
mmap_object *self = mmap_object_CAST(op);
|
|
||||||
|
|
||||||
CHECK_VALID(NULL);
|
CHECK_VALID(NULL);
|
||||||
length = self->size;
|
if (length_obj == Py_None) {
|
||||||
|
length = self->size;
|
||||||
if (!PyArg_ParseTuple(args, "i|nn:madvise", &option, &start, &length)) {
|
} else {
|
||||||
return NULL;
|
length = _As_Py_ssize_t(length_obj);
|
||||||
|
if (length == -1 && PyErr_Occurred()) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (start < 0 || start >= self->size) {
|
if (start < 0 || start >= self->size) {
|
||||||
|
@ -1200,34 +1384,26 @@ static struct PyMemberDef mmap_object_members[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct PyMethodDef mmap_object_methods[] = {
|
static struct PyMethodDef mmap_object_methods[] = {
|
||||||
{"close", mmap_close_method, METH_NOARGS},
|
MMAP_MMAP_CLOSE_METHODDEF
|
||||||
{"find", mmap_find_method, METH_VARARGS},
|
MMAP_MMAP_FIND_METHODDEF
|
||||||
{"rfind", mmap_rfind_method, METH_VARARGS},
|
MMAP_MMAP_RFIND_METHODDEF
|
||||||
{"flush", mmap_flush_method, METH_VARARGS},
|
MMAP_MMAP_FLUSH_METHODDEF
|
||||||
#ifdef HAVE_MADVISE
|
MMAP_MMAP_MADVISE_METHODDEF
|
||||||
{"madvise", mmap_madvise_method, METH_VARARGS},
|
MMAP_MMAP_MOVE_METHODDEF
|
||||||
#endif
|
MMAP_MMAP_READ_METHODDEF
|
||||||
{"move", mmap_move_method, METH_VARARGS},
|
MMAP_MMAP_READ_BYTE_METHODDEF
|
||||||
{"read", mmap_read_method, METH_VARARGS},
|
MMAP_MMAP_READLINE_METHODDEF
|
||||||
{"read_byte", mmap_read_byte_method, METH_NOARGS},
|
MMAP_MMAP_RESIZE_METHODDEF
|
||||||
{"readline", mmap_read_line_method, METH_NOARGS},
|
MMAP_MMAP_SEEK_METHODDEF
|
||||||
#if defined(MS_WINDOWS) || defined(HAVE_MREMAP)
|
MMAP_MMAP_SEEKABLE_METHODDEF
|
||||||
{"resize", mmap_resize_method, METH_VARARGS},
|
MMAP_MMAP_SIZE_METHODDEF
|
||||||
#endif
|
MMAP_MMAP_TELL_METHODDEF
|
||||||
{"seek", mmap_seek_method, METH_VARARGS},
|
MMAP_MMAP_WRITE_METHODDEF
|
||||||
{"seekable", mmap_seekable_method, METH_NOARGS},
|
MMAP_MMAP_WRITE_BYTE_METHODDEF
|
||||||
{"size", mmap_size_method, METH_NOARGS},
|
MMAP_MMAP___ENTER___METHODDEF
|
||||||
{"tell", mmap_tell_method, METH_NOARGS},
|
MMAP_MMAP___EXIT___METHODDEF
|
||||||
{"write", mmap_write_method, METH_VARARGS},
|
MMAP_MMAP___SIZEOF___METHODDEF
|
||||||
{"write_byte", mmap_write_byte_method, METH_VARARGS},
|
MMAP_MMAP__PROTECT_METHODDEF
|
||||||
{"__enter__", mmap__enter__method, METH_NOARGS},
|
|
||||||
{"__exit__", mmap__exit__method, METH_VARARGS},
|
|
||||||
#ifdef MS_WINDOWS
|
|
||||||
{"__sizeof__", mmap__sizeof__method, METH_NOARGS},
|
|
||||||
#ifdef Py_DEBUG
|
|
||||||
{"_protect", mmap_protect_method, METH_VARARGS},
|
|
||||||
#endif // Py_DEBUG
|
|
||||||
#endif // MS_WINDOWS
|
|
||||||
{NULL, NULL} /* sentinel */
|
{NULL, NULL} /* sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1240,7 +1416,7 @@ static PyGetSetDef mmap_object_getset[] = {
|
||||||
/* Functions for treating an mmap'ed file as a buffer */
|
/* Functions for treating an mmap'ed file as a buffer */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mmap_buffer_getbuf(PyObject *op, Py_buffer *view, int flags)
|
mmap_buffer_getbuf_lock_held(PyObject *op, Py_buffer *view, int flags)
|
||||||
{
|
{
|
||||||
mmap_object *self = mmap_object_CAST(op);
|
mmap_object *self = mmap_object_CAST(op);
|
||||||
CHECK_VALID(-1);
|
CHECK_VALID(-1);
|
||||||
|
@ -1251,23 +1427,45 @@ mmap_buffer_getbuf(PyObject *op, Py_buffer *view, int flags)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
mmap_buffer_getbuf(PyObject *op, Py_buffer *view, int flags)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(op);
|
||||||
|
result = mmap_buffer_getbuf_lock_held(op, view, flags);
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mmap_buffer_releasebuf(PyObject *op, Py_buffer *Py_UNUSED(view))
|
mmap_buffer_releasebuf(PyObject *op, Py_buffer *Py_UNUSED(view))
|
||||||
{
|
{
|
||||||
mmap_object *self = mmap_object_CAST(op);
|
mmap_object *self = mmap_object_CAST(op);
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(self);
|
||||||
self->exports--;
|
self->exports--;
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
}
|
}
|
||||||
|
|
||||||
static Py_ssize_t
|
static Py_ssize_t
|
||||||
mmap_length(PyObject *op)
|
mmap_length_lock_held(PyObject *op)
|
||||||
{
|
{
|
||||||
mmap_object *self = mmap_object_CAST(op);
|
mmap_object *self = mmap_object_CAST(op);
|
||||||
CHECK_VALID(-1);
|
CHECK_VALID(-1);
|
||||||
return self->size;
|
return self->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Py_ssize_t
|
||||||
|
mmap_length(PyObject *op)
|
||||||
|
{
|
||||||
|
Py_ssize_t result;
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(op);
|
||||||
|
result = mmap_length_lock_held(op);
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
mmap_item(PyObject *op, Py_ssize_t i)
|
mmap_item_lock_held(PyObject *op, Py_ssize_t i)
|
||||||
{
|
{
|
||||||
mmap_object *self = mmap_object_CAST(op);
|
mmap_object *self = mmap_object_CAST(op);
|
||||||
CHECK_VALID(NULL);
|
CHECK_VALID(NULL);
|
||||||
|
@ -1284,7 +1482,16 @@ mmap_item(PyObject *op, Py_ssize_t i)
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
mmap_subscript(PyObject *op, PyObject *item)
|
mmap_item(PyObject *op, Py_ssize_t i) {
|
||||||
|
PyObject *result;
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(op);
|
||||||
|
result = mmap_item_lock_held(op, i);
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_subscript_lock_held(PyObject *op, PyObject *item)
|
||||||
{
|
{
|
||||||
mmap_object *self = mmap_object_CAST(op);
|
mmap_object *self = mmap_object_CAST(op);
|
||||||
CHECK_VALID(NULL);
|
CHECK_VALID(NULL);
|
||||||
|
@ -1346,8 +1553,18 @@ mmap_subscript(PyObject *op, PyObject *item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
mmap_subscript(PyObject *op, PyObject *item)
|
||||||
|
{
|
||||||
|
PyObject *result;
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(op);
|
||||||
|
result = mmap_subscript_lock_held(op, item);
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mmap_ass_item(PyObject *op, Py_ssize_t i, PyObject *v)
|
mmap_ass_item_lock_held(PyObject *op, Py_ssize_t i, PyObject *v)
|
||||||
{
|
{
|
||||||
const char *buf;
|
const char *buf;
|
||||||
mmap_object *self = mmap_object_CAST(op);
|
mmap_object *self = mmap_object_CAST(op);
|
||||||
|
@ -1378,7 +1595,17 @@ mmap_ass_item(PyObject *op, Py_ssize_t i, PyObject *v)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mmap_ass_subscript(PyObject *op, PyObject *item, PyObject *value)
|
mmap_ass_item(PyObject *op, Py_ssize_t i, PyObject *v)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(op);
|
||||||
|
result = mmap_ass_item_lock_held(op, i, v);
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
mmap_ass_subscript_lock_held(PyObject *op, PyObject *item, PyObject *value)
|
||||||
{
|
{
|
||||||
mmap_object *self = mmap_object_CAST(op);
|
mmap_object *self = mmap_object_CAST(op);
|
||||||
CHECK_VALID(-1);
|
CHECK_VALID(-1);
|
||||||
|
@ -1474,6 +1701,16 @@ mmap_ass_subscript(PyObject *op, PyObject *item, PyObject *value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
mmap_ass_subscript(PyObject *op, PyObject *item, PyObject *value)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(op);
|
||||||
|
result = mmap_ass_subscript_lock_held(op, item, value);
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict);
|
new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue