rapidyaml 0.15.2
parse and emit YAML, and do it fast
Loading...
Searching...
No Matches
Get number of digits

Functions

template<class T>
auto c4::digits_dec (T v) noexcept -> typename std::enable_if< sizeof(T)==1u, unsigned >::type
 decimal digits for 8 bit integers
template<class T>
auto c4::digits_dec (T v) noexcept -> typename std::enable_if< sizeof(T)==2u, unsigned >::type
 decimal digits for 16 bit integers
template<class T>
auto c4::digits_dec (T v) noexcept -> typename std::enable_if< sizeof(T)==4u, unsigned >::type
 decimal digits for 32 bit integers
template<class T>
auto c4::digits_dec (T v) noexcept -> typename std::enable_if< sizeof(T)==8u, unsigned >::type
 decimal digits for 64 bit integers
template<class T>
unsigned c4::digits_hex (T v) noexcept
 return the number of digits required to encode an hexadecimal number.
template<class T>
unsigned c4::digits_bin (T v) noexcept
 return the number of digits required to encode a binary number.
template<class T>
unsigned c4::digits_oct (T v_) noexcept
 return the number of digits required to encode an octal number.

Detailed Description

Note
At first sight this code may look heavily branchy and therefore inefficient. However, measurements revealed this to be the fastest among the alternatives.
See also
https://github.com/biojppm/c4core/pull/77

Function Documentation

◆ digits_dec() [1/4]

template<class T>
auto c4::digits_dec ( T v) ->typenamestd::enable_if< sizeof(T)==1u, unsigned >::type
inlinenoexcept

decimal digits for 8 bit integers

Definition at line 432 of file charconv.hpp.

434{
435 C4_STATIC_ASSERT(std::is_integral<T>::value);
436 C4_ASSERT(v >= 0);
437 return ((v >= 100) ? 3u : ((v >= 10) ? 2u : 1u));
438}

Referenced by itoa(), itoa(), itoa(), utoa(), utoa(), write_dec(), and write_dec_unchecked().

◆ digits_dec() [2/4]

template<class T>
auto c4::digits_dec ( T v) ->typenamestd::enable_if< sizeof(T)==2u, unsigned >::type
inlinenoexcept

decimal digits for 16 bit integers

Definition at line 443 of file charconv.hpp.

445{
446 C4_STATIC_ASSERT(std::is_integral<T>::value);
447 C4_ASSERT(v >= 0);
448 return ((v >= 10000) ? 5u : (v >= 1000) ? 4u : (v >= 100) ? 3u : (v >= 10) ? 2u : 1u);
449}

◆ digits_dec() [3/4]

template<class T>
auto c4::digits_dec ( T v) ->typenamestd::enable_if< sizeof(T)==4u, unsigned >::type
inlinenoexcept

decimal digits for 32 bit integers

Definition at line 454 of file charconv.hpp.

456{
457 C4_STATIC_ASSERT(std::is_integral<T>::value);
458 C4_ASSERT(v >= 0);
459 return ((v >= 1000000000) ? 10u : (v >= 100000000) ? 9u : (v >= 10000000) ? 8u :
460 (v >= 1000000) ? 7u : (v >= 100000) ? 6u : (v >= 10000) ? 5u :
461 (v >= 1000) ? 4u : (v >= 100) ? 3u : (v >= 10) ? 2u : 1u);
462}

◆ digits_dec() [4/4]

template<class T>
auto c4::digits_dec ( T v) ->typenamestd::enable_if< sizeof(T)==8u, unsigned >::type
inlinenoexcept

decimal digits for 64 bit integers

Definition at line 467 of file charconv.hpp.

469{
470 // thanks @fargies!!!
471 // https://github.com/biojppm/c4core/pull/77#issuecomment-1063753568
472 C4_STATIC_ASSERT(std::is_integral<T>::value);
473 C4_ASSERT(v >= 0);
474 if(v >= 1000000000) // 10
475 {
476 if(v >= 100000000000000) // 15 [15-20] range
477 {
478 if(v >= 100000000000000000) // 18 (15 + (20 - 15) / 2)
479 {
480 if((typename std::make_unsigned<T>::type)v >= 10000000000000000000u) // 20
481 return 20u;
482 else
483 return (v >= 1000000000000000000) ? 19u : 18u;
484 }
485 else if(v >= 10000000000000000) // 17
486 {
487 return 17u;
488 }
489 else
490 {
491 return(v >= 1000000000000000) ? 16u : 15u;
492 }
493 }
494 else if(v >= 1000000000000) // 13
495 {
496 return (v >= 10000000000000) ? 14u : 13u;
497 }
498 else if(v >= 100000000000) // 12
499 {
500 return 12;
501 }
502 else
503 {
504 return(v >= 10000000000) ? 11u : 10u;
505 }
506 }
507 else if(v >= 10000) // 5 [5-9] range
508 {
509 if(v >= 10000000) // 8
510 return (v >= 100000000) ? 9u : 8u;
511 else if(v >= 1000000) // 7
512 return 7;
513 else
514 return (v >= 100000) ? 6u : 5u;
515 }
516 else if(v >= 100)
517 {
518 return (v >= 1000) ? 4u : 3u;
519 }
520 else
521 {
522 return (v >= 10) ? 2u : 1u;
523 }
524}

◆ digits_hex()

template<class T>
unsigned c4::digits_hex ( T v)
inlinenoexcept

return the number of digits required to encode an hexadecimal number.

Definition at line 529 of file charconv.hpp.

530{
531 C4_STATIC_ASSERT(std::is_integral<T>::value);
532 C4_ASSERT(v >= 0);
533 return v ? 1u + (msb((typename std::make_unsigned<T>::type)v) >> 2u) : 1u;
534}

Referenced by itoa(), itoa(), utoa(), utoa(), write_hex(), and write_hex_unchecked().

◆ digits_bin()

template<class T>
unsigned c4::digits_bin ( T v)
inlinenoexcept

return the number of digits required to encode a binary number.

Definition at line 538 of file charconv.hpp.

539{
540 C4_STATIC_ASSERT(std::is_integral<T>::value);
541 C4_ASSERT(v >= 0);
542 return v ? 1u + msb((typename std::make_unsigned<T>::type)v) : 1u;
543}

Referenced by itoa(), itoa(), utoa(), utoa(), write_bin(), and write_bin_unchecked().

◆ digits_oct()

template<class T>
unsigned c4::digits_oct ( T v_)
inlinenoexcept

return the number of digits required to encode an octal number.

Definition at line 547 of file charconv.hpp.

548{
549 // TODO: is there a better way?
550 C4_STATIC_ASSERT(std::is_integral<T>::value);
551 C4_ASSERT(v_ >= 0);
552 using U = typename std::conditional<sizeof(T) <= sizeof(unsigned),
553 unsigned,
554 typename std::make_unsigned<T>::type>::type;
555 U v = (U) v_; // safe because we require v_ >= 0 // NOLINT
556 uint32_t n_ = 1;
557 enum : U {
558 b2_ = 64u,
559 b3_ = 64u * 8u,
560 b4_ = 64u * 8u * 8u,
561 };
562 while(true)
563 {
564 if(v < 8u)
565 return n_;
566 else if(v < b2_)
567 return n_ + 1;
568 else if(v < b3_)
569 return n_ + 2;
570 else if(v < b4_)
571 return n_ + 3;
572 v /= (U) b4_;
573 n_ += 4;
574 }
575}

Referenced by itoa(), itoa(), utoa(), utoa(), write_oct(), and write_oct_unchecked().