read() error msg fixed
[scilab.git] / scilab / modules / io / sci_gateway / cpp / sci_read.cpp
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2014 - Scilab Enterprises - Antoine ELIAS
4 * Copyright (C) 2015 - Scilab Enterprises - Sylvain GENIN
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 <string.h>
18 #include "function.hxx"
19 #include "io_gw.hxx"
20 #include "string.hxx"
21 #include "double.hxx"
22 #include "int.hxx"
23 #include "filemanager.hxx"
24 #include "readwrite.hxx"
25
26 extern "C"
27 {
28 #include "sci_malloc.h"
29 #include "Scierror.h"
30 #include "expandPathVariable.h"
31
32     extern int C2F(clunit)(int*, char const*, int*, int);
33
34     extern int C2F(readdoublefile)(int* ID, double* dat, int* m, int* n, int* err);
35     extern int C2F(readdoublefileform)(int* ID, char* form, double* dat, int* m, int* n, int* err, int);
36     extern int C2F(readdoublelinefile)(int* ID, double* dat, int* n, int* err);
37     extern int C2F(readdoublelinefileform)(int* ID, char* form, double* dat, int* n, int* err, int);
38
39     extern int C2F(readintfileform)(int* ID, char* form, int* dat, int* m, int* n, int* err, int);
40     extern int C2F(readintlinefileform)(int* ID, char* form, int* dat, int* n, int* err, int);
41
42     extern int C2F(readstringfile)(int* ID, char* form, char* dat, int* siz, int* err, int);
43     extern int C2F(readstring)(char* form, char* dat, int* siz, int* err, int);
44
45 }
46
47 template<typename T>
48 bool is_of_type(const std::string & Str)
49 {
50     std::istringstream iss(Str);
51
52     T tmp;
53     return (iss >> tmp) && (iss.eof());
54 }
55
56 /*--------------------------------------------------------------------------*/
57 types::Function::ReturnValue sci_read(types::typed_list &in, int _iRetCount, types::typed_list &out)
58 {
59     int iID = 0;
60     int iAcces = 0;
61     int iRhs = static_cast<int>(in.size());
62     char* pstFormat = NULL;
63     types::InternalType::ScilabType itTypeOfData = types::InternalType::ScilabDouble;
64
65     if (iRhs < 3 || iRhs > 5)
66     {
67         Scierror(77, _("%s: Wrong number of input argument(s): %d to %d expected.\n"), "read", 2, 4);
68         return types::Function::Error;
69     }
70
71     //file
72     if (in[0]->isString())
73     {
74         types::String* pSPath = in[0]->getAs<types::String>();
75
76         if (pSPath->isScalar() == false)
77         {
78             Scierror(999, _("%s: Wrong type for input argument #%d : string expected.\n"), "read", 1);
79             return types::Function::Error;
80         }
81
82         int piMode[2] = { -1, 0};
83         char* pstFilename = wide_string_to_UTF8(pSPath->get(0));
84         int iErr = C2F(clunit)(&iID, pstFilename, piMode, (int)strlen(pstFilename));
85
86         if (iErr == 240)
87         {
88             closeFile(in[0], iID);
89             Scierror(999, _("File \"%s\" already exists or directory write access denied.\n"), pstFilename);
90             FREE(pstFilename);
91             return types::Function::Error;
92         }
93
94         if (iErr == 241)
95         {
96             closeFile(in[0], iID);
97             Scierror(999, _("File \"%s\" does not exist or read access denied.\n"), pstFilename);
98             FREE(pstFilename);
99             return types::Function::Error;
100         }
101
102         FREE(pstFilename);
103     }
104     else if (in[0]->isDouble())
105     {
106         types::Double* pDId = in[0]->getAs<types::Double>();
107         if (pDId->isScalar() == false)
108         {
109             Scierror(999, _("%s: Wrong type for input argument #%d : A real scalar expected.\n"), "read", 1);
110             return types::Function::Error;
111         }
112
113         iID = (int)pDId->get(0);
114         if (iID == -1)
115         {
116             iID = FileManager::getCurrentFile();
117         }
118     }
119     else
120     {
121         Scierror(999, _("%s: Wrong type for input argument #%d : A real scalar or file descriptor expected.\n"), "read", 1);
122         return types::Function::Error;
123     }
124
125     if (iRhs > 3)
126     {
127         int iPos = iRhs - 1;
128         if (in[iPos]->isString() == false)
129         {
130             closeFile(in[0], iID);
131             Scierror(999, _("%s: Wrong type for input argument #%d : string expected.\n"), "read", iRhs);
132             return types::Function::Error;
133         }
134
135         types::String* pSFormat = in[iPos]->getAs<types::String>();
136         if (pSFormat->isScalar() == false)
137         {
138             closeFile(in[0], iID);
139             Scierror(999, _("%s: Wrong type for input argument #%d : string expected.\n"), "read", iRhs);
140             return types::Function::Error;
141         }
142
143         //checkformat
144         pstFormat = wide_string_to_UTF8(pSFormat->get(0));
145
146         itTypeOfData = checkformat(pstFormat);
147         if (itTypeOfData == types::InternalType::ScilabNull)
148         {
149             FREE(pstFormat);
150             closeFile(in[0], iID);
151             Scierror(999, _("Incorrect file or format.\n"));
152             return types::Function::Error;
153         }
154     }
155
156     int error = 0;
157
158     if (in[1]->isDouble() == false)
159     {
160         if (pstFormat)
161         {
162             FREE(pstFormat);
163         }
164
165         closeFile(in[0], iID);
166         Scierror(999, _("%s: Wrong type for input argument #%d: A scalar integer value expected.\n"), "read", 2);
167         return types::Function::Error;
168     }
169
170     types::Double* pIn1 = in[1]->getAs<types::Double>();
171     if (pIn1->isScalar() == false)
172     {
173         if (pstFormat)
174         {
175             FREE(pstFormat);
176         }
177         closeFile(in[0], iID);
178         Scierror(999, _("%s: Wrong size for input argument #%d: A scalar integer value expected.\n"), "read", 2);
179         return types::Function::Error;
180     }
181
182     if (in[2]->isDouble() == false)
183     {
184         if (pstFormat)
185         {
186             FREE(pstFormat);
187         }
188         closeFile(in[0], iID);
189         Scierror(999, _("%s: Wrong type for input argument #%d: A scalar integer value expected.\n"), "read", 3);
190         return types::Function::Error;
191     }
192
193     types::Double* pIn2 = in[2]->getAs<types::Double>();
194     if (pIn2->isScalar() == false)
195     {
196         if (pstFormat)
197         {
198             FREE(pstFormat);
199         }
200         closeFile(in[0], iID);
201         Scierror(999, _("%s: Wrong size for input argument #%d: A scalar integer value expected.\n"), "read", 3);
202         return types::Function::Error;
203     }
204
205     int iRows = (int)pIn1->get(0);
206     int iCols = (int)pIn2->get(0);
207
208     //test dims
209     if ( (iCols <= 0) || (iRows == 0))
210     {
211         if (pstFormat)
212         {
213             FREE(pstFormat);
214         }
215         out.push_back(types::Double::Empty());
216         closeFile(in[0], iID);
217         return types::Function::OK;
218     }
219
220     if (iRows < 0)
221     {
222         if (iID != 5 /*stdin*/)
223         {
224             switch (itTypeOfData)
225             {
226                 case types::InternalType::ScilabDouble:
227                 {
228                     iRows = 1;
229                     types::Double* pD = new types::Double(iRows, iCols, false);
230
231                     if (pstFormat == NULL)
232                     {
233                         double* pdData = new double[iCols];
234                         while (error == 0)
235                         {
236                             C2F(readdoublelinefile)(&iID, pdData, &iCols, &error);
237                             if (error == 0)
238                             {
239                                 pD->resize(iRows, iCols);
240                                 for (int i = 0; i < iCols; ++i)
241                                 {
242                                     pD->set((iRows - 1), i, pdData[i]);
243                                 }
244                                 ++iRows;
245                             }
246                         }
247                         delete[] pdData;
248                     }
249                     else
250                     {
251                         double* pdData = new double[iCols];
252                         while (error == 0)
253                         {
254                             C2F(readdoublelinefileform)(&iID, pstFormat, pdData, &iCols, &error, (int)strlen(pstFormat));
255                             if (error == 0)
256                             {
257                                 pD->resize(iRows, iCols);
258                                 for (int i = 0; i < iCols; ++i)
259                                 {
260                                     pD->set((iRows - 1), i, pdData[i]);
261                                 }
262                                 ++iRows;
263                             }
264                         }
265                         delete[] pdData;
266                     }
267
268                     if (error != 2)
269                     {
270                         out.push_back(pD);
271                     }
272                     else
273                     {
274                         delete pD;
275                     }
276                 }
277                 break;
278                 case types::InternalType::ScilabInt32:
279                 {
280                     iRows = 1;
281                     types::Int32* pI = new types::Int32(iRows, iCols);
282                     int* piData = new int[iCols];
283                     while (error == 0)
284                     {
285                         C2F(readintlinefileform)(&iID, pstFormat, piData, &iCols, &error, (int)strlen(pstFormat));
286                         if (error == 0)
287                         {
288                             pI->resize(iRows, iCols);
289                             for (int i = 0; i < iCols; ++i)
290                             {
291                                 pI->set((iRows - 1), i, piData[i]);
292                             }
293                             ++iRows;
294                         }
295                     }
296
297                     delete[] piData;
298
299                     if (error != 2)
300                     {
301                         out.push_back(pI);
302                     }
303                     else
304                     {
305                         delete pI;
306                     }
307                 }
308                 break;
309                 case types::InternalType::ScilabString:
310                 {
311                     if (iCols != 1)
312                     {
313                         if (pstFormat)
314                         {
315                             FREE(pstFormat);
316                         }
317                         closeFile(in[0], iID);
318                         Scierror(999, _("%s: Wrong input argument %d.\n"), "read", 3);
319                         return types::Function::Error;
320                     }
321                     else
322                     {
323                         iRows = 1;
324                         types::String* pS = new types::String(iRows, iCols);
325                         char pCt[4096];
326
327                         while (error == 0)
328                         {
329                             int siz = 0;
330                             C2F(readstringfile)(&iID, pstFormat, pCt, &siz, &error, (int)strlen(pstFormat));
331                             pCt[siz] = '\0';
332
333                             if (error == 0)
334                             {
335                                 pS->resize(iRows, iCols);
336                                 pS->set((iRows - 1), (iCols - 1), pCt);
337                                 ++iRows;
338                             }
339                         }
340
341                         if (error != 2)
342                         {
343                             // on empty file, data are not set
344                             if (pS->get(0) == NULL)
345                             {
346                                 out.push_back(types::Double::Empty());
347                             }
348                             else
349                             {
350                                 out.push_back(pS);
351                             }
352                         }
353                         else
354                         {
355                             delete pS;
356                         }
357                     }
358                 }
359                 break;
360                 default:
361                 {
362                     if (pstFormat)
363                     {
364                         FREE(pstFormat);
365                     }
366                     closeFile(in[0], iID);
367                     Scierror(999, _("%s: Wrong type for input argument #%d : string expected.\n"), "read", 2);
368                     return types::Function::Error;
369                 }
370             }
371
372             closeFile(in[0], iID);
373         }
374         else//read from the console
375         {
376             switch (itTypeOfData)
377             {
378                 case types::InternalType::ScilabDouble:
379                 {
380                     iRows = 1;
381                     types::Double* pD = new types::Double(iRows, iCols, false);
382
383                     char pstString[4] = "(a)";
384                     char pCt[4096];
385
386                     while (error != 2)
387                     {
388                         int siz = 0;
389                         C2F(readstring)(pstString, pCt, &siz, &error, (int)strlen(pstString));
390                         pCt[siz] = '\0';
391
392                         if ((siz == 1) && (pCt[0] == ' '))
393                         {
394                             break;
395                         }
396
397                         char* pch;
398                         int iColsTempo = 0;
399                         pch = strtok(pCt, " ");
400                         double* pdData = new double[iCols];
401                         while ((pch != NULL) && (error == 0) && (iColsTempo < iCols))
402                         {
403                             if (is_of_type<double>(pch))
404                             {
405                                 pdData[iColsTempo] = atof(pch);
406                                 iColsTempo++;
407                             }
408                             else
409                             {
410                                 error = 2;
411                             }
412                             pch = strtok(NULL, " ");
413                         }
414
415                         if ((siz == 1) && (iColsTempo == 0))
416                         {
417                             delete[] pdData;
418                             break;
419                         }
420                         if (iColsTempo != iCols)
421                         {
422                             delete[] pdData;
423                             delete pD;
424                             if (pstFormat)
425                             {
426                                 FREE(pstFormat);
427                             }
428
429                             Scierror(999, _("%s: Input missing from console.\n"), "read");
430                             return types::Function::Error;
431                         }
432                         else
433                         {
434                             pD->resize(iRows, iCols);
435                             for (int i = 0; i < iCols; i++)
436                             {
437                                 pD->set((iRows - 1), i, pdData[i]);
438                             }
439                             delete[] pdData;
440                         }
441
442                         //next line
443                         ++iRows;
444                     }
445
446                     if (error == 0)
447                     {
448                         out.push_back(pD);
449                     }
450                 }
451                 break;
452                 case types::InternalType::ScilabInt32:
453                 {
454                     if (pstFormat)
455                     {
456                         FREE(pstFormat);
457                     }
458
459                     Scierror(999, _("Incorrect file or format.\n"));
460                     return types::Function::Error;
461                 }
462                 case types::InternalType::ScilabString:
463                 {
464                     if (iCols != 1)
465                     {
466                         if (pstFormat)
467                         {
468                             FREE(pstFormat);
469                         }
470
471                         Scierror(999, _("%s: Wrong input argument %d.\n"), "read", 3);
472                         return types::Function::Error;
473                     }
474                     else
475                     {
476                         bool bEndWrite = false;
477                         iRows = 1;
478                         types::String* pS = new types::String(iRows, iCols);
479                         char pCt[4096];
480
481                         for (; bEndWrite == false; iRows++)
482                         {
483                             int siz = 0;
484                             C2F(readstring)(pstFormat, pCt, &siz, &error, (int)strlen(pstFormat));
485                             pCt[siz] = '\0';
486
487                             if ((siz == 1) && (pCt[0] == ' '))
488                             {
489                                 bEndWrite = true;
490                             }
491                             else
492                             {
493                                 pS->resize(iRows, iCols);
494                                 pS->set((iRows - 1), (iCols - 1), pCt);
495                             }
496                         }
497
498                         if (error == 0)
499                         {
500                             out.push_back(pS);
501                         }
502                         else
503                         {
504                             delete pS;
505                         }
506                     }
507                 }
508                 break;
509                 default:
510                     break;
511             }
512         }
513     }
514     else
515     {
516         if (iID != 5 /*stdin*/)
517         {
518             switch (itTypeOfData)
519             {
520                 case types::InternalType::ScilabDouble:
521                 {
522                     types::Double* pD = new types::Double(iRows, iCols, false);
523                     double* pd = pD->get();
524
525                     if (pstFormat == NULL)
526                     {
527                         C2F(readdoublefile)(&iID, pd, &iRows, &iCols, &error);
528                     }
529                     else
530                     {
531                         C2F(readdoublefileform)(&iID, pstFormat, pd, &iRows, &iCols, &error, (int)strlen(pstFormat));
532                     }
533
534                     if (error == 0)
535                     {
536                         out.push_back(pD);
537                     }
538                     else
539                     {
540                         delete pD;
541                     }
542                 }
543                 break;
544                 case types::InternalType::ScilabInt32:
545                 {
546                     types::Int32* pI = new types::Int32(iRows, iCols);
547                     int* pi = pI->get();
548
549                     C2F(readintfileform)(&iID, pstFormat, pi, &iRows, &iCols, &error, (int)strlen(pstFormat));
550
551                     if (error == 0)
552                     {
553                         out.push_back(pI);
554                     }
555                     else
556                     {
557                         delete pI;
558                     }
559                 }
560                 break;
561                 case types::InternalType::ScilabString:
562                 {
563                     types::String* pS = new types::String(iRows, iCols);
564                     char pCt[4096];
565                     for (int i = 0; i < iCols * iRows; ++i)
566                     {
567                         int siz = 0;
568                         C2F(readstringfile)(&iID, pstFormat, pCt, &siz, &error, (int)strlen(pstFormat));
569                         pCt[siz] = '\0';
570                         pS->set(i, pCt);
571                     }
572
573                     if (error == 0)
574                     {
575                         out.push_back(pS);
576                     }
577                     else
578                     {
579                         delete pS;
580                     }
581                 }
582                 break;
583                 default:
584                 {
585                     if (pstFormat)
586                     {
587                         FREE(pstFormat);
588                     }
589
590                     Scierror(999, _("%s: Wrong type for input argument #%d : string expected.\n"), "read", 2);
591                     closeFile(in[0], iID);
592                     return types::Function::Error;
593                 }
594             }
595
596             //close file
597             closeFile(in[0], iID);
598
599             if (error == 2)
600             {
601                 if (pstFormat)
602                 {
603                     FREE(pstFormat);
604                 }
605
606                 Scierror(999, _("Incorrect file or format.\n"));
607                 return types::Function::Error;
608             }
609         }
610         else//read from the console
611         {
612             switch (itTypeOfData)
613             {
614                 case types::InternalType::ScilabDouble:
615                 {
616                     types::Double* pD = new types::Double(iRows, iCols, false);
617
618                     char pstString[4] = "(a)";
619                     char pCt[4096];
620
621                     for (int i = 0; i < iRows && error == 0; ++i)
622                     {
623                         int siz = 0;
624                         C2F(readstring)(pstString, pCt, &siz, &error, (int)strlen(pstString));
625                         pCt[siz] = '\0';
626
627                         char* pch;
628                         int iColsTempo = 0;
629                         pch = strtok(pCt, " ");
630                         while (pch != NULL && error == 0)
631                         {
632                             if (is_of_type<double>(pch))
633                             {
634                                 pD->set(i, iColsTempo, atof(pch));
635                                 iColsTempo++;
636                             }
637                             else
638                             {
639                                 error = 2;
640                             }
641                             pch = strtok(NULL, " ");
642                         }
643
644                         if (iColsTempo != iCols)
645                         {
646                             delete pD;
647                             FREE(pstFormat);
648                             Scierror(999, _("%s: Input missing from console.\n"), "read");
649                             return types::Function::Error;
650                         }
651                     }
652
653                     if (error == 0)
654                     {
655                         out.push_back(pD);
656                     }
657                     else
658                     {
659                         delete pD;
660                     }
661                 }
662                 break;
663                 case types::InternalType::ScilabInt32:
664                 {
665                     if (pstFormat)
666                     {
667                         FREE(pstFormat);
668                     }
669
670                     Scierror(999, _("Incorrect file or format.\n"));
671                     return types::Function::Error;
672                 }
673                 case types::InternalType::ScilabString:
674                 {
675                     if (iCols != 1)
676                     {
677                         if (pstFormat)
678                         {
679                             FREE(pstFormat);
680                         }
681
682                         Scierror(999, _("%s: Wrong input argument %d.\n"), "read", 3);
683                         return types::Function::Error;
684                     }
685                     else
686                     {
687                         types::String* pS = new types::String(iRows, iCols);
688                         char pCt[4096];
689
690                         for (int i = 0; i < (iRows); i++)
691                         {
692                             int siz = 0;
693                             C2F(readstring)(pstFormat, pCt, &siz, &error, (int)strlen(pstFormat));
694                             pCt[siz] = '\0';
695                             pS->set(i, pCt);
696                         }
697
698                         if (error == 0)
699                         {
700                             out.push_back(pS);
701                         }
702                         else
703                         {
704                             delete pS;
705                         }
706                     }
707                 }
708                 break;
709                 default:
710                     break;
711             }
712         }
713
714         if (error != 0)
715         {
716             if (pstFormat)
717             {
718                 FREE(pstFormat);
719             }
720             closeFile(in[0], iID);
721             Scierror(999, _("Incorrect file or format.\n"));
722             return types::Function::Error;
723         }
724     }
725
726     if (pstFormat)
727     {
728         FREE(pstFormat);
729     }
730
731     return types::Function::OK;
732 }