blob: 3a9452eac2bf34ae26d5db3407bb522c28adaa4d
1 | /* |
2 | * C99-compatible strtod() implementation |
3 | * Copyright (c) 2012 Ronald S. Bultje <rsbultje@gmail.com> |
4 | * |
5 | * This file is part of FFmpeg. |
6 | * |
7 | * FFmpeg is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU Lesser General Public |
9 | * License as published by the Free Software Foundation; either |
10 | * version 2.1 of the License, or (at your option) any later version. |
11 | * |
12 | * FFmpeg is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | * Lesser General Public License for more details. |
16 | * |
17 | * You should have received a copy of the GNU Lesser General Public |
18 | * License along with FFmpeg; if not, write to the Free Software |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | */ |
21 | |
22 | #include <limits.h> |
23 | #include <stdlib.h> |
24 | |
25 | #include "libavutil/avstring.h" |
26 | #include "libavutil/mathematics.h" |
27 | |
28 | static char *check_nan_suffix(char *s) |
29 | { |
30 | char *start = s; |
31 | |
32 | if (*s++ != '(') |
33 | return start; |
34 | |
35 | while ((*s >= 'a' && *s <= 'z') || (*s >= 'A' && *s <= 'Z') || |
36 | (*s >= '0' && *s <= '9') || *s == '_') |
37 | s++; |
38 | |
39 | return *s == ')' ? s + 1 : start; |
40 | } |
41 | |
42 | #undef strtod |
43 | double strtod(const char *, char **); |
44 | |
45 | double avpriv_strtod(const char *nptr, char **endptr) |
46 | { |
47 | char *end; |
48 | double res; |
49 | |
50 | /* Skip leading spaces */ |
51 | while (av_isspace(*nptr)) |
52 | nptr++; |
53 | |
54 | if (!av_strncasecmp(nptr, "infinity", 8)) { |
55 | end = nptr + 8; |
56 | res = INFINITY; |
57 | } else if (!av_strncasecmp(nptr, "inf", 3)) { |
58 | end = nptr + 3; |
59 | res = INFINITY; |
60 | } else if (!av_strncasecmp(nptr, "+infinity", 9)) { |
61 | end = nptr + 9; |
62 | res = INFINITY; |
63 | } else if (!av_strncasecmp(nptr, "+inf", 4)) { |
64 | end = nptr + 4; |
65 | res = INFINITY; |
66 | } else if (!av_strncasecmp(nptr, "-infinity", 9)) { |
67 | end = nptr + 9; |
68 | res = -INFINITY; |
69 | } else if (!av_strncasecmp(nptr, "-inf", 4)) { |
70 | end = nptr + 4; |
71 | res = -INFINITY; |
72 | } else if (!av_strncasecmp(nptr, "nan", 3)) { |
73 | end = check_nan_suffix(nptr + 3); |
74 | res = NAN; |
75 | } else if (!av_strncasecmp(nptr, "+nan", 4) || |
76 | !av_strncasecmp(nptr, "-nan", 4)) { |
77 | end = check_nan_suffix(nptr + 4); |
78 | res = NAN; |
79 | } else if (!av_strncasecmp(nptr, "0x", 2) || |
80 | !av_strncasecmp(nptr, "-0x", 3) || |
81 | !av_strncasecmp(nptr, "+0x", 3)) { |
82 | /* FIXME this doesn't handle exponents, non-integers (float/double) |
83 | * and numbers too large for long long */ |
84 | res = strtoll(nptr, &end, 16); |
85 | } else { |
86 | res = strtod(nptr, &end); |
87 | } |
88 | |
89 | if (endptr) |
90 | *endptr = end; |
91 | |
92 | return res; |
93 | } |
94 |