fix some gcc 4.9 valid warnings
[scilab.git] / scilab / modules / fileio / src / cpp / mgetl.cpp
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 *
6 * This file must be used under the terms of the CeCILL.
7 * This source file is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution.  The terms
9 * are also available at
10 * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
11 *
12 */
13 /*--------------------------------------------------------------------------*/
14 #include <string.h>
15 #include "filemanager.hxx"
16
17 extern "C"
18 {
19 #ifdef _MSC_VER
20 #include <Windows.h>
21 #endif
22 #include "mgetl.h"
23 #include "mopen.h"
24 #include "sci_malloc.h"
25 #include "os_string.h"
26 #include "mtell.h"
27 #include "mseek.h"
28 #include "sciprint.h"
29 }
30
31 #include <iostream>
32 #include <fstream>
33 /*--------------------------------------------------------------------------*/
34 // we do not want to depend on the OS specific LINE_MAX setting
35 #ifdef LINE_MAX
36 #undef LINE_MAX
37 #endif
38 #define LINE_MAX 4096
39
40 #define CR L'\r'
41 #define LF L'\n'
42 #define EMPTYSTRW L""
43 #define EMPTYSTR ""
44 /*--------------------------------------------------------------------------*/
45 static wchar_t *removeEOL(wchar_t *_inString);
46 static char *convertAnsiToUtf(char *_inString);
47 static wchar_t* getLine(wchar_t* _pstLine, int _iLineSize, types::File* _pFile);
48 /*--------------------------------------------------------------------------*/
49 #define UTF_16BE_BOM 0xFEFF // 0xFEFF = to_wide_string(0xEFBBBF)
50 /*--------------------------------------------------------------------------*/
51 wchar_t **mgetl(int fd, int nbLinesIn, int *nbLinesOut, int *ierr)
52 {
53     wchar_t **strLines = NULL;
54     types::File* pFile = NULL;
55     int iLineSizeMult = 1;
56     *ierr = MGETL_ERROR;
57     *nbLinesOut = 0;
58
59     pFile = FileManager::getFile(fd);
60
61     if (nbLinesIn < 0 && fd == 5)
62     {
63         nbLinesIn = 1;
64     }
65
66     /*try std version*/
67     //{
68     //    int posix_handle = ::_fileno(pFile->getFiledesc());
69
70     //    std::ifstream ifs(::_wfdopen(posix_handle, pFile->getFileMode().c_str()));
71     //    std::list<string> lst;
72     //    std::string str;
73
74     //    while(ifs.eof() == false && lst.size() < nbLinesIn)
75     //    {
76     //        std::getline(ifs, str);
77     //        lst.push_back(str);
78     //    }
79
80     //    sciprint("size : %d\n", lst.size());
81
82     //    *nbLinesOut =  (int)lst.size();
83     //    if(*nbLinesOut == 0)
84     //    {
85     //        return NULL;
86     //    }
87
88     //    strLines = (wchar_t**)MALLOC(sizeof(wchar_t*) * *nbLinesOut);
89     //    for(int i = 0 ; i < *nbLinesOut ; i++)
90     //    {
91     //        strLines[i] = to_wide_string(lst.front().c_str());
92     //        lst.pop_front();
93     //    }
94
95     //    return strLines;
96     //}
97
98     if (pFile)
99     {
100         wchar_t* Line = (wchar_t*)MALLOC(LINE_MAX * iLineSizeMult * sizeof(wchar_t));
101         int nbLines = 0;
102         long long iPos = 0;
103         if (nbLinesIn < 0)
104         {
105             strLines = (wchar_t **)MALLOC(sizeof(wchar_t *));
106             if (strLines == NULL)
107             {
108                 *nbLinesOut = 0;
109                 *ierr = MGETL_MEMORY_ALLOCATION_ERROR;
110                 return NULL;
111             }
112             while ( getLine ( Line, LINE_MAX * iLineSizeMult, pFile ) != NULL )
113             {
114                 if (((int) wcslen(Line)) >= (LINE_MAX * iLineSizeMult) - 1)
115                 {
116                     FREE(Line);
117                     iLineSizeMult++;
118                     Line = (wchar_t*)MALLOC(LINE_MAX * iLineSizeMult * sizeof(wchar_t));
119                     mseek(fd, iPos, SEEK_SET);
120
121                     continue;
122                 }
123
124                 iPos = mtell(fd);
125                 /* UTF-16 BOM */
126                 if ((nbLines == 0) && (Line[0] == UTF_16BE_BOM))
127                 {
128                     wchar_t* tmpLine = os_wcsdup(Line);
129                     memset(Line, 0x00, LINE_MAX * iLineSizeMult);
130                     wcscpy(Line, &tmpLine[1]);
131                 }
132
133                 nbLines++;
134                 strLines = (wchar_t **)REALLOC(strLines, nbLines * sizeof(wchar_t *));
135                 if (strLines == NULL)
136                 {
137                     *nbLinesOut = 0;
138                     *ierr = MGETL_MEMORY_ALLOCATION_ERROR;
139                     return NULL;
140                 }
141
142                 strLines[nbLines - 1] = os_wcsdup(removeEOL(Line));
143                 if (strLines[nbLines - 1] == NULL)
144                 {
145                     *nbLinesOut = 0;
146                     *ierr = MGETL_MEMORY_ALLOCATION_ERROR;
147                     return NULL;
148                 }
149                 wcscpy(Line, EMPTYSTRW);
150             }
151             *nbLinesOut = nbLines;
152             *ierr = MGETL_NO_ERROR;
153         }
154         else
155         {
156             if (nbLinesIn == 0)
157             {
158                 *ierr = MGETL_EOF;
159                 *nbLinesOut = 0;
160                 if (strLines)
161                 {
162                     FREE(strLines);
163                 }
164                 strLines = NULL;
165             }
166             else
167             {
168                 BOOL bContinue = TRUE;
169                 BOOL bEOF = FALSE;
170                 strLines = (wchar_t **)MALLOC(sizeof(wchar_t *) * nbLinesIn);
171                 if (strLines == NULL)
172                 {
173                     *nbLinesOut = 0;
174                     *ierr = MGETL_MEMORY_ALLOCATION_ERROR;
175                     return NULL;
176                 }
177
178                 do
179                 {
180                     if (nbLines < nbLinesIn)
181                     {
182                         bool header = false;
183                         /* UTF-16 BOM */
184                         if ((ftell(pFile->getFiledesc()) == 0) && (nbLines == 0))
185                         {
186                             header = true;
187                         }
188
189                         if ( getLine ( Line, LINE_MAX * iLineSizeMult, pFile) != NULL)
190                         {
191                             if (((int) wcslen(Line)) >= (LINE_MAX * iLineSizeMult) - 1)
192                             {
193                                 FREE(Line);
194                                 iLineSizeMult++;
195                                 Line = (wchar_t*)MALLOC(LINE_MAX * iLineSizeMult * sizeof(wchar_t));
196                                 mseek(fd, iPos, SEEK_SET);
197
198                                 continue;
199                             }
200
201                             iPos = mtell(fd);
202
203                             if (header && (Line[0] == UTF_16BE_BOM))
204                             {
205                                 wchar_t* tmpLine = os_wcsdup(Line);
206                                 memset(Line, 0x00, LINE_MAX * iLineSizeMult);
207                                 wcscpy(Line, &tmpLine[1]);
208                             }
209                             nbLines++;
210                             strLines[nbLines - 1] = os_wcsdup(removeEOL(Line));
211                             if (strLines[nbLines - 1] == NULL)
212                             {
213                                 *nbLinesOut = 0;
214                                 *ierr = MGETL_MEMORY_ALLOCATION_ERROR;
215                                 return NULL;
216                             }
217                             wcscpy(Line, EMPTYSTRW);
218                         }
219                         else
220                         {
221                             /* EOF */
222                             if (feof(pFile->getFiledesc()))
223                             {
224                                 bEOF = TRUE;
225                             }
226                             bContinue = FALSE;
227                         }
228                     }
229                     else
230                     {
231                         bContinue = FALSE;
232                     }
233                 }
234                 while (bContinue);
235
236                 *nbLinesOut = nbLines;
237                 if (bEOF)
238                 {
239                     *ierr = MGETL_EOF;
240                 }
241                 else
242                 {
243                     *ierr = MGETL_NO_ERROR;
244                 }
245             }
246         }
247         FREE(Line);
248     }
249     return strLines;
250 }
251 /*--------------------------------------------------------------------------*/
252 wchar_t* getLine(wchar_t* _pstLine, int _iLineSize, types::File* _pFile)
253 {
254     char* pstTemp = (char*)MALLOC(sizeof(char) * _iLineSize);
255     if (fgets(pstTemp, _iLineSize, _pFile->getFiledesc()) == NULL)
256     {
257         FREE(pstTemp);
258         return NULL;
259     }
260
261     wchar_t* pstTempWide = to_wide_string(pstTemp);
262     wcscpy(_pstLine, pstTempWide);
263     FREE(pstTemp);
264     FREE(pstTempWide);
265     return _pstLine;
266 }
267 /*--------------------------------------------------------------------------*/
268 wchar_t *removeEOL(wchar_t *_inString)
269 {
270     if (_inString)
271     {
272         wchar_t *pos = wcschr(_inString, LF);
273         if (pos)
274         {
275             *pos = 0;
276         }
277
278         pos = wcschr(_inString, CR);
279         if (pos)
280         {
281             *pos = 0;
282         }
283     }
284     return _inString;
285 }
286 /*--------------------------------------------------------------------------*/
287 /*
288 * convert ansi to Utf
289 */
290 static char *convertAnsiToUtf(char *_inString)
291 {
292     char *outString = NULL;
293     if (_inString)
294     {
295 #ifdef _MSC_VER
296         if (IsValidUTF8(_inString))
297         {
298             outString = os_strdup(_inString);
299         }
300         else
301         {
302             /* conversion ANSI to UTF */
303             int Len = 0;
304             int newLen = 0;
305             BSTR bstrCode = NULL;
306
307             Len = MultiByteToWideChar(CP_ACP, 0, _inString, lstrlen(_inString), NULL, NULL);
308             bstrCode = SysAllocStringLen(NULL, Len);
309             if (bstrCode)
310             {
311                 MultiByteToWideChar(CP_ACP, 0, _inString, lstrlen(_inString), bstrCode, Len);
312                 newLen = WideCharToMultiByte(CP_UTF8, 0, bstrCode, -1, outString, 0, NULL, NULL);
313                 outString = (char*) MALLOC(sizeof(char) * (newLen + 1));
314                 if (outString)
315                 {
316                     WideCharToMultiByte(CP_UTF8, 0, bstrCode, -1, outString, newLen, NULL, NULL);
317                 }
318                 else
319                 {
320                     outString = os_strdup(_inString);
321                 }
322                 SysFreeString(bstrCode);
323                 bstrCode = NULL;
324             }
325             else
326             {
327                 outString = os_strdup(_inString);
328             }
329         }
330 #else
331         if (IsValidUTF8(_inString))
332         {
333             outString = os_strdup(_inString);
334         }
335         else
336         {
337             int len = (int)strlen(_inString);
338             int i = 0;
339
340             outString = (char*)MALLOC(((len * 3) + 1) * sizeof(char));
341             if (outString == NULL)
342             {
343                 return NULL;
344             }
345
346             strcpy(outString, EMPTYSTR);
347
348             for (i = 0; i < len; i++)
349             {
350                 char *outUtfChar = NULL;
351                 unsigned char inAnsiChar = 0;
352
353                 if (_inString[i] < 0)
354                 {
355                     inAnsiChar = 256 + _inString[i];
356                 }
357                 else
358                 {
359                     inAnsiChar = _inString[i];
360                 }
361
362                 if (inAnsiChar < 128)
363                 {
364                     outUtfChar = (char *)CALLOC(2, sizeof(char));
365                     if (outUtfChar)
366                     {
367                         outUtfChar[0] = inAnsiChar;
368                         outUtfChar[1] = 0;
369                     }
370                 }
371                 else
372                 {
373                     outUtfChar = (char *)CALLOC(3, sizeof(char));
374                     if (outUtfChar)
375                     {
376                         outUtfChar[0] = (inAnsiChar >> 6) | 0xC0;
377                         outUtfChar[1] = (inAnsiChar & 0x3F) | 0x80;
378                         outUtfChar[2] = 0;
379                     }
380                 }
381
382                 if (outUtfChar)
383                 {
384                     strcat(outString, outUtfChar);
385                     FREE(outUtfChar);
386                     outUtfChar = NULL;
387                 }
388             }
389         }
390 #endif
391     }
392     return outString;
393 }
394 /*--------------------------------------------------------------------------*/