* Parse hex values like 0xff, -0xff, 0XdeAdBeaf42, cannot be trailed by '.', 'p', or 'P'. * Overflows if string is more than 16 valid hex digits. Otherwise similar to parse_integer. */
| 124 | * Overflows if string is more than 16 valid hex digits. Otherwise similar to parse_integer. |
| 125 | */ |
| 126 | static const char *parse_hex_integer(const char *buf, size_t len, uint64_t *value, int *status) |
| 127 | { |
| 128 | uint64_t x = 0; |
| 129 | const char *k, *k2, *end = buf + len; |
| 130 | int sign, status_; |
| 131 | unsigned char c; |
| 132 | |
| 133 | if (!status) { |
| 134 | status = &status_; |
| 135 | } |
| 136 | if (buf == end) { |
| 137 | *status = PARSE_INTEGER_END; |
| 138 | return buf; |
| 139 | } |
| 140 | sign = *buf == '-'; |
| 141 | buf += sign; |
| 142 | if (end - buf < 2 || buf[0] != '0' || (buf[1] | 0x20) != 'x') { |
| 143 | *status = PARSE_INTEGER_UNMATCHED; |
| 144 | return buf - sign; |
| 145 | } |
| 146 | buf += 2; |
| 147 | k = buf; |
| 148 | k2 = end; |
| 149 | if (end - buf > 16) { |
| 150 | k2 = buf + 16; |
| 151 | } |
| 152 | while (buf != k2) { |
| 153 | c = (unsigned char)*buf; |
| 154 | if (c >= '0' && c <= '9') { |
| 155 | x = x * 16 + c - '0'; |
| 156 | } else { |
| 157 | /* Lower case. */ |
| 158 | c |= 0x20; |
| 159 | if (c >= 'a' && c <= 'f') { |
| 160 | x = x * 16 + c - 'a' + 10; |
| 161 | } else { |
| 162 | break; |
| 163 | } |
| 164 | } |
| 165 | ++buf; |
| 166 | } |
| 167 | if (buf == k) { |
| 168 | if (sign) { |
| 169 | *status = PARSE_INTEGER_INVALID; |
| 170 | return 0; |
| 171 | } else { |
| 172 | /* No number was matched, but it isn't an invalid number either. */ |
| 173 | *status = PARSE_INTEGER_UNMATCHED; |
| 174 | return buf; |
| 175 | } |
| 176 | } |
| 177 | if (buf == end) { |
| 178 | goto done; |
| 179 | } |
| 180 | c = (unsigned char)*buf; |
| 181 | if (buf == k2) { |
| 182 | if (c >= '0' && c <= '9') { |
| 183 | *status = sign ? PARSE_INTEGER_UNDERFLOW : PARSE_INTEGER_OVERFLOW; |