LAL  7.5.0.1-bede9b2
StringConvert.c
Go to the documentation of this file.
1 /*
2 * Copyright (C) 2007 Jolien Creighton, Peter Shawhan
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with with program; see the file COPYING. If not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 * MA 02110-1301 USA
18 */
19 
20 /**
21  * \file
22  * \ingroup StringInput_h
23  * \authors Creighton, T. D.
24  * \authors Shawhan, P. S.
25  *
26  * \brief Converts a string into a numerical value.
27  *
28  * ### Description ###
29  *
30  * These routines parse the string <tt>*string</tt> and compute a numerical
31  * value <tt>*value</tt> of the appropriate datatype. If
32  * \c endptr\f$\neq\f$\c NULL, then after conversion <tt>*endptr</tt>
33  * will point to the character after the last character used in the
34  * conversion. The routine will always return without error if the
35  * arguments are valid, regardless of the contents of \c string;
36  * failure to parse a number is indicated by <tt>*endptr</tt> being set
37  * equal to \c string (provided \c endptr\f$\neq\f$\c NULL).
38  *
39  * For integer or floating-point conversion to occur, \c string must
40  * consist of zero or more whitespace characters followed by a number in
41  * any standard base-ten integer or floating-point representation
42  * (described in detail below); the conversion will stop as soon as the
43  * routine encounters a character that is not part of the number. For
44  * instance, parsing the string <tt>" 123bad"</tt> will return
45  * <tt>*value</tt>=123, and <tt>*endptr</tt> will point to the substring
46  * <tt>"bad"</tt>; it is up to the calling routine to determine whether
47  * this is an acceptable input. By contrast, parsing the string
48  * <tt>" bad"</tt> will leave <tt>*value</tt> unchanged and <tt>*endptr</tt>
49  * pointing to the start of the original string. In general, if the
50  * routine returns with <tt>*endptr</tt>\f$\neq\f$\c string and
51  * <tt>**endptr</tt> is a whitespace or <tt>'\0'</tt> character, then the
52  * format was unambiguously acceptable.
53  *
54  * Complex conversion is essentially equivalent to performing
55  * floating-point conversion on \c string to get the real part, and
56  * again on <tt>*endptr</tt> to get the imaginary part. Normally this
57  * means that an acceptable format is two floating-point representations
58  * separated by (and possibly preceded with) whitespace, although the
59  * intervening whitespace can be omitted if the separation between the
60  * two numbers is unambiguous. Thus the string <tt>"-1.0+3.5"</tt> will be
61  * unambiguously read as \f$-1.0+3.5i\f$, but <tt>"-1.03.5"</tt> will be read
62  * as \f$-1.03+0.5i\f$ (since the conversion of the real part stops at the
63  * second <tt>'.'</tt> character), which may or may not be the intended
64  * conversion.
65  *
66  * ### Algorithm ###
67  *
68  * These functions emulate the standard C functions <tt>strtol()</tt>,
69  * <tt>strtoul()</tt>, and <tt>strtod()</tt>, except that they follow LAL
70  * calling conventions and return values of the appropriate LAL datatypes.
71  * For integer conversion, only base-ten (decimal) representations are
72  * supported. Otherwise, the valid format is as for the corresponding C
73  * functions, which we summarize below:
74  *
75  * A string to be converted to an \c INT\f$n\f$ (where \f$n\f$=2, 4, or 8)
76  * consists of zero or more whitespace characters as determined by
77  * <tt>isspace()</tt>, followed optionally by a single <tt>'+'</tt> or
78  * <tt>'-'</tt> character, followed by one or more decimal digits;
79  * conversion stops at the first non-digit character after this. If the
80  * result would overflow or underflow the \c INT\f$n\f$ representation,
81  * then the value is set to \c LAL_INT\f$n\f$\c _MAX\f$=2^{8n-1}-1\f$ or \c
82  * LAL_INT\f$n\f$\c _MIN\f$=-2^{8n-1}\f$, respectively.
83  *
84  * A string to be converted to a \c UINT\f$n\f$ follows the same format,
85  * except that a leading negative sign character <tt>'-'</tt> is \e ignored
86  * (the routine will compute the magnitude of the result), and the return
87  * value is capped at \c LAL_UINT\f$n\f$\c _MAX\f$=2^{8n}-1\f$.
88  *
89  * A string to be converted to a floating-point number (\c REAL4 or \c
90  * REAL8) consists of zero or more whitespace characters as determined by
91  * <tt>isspace()</tt>, followed optionally by a single <tt>'+'</tt> or
92  * <tt>'-'</tt> character, followed by a sequence of one or more decimal
93  * digits optionally containing a decimal point <tt>'.'</tt>, optionally
94  * followed by an exponent. An exponent consists of a single <tt>'E'</tt>
95  * or <tt>'e'</tt> character, followed optionally by a single <tt>'+'</tt>
96  * or <tt>'-'</tt> character, followed by a sequence of one or more decimal
97  * digits. If the converted value would overflow, \f$\pm\f$\c
98  * LAL_REAL\f$n\f$\c _MAX is returned, as appropriate. If the value would
99  * underflow, 0 is returned.
100  *
101  * A string to be converted to a complex number (\c COMPLEX8 or \c
102  * COMPLEX16) consists of two floating-point format substrings concatenated
103  * together, where the first character of the second substring cannot be
104  * interpreted as a continuation of the first number. Usually this means
105  * that the second substring will contain at least one leading whitespace
106  * character, though this is not strictly necessary. Overflow or underflow
107  * is dealt with as above.
108  */
109 
110 /** \cond DONT_DOXYGEN */
111 #include <complex.h>
112 #include <ctype.h>
113 #include <lal/LALStdlib.h>
114 #include <lal/LALConstants.h>
115 #include <lal/StringInput.h>
116 
117 #define LAL_INT8_ABSMIN LAL_UINT8_C(9223372036854775808)
118 #define LAL_INT4_ABSMIN LAL_UINT8_C(2147483648)
119 #define LAL_INT2_ABSMIN LAL_UINT8_C(32768)
120 
121 /* Maximum number of digits we ever need to parse for an integer. */
122 #define LAL_UINT8_MAXDIGITS (20)
123 
124 /* Internal function to parse integer strings into UINT8 magnitudes
125  plus a sign. */
126 static UINT8
127 LALStringToU8AndSign(INT2 * sign, const CHAR * string, CHAR ** endptr)
128 {
129  union {
130  char *s;
131  const char *cs;
132  } bad; /* there is a REASON for warnings... */
133  const CHAR *here = string; /* current position in string */
134  CHAR c; /* current character in string */
135  UINT4 n = LAL_UINT8_MAXDIGITS - 1; /* number of worry-free digits */
136  UINT8 value; /* current converted value */
137 
138  /* Skip leading space, and read sign character, if any. */
139  *sign = 1;
140  while (isspace(*here))
141  here++;
142  if (*here == '+')
143  here++;
144  else if (*here == '-') {
145  *sign = -1;
146  here++;
147  }
148 
149  /* Read first digit. Abort if it's not a digit. */
150  if (isdigit((int) (c = *here))) {
151  value = (UINT8) (c - '0');
152  here++;
153  } else {
154  bad.cs = string; /* ... and this avoids the warnings... BAD! */
155  *endptr = bad.s;
156  return 0;
157  }
158 
159  /* Otherwise, start reading number. Stop if we get close to
160  overflowing. */
161  while (isdigit((int) (c = *here)) && --n) {
162  value *= LAL_INT8_C(10);
163  value += (UINT8) (c - '0');
164  here++;
165  }
166 
167  /* Proceed with caution near overflow. At this point, if n==0, then
168  c = *here is the (LAL_UINT8_MAXDIGITS)th digit read, but value
169  does not yet incorporate it. */
170  if (!n) {
171  here++;
172  if (isdigit((int) (*here))) {
173  value = LAL_UINT8_MAX;
174  do
175  here++;
176  while (isdigit((int) (*here)));
177  } else if (value > LAL_UINT8_MAX / LAL_INT8_C(10)) {
178  value = LAL_UINT8_MAX;
179  } else {
180  UINT8 increment = (UINT8) (c - '0');
181  value *= 10;
182  if (value > LAL_UINT8_MAX - increment)
183  value = LAL_UINT8_MAX;
184  else
185  value += increment;
186  }
187  }
188 
189  /* Return appropriate values. */
190  bad.cs = here; /* ... and this avoids the warnings... BAD! */
191  *endptr = bad.s;
192  return value;
193 }
194 
195 /** \endcond */
196 
197 void
198 LALStringToU2(LALStatus * stat, UINT2 * value, const CHAR * string,
199  CHAR ** endptr)
200 {
201  UINT8 absValue; /* magnitude of parsed number */
202  INT2 sign; /* sign of parsed number */
203  CHAR *end; /* substring following parsed number */
204 
205  INITSTATUS(stat);
206 
207  /* Check for valid input arguments. */
208  ASSERT(value, stat, STRINGINPUTH_ENUL, STRINGINPUTH_MSGENUL);
209  ASSERT(string, stat, STRINGINPUTH_ENUL, STRINGINPUTH_MSGENUL);
210 
211  /* Parse string. Return if nothing was parsed. */
212  absValue = LALStringToU8AndSign(&sign, string, &end);
213  if (string == end) {
214  if (endptr)
215  *endptr = end;
216  RETURN(stat);
217  }
218 
219  /* Cap (if necessary), cast, and return. */
220  if (absValue > LAL_UINT2_MAX)
221  *value = (UINT2) (LAL_UINT2_MAX);
222  else
223  *value = (UINT2) (absValue);
224  if (endptr)
225  *endptr = end;
226  RETURN(stat);
227 }
228 
229 
230 
231 void
232 LALStringToU4(LALStatus * stat, UINT4 * value, const CHAR * string,
233  CHAR ** endptr)
234 {
235  UINT8 absValue; /* magnitude of parsed number */
236  INT2 sign; /* sign of parsed number */
237  CHAR *end; /* substring following parsed number */
238 
239  INITSTATUS(stat);
240 
241  /* Check for valid input arguments. */
242  ASSERT(value, stat, STRINGINPUTH_ENUL, STRINGINPUTH_MSGENUL);
243  ASSERT(string, stat, STRINGINPUTH_ENUL, STRINGINPUTH_MSGENUL);
244 
245  /* Parse string. Return if nothing was parsed. */
246  absValue = LALStringToU8AndSign(&sign, string, &end);
247  if (string == end) {
248  if (endptr)
249  *endptr = end;
250  RETURN(stat);
251  }
252 
253  /* Cap (if necessary), cast, and return. */
254  if (absValue > LAL_UINT4_MAX)
255  *value = (UINT4) (LAL_UINT4_MAX);
256  else
257  *value = (UINT4) (absValue);
258  if (endptr)
259  *endptr = end;
260  RETURN(stat);
261 }
262 
263 
264 
265 void
266 LALStringToU8(LALStatus * stat, UINT8 * value, const CHAR * string,
267  CHAR ** endptr)
268 {
269  UINT8 absValue; /* magnitude of parsed number */
270  INT2 sign; /* sign of parsed number */
271  CHAR *end; /* substring following parsed number */
272 
273  INITSTATUS(stat);
274 
275  /* Check for valid input arguments. */
276  ASSERT(value, stat, STRINGINPUTH_ENUL, STRINGINPUTH_MSGENUL);
277  ASSERT(string, stat, STRINGINPUTH_ENUL, STRINGINPUTH_MSGENUL);
278 
279  /* Parse string. Return if nothing was parsed. */
280  absValue = LALStringToU8AndSign(&sign, string, &end);
281  if (string == end) {
282  if (endptr)
283  *endptr = end;
284  RETURN(stat);
285  }
286 
287  /* Set values and return. */
288  *value = absValue;
289  if (endptr)
290  *endptr = end;
291  RETURN(stat);
292 }
293 
294 
295 
296 void
297 LALStringToI2(LALStatus * stat, INT2 * value, const CHAR * string,
298  CHAR ** endptr)
299 {
300  UINT8 absValue; /* magnitude of parsed number */
301  INT2 sign; /* sign of parsed number */
302  CHAR *end; /* substring following parsed number */
303 
304  INITSTATUS(stat);
305 
306  /* Check for valid input arguments. */
307  ASSERT(value, stat, STRINGINPUTH_ENUL, STRINGINPUTH_MSGENUL);
308  ASSERT(string, stat, STRINGINPUTH_ENUL, STRINGINPUTH_MSGENUL);
309 
310  /* Parse string. Return if nothing was parsed. */
311  absValue = LALStringToU8AndSign(&sign, string, &end);
312  if (string == end) {
313  if (endptr)
314  *endptr = end;
315  RETURN(stat);
316  }
317 
318  /* Cap (if necessary), cast, and return. */
319  if (sign > 0) {
320  if (absValue > LAL_INT2_MAX)
321  *value = (INT2) (LAL_INT2_MAX);
322  else
323  *value = (INT2) (absValue);
324  } else {
325  if (absValue > LAL_INT2_ABSMIN)
326  *value = (INT2) (-LAL_INT2_ABSMIN);
327  else
328  *value = (INT2) (-absValue);
329  }
330  if (endptr)
331  *endptr = end;
332  RETURN(stat);
333 }
334 
335 
336 
337 void
338 LALStringToI4(LALStatus * stat, INT4 * value, const CHAR * string,
339  CHAR ** endptr)
340 {
341  UINT8 absValue; /* magnitude of parsed number */
342  INT2 sign; /* sign of parsed number */
343  CHAR *end; /* substring following parsed number */
344 
345  INITSTATUS(stat);
346 
347  /* Check for valid input arguments. */
348  ASSERT(value, stat, STRINGINPUTH_ENUL, STRINGINPUTH_MSGENUL);
349  ASSERT(string, stat, STRINGINPUTH_ENUL, STRINGINPUTH_MSGENUL);
350 
351  /* Parse string. Return if nothing was parsed. */
352  absValue = LALStringToU8AndSign(&sign, string, &end);
353  if (string == end) {
354  if (endptr)
355  *endptr = end;
356  RETURN(stat);
357  }
358 
359  /* Cap (if necessary), cast, and return. */
360  if (sign > 0) {
361  if (absValue > LAL_INT4_MAX)
362  *value = (INT4) (LAL_INT4_MAX);
363  else
364  *value = (INT4) (absValue);
365  } else {
366  if (absValue > LAL_INT4_ABSMIN)
367  *value = (INT4) (-LAL_INT4_ABSMIN);
368  else
369  *value = (INT4) (-absValue);
370  }
371  if (endptr)
372  *endptr = end;
373  RETURN(stat);
374 }
375 
376 
377 
378 void
379 LALStringToI8(LALStatus * stat, INT8 * value, const CHAR * string,
380  CHAR ** endptr)
381 {
382  UINT8 absValue; /* magnitude of parsed number */
383  INT2 sign; /* sign of parsed number */
384  CHAR *end; /* substring following parsed number */
385 
386  INITSTATUS(stat);
387 
388  /* Check for valid input arguments. */
389  ASSERT(value, stat, STRINGINPUTH_ENUL, STRINGINPUTH_MSGENUL);
390  ASSERT(string, stat, STRINGINPUTH_ENUL, STRINGINPUTH_MSGENUL);
391 
392  /* Parse string. Return if nothing was parsed. */
393  absValue = LALStringToU8AndSign(&sign, string, &end);
394  if (string == end) {
395  if (endptr)
396  *endptr = end;
397  RETURN(stat);
398  }
399 
400  /* Cap (if necessary), cast, and return. */
401  if (sign > 0) {
402  if (absValue > LAL_INT8_MAX)
403  *value = (INT8) (LAL_INT8_MAX);
404  else
405  *value = (INT8) (absValue);
406  } else {
407  if (absValue > LAL_INT8_ABSMIN)
408  *value = (INT8) (-LAL_INT8_ABSMIN);
409  else
410  *value = (INT8) (-absValue);
411  }
412  if (endptr)
413  *endptr = end;
414  RETURN(stat);
415 }
416 
417 
418 
419 void
420 LALStringToS(LALStatus * stat, REAL4 * value, const CHAR * string,
421  CHAR ** endptr)
422 {
423  REAL8 myValue; /* internal representation of value */
424  CHAR *end; /* substring following parsed number */
425 
426  INITSTATUS(stat);
427 
428  /* Check for valid input arguments. */
429  ASSERT(value, stat, STRINGINPUTH_ENUL, STRINGINPUTH_MSGENUL);
430  ASSERT(string, stat, STRINGINPUTH_ENUL, STRINGINPUTH_MSGENUL);
431 
432  /* Parse string. Return if nothing was parsed. */
433  myValue = strtod(string, &end);
434  if (string == end) {
435  if (endptr)
436  *endptr = end;
437  RETURN(stat);
438  }
439 
440  /* Cap (if necessary), cast, and return. */
441  if (myValue > LAL_REAL4_MAX)
442  *value = (REAL4) (LAL_REAL4_MAX);
443  else if (myValue < -LAL_REAL4_MAX)
444  *value = (REAL4) (-LAL_REAL4_MAX);
445  else
446  *value = (REAL4) (myValue);
447  if (endptr)
448  *endptr = end;
449  RETURN(stat);
450 }
451 
452 
453 
454 void
455 LALStringToD(LALStatus * stat, REAL8 * value, const CHAR * string,
456  CHAR ** endptr)
457 {
458  REAL8 myValue; /* internal representation of value */
459  CHAR *end; /* substring following parsed number */
460 
461  INITSTATUS(stat);
462 
463  /* Check for valid input arguments. */
464  ASSERT(value, stat, STRINGINPUTH_ENUL, STRINGINPUTH_MSGENUL);
465  ASSERT(string, stat, STRINGINPUTH_ENUL, STRINGINPUTH_MSGENUL);
466 
467  /* Parse string. Return if nothing was parsed. */
468  myValue = strtod(string, &end);
469  if (string == end) {
470  if (endptr)
471  *endptr = end;
472  RETURN(stat);
473  }
474 
475  /* Set values and return. */
476  if (myValue > LAL_REAL8_MAX)
477  *value = LAL_REAL8_MAX;
478  else if (myValue < -LAL_REAL8_MAX)
479  *value = -LAL_REAL8_MAX;
480  else
481  *value = myValue;
482  if (endptr)
483  *endptr = end;
484  RETURN(stat);
485 }
486 
487 
488 
489 void
490 LALStringToC(LALStatus * stat, COMPLEX8 * value, const CHAR * string,
491  CHAR ** endptr)
492 {
493  REAL4 re, im; /* real and imaginary parts */
494  CHAR *end; /* substring following parsed numbers */
495 
496  INITSTATUS(stat);
497  ATTATCHSTATUSPTR(stat);
498 
499  /* Check for valid input arguments. */
500  ASSERT(value, stat, STRINGINPUTH_ENUL, STRINGINPUTH_MSGENUL);
501  ASSERT(string, stat, STRINGINPUTH_ENUL, STRINGINPUTH_MSGENUL);
502 
503  /* Parse string. Return if nothing was parsed. */
504  TRY(LALStringToS(stat->statusPtr, &re, string, &end), stat);
505  TRY(LALStringToS(stat->statusPtr, &im, end, &end), stat);
506  if (string == end) {
507  if (endptr)
508  *endptr = end;
509  DETATCHSTATUSPTR(stat);
510  RETURN(stat);
511  }
512 
513  /* Set values and return. */
514  *value = re;
515  *value += im * I;
516  if (endptr)
517  *endptr = end;
518  DETATCHSTATUSPTR(stat);
519  RETURN(stat);
520 }
521 
522 
523 
524 void
525 LALStringToZ(LALStatus * stat, COMPLEX16 * value, const CHAR * string,
526  CHAR ** endptr)
527 {
528  REAL8 re, im; /* real and imaginary parts */
529  CHAR *end; /* substring following parsed numbers */
530 
531  INITSTATUS(stat);
532  ATTATCHSTATUSPTR(stat);
533 
534  /* Check for valid input arguments. */
535  ASSERT(value, stat, STRINGINPUTH_ENUL, STRINGINPUTH_MSGENUL);
536  ASSERT(string, stat, STRINGINPUTH_ENUL, STRINGINPUTH_MSGENUL);
537 
538  /* Parse string. Return if nothing was parsed. */
539  TRY(LALStringToD(stat->statusPtr, &re, string, &end), stat);
540  TRY(LALStringToD(stat->statusPtr, &im, end, &end), stat);
541  if (string == end) {
542  if (endptr)
543  *endptr = end;
544  DETATCHSTATUSPTR(stat);
545  RETURN(stat);
546  }
547 
548  /* Set values and return. */
549  *value = re;
550  *value += im * I;
551  if (endptr)
552  *endptr = end;
553  DETATCHSTATUSPTR(stat);
554  RETURN(stat);
555 }
#define TRY(func, statusptr)
#define ATTATCHSTATUSPTR(statusptr)
#define ASSERT(assertion, statusptr, code, mesg)
#define DETATCHSTATUSPTR(statusptr)
#define INITSTATUS(statusptr)
#define RETURN(statusptr)
static int sign(int s)
Definition: LALStringTest.c:27
void LALStringToU4(LALStatus *stat, UINT4 *value, const CHAR *string, CHAR **endptr)
void LALStringToZ(LALStatus *stat, COMPLEX16 *value, const CHAR *string, CHAR **endptr)
void LALStringToU8(LALStatus *stat, UINT8 *value, const CHAR *string, CHAR **endptr)
void LALStringToI4(LALStatus *stat, INT4 *value, const CHAR *string, CHAR **endptr)
void LALStringToS(LALStatus *stat, REAL4 *value, const CHAR *string, CHAR **endptr)
void LALStringToC(LALStatus *stat, COMPLEX8 *value, const CHAR *string, CHAR **endptr)
void LALStringToU2(LALStatus *stat, UINT2 *value, const CHAR *string, CHAR **endptr)
void LALStringToD(LALStatus *stat, REAL8 *value, const CHAR *string, CHAR **endptr)
void LALStringToI2(LALStatus *stat, INT2 *value, const CHAR *string, CHAR **endptr)
void LALStringToI8(LALStatus *stat, INT8 *value, const CHAR *string, CHAR **endptr)
#define LAL_UINT4_MAX
Definition: LALConstants.h:80
#define LAL_INT2_MAX
Definition: LALConstants.h:84
#define LAL_REAL4_MAX
Largest normalized REAL4 number (2-2^-23)*2^127.
Definition: LALConstants.h:55
#define LAL_INT4_MAX
Definition: LALConstants.h:83
#define LAL_UINT8_MAX
Definition: LALConstants.h:79
#define LAL_UINT2_MAX
Definition: LALConstants.h:81
#define LAL_INT8_MAX
Definition: LALConstants.h:82
#define LAL_REAL8_MAX
Largest normalized REAL8 number (2-2^-52)*2^1023.
Definition: LALConstants.h:59
uint64_t UINT8
Eight-byte unsigned integer; on some platforms this is equivalent to unsigned long int instead.
double complex COMPLEX16
Double-precision floating-point complex number (16 bytes total)
#define LAL_INT8_C(c)
Macro for use in defining v as an INT8 constant.
double REAL8
Double precision real floating-point number (8 bytes).
int16_t INT2
Two-byte signed integer.
int64_t INT8
Eight-byte signed integer; on some platforms this is equivalent to long int instead.
uint16_t UINT2
Two-byte unsigned integer.
char CHAR
One-byte signed integer, see Headers LAL(Atomic)Datatypes.h for more details.
uint32_t UINT4
Four-byte unsigned integer.
float complex COMPLEX8
Single-precision floating-point complex number (8 bytes total)
int32_t INT4
Four-byte signed integer.
float REAL4
Single precision real floating-point number (4 bytes).
#define STRINGINPUTH_ENUL
Unexpected null pointer in arguments.
Definition: StringInput.h:120
LAL status structure, see The LALStatus structure for more details.
Definition: LALDatatypes.h:947
struct tagLALStatus * statusPtr
Pointer to the next node in the list; NULL if this function is not reporting a subroutine error.
Definition: LALDatatypes.h:954