Loading [MathJax]/extensions/TeX/AMSsymbols.js
LAL 7.7.0.1-00ddc7f
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
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. */
126static UINT8
127LALStringToU8AndSign(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
197void
198LALStringToU2(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
231void
232LALStringToU4(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
265void
266LALStringToU8(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
296void
297LALStringToI2(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
337void
338LALStringToI4(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
378void
379LALStringToI8(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
419void
420LALStringToS(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
454void
455LALStringToD(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
489void
490LALStringToC(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
524void
525LALStringToZ(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