2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2010-2011 - DIGITEO - Allan CORNET
5 * This file must be used under the terms of the CeCILL.
6 * This source file is licensed as described in the file COPYING, which
7 * you should have received as part of this distribution. The terms
8 * are also available at
9 * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
17 #include "stringToComplex.h"
18 #include "stringToDouble.h"
21 #include "strdup_windows.h"
24 #include "csv_strsubst.h"
25 /* ========================================================================== */
28 #define ComplexCharI 'i'
29 #define ComplexCharJ 'j'
30 #define ComplexScilab "%i"
32 /* ========================================================================== */
35 #define strnicmp strncasecmp
38 #define stricmp _stricmp
42 #define strnicmp _strnicmp
44 /* ========================================================================== */
45 static int ParseNumber(const char* tx);
46 static stringToComplexError ParseComplexValue(const char *tx, BOOL bConvertByNAN, double *real, double *imag);
47 static char *midstring(const char *tx, size_t pos, int nb);
48 static char *leftstring(const char *tx, size_t pos);
49 static BOOL is_unit_imaginary (const char *src, double *im);
50 static double returnNAN(void);
51 /* ========================================================================== */
52 csv_complexArray *stringsToCsvComplexArray(const char **pSTRs, int nbElements,
55 stringToComplexError *ierr)
57 csv_complexArray *pCsvComplexArray = NULL;
59 *ierr = STRINGTOCOMPLEX_ERROR;
67 *ierr = STRINGTOCOMPLEX_MEMORY_ALLOCATION;
71 pCsvComplexArray = createCsvComplexArrayEmpty(nbElements);
75 for (i = 0; i < nbElements; i++)
77 doublecomplex dComplexValue = stringToComplex(pSTRs[i], decimal, bConvertByNAN, ierr);
78 if (*ierr != STRINGTOCOMPLEX_NO_ERROR)
80 freeCsvComplexArray(pCsvComplexArray);
85 pCsvComplexArray->realPart[i] = dComplexValue.r;
86 pCsvComplexArray->imagPart[i] = dComplexValue.i;
89 cleanImagPartCsvComplexArray(pCsvComplexArray);
93 *ierr = STRINGTOCOMPLEX_MEMORY_ALLOCATION;
96 return pCsvComplexArray;
98 /* ========================================================================== */
99 doublecomplex stringToComplex(const char *pSTR, const char *decimal, BOOL bConvertByNAN, stringToComplexError *ierr)
101 doublecomplex dComplexValue;
102 *ierr = STRINGTOCOMPLEX_ERROR;
104 dComplexValue.r = 0.;
105 dComplexValue.i = 0.;
111 char * pStrWithOutBlanks = csv_strsubst(pSTR, " ", "");
113 pStrWithOutBlanks = csv_strsubst(pStrWithOutBlanks, decimal, ".");
115 if (pStrWithOutBlanks)
117 int lenStrWithOutBlanks = (int) strlen(pStrWithOutBlanks);
119 /* case .4 replaced by 0.4 */
120 if (pStrWithOutBlanks[0] == '.')
122 /* case .4 replaced by 0.4 */
123 char *pstStrTemp = (char*)MALLOC(sizeof(char) * (lenStrWithOutBlanks + strlen("0") + 1));
124 strcpy(pstStrTemp, "0");
125 strcat(pstStrTemp, pStrWithOutBlanks);
126 FREE(pStrWithOutBlanks);
127 pStrWithOutBlanks = pstStrTemp;
130 if (lenStrWithOutBlanks > 1)
132 if (((pStrWithOutBlanks[0] == '+') || (pStrWithOutBlanks[0] == '-')) &&
133 (pStrWithOutBlanks[1] == '.'))
135 /* case +.4 replaced by +0.4 */
136 char *pstStrTemp = csv_strsubst(pStrWithOutBlanks, "+.", "+0.");
137 FREE(pStrWithOutBlanks);
139 /* case -.4 replaced by -0.4 */
140 pStrWithOutBlanks = csv_strsubst(pstStrTemp, "-.", "-0.");
146 /* Case: "i", "+i", "-i", and with "j" */
147 if (is_unit_imaginary (pStrWithOutBlanks, &imag))
149 *ierr = STRINGTOCOMPLEX_NO_ERROR;
150 dComplexValue.r = 0.;
151 dComplexValue.i = imag;
155 *ierr = ParseComplexValue(pStrWithOutBlanks, bConvertByNAN, &real, &imag);
157 FREE(pStrWithOutBlanks);
158 pStrWithOutBlanks = NULL;
160 dComplexValue.r = real;
161 dComplexValue.i = imag;
163 return dComplexValue;
165 /* ========================================================================== */
166 static int ParseNumber(const char* tx)
180 if ((tx[len] == '+') || (tx[len] == '-'))
186 while (isdigit(tx[len]))
192 if (tx[lookahead] == '.')
196 while (isdigit(tx[len + lookahead]))
203 if ((tx[lookahead] == 'E') || (tx[lookahead] == 'e') ||
204 (tx[lookahead] == 'D') || (tx[lookahead] == 'd'))
208 if ((tx[lookahead] == '+') || (tx[lookahead] == '-'))
214 while (isdigit(tx[len + lookahead]))
223 /* ========================================================================== */
224 static stringToComplexError ParseComplexValue(const char *tx, BOOL bConvertByNAN, double *real, double *imag)
226 stringToDoubleError ierrDouble = STRINGTODOUBLE_NO_ERROR;
227 stringToComplexError ierr = STRINGTOCOMPLEX_NO_ERROR;
228 char *rnum_string = NULL;
229 char *inum_string = NULL;
231 BOOL haveImagI = FALSE;
232 char *modifiedTxt = NULL;
234 *real = stringToDouble(tx, FALSE, &ierrDouble);
237 /* test on strlen(tx) > 1 to remove case 'e' */
238 if ((int)strlen(tx) < 2)
240 if (ierrDouble == STRINGTODOUBLE_NO_ERROR)
242 ierr = (stringToComplexError) ierrDouble;
248 ierrDouble = STRINGTODOUBLE_NOT_A_NUMBER;
256 ierr = (stringToComplexError) ierrDouble;
260 else if (ierrDouble != STRINGTODOUBLE_NO_ERROR)
262 modifiedTxt = csv_strsubst(tx, ComplexScilab, ComplexI);
263 lnum = ParseNumber(modifiedTxt);
266 /* manages special cases nan + nani, ... */
267 if (strnicmp(modifiedTxt, NanString, strlen(NanString)) == 0)
269 lnum = strlen(NanString);
271 else if (strnicmp(modifiedTxt, InfString, strlen(InfString)) == 0)
273 lnum = strlen(InfString);
275 else if (strnicmp(modifiedTxt, NegInfString, strlen(NegInfString)) == 0)
277 lnum = strlen(NegInfString);
279 else if (strnicmp(modifiedTxt, PosInfString, strlen(PosInfString)) == 0)
281 lnum = strlen(PosInfString);
283 else if (strnicmp(modifiedTxt, NegNanString, strlen(NegNanString)) == 0)
285 lnum = strlen(NegNanString);
287 else if (strnicmp(modifiedTxt, PosNanString, strlen(PosNanString)) == 0)
289 lnum = strlen(PosNanString);
292 inum_string = midstring(modifiedTxt, lnum, -1);
294 if ((inum_string[strlen(inum_string) - 1] == 'i') ||
295 (inum_string[strlen(inum_string) - 1] == 'j'))
297 inum_string[strlen(inum_string) - 1] = 0;
298 if (inum_string[strlen(inum_string) - 1] == '*')
300 inum_string[strlen(inum_string) - 1] = 0;
303 if (strcmp(inum_string, "+") == 0)
306 inum_string = strdup("+1");
309 if (strcmp(inum_string, "-") == 0)
312 inum_string = strdup("-1");
320 rnum_string = leftstring(modifiedTxt, lnum);
322 if (strcmp(inum_string, "") == 0)
324 *imag = stringToDouble(rnum_string, bConvertByNAN, &ierrDouble);
325 ierr = (stringToComplexError)(ierrDouble);
333 stringToDoubleError ierrReal = STRINGTODOUBLE_NO_ERROR;
334 stringToDoubleError ierrImag = STRINGTODOUBLE_NO_ERROR;
335 dReal = stringToDouble(rnum_string, FALSE, &ierrReal);
336 dImag = stringToDouble(inum_string, FALSE, &ierrImag);
338 if ((ierrReal == STRINGTODOUBLE_NO_ERROR) && (ierrImag == STRINGTODOUBLE_NO_ERROR))
344 ierr = STRINGTOCOMPLEX_NO_ERROR;
350 ierr = STRINGTOCOMPLEX_ERROR;
355 ierr = STRINGTOCOMPLEX_NO_ERROR;
364 ierr = STRINGTOCOMPLEX_NO_ERROR;
370 ierr = STRINGTOCOMPLEX_ERROR;
393 /* ========================================================================== */
394 static char *midstring(const char *tx, size_t pos, int nb)
396 char *returnString = NULL;
399 int lenTx = (int) strlen(tx);
414 returnString = (char*)MALLOC(sizeof(char) * newLen);
415 strncpy(returnString, &tx[pos], posEnd);
416 returnString[posEnd] = 0;
421 /* ========================================================================== */
422 static char *leftstring(const char *tx, size_t pos)
424 char *returnString = NULL;
427 int lenTx = (int) strlen(tx);
428 returnString = strdup(tx);
429 if ((pos > lenTx) || (pos < 0))
435 returnString[pos] = 0;
440 /* ========================================================================== */
441 static BOOL is_unit_imaginary (const char *src, double *im)
443 char *modifiedSrc = csv_strsubst(src, ComplexScilab, ComplexI);
444 char *nextChar = NULL;
445 BOOL isUnitImag = FALSE;
447 if (modifiedSrc == NULL)
452 if (modifiedSrc[0] == LessChar)
455 nextChar = modifiedSrc + 1;
460 if (modifiedSrc[0] == PlusChar)
462 nextChar = modifiedSrc + 1;
466 nextChar = modifiedSrc;
472 if ((nextChar[0] == ComplexCharI || nextChar[0] == ComplexCharJ) && nextChar[1] == 0)
485 /* ========================================================================== */
486 static double returnNAN(void)
488 static int first = 1;
489 static double nan = 1.0;
493 nan = (nan - (double) first) / (nan - (double) first);
498 // =============================================================================