1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2010 - DIGITEO - Allan CORNET
4 * Copyright (C) 2010 - DIGITEO - Antoine ELIAS
5 * Copyright (C) 2019 - ESI - Antoine ELIAS
6 *
7 * Copyright (C) 2012 - 2016 - Scilab Enterprises
8 *
9 * This file is hereby licensed under the terms of the GNU GPL v2.0,
10 * pursuant to article 5.3.4 of the CeCILL v.2.1.
11 * This file was originally licensed under the terms of the CeCILL v2.1,
12 * and continues to be available under such terms.
13 * For more information, see the COPYING file which you should have received
14 * along with this program.
15 *
16 */
17 
18 #include <fstream>
19 #include <iostream>
20 
21 extern "C"
22 {
23 #include "charEncoding.h"
24 #include "freeArrayOfString.h"
25 #include "mgetl.h"
26 #include "sci_malloc.h"
27 #include "sciprint.h"
28 }
29 #include "filemanager.hxx"
30 
31 #include <stdio.h>
32 #include <string.h>
33 
34 #ifdef _MSC_VER
35 #include <Windows.h>
36 #endif
37 
38 static const unsigned char UTF8_BOM[] = {0xEF, 0xBB, 0xBF, 0x00};
39 
40 //remove \r
rtrim(wchar_t * s)41 inline void rtrim(wchar_t* s)
42 {
43     size_t n = wcslen(s);
44     if (n && s[n - 1] == L'\r')
45     {
46         s[n - 1] = 0;
47     }
48 }
49 
mgetl(int iFileID,int iLineCount,wchar_t *** pwstLines)50 int mgetl(int iFileID, int iLineCount, wchar_t*** pwstLines)
51 {
52     *pwstLines = NULL;
53 
54     // get file descriptor
55     types::File* pFile = FileManager::getFile(iFileID);
56     FILE* fd;
57     if (pFile != NULL)
58     {
59         fd = pFile->getFiledesc();
60     }
61     else
62     {
63         return -1;
64     }
65 
66     if (iLineCount == 0)
67     {
68         return 0;
69     }
70 
71     // check file is not empty
72     if (ftell(fd) == 0)
73     {
74         char cValues[4] = {0x00, 0x00, 0x00, 0x00};
75         if (fgets(cValues, 4 * sizeof(char), fd) != NULL)
76         {
77             // skip BOM
78             if (strcmp(cValues, (const char*)UTF8_BOM) != 0)
79             {
80                 rewind(fd);
81             }
82         }
83     }
84 
85     int orig = ftell(fd);
86 
87     std::string str;
88     std::vector<std::string> lst;
89 
90     if (iFileID == 5)
91     {
92         // read from stdin
93         while ((iLineCount == -1 || lst.size() < iLineCount) && std::getline(std::cin, str))
94         {
95             lst.push_back(str);
96         }
97     }
98     else
99     {
100 #ifndef _MSC_VER
101         //must reopen the file
102         std::wstring wname = pFile->getFilename();
103         char* name = wide_string_to_UTF8(wname.data());
104         std::ifstream ifs(name);
105         FREE(name);
106         //seek to same position
107         ifs.seekg(orig);
108 #else
109         std::ifstream ifs(fd);
110 #endif
111         while ((iLineCount == -1 || lst.size() < iLineCount) && std::getline(ifs, str))
112         {
113             lst.push_back(str);
114         }
115 #ifndef _MSC_VER
116         auto pos = ifs.tellg();
117         if (pos == -1)
118         {
119             fseek(fd, 0, SEEK_END);
120         }
121         else
122         {
123             fseek(fd, pos, SEEK_SET);
124         }
125 
126         ifs.close();
127 #endif
128     }
129 
130     int nbLinesOut = (int)lst.size();
131     if (nbLinesOut == 0)
132     {
133         return 0;
134     }
135 
136     *pwstLines = (wchar_t**)MALLOC(nbLinesOut * sizeof(wchar_t*));
137     if (*pwstLines == NULL)
138     {
139         return -1;
140     }
141 
142     for (int i = 0; i < nbLinesOut; ++i)
143     {
144         wchar_t* str = to_wide_string(lst[i].data());
145         rtrim(str);
146         (*pwstLines)[i] = str;
147     }
148 
149     return nbLinesOut;
150 }
151