[fileio] allow mopen and mclose to handle multiple files 99/21699/5
mottelet [Fri, 5 Feb 2021 14:23:04 +0000 (15:23 +0100)]
It would allow

files = listfiles("*.sce");
hash(mopen(files),"sha256")

if https://codereview.scilab.org/#/c/21697/ is merged, as hash() already
handles arrays of file descriptors.

Change-Id: I03e0224f66446f893336ccbe7569e01e460da119

scilab/modules/fileio/help/en_US/mclose.xml
scilab/modules/fileio/help/en_US/mopen.xml
scilab/modules/fileio/sci_gateway/cpp/sci_mclose.cpp
scilab/modules/fileio/sci_gateway/cpp/sci_mopen.cpp
scilab/modules/fileio/tests/unit_tests/mclose.tst
scilab/modules/fileio/tests/unit_tests/mopen.tst [new file with mode: 0644]

index 1209432..a9044c4 100644 (file)
 <refentry xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svg="http://www.w3.org/2000/svg" xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:db="http://docbook.org/ns/docbook" xmlns:scilab="http://www.scilab.org" xml:lang="en" xml:id="mclose">
     <refnamediv>
         <refname>mclose</refname>
-        <refpurpose>closes an opened file</refpurpose>
+        <refpurpose>closes opened files</refpurpose>
     </refnamediv>
     <refsynopsisdiv>
         <title>Syntax</title>
         <synopsis>
-            err = mclose([fd])
+            err = mclose(fd)
+            err = mclose(paths)
             mclose('all')
         </synopsis>
     </refsynopsisdiv>
                 <term>fd</term>
                 <listitem>
                     <para>
-                        a scalar: the <varname>fd</varname> parameter returned by the function <function>mopen</function> is used as a file descriptor.
+                        a matrix of integers: the <varname>fd</varname> matrix returned by the function <function>mopen</function> is used as a matrix of file descriptors.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>paths</term>
+                <listitem>
+                    <para>
+                        a matrix of strings: the absolute paths of files to be closed.
                     </para>
                 </listitem>
             </varlistentry>
             <varlistentry>
                 <term>err</term>
                 <listitem>
-                    <para>a scalar: an error indicator.</para>
+                    <para>a matrix of integers: error indicators.</para>
                 </listitem>
             </varlistentry>
         </variablelist>
@@ -48,9 +57,9 @@
     <refsection>
         <title>Description</title>
         <para>
-            <function>mclose</function> must be used to close a file opened by
+            <function>mclose</function> must be used to close files opened by
             <function>mopen</function>. If <varname>fd</varname> is omitted
-            <function>mclose</function> closes the last opend file.
+            <function>mclose</function> closes the last opened file.
         </para>
         <para>
             <code>mclose('all')</code> closes all files opened by
index 7c08db1..54481fd 100644 (file)
 <refentry xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svg="http://www.w3.org/2000/svg" xmlns:ns4="http://www.w3.org/1999/xhtml" xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:db="http://docbook.org/ns/docbook" xmlns:scilab="http://www.scilab.org" xml:id="mopen" xml:lang="en">
     <refnamediv>
         <refname>mopen</refname>
-        <refpurpose>opens a file in Scilab</refpurpose>
+        <refpurpose>opens files in Scilab</refpurpose>
     </refnamediv>
     <refsynopsisdiv>
         <title>Syntax</title>
-        <synopsis>[fd, err] = mopen(file [, mode, swap ])</synopsis>
+        <synopsis>[fd, err] = mopen(files [, mode, swap ])</synopsis>
     </refsynopsisdiv>
     <refsection>
         <title>Arguments</title>
         <variablelist>
             <varlistentry>
-                <term>file</term>
+                <term>files</term>
                 <listitem>
-                    <para>a character string containing the path of the file to open.</para>
+                    <para>a matrix of strings containing the paths of the files to open.</para>
                 </listitem>
             </varlistentry>
             <varlistentry>
                 <term>mode</term>
                 <listitem>
-                    <para>a character string specifying the access mode requested for the file.</para>
+                    <para>a string specifying the access mode requested for the files.</para>
                 </listitem>
             </varlistentry>
             <varlistentry>
@@ -52,7 +52,7 @@
             <varlistentry>
                 <term>err</term>
                 <listitem>
