@@ -509,6 +509,92 @@ parse_int_string(UC const *p, UC const *pend, T &value,
509509
510510 UC const *const start_digits = p;
511511
512+ if constexpr (std::is_same_v<T, std::uint8_t >) {
513+ const size_t len = (size_t )(pend - p);
514+ if (len == 0 ) {
515+ if (has_leading_zeros) {
516+ value = 0 ;
517+ answer.ec = std::errc ();
518+ answer.ptr = p;
519+ } else {
520+ answer.ec = std::errc::invalid_argument;
521+ answer.ptr = first;
522+ }
523+ return answer;
524+ }
525+
526+ union {
527+ uint8_t as_str[4 ];
528+ uint32_t as_int;
529+ } digits;
530+
531+ if (cpp20_and_in_constexpr ()) {
532+ digits.as_int = 0 ;
533+ for (size_t j = 0 ; j < 4 && j < len; ++j) {
534+ digits.as_str [j] = static_cast <uint8_t >(p[j]);
535+ }
536+ } else if (len >= 4 ) {
537+ memcpy (&digits.as_int , p, 4 );
538+ } else {
539+ uint32_t b0 = static_cast <uint8_t >(p[0 ]);
540+ uint32_t b1 = (len > 1 ) ? static_cast <uint8_t >(p[1 ]) : 0xFFu ;
541+ uint32_t b2 = (len > 2 ) ? static_cast <uint8_t >(p[2 ]) : 0xFFu ;
542+ uint32_t b3 = 0xFFu ;
543+ #if FASTFLOAT_IS_BIG_ENDIAN
544+ digits.as_int = (b0 << 24 ) | (b1 << 16 ) | (b2 << 8 ) | b3;
545+ #else
546+ digits.as_int = b0 | (b1 << 8 ) | (b2 << 16 ) | (b3 << 24 );
547+ #endif
548+ }
549+
550+ uint32_t magic =
551+ ((digits.as_int + 0x46464646u ) | (digits.as_int - 0x30303030u )) &
552+ 0x80808080u ;
553+ uint32_t tz = (uint32_t )std::__countr_zero (magic); // 7, 15, 23, 31, or 32
554+ uint32_t nd = (tz == 32 ) ? 4 : (tz >> 3 );
555+ nd = (uint32_t )std::min ((size_t )nd, len);
556+ if (nd == 0 ) {
557+ if (has_leading_zeros) {
558+ value = 0 ;
559+ answer.ec = std::errc ();
560+ answer.ptr = p;
561+ return answer;
562+ }
563+ answer.ec = std::errc::invalid_argument;
564+ answer.ptr = first;
565+ return answer;
566+ }
567+ if (nd > 3 ) {
568+ const UC *q = p + nd;
569+ size_t rem = len - nd;
570+ while (rem) {
571+ if (*q < UC (' 0' ) || *q > UC (' 9' ))
572+ break ;
573+ ++q;
574+ --rem;
575+ }
576+ answer.ec = std::errc::result_out_of_range;
577+ answer.ptr = q;
578+ return answer;
579+ }
580+
581+ digits.as_int ^= 0x30303030u ;
582+ digits.as_int <<= ((4 - nd) * 8 );
583+
584+ uint32_t check = ((digits.as_int >> 24 ) & 0xff ) |
585+ ((digits.as_int >> 8 ) & 0xff00 ) |
586+ ((digits.as_int << 8 ) & 0xff0000 );
587+ if (check > 0x00020505 ) {
588+ answer.ec = std::errc::result_out_of_range;
589+ answer.ptr = p + nd;
590+ return answer;
591+ }
592+ value = (uint8_t )((0x640a01 * digits.as_int ) >> 24 );
593+ answer.ec = std::errc ();
594+ answer.ptr = p + nd;
595+ return answer;
596+ }
597+
512598 uint64_t i = 0 ;
513599 if (base == 10 ) {
514600 loop_parse_if_eight_digits (p, pend, i); // use SIMD if possible
0 commit comments