| 394 | } |
| 395 | |
| 396 | int64_t parseTimezoneOffset(const char* cur, const char* end, Date& date) { |
| 397 | // For timezone offset ids, there are three formats allowed by Joda: |
| 398 | // |
| 399 | // 1. '+' or '-' followed by two digits: "+00" |
| 400 | // 2. '+' or '-' followed by two digits, ":", then two more digits: |
| 401 | // "+00:00" |
| 402 | // 3. '+' or '-' followed by four digits: |
| 403 | // "+0000" |
| 404 | if (cur < end) { |
| 405 | if (*cur == '-' || *cur == '+') { |
| 406 | // Long format: "+00:00" |
| 407 | if ((end - cur) >= 6 && *(cur + 3) == ':') { |
| 408 | // Fast path for the common case ("+00:00" or "-00:00"), to prevent |
| 409 | // calling getTimeZoneID(), which does a map lookup. |
| 410 | if (std::strncmp(cur + 1, "00:00", 5) == 0) { |
| 411 | date.timezoneId = 0; |
| 412 | } else { |
| 413 | date.timezoneId = tz::getTimeZoneID(std::string_view(cur, 6), false); |
| 414 | if (date.timezoneId == -1) { |
| 415 | return -1; |
| 416 | } |
| 417 | } |
| 418 | return 6; |
| 419 | } |
| 420 | // Long format without colon: "+0000" |
| 421 | else if ((end - cur) >= 5 && *(cur + 3) != ':') { |
| 422 | // Same fast path described above. |
| 423 | if (std::strncmp(cur + 1, "0000", 4) == 0) { |
| 424 | date.timezoneId = 0; |
| 425 | } else { |
| 426 | // We need to concatenate the 3 first chars with ":" followed by the |
| 427 | // last 2 chars before calling getTimeZoneID, so we use a static |
| 428 | // thread_local buffer to prevent extra allocations. |
| 429 | std::memcpy(&timezoneBuffer[0], cur, 3); |
| 430 | std::memcpy(&timezoneBuffer[4], cur + 3, 2); |
| 431 | date.timezoneId = tz::getTimeZoneID(timezoneBuffer, false); |
| 432 | if (date.timezoneId == -1) { |
| 433 | return -1; |
| 434 | } |
| 435 | } |
| 436 | return 5; |
| 437 | } |
| 438 | // Short format: "+00" |
| 439 | else if ((end - cur) >= 3) { |
| 440 | // Same fast path described above. |
| 441 | if (std::strncmp(cur + 1, "00", 2) == 0) { |
| 442 | date.timezoneId = 0; |
| 443 | } else { |
| 444 | // We need to concatenate the 3 first chars with a trailing ":00" |
| 445 | // before calling getTimeZoneID, so we use a static thread_local |
| 446 | // buffer to prevent extra allocations. |
| 447 | std::memcpy(&timezoneBuffer[0], cur, 3); |
| 448 | std::memcpy(&timezoneBuffer[4], defaultTrailingOffset, 2); |
| 449 | date.timezoneId = tz::getTimeZoneID(timezoneBuffer, false); |
| 450 | if (date.timezoneId == -1) { |
| 451 | return -1; |
| 452 | } |
| 453 | } |
no test coverage detected