-                    <para>a scalar. Error indicator.</para>
+                    <para>a matrix of integers. Error indicators.</para>
                     <informaltable border="1">
                         <tr>
                             <td>error value:</td>
@@ -89,7 +89,7 @@
                 <term>fd</term>
                 <listitem>
                     <para>
-                        a scalar: a file descriptor (it's a positive integer).
+                        a matrix of file descriptors (they are positive integers).
                     </para>
                 </listitem>
             </varlistentry>
@@ -98,9 +98,9 @@
     <refsection>
         <title>Description</title>
         <para>
-            <function>mopen</function> may be used to open a <varname>file</varname> in a way
+            <function>mopen</function> may be used to open <varname>files</varname> in a way
             compatible with the C <function>fopen</function> procedure. Without
-            <varname>swap</varname> argument the <varname>file</varname> is supposed to be coded in "little endian IEEE
+            <varname>swap</varname> argument the <varname>files</varname> are supposed to be coded in "little endian IEEE
             format" and data are swapped if necessary to match the IEEE format of
             the processor.
         </para>
index c802d54..d1372b0 100644 (file)
@@ -1,8 +1,8 @@
 /*
  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
  *  Copyright (C) 2010-2010 - DIGITEO - Antoine ELIAS
- *
- * Copyright (C) 2012 - 2016 - Scilab Enterprises
+ *  Copyright (C) 2012 - 2016 - Scilab Enterprises
+ *  Copyright (C) 2021 - St├ęphane MOTTELET
  *
  * This file is hereby licensed under the terms of the GNU GPL v2.0,
  * pursuant to article 5.3.4 of the CeCILL v.2.1.
@@ -26,69 +26,84 @@ extern "C"
 #include "localization.h"
 #include "mclose.h"
 #include "os_string.h"
+#include "sciprint.h"
 }
-#include "stdio.h"
 
 types::Function::ReturnValue sci_mclose(types::typed_list &in, int _iRetCount, types::typed_list &out)
 {
+    types::Double* pDblRet;
     int iRet = 0;
+
     if (in.size() == 0)
     {
         //close current file
         iRet = mcloseCurrentFile();
+        pDblRet = new types::Double(static_cast<double>(iRet));
     }
     else if (in.size() == 1)
     {
         if (in[0]->isString())
         {
             types::String *pS = in[0]->getAs<types::String>();
-            if (pS->getSize() != 1)
-            {
-                Scierror(999, _("%s: Wrong type for input argument #%d: A String expected.\n"), "mclose", 1);
-                return types::Function::Error;
-            }
+            pDblRet = new types::Double(pS->getDims(),pS->getDimsArray());
+            pDblRet->setZeros();
 
-            if (FileManager::isOpened(pS->get(0)))
-            {
-                int iFileID = FileManager::getFileID(pS->get(0));
-                if (iFileID == -1)
-                {
-                    char* pst = wide_string_to_UTF8(pS->get(0));
-                    Scierror(999, _("%s: File not found: '%s'.\n"), "mclose", pst);
-                    FREE(pst);
-                    return types::Function::Error;
-                }
-                iRet = mclose(iFileID);
-            }
-            else if (os_wcsicmp(pS->get(0), L"all") == 0)
+            if (pS->getSize()==1 && os_wcsicmp(pS->get(0), L"all") == 0)
             {
                 iRet = mcloseAll();
+                pDblRet->set(0,static_cast<double>(iRet));
             }
             else
             {
-                Scierror(999, _("%s: Wrong input arguments: '%s' expected.\n"), "mclose", "all");
-                return types::Function::Error;
+                for (int i=0; i < pS->getSize(); i++)
+                {
+                    if (FileManager::isOpened(pS->get(i)))
+                    {
+                        int iFileID = FileManager::getFileID(pS->get(i));
+                        if (iFileID == -1)
+                        {
+                            char* pst = wide_string_to_UTF8(pS->get(i));
+                            Scierror(999, _("%s: File not found: '%s'.\n"), "mclose", pst);
+                            FREE(pst);
+                            pDblRet->killMe();
+                            return types::Function::Error;
+                        }
+                        iRet = mclose(iFileID);
+                        pDblRet->set(i,static_cast<double>(iRet));
+                    } else {
+                         sciprint(_("%s: Cannot close file %ls: File is not active.\n"), "mclose", pS->get(i));
+                    }
+                }
             }
         }
         else if (in[0]->isDouble())
         {
-            types::Double* pD = in[0]->getAs<types::Double>();
-            if (pD->getSize() != 1 || pD->isComplex())
+            types::Double* pDblIn = in[0]->getAs<types::Double>();
+
+            if (pDblIn->isComplex())
             {
-                Scierror(999, _("%s: Wrong type for input argument #%d: A real expected.\n"), "mclose", 1);
+                Scierror(999, _("%s: Wrong type for input argument #%d: A real matrix expected.\n"), "mclose", 1);
                 return types::Function::Error;
             }
 
-            int iVal = static_cast<int>(pD->get(0));
-            switch (iVal)
+            pDblRet = new types::Double(pDblIn->getDims(),pDblIn->getDimsArray());
+            pDblRet->setZeros();
+
+            for (int i=0; i < pDblIn->getSize(); i++)
             {
-                case 0: // stderr
-                case 5: // stdin
-                case 6: // stdout
-                    Scierror(999, _("%s: Wrong file descriptor: %d.\n"), "mclose", iVal);
-                    return types::Function::Error;
+                int iVal = static_cast<int>(pDblIn->get(i));
+                switch (iVal)
+                {
+                    case 0: // stderr
+                    case 5: // stdin
+                    case 6: // stdout
+                        Scierror(999, _("%s: Wrong file descriptor: %d.\n"), "mclose", iVal);
+                        pDblRet->killMe();
+                        return types::Function::Error;
+                }
+                iRet = mclose(iVal);
+                pDblRet->set(i,static_cast<double>(iRet));
             }
-            iRet = mclose(iVal);
         }
         else
         {
@@ -102,8 +117,7 @@ types::Function::ReturnValue sci_mclose(types::typed_list &in, int _iRetCount, t
         return types::Function::Error;
     }
 
-    types::Double* pD = new types::Double(static_cast<double>(iRet));
-    out.push_back(pD);
+    out.push_back(pDblRet);
     return types::Function::OK;
 }
 /*--------------------------------------------------------------------------*/
index 8043344..8305c17 100644 (file)
@@ -56,15 +56,6 @@ types::Function::ReturnValue sci_mopen(types::typed_list &in, int _iRetCount, ty
             return types::Function::Error;
         }
 
-        types::String* pS1 = in[0]->getAs<types::String>();
-        if (pS1->getSize() != 1)
-        {
-            Scierror(999, _("%s: Wrong size for input argument #%d: string expected.\n"), "mopen", 1);
-            return types::Function::Error;
-        }
-
-        pstFilename = expandPathVariableW(pS1->get(0));
-
         if (in.size() >= 2)
         {
             //mode
@@ -125,55 +116,61 @@ types::Function::ReturnValue sci_mopen(types::typed_list &in, int _iRetCount, ty
         return types::Function::Error;
     }
 
-    wchar_t* pwstTemp = get_full_pathW(pstFilename);
-    iErr = mopen(pwstTemp, pstMode, iSwap, &iID);
-    if (iErr != MOPEN_NO_ERROR)
+    types::String* pS1 = in[0]->getAs<types::String>();
+    types::Double* pD = new types::Double(pS1->getRows(),pS1->getCols());
+    types::Double* pD2 = new types::Double(pS1->getRows(),pS1->getCols());
+
+    for (int i=0; i<pS1->getSize(); i++)
     {
-        //mange file open errors
-        if (_iRetCount <= 1)
+        pstFilename = expandPathVariableW(pS1->get(i));
+        wchar_t* pwstTemp = get_full_pathW(pstFilename);
+        iErr = mopen(pwstTemp, pstMode, iSwap, &iID);
+        
+        if (iErr != MOPEN_NO_ERROR)
         {
-            switch (iErr)
+            //mange file open errors
+            if (_iRetCount <= 1)
             {
-                case MOPEN_CAN_NOT_OPEN_FILE:
+                switch (iErr)
                 {
-                    char* pst = wide_string_to_UTF8(pstFilename);
-                    Scierror(999, _("%s: Cannot open file %s.\n"), "mopen", pst);
-                    FREE(pst);
-                    FREE(pstFilename);
-                    FREE(pwstTemp);
-                    pstFilename = NULL;
-                    return types::Function::Error;
-                }
-                case MOPEN_INVALID_FILENAME:
-                {
-                    Scierror(999, _("%s: invalid filename.\n"), "mopen");
-                    FREE(pstFilename);
-                    FREE(pwstTemp);
-                    pstFilename = NULL;
-                    return types::Function::Error;
-                }
-                case MOPEN_INVALID_STATUS:
-                {
-                    Scierror(999, _("%s: invalid status.\n"), "mopen");
-                    FREE(pstFilename);
-                    FREE(pwstTemp);
-                    pstFilename = NULL;
-                    return types::Function::Error;
+                    case MOPEN_CAN_NOT_OPEN_FILE:
+                    {
+                        char* pst = wide_string_to_UTF8(pstFilename);
+                        Scierror(999, _("%s: Cannot open file %s.\n"), "mopen", pst);
+                        FREE(pst);
+                    }
+                    case MOPEN_INVALID_FILENAME:
+                    {
+                        Scierror(999, _("%s: invalid filename.\n"), "mopen");
+                    }
+                    case MOPEN_INVALID_STATUS:
+                    {
+                        Scierror(999, _("%s: invalid status.\n"), "mopen");
+                    }
                 }
+                FREE(pstFilename);
+                FREE(pwstTemp);
+                pD->killMe();
+                pD2->killMe();
+                return types::Function::Error;
             }
         }
-    }
 
-    FREE(pwstTemp);
-    FREE(pstFilename);
+        FREE(pwstTemp);
+        FREE(pstFilename);        
+        pD->set(i,static_cast<double>(iID));
+        pD2->set(i,static_cast<double>(iErr));        
+    }
 
-    types::Double* pD = new types::Double(static_cast<double>(iID));
     out.push_back(pD);
 
     if (_iRetCount == 2)
     {
-        types::Double* pD2 = new types::Double(iErr);
         out.push_back(pD2);
     }
+    else
+    {
+        pD2->killMe();        
+    }
     return types::Function::OK;
 }
