sapling/edenscmnative/litemmap.pyx
Jun Wu a17a87bf4f setup: move native extensions to edenscmnative
Summary:
This just moves things around. So native and pure Python modules are split to
different Python packages. This makes it possible to use the standard zip
importer without hacks (ex. `hgdemandimport/embeddedimport`).

This diff is mostly about moving things. While `make local` still works,
it does break nupkg build, which will be fixed in a later diff.

Reviewed By: kulshrax

Differential Revision: D15798642

fbshipit-source-id: 5d83f17099aa198df0acd5b7a99667e2f35fe7b4
2019-06-19 17:55:49 -07:00

80 lines
2.3 KiB
Cython

# litemmap.pyx - read-only mmap implementation that does not keep a fd open
#
# Copyright 2018 Facebook, Inc.
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
import mmap as pymmap
IF UNAME_SYSNAME == "Windows":
# Not supporting windows for now - fallback to Python's mmap
mmap = pymmap.mmap
ELSE:
from cpython.bytes cimport PyBytes_FromStringAndSize
from libc.errno cimport errno
from posix cimport mman, stat
import os
cdef extern from "sys/mman.h":
cdef char *MAP_FAILED
cdef _raise_oserror(message=''):
if message:
message += b': '
message += os.strerror(errno)
return OSError(errno, message)
cdef class mmap:
cdef char *ptr
cdef size_t len
def __cinit__(self, int fd, size_t length, int
access=pymmap.ACCESS_READ):
cdef stat.struct_stat st
# Only support read-only case
if access != pymmap.ACCESS_READ:
raise RuntimeError(b'access %s is unsupported' % access)
# If length is 0, read size from file
if length == 0:
r = stat.fstat(fd, &st)
if r != 0:
_raise_oserror(b'fstat failed')
length = st.st_size
self.ptr = <char*>mman.mmap(NULL, length, mman.PROT_READ,
mman.MAP_SHARED, fd, 0)
if self.ptr == MAP_FAILED:
_raise_oserror(b'mmap failed')
self.len = length
cpdef close(self):
if self.ptr == NULL:
return
r = mman.munmap(self.ptr, self.len)
if r != 0:
_raise_oserror(b'munmap failed')
self.ptr = NULL
def __getslice__(self, Py_ssize_t i, Py_ssize_t j):
if self.ptr == NULL:
raise RuntimeError(b'mmap closed')
if i < 0:
i = 0
if j > self.len:
j = self.len
if i > j:
i = j
return PyBytes_FromStringAndSize(self.ptr + i, j - i)
def __len__(self):
return self.len
def __dealloc__(self):
self.close()