1 2 /* 3 * Copyright (C) Igor Sysoev 4 * Copyright (C) NGINX, Inc. 5 */ 6 7 #include <nxt_main.h> 8 9 10 /* 11 * nxt_int_parse() returns size_t value >= 0 on success, 12 * -1 on failure, and -2 on overflow. 13 */ 14 15 nxt_int_t 16 nxt_int_parse(const u_char *p, size_t len) 17 { 18 u_char c; 19 nxt_uint_t val; 20 21 if (nxt_fast_path(len != 0)) { 22 23 val = 0; 24 25 do { 26 c = *p++; 27 28 /* Values below '0' become >= 208. */ 29 c = c - '0'; 30 31 if (nxt_slow_path(c > 9)) { 32 return -1; 33 } 34 35 val = val * 10 + c; 36 37 if (nxt_slow_path((nxt_int_t) val < 0)) { 38 /* An overflow. */ 39 return -2; 40 } 41 42 len--; 43 44 } while (len != 0); 45 46 return val; 47 } 48 49 return -1; 50 } 51 52 53 /* 54 * nxt_size_t_parse() returns size_t value >= 0 on success, 55 * -1 on failure, and -2 on overflow. 56 */ 57 58 ssize_t 59 nxt_size_t_parse(const u_char *p, size_t len) 60 { 61 u_char c; 62 size_t val; 63 64 if (nxt_fast_path(len != 0)) { 65 66 val = 0; 67 68 do { 69 c = *p++; 70 71 /* Values below '0' become >= 208. */ 72 c = c - '0'; 73 74 if (nxt_slow_path(c > 9)) { 75 return -1; 76 } 77 78 val = val * 10 + c; 79 80 if (nxt_slow_path((ssize_t) val < 0)) { 81 /* An overflow. */ 82 return -2; 83 } 84 85 len--; 86 87 } while (len != 0); 88 89 return val; 90 } 91 92 return -1; 93 } 94 95 96 /* 97 * nxt_size_parse() parses size string with optional K or M units and 98 * returns size_t value >= 0 on success, -1 on failure, and -2 on overflow. 99 */ 100 101 ssize_t 102 nxt_size_parse(const u_char *p, size_t len) 103 { 104 u_char c, unit; 105 size_t val, max; 106 nxt_uint_t shift; 107 108 if (nxt_fast_path(len != 0)) { 109 110 len--; 111 112 /* Upper case. */ 113 unit = p[len] & ~0x20; 114 115 switch (unit) { 116 117 case 'G': 118 max = NXT_SIZE_T_MAX >> 30; 119 shift = 30; 120 break; 121 122 case 'M': 123 max = NXT_SIZE_T_MAX >> 20; 124 shift = 20; 125 break; 126 127 case 'K': 128 max = NXT_SIZE_T_MAX >> 10; 129 shift = 10; 130 break; 131 132 default: 133 max = NXT_SIZE_T_MAX; 134 shift = 0; 135 len++; 136 break; 137 } 138 139 if (nxt_fast_path(len != 0)) { 140 141 val = 0; 142 143 do { 144 c = *p++; 145 146 /* Values below '0' become >= 208. */ 147 c = c - '0'; 148 149 if (nxt_slow_path(c > 9)) { 150 return -1; 151 } 152 153 val = val * 10 + c; 154 155 if (nxt_slow_path(val > max)) { 156 /* An overflow. */ 157 return -2; 158 } 159 160 len--; 161 162 } while (len != 0); 163 164 return val << shift; 165 } 166 } 167 168 return -1; 169 } 170 171 172 /* 173 * nxt_off_t_parse() returns nxt_off_t value >= 0 on success, 174 * -1 on failure, and -2 on overflow. 175 */ 176 177 nxt_off_t 178 nxt_off_t_parse(const u_char *p, size_t len) 179 { 180 u_char c; 181 nxt_uoff_t val; 182 183 if (nxt_fast_path(len != 0)) { 184 185 val = 0; 186 187 do { 188 c = *p++; 189 190 /* Values below '0' become >= 208. */ 191 c = c - '0'; 192 193 if (nxt_slow_path(c > 9)) { 194 return -1; 195 } 196 197 val = val * 10 + c; 198 199 if (nxt_slow_path((nxt_off_t) val < 0)) { 200 /* An overflow. */ 201 return -2; 202 } 203 204 len--; 205 206 } while (len != 0); 207 208 return val; 209 } 210 211 return -1; 212 } 213 214 215 /* 216 * nxt_str_int_parse() returns nxt_int_t value >= 0 on success, 217 * -1 on failure, and -2 on overflow and also updates the 's' argument. 218 */ 219 220 nxt_int_t 221 nxt_str_int_parse(nxt_str_t *s) 222 { 223 u_char c, *p; 224 size_t len; 225 nxt_uint_t val; 226 227 len = s->len; 228 229 if (nxt_slow_path(len == 0)) { 230 return -1; 231 } 232 233 p = s->data; 234 val = 0; 235 236 do { 237 c = *p; 238 239 /* Values below '0' become >= 208. */ 240 c = c - '0'; 241 242 if (c > 9) { 243 break; 244 } 245 246 val = val * 10 + c; 247 248 if (nxt_slow_path((nxt_int_t) val < 0)) { 249 /* An overflow. */ 250 return -2; 251 } 252 253 p++; 254 len--; 255 256 } while (len != 0); 257 258 s->len = len; 259 s->data = p; 260 261 return val; 262 } 263 264 265 /* 266 * nxt_number_parse() returns a double value >= 0 and updates the start 267 * argument on success, or returns -1 on failure or -2 on overflow. 268 */ 269 270 double 271 nxt_number_parse(const u_char **start, const u_char *end) 272 { 273 u_char c; 274 nxt_uint_t integral, frac, power; 275 const u_char *p; 276 277 p = *start; 278 integral = 0; 279 280 while (p < end) { 281 c = *p; 282 283 if (c == '.') { 284 goto dot; 285 } 286 287 /* Values below '0' become >= 208. */ 288 c = c - '0'; 289 290 if (c > 9) { 291 break; 292 } 293 294 integral = integral * 10 + c; 295 296 if (nxt_slow_path((nxt_int_t) integral < 0)) { 297 /* An overflow. */ 298 return -2; 299 } 300 301 p++; 302 } 303 304 if (nxt_fast_path(p != *start)) { 305 *start = p; 306 return integral; 307 } 308 309 /* No value. */ 310 return -1; 311 312 dot: 313 314 if (nxt_slow_path(p == *start)) { 315 /* No leading digit before dot. */ 316 return -1; 317 } 318 319 frac = 0; 320 power = 1; 321 322 for (p++; p < end; p++) { 323 c = *p; 324 325 /* Values below '0' become >= 208. */ 326 c = c - '0'; 327 328 if (c > 9) { 329 break; 330 } 331 332 frac = frac * 10 + c; 333 power *= 10; 334 335 if (nxt_slow_path((nxt_int_t) frac < 0 || (nxt_int_t) power < 0)) { 336 /* An overflow. */ 337 return -2; 338 } 339 } 340 341 *start = p; 342 343 return integral + (double) frac / power; 344 } 345