* Try to parse value as an integer. The accepted formats are the * usual decimal, octal, or hexadecimal formats, as well as floating-point * formats (which will be rounded to integer after any units conversion). * Optionally, the value can be followed by a unit name if "flags" indicates * a unit is allowed. * * If the string parses okay, return true, else false. * If okay and result is not
| 7155 | * HINT message, or NULL if no hint provided. |
| 7156 | */ |
| 7157 | bool |
| 7158 | parse_int(const char *value, int *result, int flags, const char **hintmsg) |
| 7159 | { |
| 7160 | /* |
| 7161 | * We assume here that double is wide enough to represent any integer |
| 7162 | * value with adequate precision. |
| 7163 | */ |
| 7164 | double val; |
| 7165 | char *endptr; |
| 7166 | |
| 7167 | /* To suppress compiler warnings, always set output params */ |
| 7168 | if (result) |
| 7169 | *result = 0; |
| 7170 | if (hintmsg) |
| 7171 | *hintmsg = NULL; |
| 7172 | |
| 7173 | /* |
| 7174 | * Try to parse as an integer (allowing octal or hex input). If the |
| 7175 | * conversion stops at a decimal point or 'e', or overflows, re-parse as |
| 7176 | * float. This should work fine as long as we have no unit names starting |
| 7177 | * with 'e'. If we ever do, the test could be extended to check for a |
| 7178 | * sign or digit after 'e', but for now that's unnecessary. |
| 7179 | */ |
| 7180 | errno = 0; |
| 7181 | val = strtol(value, &endptr, 0); |
| 7182 | if (*endptr == '.' || *endptr == 'e' || *endptr == 'E' || |
| 7183 | errno == ERANGE) |
| 7184 | { |
| 7185 | errno = 0; |
| 7186 | val = strtod(value, &endptr); |
| 7187 | } |
| 7188 | |
| 7189 | if (endptr == value || errno == ERANGE) |
| 7190 | return false; /* no HINT for these cases */ |
| 7191 | |
| 7192 | /* reject NaN (infinities will fail range check below) */ |
| 7193 | if (isnan(val)) |
| 7194 | return false; /* treat same as syntax error; no HINT */ |
| 7195 | |
| 7196 | /* allow whitespace between number and unit */ |
| 7197 | while (isspace((unsigned char) *endptr)) |
| 7198 | endptr++; |
| 7199 | |
| 7200 | /* Handle possible unit */ |
| 7201 | if (*endptr != '\0') |
| 7202 | { |
| 7203 | if ((flags & GUC_UNIT) == 0) |
| 7204 | return false; /* this setting does not accept a unit */ |
| 7205 | |
| 7206 | if (!convert_to_base_unit(val, |
| 7207 | endptr, (flags & GUC_UNIT), |
| 7208 | &val)) |
| 7209 | { |
| 7210 | /* invalid unit, or garbage after the unit; set hint and fail. */ |
| 7211 | if (hintmsg) |
| 7212 | { |
| 7213 | if (flags & GUC_UNIT_MEMORY) |
| 7214 | *hintmsg = memory_units_hint; |
no test coverage detected