@@ -425,17 +425,17 @@ namespace klib::string::detail {
425425 typename T = int ,
426426 typename = std::enable_if_t <std::is_integral_v<T>>
427427 >
428- constexpr void itoa_impl (T value, char *const str) {
428+ constexpr uint32_t itoa_impl (T value, char *const str) {
429429 // handle the boolalpha case first
430430 if constexpr (BoolAlpha) {
431431 if (!value) {
432432 strcpy (str, " false" );
433+ return strlen (" false" );
433434 }
434435 else {
435436 strcpy (str, " true" );
437+ return strlen (" true" );
436438 }
437-
438- return ;
439439 }
440440
441441 // Handle 0 explicitly, otherwise 0 is not printed
@@ -444,12 +444,10 @@ namespace klib::string::detail {
444444 const auto added = add_prefix<B>(str);
445445
446446 // add 0 after the prefix
447- str[added] = ' 0' ;
448-
449- // add the null terminator
450- str[added + 1 ] = ' \0 ' ;
447+ strcat (str, " 0" );
451448
452- return ;
449+ // return the string length
450+ return strlen (" 0" ) + added;
453451 }
454452
455453 uint32_t index = 0 ;
@@ -463,7 +461,7 @@ namespace klib::string::detail {
463461 // add a minus sign
464462 str[index] = ' -' ;
465463
466- // go to the next character
464+ // go to the next position
467465 index++;
468466 }
469467 }
@@ -494,59 +492,92 @@ namespace klib::string::detail {
494492 value /= b;
495493 }
496494
495+ const uint32_t pos = index + count;
496+
497497 // add a null terminator
498498 str[index + count] = ' \0 ' ;
499+
500+ return pos;
499501 }
500502
501503 template <uint32_t Digits, typename T = int >
502- constexpr void stoa_impl (T value, char *const str) {
504+ constexpr uint32_t ftoa_impl (T value, char *const str) {
505+ // handle the special cases and return
503506 if (klib::isnan (value)) {
504507 strcpy (str, " NaN" );
508+ return strlen (" NaN" );
505509 }
506510 else if (klib::isinf (value)) {
507511 strcpy (str, " Inf" );
512+ return strlen (" Inf" );
508513 }
509514 else if (value == static_cast <T>(0 .f )) {
510515 strcpy (str, " 0" );
516+ return strlen (" 0" );
511517 }
512- else {
513- int i = 0 , k = 0 ;
514518
515- // handle negative values
516- if (value < static_cast <T>(0 .f )) {
517- str[k++] = ' -' ;
518- value *= -1 ;
519- }
519+ uint32_t index = 0 ;
520520
521- do {
522- value /= 10 ;
523- i++ ;
524- }
525- while ( static_cast < int >(value) > 0 );
521+ // handle negative values
522+ if ( value < static_cast <T>( 0 . f )) {
523+ str[index++] = ' - ' ;
524+ value *= - 1 ;
525+ }
526526
527- // add the decimal seperator
528- *(str + k + i) = ' . ' ;
527+ uint32_t count = 0 ;
528+ T tmp = value ;
529529
530- value *= 10 ;
531- auto n = static_cast <int >(value);
532- value -= n;
530+ // count the characters needed without the
531+ // fractional part
532+ do {
533+ tmp /= 10 ;
534+ count++;
535+ }
536+ while (static_cast <int >(tmp) > 0 );
533537
534- while ((k - i) <= static_cast <int >(Digits)) {
535- if (k == i) {
536- k++;
537- }
538+ // save the fractional part before modifying
539+ // the value
540+ T frac = value - klib::floor (value);
538541
539- *(str + k) = ' 0' + n;
542+ // write the integer digits using the original
543+ // value
544+ for (int p = 0 ; p < count; p++) {
545+ // get the current digit
546+ const auto digit = static_cast <uint32_t >(value) % 10 ;
540547
541- value *= 10 ;
542- n = static_cast <int >(value);
543- value -= n;
544- k++;
545- }
548+ // store the digit
549+ str[index + (count - p - 1 )] = ' 0' + digit;
546550
547- // Null-terminate the string
548- *(str + k) = ' \0 ' ;
551+ // remove the digit from the value
552+ value /= 10 ;
549553 }
554+
555+ // increment the index with the digit count
556+ index += count;
557+
558+ // check if we need to add a seperator and
559+ // the fractional values
560+ if constexpr (Digits) {
561+ // add the decimal separator
562+ str[index++] = ' .' ;
563+
564+ // add all the digits after the seperator
565+ for (uint32_t d = 0 ; d < Digits; d++) {
566+ // get the first digit after the seperator, store
567+ // it and remove it from the value
568+ frac *= 10 ;
569+ const auto n = static_cast <int >(frac);
570+ frac -= n;
571+
572+ // store the digit
573+ str[index++] = ' 0' + n;
574+ }
575+ }
576+
577+ // Null-terminate the string
578+ str[index] = ' \0 ' ;
579+
580+ return index;
550581 }
551582}
552583
@@ -573,12 +604,13 @@ namespace klib::string {
573604 * @tparam typename
574605 * @param value
575606 * @param str
607+ * @return characters in buffer
576608 */
577609 template <
578610 base B = _default_base, bool Boolalpha = _default_boolalpha,
579611 typename T = int , typename = std::enable_if_t <std::is_integral_v<T>>
580612 >
581- constexpr void itoa (const T value, char *const str) {
613+ constexpr uint32_t itoa (const T value, char *const str) {
582614 // return the implementation
583615 return detail::itoa_impl<B, Boolalpha, T>(value, str);
584616 }
@@ -592,14 +624,15 @@ namespace klib::string {
592624 * typename
593625 * @param value
594626 * @param str
627+ * @return characters in buffer
595628 */
596629 template <
597630 uint32_t Digits = 5 , typename T = float ,
598631 typename = std::enable_if_t <std::is_floating_point_v<T>>
599632 >
600- constexpr void stoa (const T value, char *const str) {
633+ constexpr uint32_t ftoa (const T value, char *const str) {
601634 // return the implementation
602- return detail::stoa_impl <Digits, T>(value, str);
635+ return detail::ftoa_impl <Digits, T>(value, str);
603636 }
604637}
605638
0 commit comments