index 0cc2a8b..ebfbcd6 100644 (file)
@@ -8,14 +8,20 @@
 
 // <-- CLI SHELL MODE -->
 
-fd = mopen(TMPDIR + filesep() + 'mclose_tst','wt');
-mclose(TMPDIR + filesep() + 'mclose_tst');
+fd(1) = mopen(TMPDIR + filesep() + 'mclose_tst_1','wt');
+fd(2) = mopen(TMPDIR + filesep() + 'mclose_tst_2','wt');
 
-ierr = execstr('mclose([''file1'',''file2''])','errcatch');
-if ierr <> 999 then pause,end
+mclose(fd);
 
-ierr = execstr('mclose([1,2])','errcatch');
-if ierr <> 999 then pause,end
+mopen(TMPDIR + filesep() + 'mclose_tst_1','wt');
+mopen(TMPDIR + filesep() + 'mclose_tst_2','wt');
+
+mclose(TMPDIR + filesep() + ['mclose_tst_1','mclose_tst_2']);
+
+mopen(TMPDIR + filesep() + 'mclose_tst_1','wt');
+mopen(TMPDIR + filesep() + 'mclose_tst_2','wt');
+
+mclose("all")
 
 ierr = execstr('mclose(0)','errcatch');
 if ierr <> 999 then pause,end
diff --git a/scilab/modules/fileio/tests/unit_tests/mopen.tst b/scilab/modules/fileio/tests/unit_tests/mopen.tst
new file mode 100644 (file)
index 0000000..3ec0a5d
--- /dev/null
@@ -0,0 +1,19 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2021 - St├ęphane MOTTELET
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+
+// <-- CLI SHELL MODE -->
+
+fd = mopen(TMPDIR + filesep() + ['mclose_tst_1','mclose_tst_2'],'wt');
+mputl("test string 1",fd(1));
+mputl("test string 2",fd(2));
+mclose(fd);
+
+fd = mopen(TMPDIR + filesep() + ['mclose_tst_1','mclose_tst_2']);
+str = [mgetl(fd(1)),mgetl(fd(2))];
+mclose(fd);
+
+assert_checkequal(str,["test string 1","test string 2"]);
\ No newline at end of file