PageRenderTime 1711ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/pypy/module/mmap/interp_mmap.py

https://bitbucket.org/pypy/pypy/
Python | 378 lines | 351 code | 25 blank | 2 comment | 37 complexity | 0a05b3284b774accd1ef122b2f89dd00 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. from pypy.interpreter.error import OperationError, oefmt, wrap_oserror
  2. from pypy.interpreter.baseobjspace import W_Root
  3. from pypy.interpreter.typedef import TypeDef
  4. from pypy.interpreter.gateway import interp2app, unwrap_spec
  5. from rpython.rlib import rmmap, rarithmetic
  6. from rpython.rlib.buffer import Buffer
  7. from rpython.rlib.rmmap import RValueError, RTypeError, RMMapError
  8. from rpython.rlib.rstring import StringBuilder
  9. if rmmap.HAVE_LARGEFILE_SUPPORT:
  10. OFF_T = rarithmetic.r_longlong
  11. else:
  12. OFF_T = int
  13. class W_MMap(W_Root):
  14. def __init__(self, space, mmap_obj):
  15. self.space = space
  16. self.mmap = mmap_obj
  17. def readbuf_w(self, space):
  18. self.check_valid()
  19. return MMapBuffer(self.space, self.mmap, True)
  20. def writebuf_w(self, space):
  21. self.check_writeable()
  22. return MMapBuffer(self.space, self.mmap, False)
  23. def close(self):
  24. self.mmap.close()
  25. def read_byte(self):
  26. self.check_valid()
  27. try:
  28. return self.space.wrap(self.mmap.read_byte())
  29. except RValueError as v:
  30. raise mmap_error(self.space, v)
  31. def readline(self):
  32. self.check_valid()
  33. return self.space.wrap(self.mmap.readline())
  34. @unwrap_spec(num=int)
  35. def read(self, num=-1):
  36. self.check_valid()
  37. return self.space.wrap(self.mmap.read(num))
  38. def find(self, w_tofind, w_start=None, w_end=None):
  39. self.check_valid()
  40. space = self.space
  41. tofind = space.getarg_w('s#', w_tofind)
  42. if w_start is None:
  43. start = self.mmap.pos
  44. else:
  45. start = space.getindex_w(w_start, None)
  46. if w_end is None:
  47. end = self.mmap.size
  48. else:
  49. end = space.getindex_w(w_end, None)
  50. return space.wrap(self.mmap.find(tofind, start, end))
  51. def rfind(self, w_tofind, w_start=None, w_end=None):
  52. self.check_valid()
  53. space = self.space
  54. tofind = space.getarg_w('s#', w_tofind)
  55. if w_start is None:
  56. start = self.mmap.pos
  57. else:
  58. start = space.getindex_w(w_start, None)
  59. if w_end is None:
  60. end = self.mmap.size
  61. else:
  62. end = space.getindex_w(w_end, None)
  63. return space.wrap(self.mmap.find(tofind, start, end, True))
  64. @unwrap_spec(pos=OFF_T, whence=int)
  65. def seek(self, pos, whence=0):
  66. self.check_valid()
  67. try:
  68. self.mmap.seek(pos, whence)
  69. except RValueError as v:
  70. raise mmap_error(self.space, v)
  71. def tell(self):
  72. self.check_valid()
  73. return self.space.wrap(self.mmap.tell())
  74. def descr_size(self):
  75. self.check_valid()
  76. try:
  77. return self.space.wrap(self.mmap.file_size())
  78. except OSError as e:
  79. raise mmap_error(self.space, e)
  80. def write(self, w_data):
  81. self.check_valid()
  82. data = self.space.getarg_w('s#', w_data)
  83. self.check_writeable()
  84. try:
  85. self.mmap.write(data)
  86. except RValueError as v:
  87. raise mmap_error(self.space, v)
  88. @unwrap_spec(byte=str)
  89. def write_byte(self, byte):
  90. self.check_valid()
  91. self.check_writeable()
  92. try:
  93. self.mmap.write_byte(byte)
  94. except RMMapError as v:
  95. raise mmap_error(self.space, v)
  96. @unwrap_spec(offset=int, size=int)
  97. def flush(self, offset=0, size=0):
  98. self.check_valid()
  99. try:
  100. return self.space.wrap(self.mmap.flush(offset, size))
  101. except RValueError as v:
  102. raise mmap_error(self.space, v)
  103. except OSError as e:
  104. raise mmap_error(self.space, e)
  105. @unwrap_spec(dest=int, src=int, count=int)
  106. def move(self, dest, src, count):
  107. self.check_valid()
  108. self.check_writeable()
  109. try:
  110. self.mmap.move(dest, src, count)
  111. except RValueError as v:
  112. raise mmap_error(self.space, v)
  113. @unwrap_spec(newsize=int)
  114. def resize(self, newsize):
  115. self.check_valid()
  116. self.check_resizeable()
  117. try:
  118. self.mmap.resize(newsize)
  119. except OSError as e:
  120. raise mmap_error(self.space, e)
  121. except RValueError as e:
  122. # obscure: in this case, RValueError translates to an app-level
  123. # SystemError.
  124. raise OperationError(self.space.w_SystemError,
  125. self.space.wrap(e.message))
  126. def __len__(self):
  127. return self.space.wrap(self.mmap.size)
  128. def check_valid(self):
  129. try:
  130. self.mmap.check_valid()
  131. except RValueError as v:
  132. raise mmap_error(self.space, v)
  133. def check_writeable(self):
  134. try:
  135. self.mmap.check_writeable()
  136. except RMMapError as v:
  137. raise mmap_error(self.space, v)
  138. def check_resizeable(self):
  139. try:
  140. self.mmap.check_resizeable()
  141. except RMMapError as v:
  142. raise mmap_error(self.space, v)
  143. def descr_getitem(self, w_index):
  144. self.check_valid()
  145. space = self.space
  146. start, stop, step, length = space.decode_index4(w_index, self.mmap.size)
  147. if step == 0: # index only
  148. return space.wrap(self.mmap.getitem(start))
  149. elif step == 1:
  150. if stop - start < 0:
  151. return space.wrap("")
  152. return space.wrap(self.mmap.getslice(start, length))
  153. else:
  154. b = StringBuilder(length)
  155. for i in range(start, stop, step):
  156. b.append(self.mmap.getitem(i))
  157. return space.wrap(b.build())
  158. def descr_setitem(self, w_index, w_value):
  159. space = self.space
  160. value = space.realstr_w(w_value)
  161. self.check_valid()
  162. self.check_writeable()
  163. start, stop, step, length = space.decode_index4(w_index, self.mmap.size)
  164. if step == 0: # index only
  165. if len(value) != 1:
  166. raise oefmt(space.w_ValueError,
  167. "mmap assignment must be single-character string")
  168. self.mmap.setitem(start, value)
  169. else:
  170. if len(value) != length:
  171. raise oefmt(space.w_ValueError,
  172. "mmap slice assignment is wrong size")
  173. if step == 1:
  174. self.mmap.setslice(start, value)
  175. else:
  176. for i in range(length):
  177. self.mmap.setitem(start, value[i])
  178. start += step
  179. def descr_getslice(self, space, w_ilow, w_ihigh):
  180. self.check_valid()
  181. i = space.getindex_w(w_ilow, None)
  182. j = space.getindex_w(w_ihigh, None)
  183. if i < 0:
  184. i = 0
  185. elif i > self.mmap.size:
  186. i = self.mmap.size
  187. if j < 0:
  188. j = 0
  189. if j < i:
  190. j = i
  191. elif j > self.mmap.size:
  192. j = self.mmap.size
  193. return space.wrap(self.mmap.getslice(i, (j - i)))
  194. def descr_setslice(self, space, w_ilow, w_ihigh, w_item):
  195. self.check_valid()
  196. i = space.getindex_w(w_ilow, None)
  197. j = space.getindex_w(w_ihigh, None)
  198. if i < 0:
  199. i = 0
  200. elif i > self.mmap.size:
  201. i = self.mmap.size
  202. if j < 0:
  203. j = 0
  204. if j < i:
  205. j = i
  206. elif j > self.mmap.size:
  207. j = self.mmap.size
  208. if not space.isinstance_w(w_item, space.w_str):
  209. raise oefmt(space.w_IndexError,
  210. "mmap slice assignment must be a string")
  211. value = space.realstr_w(w_item)
  212. if len(value) != (j - i):
  213. raise oefmt(space.w_IndexError,
  214. "mmap slice assignment is wrong size")
  215. self.check_writeable()
  216. self.mmap.setslice(i, value)
  217. if rmmap._POSIX:
  218. @unwrap_spec(fileno=int, length=int, flags=int,
  219. prot=int, access=int, offset=OFF_T)
  220. def mmap(space, w_subtype, fileno, length, flags=rmmap.MAP_SHARED,
  221. prot=rmmap.PROT_WRITE | rmmap.PROT_READ,
  222. access=rmmap._ACCESS_DEFAULT, offset=0):
  223. self = space.allocate_instance(W_MMap, w_subtype)
  224. try:
  225. W_MMap.__init__(self, space,
  226. rmmap.mmap(fileno, length, flags, prot, access,
  227. offset))
  228. except OSError as e:
  229. raise mmap_error(space, e)
  230. except RMMapError as e:
  231. raise mmap_error(space, e)
  232. return space.wrap(self)
  233. elif rmmap._MS_WINDOWS:
  234. @unwrap_spec(fileno=int, length=int, tagname=str,
  235. access=int, offset=OFF_T)
  236. def mmap(space, w_subtype, fileno, length, tagname="",
  237. access=rmmap._ACCESS_DEFAULT, offset=0):
  238. self = space.allocate_instance(W_MMap, w_subtype)
  239. try:
  240. W_MMap.__init__(self, space,
  241. rmmap.mmap(fileno, length, tagname, access,
  242. offset))
  243. except OSError as e:
  244. raise mmap_error(space, e)
  245. except RMMapError as e:
  246. raise mmap_error(space, e)
  247. return space.wrap(self)
  248. W_MMap.typedef = TypeDef("mmap.mmap", None, None, "read-write",
  249. __new__ = interp2app(mmap),
  250. close = interp2app(W_MMap.close),
  251. read_byte = interp2app(W_MMap.read_byte),
  252. readline = interp2app(W_MMap.readline),
  253. read = interp2app(W_MMap.read),
  254. find = interp2app(W_MMap.find),
  255. rfind = interp2app(W_MMap.rfind),
  256. seek = interp2app(W_MMap.seek),
  257. tell = interp2app(W_MMap.tell),
  258. size = interp2app(W_MMap.descr_size),
  259. write = interp2app(W_MMap.write),
  260. write_byte = interp2app(W_MMap.write_byte),
  261. flush = interp2app(W_MMap.flush),
  262. move = interp2app(W_MMap.move),
  263. resize = interp2app(W_MMap.resize),
  264. __len__ = interp2app(W_MMap.__len__),
  265. __getitem__ = interp2app(W_MMap.descr_getitem),
  266. __setitem__ = interp2app(W_MMap.descr_setitem),
  267. __getslice__ = interp2app(W_MMap.descr_getslice),
  268. __setslice__ = interp2app(W_MMap.descr_setslice),
  269. )
  270. constants = rmmap.constants
  271. PAGESIZE = rmmap.PAGESIZE
  272. ALLOCATIONGRANULARITY = rmmap.ALLOCATIONGRANULARITY
  273. ACCESS_READ = rmmap.ACCESS_READ
  274. ACCESS_WRITE = rmmap.ACCESS_WRITE
  275. ACCESS_COPY = rmmap.ACCESS_COPY
  276. class Cache:
  277. def __init__(self, space):
  278. self.w_error = space.new_exception_class("mmap.error",
  279. space.w_EnvironmentError)
  280. def mmap_error(space, e):
  281. if isinstance(e, RValueError):
  282. return OperationError(space.w_ValueError, space.wrap(e.message))
  283. elif isinstance(e, RTypeError):
  284. return OperationError(space.w_TypeError, space.wrap(e.message))
  285. elif isinstance(e, OSError):
  286. w_error = space.fromcache(Cache).w_error
  287. return wrap_oserror(space, e, w_exception_class=w_error)
  288. else:
  289. # bogus 'e'?
  290. return OperationError(space.w_SystemError, space.wrap('%s' % e))
  291. mmap_error._dont_inline_ = True
  292. class MMapBuffer(Buffer):
  293. _immutable_ = True
  294. def __init__(self, space, mmap, readonly):
  295. self.space = space
  296. self.mmap = mmap
  297. self.readonly = readonly
  298. def getlength(self):
  299. return self.mmap.size
  300. def getitem(self, index):
  301. self.check_valid()
  302. return self.mmap.data[index]
  303. def getslice(self, start, stop, step, size):
  304. self.check_valid()
  305. if step == 1:
  306. return self.mmap.getslice(start, size)
  307. else:
  308. return Buffer.getslice(self, start, stop, step, size)
  309. def setitem(self, index, char):
  310. self.check_valid_writeable()
  311. self.mmap.data[index] = char
  312. def setslice(self, start, string):
  313. self.check_valid_writeable()
  314. self.mmap.setslice(start, string)
  315. def get_raw_address(self):
  316. self.check_valid()
  317. return self.mmap.data
  318. def check_valid(self):
  319. try:
  320. self.mmap.check_valid()
  321. except RValueError as v:
  322. raise mmap_error(self.space, v)
  323. def check_valid_writeable(self):
  324. try:
  325. self.mmap.check_valid()
  326. self.mmap.check_writeable()
  327. except RMMapError as v:
  328. raise mmap_error(self.space, v)