mgetl: fix trouble with long file and LF on Windows
[scilab.git] / scilab / modules / fileio / sci_gateway / cpp / sci_mgetl.cpp
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2006 - INRIA - Allan CORNET
4  * Copyright (C) 2010 - DIGITEO - Allan CORNET
5  *
6  * Copyright (C) 2012 - 2016 - Scilab Enterprises
7  *
8  * This file is hereby licensed under the terms of the GNU GPL v2.0,
9  * pursuant to article 5.3.4 of the CeCILL v.2.1.
10  * This file was originally licensed under the terms of the CeCILL v2.1,
11  * and continues to be available under such terms.
12  * For more information, see the COPYING file which you should have received
13  * along with this program.
14  *
15  */
16 /*--------------------------------------------------------------------------*/
17 #include "filemanager.hxx"
18 #include "fileio_gw.hxx"
19 #include "string.hxx"
20 #include "double.hxx"
21 #include "function.hxx"
22
23 extern "C"
24 {
25 #include "sci_malloc.h"
26 #include "mgetl.h"
27 #include "localization.h"
28 #include "Scierror.h"
29 #include "mopen.h"
30 #include "mclose.h"
31 #include "expandPathVariable.h"
32 #include "freeArrayOfString.h"
33 }
34
35 /*--------------------------------------------------------------------------*/
36 types::Function::ReturnValue sci_mgetl(types::typed_list &in, int _iRetCount, types::typed_list &out)
37 {
38     int iFileID = 0;
39     int iErr = 0;
40     bool bCloseFile = false;
41     int iLinesExcepted = -1;
42     int iLinesRead = -1;
43     wchar_t** wcReadedStrings   = NULL;
44
45     if (in.size() < 1 || in.size() > 2)
46     {
47         Scierror(77, _("%s: Wrong number of input arguments: %d to %d expected.\n"), "mgetl", 1, 2);
48         return types::Function::OK;
49     }
50
51     if (in.size() == 2)
52     {
53         //number of lines
54         if (in[1]->isDouble() == false)
55         {
56             Scierror(999, _("%s: Wrong type for input argument #%d: An integer value expected.\n"), "mgetl", 2);
57             return types::Function::Error;
58         }
59
60         if (in[1]->getAs<types::Double>()->isScalar() == false)
61         {
62             Scierror(999, _("%s: Wrong size for input argument #%d: An integer value expected.\n"), "mgetl", 2);
63             return types::Function::Error;
64         }
65
66         if (in[1]->getAs<types::Double>()->get(0) != (int)in[1]->getAs<types::Double>()->get(0))
67         {
68             Scierror(999, _("%s: Wrong value for input argument #%d: An integer value expected.\n"), "mgetl", 2);
69             return types::Function::Error;
70         }
71
72         iLinesExcepted = static_cast<int>(in[1]->getAs<types::Double>()->get(0));
73     }
74
75     if (in[0]->isDouble() && in[0]->getAs<types::Double>()->getSize() == 1)
76     {
77         iFileID = static_cast<int>(in[0]->getAs<types::Double>()->get(0));
78     }
79     else if (in[0]->isString() && in[0]->getAs<types::String>()->getSize() == 1)
80     {
81         wchar_t *expandedFileName = expandPathVariableW(in[0]->getAs<types::String>()->get(0));
82
83         iErr = mopen(expandedFileName, L"rt", 0, &iFileID);
84
85         if (iErr)
86         {
87             char* pst = wide_string_to_UTF8(expandedFileName);
88             switch (iErr)
89             {
90                 case MOPEN_NO_MORE_LOGICAL_UNIT:
91                     Scierror(66, _("%s: Too many files opened!\n"), "mgetl");
92                     break;
93                 case MOPEN_CAN_NOT_OPEN_FILE:
94                     Scierror(999, _("%s: Cannot open file %s.\n"), "mgetl", pst);
95                     break;
96                 case MOPEN_NO_MORE_MEMORY:
97                     Scierror(999, _("%s: No more memory.\n"), "mgetl");
98                     break;
99                 case MOPEN_INVALID_FILENAME:
100                     Scierror(999, _("%s: invalid filename %s.\n"), "mgetl", pst);
101                     break;
102                 default: //MOPEN_INVALID_STATUS
103                     Scierror(999, _("%s: invalid status.\n"), "mgetl");
104                     break;
105             }
106
107             FREE(pst);
108             FREE(expandedFileName);
109             return types::Function::Error;
110         }
111         FREE(expandedFileName);
112         bCloseFile = true;
113     }
114     else
115     {
116         //Error
117         Scierror(999, _("%s: Wrong type for input argument #%d: a String or Integer expected.\n"), "mgetl", 1);
118         return types::Function::Error;
119     }
120
121     switch (iFileID)
122     {
123         case 0: // stderr
124         case 6: // stdout
125             Scierror(999, _("%s: Wrong file descriptor: %d.\n"), "mgetl", iFileID);
126             return types::Function::Error;
127         default :
128         {
129             types::File* pFile = FileManager::getFile(iFileID);
130             // file opened with fortran open function
131             if (pFile == NULL || pFile->getFileType() == 1)
132             {
133                 Scierror(999, _("%s: Wrong file descriptor: %d.\n"), "mgetl", iFileID);
134                 return types::Function::Error;
135             }
136
137             if ((iLinesExcepted > 0) && (iFileID == 5))
138             {
139                 iLinesExcepted = 1;
140             }
141
142             iLinesRead = mgetl(iFileID, iLinesExcepted, &wcReadedStrings);
143
144             if (iLinesRead < 0)
145             {
146                 break;
147             }
148         }
149     }
150
151     if (wcReadedStrings && iLinesRead > 0)
152     {
153         types::String *pS = new types::String(iLinesRead, 1);
154         wchar_t** w = pS->get();
155         for (int i = 0; i < iLinesRead; ++i)
156         {
157             w[i] = wcReadedStrings[i];
158         }
159         out.push_back(pS);
160         FREE(wcReadedStrings);
161     }
162     else
163     {
164         out.push_back(types::Double::Empty());
165         if (wcReadedStrings)
166         {
167             FREE(wcReadedStrings);
168         }
169     }
170
171     if (bCloseFile)
172     {
173         mclose(iFileID);
174     }
175
176     return types::Function::OK;
177 }
178 /*--------------------------------------------------------------------------*/