[pypy-commit] pypy file-support-in-rpython: more support for files in RPython

fijal noreply at buildbot.pypy.org
Tue Sep 17 20:20:00 CEST 2013


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: file-support-in-rpython
Changeset: r66990:e9d5d97ed6b6
Date: 2013-09-17 20:19 +0200
http://bitbucket.org/pypy/pypy/changeset/e9d5d97ed6b6/

Log:	more support for files in RPython

diff --git a/rpython/rlib/test/test_rfile.py b/rpython/rlib/test/test_rfile.py
--- a/rpython/rlib/test/test_rfile.py
+++ b/rpython/rlib/test/test_rfile.py
@@ -4,8 +4,12 @@
 from rpython.rlib import rfile
 
 class TestFile(BaseRtypingTest):
+    def setup_class(cls):
+        cls.tmpdir = udir.join('test_rfile')
+        cls.tmpdir.ensure(dir=True)
+
     def test_open(self):
-        fname = str(udir.join('test_file', 'file_1'))
+        fname = str(self.tmpdir.join('file_1'))
 
         def f():
             f = open(fname, "w")
diff --git a/rpython/rtyper/lltypesystem/rfile.py b/rpython/rtyper/lltypesystem/rfile.py
--- a/rpython/rtyper/lltypesystem/rfile.py
+++ b/rpython/rtyper/lltypesystem/rfile.py
@@ -1,11 +1,14 @@
 
 import os
 from rpython.rlib import rposix
+from rpython.rlib.rarithmetic import r_uint
+from rpython.annotator import model as annmodel
 from rpython.rtyper.rtyper import Repr
-from rpython.rtyper.lltypesystem import lltype, rffi
-from rpython.rtyper.lltypesystem.rstr import string_repr
+from rpython.rtyper.lltypesystem import lltype, rffi, llmemory
+from rpython.rtyper.lltypesystem.rstr import string_repr, STR
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
 from rpython.rtyper.annlowlevel import hlstr
+from rpython.rtyper.lltypesystem.lloperation import llop
 
 FILE = lltype.Struct('FILE') # opaque type maybe
 FILE_WRAPPER = lltype.GcStruct("FileWrapper", ('file', lltype.Ptr(FILE)))
@@ -14,39 +17,74 @@
 
 c_open = rffi.llexternal('fopen', [rffi.CCHARP, rffi.CCHARP],
                           lltype.Ptr(FILE), compilation_info=eci)
+c_close = rffi.llexternal('fclose', [lltype.Ptr(FILE)], rffi.INT,
+                          compilation_info=eci)
+c_write = rffi.llexternal('fwrite', [rffi.CCHARP, rffi.SIZE_T, rffi.SIZE_T,
+                                     lltype.Ptr(FILE)], rffi.SIZE_T)
 
 def ll_open(name, mode):
     file_wrapper = lltype.malloc(FILE_WRAPPER)
-    name = hlstr(name)
-    mode = hlstr(mode)
-    with rffi.scoped_str2charp(name) as ll_name:
-        with rffi.scoped_str2charp(mode) as ll_mode:
-            ll_f = c_open(ll_name, ll_mode)
-            if not ll_f:
-                errno = rposix.get_errno()
-                raise OSError(errno, os.strerror(errno))
-            file_wrapper.file = ll_f
+    ll_name = rffi.str2charp(name)
+    ll_mode = rffi.str2charp(mode)
+    try:
+        ll_f = c_open(ll_name, ll_mode)
+        if not ll_f:
+            errno = rposix.get_errno()
+            raise OSError(errno, os.strerror(errno))
+        file_wrapper.file = ll_f
+    finally:
+        lltype.free(ll_name, flavor='raw')
+        lltype.free(ll_mode, flavor='raw')
     return file_wrapper
 
 def ll_write(file_wrapper, value):
+    ll_file = file_wrapper.file
     value = hlstr(value)
-    with rffi.scoped_str2charp(value) as ll_value:
-        pass
+    assert value is not None
+    ll_value = rffi.get_nonmovingbuffer(value)
+    try:
+        # NO GC OPERATIONS HERE
+        total_bytes = 0
+        ll_current = ll_value
+        while total_bytes < len(value):
+            bytes = c_write(ll_current, 1, len(value) - r_uint(total_bytes),
+                            ll_file)
+            if bytes == 0:
+                errno = rposix.get_errno()
+                raise OSError(errno, os.strerror(errno))
+            total_bytes += bytes
+            ll_current = rffi.cast(rffi.CCHARP,
+                                   rffi.cast(lltype.Unsigned, ll_value) +
+                                   total_bytes)
+    finally:
+        rffi.free_nonmovingbuffer(value, ll_value)
 
 def ll_close(file_wrapper):
-    pass
+    if file_wrapper.file:
+        # double close is allowed
+        res = c_close(file_wrapper.file)
+        file_wrapper.file = lltype.nullptr(FILE)
+        if res == -1:
+            errno = rposix.get_errno()
+            raise OSError(errno, os.strerror(errno))
 
 class FileRepr(Repr):
     lowleveltype = lltype.Ptr(FILE_WRAPPER)
 
     def __init__(self, typer):
-        pass
+        Repr.__init__(self)
 
     def rtype_constructor(self, hop):
-        arg_0 = hop.inputarg(string_repr, 0)
-        arg_1 = hop.inputarg(string_repr, 1)
+        repr = hop.rtyper.getrepr(annmodel.SomeString())
+        arg_0 = hop.inputarg(repr, 0)
+        arg_1 = hop.inputarg(repr, 1)
         hop.exception_is_here()
-        return hop.gendirectcall(ll_open, arg_0, arg_1)
+        open = hop.rtyper.getannmixlevel().delayedfunction(
+            ll_open, [annmodel.SomeString()] * 2,
+            annmodel.SomePtr(self.lowleveltype))
+        v_open = hop.inputconst(lltype.typeOf(open), open)
+        return hop.genop('direct_call', [v_open, arg_0, arg_1],
+                         resulttype=self)
 
     def rtype_method_write(self, hop):
         args_v = hop.inputargs(self, string_repr)


More information about the pypy-commit mailing list