1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2010-2011 - DIGITEO - Allan CORNET
4 *
5 * Copyright (C) 2012 - 2016 - Scilab Enterprises
6 *
7 * This file is hereby licensed under the terms of the GNU GPL v2.0,
8 * pursuant to article 5.3.4 of the CeCILL v.2.1.
9 * This file was originally licensed under the terms of the CeCILL v2.1,
10 * and continues to be available under such terms.
11 * For more information, see the COPYING file which you should have received
12 * along with this program.
13 *
14 */
15 /*--------------------------------------------------------------------------*/
16 #if defined(__linux__)
17 #define _GNU_SOURCE /* Bug 5673 fix: avoid dependency on GLIBC_2.7 */
18 #endif
19 /*--------------------------------------------------------------------------*/
20 #include <ctype.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include "sci_malloc.h"
25 #include "fscanfMat.h"
26 #include "charEncoding.h"
27 #include "BOOL.h"
28 #include "localization.h"
29 #include "Scierror.h"
30 #include "os_string.h"
31 #include "freeArrayOfString.h"
32 #include "mgetl.h"
33 #include "mopen.h"
34 #include "mclose.h"
35 #include "numericconstants_interface.h"
36 /*--------------------------------------------------------------------------*/
37 #define EOL "\n"
38 #define NanString "Nan"
39 #define InfString "Inf"
40 #define NegInfString "-Inf"
41 /*--------------------------------------------------------------------------*/
42 #if _MSC_VER
43 #define READ_ONLY_TEXT_MODE L"rt"
44 #else
45 #define READ_ONLY_TEXT_MODE L"r"
46 #endif
47 /*--------------------------------------------------------------------------*/
48 #define NB_FORMAT_SUPPORTED 7
49 static char *supportedFormat[NB_FORMAT_SUPPORTED] =
50 {"lf", "lg", "d", "i", "e", "f", "g"};
51 /*--------------------------------------------------------------------------*/
52 static BOOL itCanBeMatrixLine(char *line, char *format, char *separator);
53 static int getNbColumnsInLine(char *line, char *format, char *separator);
54 static int getNumbersColumnsInLines(char **lines, int sizelines,
55 int nbLinesText,
56 char *format, char *separator);
57 static int getNumbersLinesOfText(char **lines, int sizelines,
58 char *format, char *separator);
59 static char **splitLine(char *str, char *sep, int *toks, char meta);
60 static double *getDoubleValuesFromLines(char **lines, int sizelines,
61 int nbLinesText,
62 char *format, char *separator,
63 int m, int n);
64 static double *getDoubleValuesInLine(char *line,
65 char *format, char *separator,
66 int nbColumnsMax);
67 static BOOL checkFscanfMatFormat(char *format);
68 static char *getCleanedFormat(char *format);
69 static BOOL isOnlyBlankLine(const char *line);
70 static char **removeEmptyLinesAtTheEnd(char **lines, int *sizelines);
71 static BOOL isValidLineWithOnlyOneNumber(char *line);
72 static char ** removeTextLinesAtTheEnd(char **lines, int *sizelines, char *format, char *separator);
73 /*--------------------------------------------------------------------------*/
fscanfMat(char * filename,char * format,char * separator)74 fscanfMatResult *fscanfMat(char *filename, char *format, char *separator)
75 {
76 int fd = 0;
77 int f_swap = 0;
78 double res = 0.0;
79 int errMOPEN = MOPEN_INVALID_STATUS;
80 int i = 0;
81 int nbLinesTextDetected = 0;
82 int nbColumns = 0;
83 int nbRows = 0;
84
85
86 fscanfMatResult *resultFscanfMat = NULL;
87 wchar_t **pwstLines = NULL;
88 char **lines = NULL;
89 int nblines = 0;
90 double *dValues = NULL;
91 wchar_t* filenameW = NULL;
92
93 if ((filename == NULL) || (format == NULL) || (separator == NULL))
94 {
95 return NULL;
96 }
97
98 if (!checkFscanfMatFormat(format))
99 {
100 resultFscanfMat = (fscanfMatResult*)(MALLOC(sizeof(fscanfMatResult)));
101 if (resultFscanfMat)
102 {
103 resultFscanfMat->err = FSCANFMAT_FORMAT_ERROR;
104 resultFscanfMat->m = 0;
105 resultFscanfMat->n = 0;
106 resultFscanfMat->sizeText = 0;
107 resultFscanfMat->text = NULL;
108 resultFscanfMat->values = NULL;
109 }
110 return resultFscanfMat;
111 }
112
113 filenameW = to_wide_string(filename);
114 errMOPEN = mopen(filenameW, READ_ONLY_TEXT_MODE, f_swap, &fd);
115 FREE(filenameW);
116 if (errMOPEN != MOPEN_NO_ERROR)
117 {
118 resultFscanfMat = (fscanfMatResult*)(MALLOC(sizeof(fscanfMatResult)));
119 if (resultFscanfMat)
120 {
121 resultFscanfMat->err = FSCANFMAT_MOPEN_ERROR;
122 resultFscanfMat->m = 0;
123 resultFscanfMat->n = 0;
124 resultFscanfMat->sizeText = 0;
125 resultFscanfMat->text = NULL;
126 resultFscanfMat->values = NULL;
127 }
128 return resultFscanfMat;
129 }
130
131 nblines = mgetl(fd, -1, &pwstLines);
132 mclose(fd);
133
134 if (nblines < 0)
135 {
136 resultFscanfMat = (fscanfMatResult*)(MALLOC(sizeof(fscanfMatResult)));
137 if (resultFscanfMat)
138 {
139 resultFscanfMat->err = FSCANFMAT_READLINES_ERROR;
140 resultFscanfMat->m = 0;
141 resultFscanfMat->n = 0;
142 resultFscanfMat->sizeText = 0;
143 resultFscanfMat->text = NULL;
144 resultFscanfMat->values = NULL;
145 }
146 freeArrayOfWideString(pwstLines, nblines);
147 return resultFscanfMat;
148 }
149
150 lines = (char**)MALLOC(sizeof(char*) * nblines);
151 for (i = 0; i < nblines; i++)
152 {
153 lines[i] = wide_string_to_UTF8(pwstLines[i]);
154 }
155
156 freeArrayOfWideString(pwstLines, nblines);
157
158 lines = removeEmptyLinesAtTheEnd(lines, &nblines);
159 lines = removeTextLinesAtTheEnd(lines, &nblines, format, separator);
160
161 nbLinesTextDetected = getNumbersLinesOfText(lines, nblines, format, separator);
162 nbRows = nblines - nbLinesTextDetected;
163 nbColumns = getNumbersColumnsInLines(lines, nblines, nbLinesTextDetected, format, separator);
164
165 dValues = getDoubleValuesFromLines(lines, nblines,
166 nbLinesTextDetected,
167 format, separator,
168 nbColumns, nbRows);
169 if (dValues)
170 {
171 resultFscanfMat = (fscanfMatResult*)(MALLOC(sizeof(fscanfMatResult)));
172 if (resultFscanfMat)
173 {
174 if (nbLinesTextDetected > 0)
175 {
176 if (lines)
177 {
178 for (i = nbLinesTextDetected; i < nblines; i++)
179 {
180 if (lines[i])
181 {
182 FREE(lines[i]);
183 lines[i] = NULL;
184 }
185 }
186 }
187 resultFscanfMat->text = lines;
188 }
189 else
190 {
191 freeArrayOfString(lines, nblines);
192 resultFscanfMat->text = NULL;
193 }
194 resultFscanfMat->sizeText = nbLinesTextDetected;
195 resultFscanfMat->m = nbRows;
196 resultFscanfMat->n = nbColumns;
197 resultFscanfMat->values = dValues;
198 resultFscanfMat->err = FSCANFMAT_NO_ERROR;
199 }
200 else
201 {
202 FREE(dValues);
203 freeArrayOfString(lines, nblines);
204 }
205 }
206 else
207 {
208 freeArrayOfString(lines, nblines);
209 if (nbColumns == 0 || nbRows == 0)
210 {
211 resultFscanfMat = (fscanfMatResult*)(MALLOC(sizeof(fscanfMatResult)));
212 if (resultFscanfMat)
213 {
214 resultFscanfMat->err = FSCANFMAT_READLINES_ERROR;
215 resultFscanfMat->m = 0;
216 resultFscanfMat->n = 0;
217 resultFscanfMat->sizeText = 0;
218 resultFscanfMat->text = NULL;
219 resultFscanfMat->values = NULL;
220 }
221 }
222 }
223 return resultFscanfMat;
224 }
225 /*--------------------------------------------------------------------------*/
freeFscanfMatResult(fscanfMatResult * resultStruct)226 void freeFscanfMatResult(fscanfMatResult *resultStruct)
227 {
228 if (resultStruct)
229 {
230 if (resultStruct->text)
231 {
232 freeArrayOfString(resultStruct->text, resultStruct->sizeText);
233 resultStruct->text = NULL;
234 }
235
236 if (resultStruct->values)
237 {
238 FREE(resultStruct->values);
239 resultStruct->values = NULL;
240 }
241
242 resultStruct->err = FSCANFMAT_ERROR;
243 resultStruct->m = 0;
244 resultStruct->n = 0;
245 resultStruct->sizeText = 0;
246
247 FREE(resultStruct);
248 resultStruct = NULL;
249 }
250 }
251 /*--------------------------------------------------------------------------*/
itCanBeMatrixLine(char * line,char * format,char * separator)252 static BOOL itCanBeMatrixLine(char *line, char *format, char *separator)
253 {
254 if (line)
255 {
256 int ierr = 0;
257 double dValue = 0.;
258
259 ierr = sscanf(line, format, &dValue);
260
261 if ((ierr == EOF) || (ierr == 0))
262 {
263 char *str = os_strdup(line);
264 if (str)
265 {
266 ierr = sscanf(line, "%4s", str);
267
268 if ((ierr != 0) && (ierr != EOF))
269 {
270 if ((strncmp(str, NanString, (int)strlen(NanString)) == 0) ||
271 (strncmp(str, NegInfString, (int)strlen(NegInfString)) == 0) ||
272 (strncmp(str, InfString, (int)strlen(InfString)) == 0))
273 {
274 FREE(str);
275 str = NULL;
276 return TRUE;
277 }
278 }
279 FREE(str);
280 str = NULL;
281 }
282 }
283 else
284 {
285 return TRUE;
286 }
287 }
288 return FALSE;
289 }
290 /*--------------------------------------------------------------------------*/
getNumbersLinesOfText(char ** lines,int sizelines,char * format,char * separator)291 static int getNumbersLinesOfText(char **lines, int sizelines,
292 char *format, char *separator)
293 {
294 int numberOfLines = 0;
295 if (lines)
296 {
297 int i = 0;
298 for (i = 0; i < sizelines; i++)
299 {
300 if (!itCanBeMatrixLine(lines[i], format, separator))
301 {
302 numberOfLines++;
303 }
304 else
305 {
306 return numberOfLines;
307 }
308 }
309 }
310 return numberOfLines;
311 }
312 /*--------------------------------------------------------------------------*/
getNumbersColumnsInLines(char ** lines,int sizelines,int nbLinesText,char * format,char * separator)313 static int getNumbersColumnsInLines(char **lines, int sizelines,
314 int nbLinesText,
315 char *format, char *separator)
316 {
317 int previousNbColumns = 0;
318 int NbColumns = 0;
319 BOOL firstLine = TRUE;
320 if (lines)
321 {
322 int i = 0;
323 int firstLinesMatrix = nbLinesText;
324 for (i = firstLinesMatrix; i < sizelines; i++)
325 {
326 NbColumns = getNbColumnsInLine(lines[i], format, separator);
327 if (firstLine)
328 {
329 previousNbColumns = NbColumns;
330 firstLine = FALSE;
331 }
332 else
333 {
334 if (previousNbColumns != NbColumns)
335 {
336 return 0;
337 }
338 }
339 }
340 }
341 return NbColumns;
342 }
343 /*--------------------------------------------------------------------------*/
getNbColumnsInLine(char * line,char * format,char * separator)344 static int getNbColumnsInLine(char *line, char *format, char *separator)
345 {
346 int nbColums = 0;
347
348 if (line && format && separator)
349 {
350 int i = 0;
351 int nbTokens = 0;
352 char **splittedStr = splitLine(line, separator, &nbTokens, 0);
353 if (nbTokens == 0)
354 {
355 freeArrayOfString(splittedStr, nbTokens);
356 return nbColums;
357 }
358 if (splittedStr)
359 {
360 for (i = 0; i < nbTokens; i++)
361 {
362 double dValue = 0.;
363 int ierr = sscanf(splittedStr[i], format, &dValue);
364 if ((ierr != 0) && (ierr != EOF))
365 {
366 nbColums++;
367 }
368 else
369 {
370 char *str = os_strdup(splittedStr[i]);
371 strcpy(str, "");
372
373 ierr = sscanf(splittedStr[i], "%4s", str);
374
375 if ((ierr != 0) && (ierr != EOF))
376 {
377 if ( (strcmp(str, NanString) == 0) ||
378 (strcmp(str, NegInfString) == 0) ||
379 (strcmp(str, InfString) == 0) )
380 {
381 nbColums++;
382 }
383 else
384 {
385 freeArrayOfString(splittedStr, nbTokens);
386 /* bug 6889 */
387 if (nbColums)
388 {
389 nbColums--;
390 }
391 FREE(str);
392 str = NULL;
393 return nbColums;
394 }
395 }
396 else
397 {
398 FREE(str);
399 str = NULL;
400 freeArrayOfString(splittedStr, nbTokens);
401 return nbColums;
402 }
403
404 FREE(str);
405 str = NULL;
406 }
407 }
408 freeArrayOfString(splittedStr, nbTokens);
409 }
410 }
411 return nbColums;
412 }
413 /*--------------------------------------------------------------------------*/
splitLine(char * str,char * sep,int * toks,char meta)414 static char **splitLine(char *str, char *sep, int *toks, char meta)
415 {
416 char **retstr = NULL;
417 char *idx = NULL;
418 char *end = NULL;
419 char *sep_end = NULL;
420 char *sep_idx = NULL;
421 int len = 0;
422 int curr_str = 0;
423 char last_char = 0xFF;
424
425 *toks = 0;
426
427 if ((sep == NULL) || (str == NULL))
428 {
429 return NULL;
430 }
431
432 sep_end = sep + strlen(sep);
433 end = str + strlen(str);
434
435 sep_idx = sep;
436 idx = str;
437
438 if (strstr(str, sep) == NULL)
439 {
440 if ((int)strlen(str) > 0)
441 {
442 if (isValidLineWithOnlyOneNumber(str))
443 {
444 retstr = (char **) MALLOC(sizeof(char *));
445 if (retstr)
446 {
447 retstr[0] = os_strdup(str);
448 *toks = 1;
449 }
450 }
451 }
452 return retstr;
453 }
454
455 retstr = (char **) MALLOC((sizeof(char *) * (int)strlen(str)));
456 if (retstr == NULL)
457 {
458 *toks = 0;
459 return NULL;
460 }
461
462 while (idx < end)
463 {
464 while (sep_idx < sep_end)
465 {
466 if ((*idx == *sep_idx) && (last_char != meta))
467 {
468 if (len > 0)
469 {
470 if (curr_str < (int)strlen(str))
471 {
472 retstr[curr_str] = (char *) MALLOC((sizeof(char) * len) + 1);
473
474 if (retstr[curr_str] == NULL)
475 {
476 freeArrayOfString(retstr, curr_str);
477 *toks = 0;
478 return NULL;
479 }
480 memcpy(retstr[curr_str], (idx - len), len);
481 retstr[curr_str][len] = 0;
482 len = 0;
483 curr_str++;
484 last_char = *idx;
485 idx++;
486 }
487
488 if (curr_str >= (int)strlen(str))
489 {
490 *toks = curr_str + 1;
491 return retstr;
492 }
493 }
494 else
495 {
496 last_char = *idx;
497 idx++;
498 sep_idx = sep;
499 len = 0;
500 }
501 }
502 else
503 {
504 sep_idx++;
505 }
506 }
507
508 sep_idx = sep;
509 len++;
510 last_char = *idx;
511 idx++;
512 }
513
514 if (len > 0)
515 {
516 retstr[curr_str] = (char *) MALLOC((sizeof(char) * len) + 1);
517
518 if (retstr[curr_str] == NULL)
519 {
520 *toks = 0;
521 FREE(retstr);
522 return NULL;
523 }
524
525 memcpy(retstr[curr_str], (idx - len), len);
526 retstr[curr_str][len] = 0;
527
528 *toks = curr_str + 1;
529 }
530 return retstr;
531 }
532 /*--------------------------------------------------------------------------*/
getDoubleValuesFromLines(char ** lines,int sizelines,int nbLinesText,char * format,char * separator,int m,int n)533 static double *getDoubleValuesFromLines(char **lines, int sizelines,
534 int nbLinesText,
535 char *format, char *separator,
536 int m, int n)
537 {
538 double *dValues = NULL;
539
540 if (m == 0 || n == 0)
541 {
542 return NULL;
543 }
544
545 dValues = (double*) MALLOC(sizeof(double) * (m * n));
546 if (dValues)
547 {
548 int i = 0;
549 int firstLinesMatrix = nbLinesText;
550 for (i = firstLinesMatrix; i < sizelines; i++)
551 {
552 double *dValsTmp = getDoubleValuesInLine(lines[i], format, separator, m);
553 if (dValsTmp)
554 {
555 int j = 0;
556 for (j = 0; j < m; j++)
557 {
558 dValues[(i - firstLinesMatrix) + n * j] = dValsTmp[j];
559 }
560 FREE(dValsTmp);
561 dValsTmp = NULL;
562 }
563 }
564 }
565 return dValues;
566 }
567 /*--------------------------------------------------------------------------*/
getDoubleValuesInLine(char * line,char * format,char * separator,int nbColumnsMax)568 static double *getDoubleValuesInLine(char *line,
569 char *format, char *separator,
570 int nbColumnsMax)
571 {
572 double *dValues = NULL;
573
574 if (line && format && separator)
575 {
576 int nbTokens = 0;
577 char **splittedStr = splitLine(line, separator, &nbTokens, 0);
578 if (splittedStr)
579 {
580 int i = 0;
581 dValues = (double*)MALLOC(sizeof(double) * nbColumnsMax);
582 for (i = 0; i < nbColumnsMax; i++)
583 {
584 int ierr = 0;
585 double dValue = 0.;
586 char *cleanedFormat = getCleanedFormat(format);
587 int iLen = (int)strlen(cleanedFormat);
588 switch (cleanedFormat[iLen - 1])
589 {
590 case 'e' :
591 case 'g' :
592 case 'f' :
593 {
594 if (cleanedFormat[iLen - 2] == 'l')
595 {
596 double tmp = 0.;
597 ierr = sscanf(splittedStr[i], cleanedFormat, &tmp);
598 dValue = tmp;
599 }
600 else
601 {
602 float tmp = 0.;
603 ierr = sscanf(splittedStr[i], cleanedFormat, &tmp);
604 dValue = tmp;
605 }
606 break;
607 }
608 case 'd' :
609 case 'i' :
610 {
611 int tmp = 0;
612 ierr = sscanf(splittedStr[i], cleanedFormat, &tmp);
613 dValue = tmp;
614 break;
615 }
616 }
617
618 FREE(cleanedFormat);
619
620 if ((ierr != 0) && (ierr != EOF))
621 {
622 dValues[i] = dValue;
623 }
624 else
625 {
626 char *str = os_strdup(line);
627 strcpy(str, "");
628 ierr = sscanf(splittedStr[i], "%4s", str);
629 if ((ierr != 0) && (ierr != EOF))
630 {
631 if ( (strcmp(str, NanString) == 0) ||
632 (strcmp(str, NegInfString) == 0) ||
633 (strcmp(str, InfString) == 0) )
634 {
635 if (strcmp(str, NanString) == 0)
636 {
637 dValues[i] = nc_nan();
638 }
639
640 if (strcmp(str, NegInfString) == 0)
641 {
642 dValues[i] = nc_neginf();
643 }
644
645 if (strcmp(str, InfString) == 0)
646 {
647 dValues[i] = nc_inf();
648 }
649 }
650 else
651 {
652 freeArrayOfString(splittedStr, nbTokens);
653 FREE(dValues);
654 dValues = NULL;
655 FREE(str);
656 str = NULL;
657 return NULL;
658 }
659 }
660 else
661 {
662 freeArrayOfString(splittedStr, nbTokens);
663 FREE(dValues);
664 dValues = NULL;
665 FREE(str);
666 str = NULL;
667 return NULL;
668 }
669 FREE(str);
670 str = NULL;
671 }
672 }
673 freeArrayOfString(splittedStr, nbTokens);
674 }
675 }
676
677 return dValues;
678 }
679 /*--------------------------------------------------------------------------*/
checkFscanfMatFormat(char * format)680 static BOOL checkFscanfMatFormat(char *format)
681 {
682 if (format)
683 {
684 char *tokenPercent1 = strchr(format, '%');
685 char *tokenPercent2 = strrchr(format, '%');
686 if ((tokenPercent2 && tokenPercent1) && (tokenPercent1 == tokenPercent2))
687 {
688 char *cleanedFormat = getCleanedFormat(format);
689 if (cleanedFormat)
690 {
691 FREE(cleanedFormat);
692 cleanedFormat = NULL;
693 return TRUE;
694 }
695 }
696 }
697 return FALSE;
698 }
699 /*--------------------------------------------------------------------------*/
getCleanedFormat(char * format)700 static char *getCleanedFormat(char *format)
701 {
702 char *cleanedFormat = NULL;
703 if (format)
704 {
705 char *percent = strchr(format, '%');
706 if (percent)
707 {
708 int i = 0;
709 for (i = 0; i < NB_FORMAT_SUPPORTED; i++)
710 {
711 char *token = strstr(percent, supportedFormat[i]);
712 if (token)
713 {
714 int nbcharacters = (int)(strlen(percent) - strlen(token));
715 cleanedFormat = os_strdup(percent);
716 cleanedFormat[nbcharacters] = 0;
717 if ( (nbcharacters - 1 > 0) && (isdigit(cleanedFormat[nbcharacters - 1]) ||
718 (cleanedFormat[nbcharacters - 1]) == '.') ||
719 (cleanedFormat[nbcharacters - 1]) == '%')
720 {
721 strcat(cleanedFormat, supportedFormat[i]);
722 return cleanedFormat;
723 }
724 else
725 {
726 FREE(cleanedFormat);
727 cleanedFormat = NULL;
728 }
729 }
730 }
731 }
732 }
733 return cleanedFormat;
734 }
735 /*--------------------------------------------------------------------------*/
removeEmptyLinesAtTheEnd(char ** lines,int * sizelines)736 static char **removeEmptyLinesAtTheEnd(char **lines, int *sizelines)
737 {
738 int i = 0;
739 int nbLinesToRemove = 0;
740 if (lines)
741 {
742 for (i = *sizelines - 1; i >= 0; i--)
743 {
744 if (lines[i])
745 {
746 if ( (strcmp(lines[i], "") == 0) || (isOnlyBlankLine(lines[i])) )
747 {
748 FREE(lines[i]);
749 lines[i] = NULL;
750 nbLinesToRemove++;
751 }
752 else
753 {
754 break;
755 }
756 }
757 }
758
759 if (nbLinesToRemove > 0)
760 {
761 lines = (char**)REALLOC(lines, sizeof(char*) * (*sizelines - nbLinesToRemove));
762 *sizelines = *sizelines - nbLinesToRemove;
763 }
764 }
765 else
766 {
767 *sizelines = 0;
768 }
769 return lines;
770 }
771 /*--------------------------------------------------------------------------*/
isValidLineWithOnlyOneNumber(char * line)772 static BOOL isValidLineWithOnlyOneNumber(char *line)
773 {
774 if (line)
775 {
776 char *pEnd = NULL;
777 strtod(line, &pEnd);
778 if ((pEnd) && ((int)strlen(pEnd) == 0))
779 {
780 return TRUE;
781 }
782 else
783 {
784 if ((strncmp(line, NanString, (int)strlen(NanString)) == 0) ||
785 (strncmp(line, NegInfString, (int)strlen(NegInfString)) == 0) ||
786 (strncmp(line, InfString, (int)strlen(InfString)) == 0))
787 {
788 return TRUE;
789 }
790 }
791 }
792 return FALSE;
793 }
794 /*--------------------------------------------------------------------------*/
isOnlyBlankLine(const char * line)795 static BOOL isOnlyBlankLine(const char *line)
796 {
797 if (line)
798 {
799 int i = 0;
800 for (i = 0; i < (int) strlen(line); i++)
801 {
802 if (line[i] != ' ')
803 {
804 return FALSE;
805 }
806 }
807 }
808 return TRUE;
809 }
810 /*--------------------------------------------------------------------------*/
removeTextLinesAtTheEnd(char ** lines,int * sizelines,char * format,char * separator)811 static char ** removeTextLinesAtTheEnd(char **lines, int *sizelines, char *format, char *separator)
812 {
813 char **linesReturned = NULL;
814 int i = 0;
815 int nbLinesToRemove = 0;
816
817 for (i = *sizelines - 1; i > 0; i--)
818 {
819 if (itCanBeMatrixLine(lines[i], format, separator) == FALSE)
820 {
821 nbLinesToRemove++;
822 FREE(lines[i]);
823 lines[i] = NULL;
824 }
825 else
826 {
827 break;
828 }
829 }
830
831 if (nbLinesToRemove > 0)
832 {
833 //must free last lines.
834 *sizelines = *sizelines - nbLinesToRemove;
835 linesReturned = lines;
836 }
837 else
838 {
839 linesReturned = lines;
840 }
841
842 return linesReturned;
843
844 }
845 /*--------------------------------------------------------------------------*/
846