1 /* -*- Mode: C; c-file-style: "python" -*- */
6 /* ascii character tests (as opposed to locale tests) */
7 #define ISSPACE(c) ((c) == ' ' || (c) == '\f' || (c) == '\n' || \
8 (c) == '\r' || (c) == '\t' || (c) == '\v')
9 #define ISDIGIT(c) ((c) >= '0' && (c) <= '9')
10 #define ISXDIGIT(c) (ISDIGIT(c) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F'))
15 * @nptr: the string to convert to a numeric value.
16 * @endptr: if non-%NULL, it returns the character after
17 * the last character used in the conversion.
19 * Converts a string to a #gdouble value.
20 * This function behaves like the standard strtod() function
21 * does in the C locale. It does this without actually
22 * changing the current locale, since that would not be
25 * This function is typically used when reading configuration
26 * files or other non-user input that should be locale independent.
27 * To handle input from the user you should normally use the
28 * locale-sensitive system strtod() function.
30 * If the correct value would cause overflow, plus or minus %HUGE_VAL
31 * is returned (according to the sign of the value), and %ERANGE is
32 * stored in %errno. If the correct value would cause underflow,
33 * zero is returned and %ERANGE is stored in %errno.
35 * This function resets %errno before calling strtod() so that
36 * you can reliably detect overflow and underflow.
38 * Return value: the #gdouble value.
41 PyOS_ascii_strtod(const char *nptr
,
46 struct lconv
*locale_data
;
47 const char *decimal_point
;
48 int decimal_point_len
;
49 const char *p
, *decimal_point_pos
;
50 const char *end
= NULL
; /* Silence gcc */
52 /* g_return_val_if_fail (nptr != NULL, 0); */
57 locale_data
= localeconv();
58 decimal_point
= locale_data
->decimal_point
;
59 decimal_point_len
= strlen(decimal_point
);
61 assert(decimal_point_len
!= 0);
63 decimal_point_pos
= NULL
;
64 if (decimal_point
[0] != '.' ||
65 decimal_point
[1] != 0)
68 /* Skip leading space */
72 /* Skip leading optional sign */
73 if (*p
== '+' || *p
== '-')
77 (p
[1] == 'x' || p
[1] == 'X'))
80 /* HEX - find the (optional) decimal point */
87 decimal_point_pos
= p
++;
92 if (*p
== 'p' || *p
== 'P')
94 if (*p
== '+' || *p
== '-')
108 decimal_point_pos
= p
++;
113 if (*p
== 'e' || *p
== 'E')
115 if (*p
== '+' || *p
== '-')
122 /* For the other cases, we need not convert the decimal point */
125 /* Set errno to zero, so that we can distinguish zero results
129 if (decimal_point_pos
)
133 /* We need to convert the '.' to the locale specific decimal point */
134 copy
= malloc(end
- nptr
+ 1 + decimal_point_len
);
137 memcpy(c
, nptr
, decimal_point_pos
- nptr
);
138 c
+= decimal_point_pos
- nptr
;
139 memcpy(c
, decimal_point
, decimal_point_len
);
140 c
+= decimal_point_len
;
141 memcpy(c
, decimal_point_pos
+ 1, end
- (decimal_point_pos
+ 1));
142 c
+= end
- (decimal_point_pos
+ 1);
145 val
= strtod(copy
, &fail_pos
);
149 if (fail_pos
> decimal_point_pos
)
150 fail_pos
= (char *)nptr
+ (fail_pos
- copy
) - (decimal_point_len
- 1);
152 fail_pos
= (char *)nptr
+ (fail_pos
- copy
);
159 val
= strtod(nptr
, &fail_pos
);
169 * PyOS_ascii_formatd:
170 * @buffer: A buffer to place the resulting string in
171 * @buf_len: The length of the buffer.
172 * @format: The printf()-style format to use for the
173 * code to use for converting.
174 * @d: The #gdouble to convert
176 * Converts a #gdouble to a string, using the '.' as
177 * decimal point. To format the number you pass in
178 * a printf()-style format string. Allowed conversion
179 * specifiers are 'e', 'E', 'f', 'F', 'g' and 'G'.
181 * Return value: The pointer to the buffer with the converted string.
184 PyOS_ascii_formatd(char *buffer
,
189 struct lconv
*locale_data
;
190 const char *decimal_point
;
191 int decimal_point_len
;
196 /* g_return_val_if_fail (buffer != NULL, NULL); */
197 /* g_return_val_if_fail (format[0] == '%', NULL); */
198 /* g_return_val_if_fail (strpbrk (format + 1, "'l%") == NULL, NULL); */
200 format_char
= format
[strlen(format
) - 1];
202 /* g_return_val_if_fail (format_char == 'e' || format_char == 'E' || */
203 /* format_char == 'f' || format_char == 'F' || */
204 /* format_char == 'g' || format_char == 'G', */
207 if (format
[0] != '%')
210 if (strpbrk(format
+ 1, "'l%"))
213 if (!(format_char
== 'e' || format_char
== 'E' ||
214 format_char
== 'f' || format_char
== 'F' ||
215 format_char
== 'g' || format_char
== 'G'))
219 PyOS_snprintf(buffer
, buf_len
, format
, d
);
221 locale_data
= localeconv();
222 decimal_point
= locale_data
->decimal_point
;
223 decimal_point_len
= strlen(decimal_point
);
225 assert(decimal_point_len
!= 0);
227 if (decimal_point
[0] != '.' ||
228 decimal_point
[1] != 0)
232 if (*p
== '+' || *p
== '-')
235 while (isdigit((unsigned char)*p
))
238 if (strncmp(p
, decimal_point
, decimal_point_len
) == 0)
242 if (decimal_point_len
> 1) {
243 rest_len
= strlen(p
+ (decimal_point_len
- 1));
244 memmove(p
, p
+ (decimal_point_len
- 1),
255 PyOS_ascii_atof(const char *nptr
)
257 return PyOS_ascii_strtod(nptr
, NULL
);