/*
 * Copyright (C) 2020-2021 Aloysius Indrayanto
 *
 * This file is part of the eCxx library, see LICENSE file for the license details.
 */


#ifndef ECXX_CTL_CONVERT_H
#define ECXX_CTL_CONVERT_H


#include <eCxx/CTL/FixedPoint.h>
#include <eCxx/CTL/String.h>
#include <eCxx/CTL/UninstantiableUncopyable.h>


namespace eCxx {


//
// Various conversion utilities
//
class Convert : public Uncopyable {
    public:
        typedef String<0>::Pointer  StringPointer;
        typedef String<0>::SizeType StringSizeType;

        enum class NumSign : uint8_t {
            None_Minus,   // Positive number : none  ; Negative number : -
            Plus_Minus,   // Positive number : +     ; Negative number : -
            Space_Minus   // Positive number : space ; Negative number : -
        };

        enum class NumPad : uint8_t {
            Space, // Padded with leading space(s) before the number sign
            Zero   // Padded with leading zero(es) after the number sign
        };

        enum class NumFormat : uint8_t {
            Lowercase,           // Lowercase without 0b or 0 or 0x prefix
            LowercaseWithPrefix, // Lowercase with    0b or 0 or 0x prefix
            Uppercase,           // Uppercase without 0B or 0 or 0X prefix (only meaningful for binary and hexadecimal)
            UppercaseWithPrefix  // Uppercase with    0B or 0 or 0X prefix (only meaningful for binary and hexadecimal)
        };

    private:
        inline  Convert() {};
        inline ~Convert() {}

    public:
        // Reverse characters
        template <size_t MaxCapacity> static inline void reverseCharacters(String<MaxCapacity>& str) noexcept;

        // Convert case
        template <size_t MaxCapacity> static inline void toLowercase(String<MaxCapacity>& str) noexcept;
        template <size_t MaxCapacity> static inline void toUppercase(String<MaxCapacity>& str) noexcept;

        // Convert fixed point to decimal string
        template <size_t MaxCapacity> static inline void toDecString(
            String<MaxCapacity>& str,
            const FixedPoint&    value,
            NumSign              numSign            = NumSign::None_Minus,
            uint8_t              minFieldWidth      = 0,
            NumPad               numPad             = NumPad::Space,
            bool                 thousandsSeparator = false
        ) noexcept;

        // Convert 8-bit signed and unsigned integer to binary string
        template <size_t MaxCapacity> static inline void toBinString(
            String<MaxCapacity>& str,
            int8_t               value,
            NumSign              numSign       = NumSign::None_Minus,
            uint8_t              minFieldWidth = 0,
            NumPad               numPad        = NumPad::Space,
            NumFormat            format        = NumFormat::LowercaseWithPrefix
        ) noexcept;

        template <size_t MaxCapacity> static inline void toBinString(
            String<MaxCapacity>& str,
            uint8_t              value,
            NumSign              numSign       = NumSign::None_Minus,
            uint8_t              minFieldWidth = 0,
            NumPad               numPad        = NumPad::Space,
            NumFormat            format        = NumFormat::LowercaseWithPrefix
        ) noexcept;

        // Convert 16-bit signed and unsigned integer to binary string
        template <size_t MaxCapacity> static inline void toBinString(
            String<MaxCapacity>& str,
            int16_t              value,
            NumSign              numSign       = NumSign::None_Minus,
            uint8_t              minFieldWidth = 0,
            NumPad               numPad        = NumPad::Space,
            NumFormat            format        = NumFormat::LowercaseWithPrefix
        ) noexcept;

        template <size_t MaxCapacity> static inline void toBinString(
            String<MaxCapacity>& str,
            uint16_t             value,
            NumSign              numSign       = NumSign::None_Minus,
            uint8_t              minFieldWidth = 0,
            NumPad               numPad        = NumPad::Space,
            NumFormat            format        = NumFormat::LowercaseWithPrefix
        ) noexcept;

        // Convert 32-bit signed and unsigned integer to binary string
        template <size_t MaxCapacity> static inline void toBinString(
            String<MaxCapacity>& str,
            int32_t              value,
            NumSign              numSign       = NumSign::None_Minus,
            uint8_t              minFieldWidth = 0,
            NumPad               numPad        = NumPad::Space,
            NumFormat            format        = NumFormat::LowercaseWithPrefix
        ) noexcept;

        template <size_t MaxCapacity> static inline void toBinString(
            String<MaxCapacity>& str,
            uint32_t             value,
            NumSign              numSign       = NumSign::None_Minus,
            uint8_t              minFieldWidth = 0,
            NumPad               numPad        = NumPad::Space,
            NumFormat            format        = NumFormat::LowercaseWithPrefix
        ) noexcept;

        // Convert 64-bit signed and unsigned integer to binary string
        template <size_t MaxCapacity> static inline void toBinString(
            String<MaxCapacity>& str,
            int64_t              value,
            NumSign              numSign       = NumSign::None_Minus,
            uint8_t              minFieldWidth = 0,
            NumPad               numPad        = NumPad::Space,
            NumFormat            format        = NumFormat::LowercaseWithPrefix
        ) noexcept;

        template <size_t MaxCapacity> static inline void toBinString(
            String<MaxCapacity>& str,
            uint64_t             value,
            NumSign              numSign       = NumSign::None_Minus,
            uint8_t              minFieldWidth = 0,
            NumPad               numPad        = NumPad::Space,
            NumFormat            format        = NumFormat::LowercaseWithPrefix
        ) noexcept;

        // Convert 8-bit signed and unsigned integer to octal string
        template <size_t MaxCapacity> static inline void toOctString(
            String<MaxCapacity>& str,
            int8_t               value,
            NumSign              numSign       = NumSign::None_Minus,
            uint8_t              minFieldWidth = 0,
            NumPad               numPad        = NumPad::Space,
            NumFormat            format        = NumFormat::LowercaseWithPrefix
        ) noexcept;

        template <size_t MaxCapacity> static inline void toOctString(
            String<MaxCapacity>& str,
            uint8_t              value,
            NumSign              numSign       = NumSign::None_Minus,
            uint8_t              minFieldWidth = 0,
            NumPad               numPad        = NumPad::Space,
            NumFormat            format        = NumFormat::LowercaseWithPrefix
        ) noexcept;

        // Convert 16-bit signed and unsigned integer to octal string
        template <size_t MaxCapacity> static inline void toOctString(
            String<MaxCapacity>& str,
            int16_t              value,
            NumSign              numSign       = NumSign::None_Minus,
            uint8_t              minFieldWidth = 0,
            NumPad               numPad        = NumPad::Space,
            NumFormat            format        = NumFormat::LowercaseWithPrefix
        ) noexcept;

        template <size_t MaxCapacity> static inline void toOctString(
            String<MaxCapacity>& str,
            uint16_t             value,
            NumSign              numSign       = NumSign::None_Minus,
            uint8_t              minFieldWidth = 0,
            NumPad               numPad        = NumPad::Space,
            NumFormat            format        = NumFormat::LowercaseWithPrefix
        ) noexcept;

        // Convert 32-bit signed and unsigned integer to octal string
        template <size_t MaxCapacity> static inline void toOctString(
            String<MaxCapacity>& str,
            int32_t              value,
            NumSign              numSign       = NumSign::None_Minus,
            uint8_t              minFieldWidth = 0,
            NumPad               numPad        = NumPad::Space,
            NumFormat            format        = NumFormat::LowercaseWithPrefix
        ) noexcept;

        template <size_t MaxCapacity> static inline void toOctString(
            String<MaxCapacity>& str,
            uint32_t             value,
            NumSign              numSign       = NumSign::None_Minus,
            uint8_t              minFieldWidth = 0,
            NumPad               numPad        = NumPad::Space,
            NumFormat            format        = NumFormat::LowercaseWithPrefix
        ) noexcept;

        // Convert 64-bit signed and unsigned integer to octal string
        template <size_t MaxCapacity> static inline void toOctString(
            String<MaxCapacity>& str,
            int64_t              value,
            NumSign              numSign       = NumSign::None_Minus,
            uint8_t              minFieldWidth = 0,
            NumPad               numPad        = NumPad::Space,
            NumFormat            format        = NumFormat::LowercaseWithPrefix
        ) noexcept;

        template <size_t MaxCapacity> static inline void toOctString(
            String<MaxCapacity>& str,
            uint64_t             value,
            NumSign              numSign       = NumSign::None_Minus,
            uint8_t              minFieldWidth = 0,
            NumPad               numPad        = NumPad::Space,
            NumFormat            format        = NumFormat::LowercaseWithPrefix
        ) noexcept;

        // Convert 8-bit signed and unsigned integer to decimal string
        template <size_t MaxCapacity> static inline void toDecString(
            String<MaxCapacity>& str,
            int8_t               value,
            NumSign              numSign            = NumSign::None_Minus,
            uint8_t              minFieldWidth      = 0,
            NumPad               numPad             = NumPad::Space,
            bool                 thousandsSeparator = false
        ) noexcept;

        template <size_t MaxCapacity> static inline void toDecString(
            String<MaxCapacity>& str,
            uint8_t              value,
            NumSign              numSign            = NumSign::None_Minus,
            uint8_t              minFieldWidth      = 0,
            NumPad               numPad             = NumPad::Space,
            bool                 thousandsSeparator = false
        ) noexcept;

        // Convert 16-bit signed and unsigned integer to decimal string
        template <size_t MaxCapacity> static inline void toDecString(
            String<MaxCapacity>& str,
            int16_t              value,
            NumSign              numSign            = NumSign::None_Minus,
            uint8_t              minFieldWidth      = 0,
            NumPad               numPad             = NumPad::Space,
            bool                 thousandsSeparator = false
        ) noexcept;

        template <size_t MaxCapacity> static inline void toDecString(
            String<MaxCapacity>& str,
            uint16_t             value,
            NumSign              numSign            = NumSign::None_Minus,
            uint8_t              minFieldWidth      = 0,
            NumPad               numPad             = NumPad::Space,
            bool                 thousandsSeparator = false
        ) noexcept;

        // Convert 32-bit signed and unsigned integer to decimal string
        template <size_t MaxCapacity> static inline void toDecString(
            String<MaxCapacity>& str,
            int32_t              value,
            NumSign              numSign            = NumSign::None_Minus,
            uint8_t              minFieldWidth      = 0,
            NumPad               numPad             = NumPad::Space,
            bool                 thousandsSeparator = false
        ) noexcept;

        template <size_t MaxCapacity> static inline void toDecString(
            String<MaxCapacity>& str,
            uint32_t             value,
            NumSign              numSign            = NumSign::None_Minus,
            uint8_t              minFieldWidth      = 0,
            NumPad               numPad             = NumPad::Space,
            bool                 thousandsSeparator = false
        ) noexcept;

        // Convert 64-bit signed and unsigned integer to decimal string
        template <size_t MaxCapacity> static inline void toDecString(
            String<MaxCapacity>& str,
            int64_t              value,
            NumSign              numSign            = NumSign::None_Minus,
            uint8_t              minFieldWidth      = 0,
            NumPad               numPad             = NumPad::Space,
            bool                 thousandsSeparator = false
        ) noexcept;

        template <size_t MaxCapacity> static inline void toDecString(
            String<MaxCapacity>& str,
            uint64_t             value,
            NumSign              numSign            = NumSign::None_Minus,
            uint8_t              minFieldWidth      = 0,
            NumPad               numPad             = NumPad::Space,
            bool                 thousandsSeparator = false
        ) noexcept;

        // Convert 8-bit signed and unsigned integer to hexadecimal string
        template <size_t MaxCapacity> static inline void toHexString(
            String<MaxCapacity>& str,
            int8_t               value,
            NumSign              numSign       = NumSign::None_Minus,
            uint8_t              minFieldWidth = 0,
            NumPad               numPad        = NumPad::Space,
            NumFormat            format        = NumFormat::LowercaseWithPrefix
        ) noexcept;

        template <size_t MaxCapacity> static inline void toHexString(
            String<MaxCapacity>& str,
            uint8_t              value,
            NumSign              numSign       = NumSign::None_Minus,
            uint8_t              minFieldWidth = 0,
            NumPad               numPad        = NumPad::Space,
            NumFormat            format        = NumFormat::LowercaseWithPrefix
        ) noexcept;

        // Convert 16-bit signed and unsigned integer to hexadecimal string
        template <size_t MaxCapacity> static inline void toHexString(
            String<MaxCapacity>& str,
            int16_t              value,
            NumSign              numSign       = NumSign::None_Minus,
            uint8_t              minFieldWidth = 0,
            NumPad               numPad        = NumPad::Space,
            NumFormat            format        = NumFormat::LowercaseWithPrefix
        ) noexcept;

        template <size_t MaxCapacity> static inline void toHexString(
            String<MaxCapacity>& str,
            uint16_t             value,
            NumSign              numSign       = NumSign::None_Minus,
            uint8_t              minFieldWidth = 0,
            NumPad               numPad        = NumPad::Space,
            NumFormat            format        = NumFormat::LowercaseWithPrefix
        ) noexcept;

        // Convert 32-bit signed and unsigned integer to hexadecimal string
        template <size_t MaxCapacity> static inline void toHexString(
            String<MaxCapacity>& str,
            int32_t              value,
            NumSign              numSign       = NumSign::None_Minus,
            uint8_t              minFieldWidth = 0,
            NumPad               numPad        = NumPad::Space,
            NumFormat            format        = NumFormat::LowercaseWithPrefix
        ) noexcept;

        template <size_t MaxCapacity> static inline void toHexString(
            String<MaxCapacity>& str,
            uint32_t             value,
            NumSign              numSign       = NumSign::None_Minus,
            uint8_t              minFieldWidth = 0,
            NumPad               numPad        = NumPad::Space,
            NumFormat            format        = NumFormat::LowercaseWithPrefix
        ) noexcept;

        // Convert 64-bit signed and unsigned integer to hexadecimal string
        template <size_t MaxCapacity> static inline void toHexString(
            String<MaxCapacity>& str,
            int64_t              value,
            NumSign              numSign       = NumSign::None_Minus,
            uint8_t              minFieldWidth = 0,
            NumPad               numPad        = NumPad::Space,
            NumFormat            format        = NumFormat::LowercaseWithPrefix
        ) noexcept;

        template <size_t MaxCapacity> static inline void toHexString(
            String<MaxCapacity>& str,
            uint64_t             value,
            NumSign              numSign       = NumSign::None_Minus,
            uint8_t              minFieldWidth = 0,
            NumPad               numPad        = NumPad::Space,
            NumFormat            format        = NumFormat::LowercaseWithPrefix
        ) noexcept;

    private:
        static void _reverseCharacters(StringPointer ptr, StringSizeType length) noexcept;

        static void _toLowercase(StringPointer ptr, StringSizeType length) noexcept;
        static void _toUppercase(StringPointer ptr, StringSizeType length) noexcept;

        static void _toDecString(
            StringPointer     stringPtrBeg,
            StringSizeType&   resultLength,       StringSizeType stringCapacity,
            const FixedPoint& value,              NumSign        numSign,
            uint8_t           minFieldWidth,      NumPad         numPad,
            bool              thousandsSeparator
        ) noexcept;

        static void _toBinString(
            StringPointer   stringPtrBeg,
            StringSizeType& resultLength,  StringSizeType stringCapacity,
            uint16_t        value,         NumSign        numSign,
            uint8_t         minFieldWidth, NumPad         numPad,
            NumFormat       format,        bool           negativeNumber
        ) noexcept;

        static void _toBinString(
            StringPointer   stringPtrBeg,
            StringSizeType& resultLength,  StringSizeType stringCapacity,
            uint32_t        value,         NumSign        numSign,
            uint8_t         minFieldWidth, NumPad         numPad,
            NumFormat       format,        bool           negativeNumber
        ) noexcept;

        static void _toBinString(
            StringPointer   stringPtrBeg,
            StringSizeType& resultLength,  StringSizeType stringCapacity,
            uint64_t        value,         NumSign        numSign,
            uint8_t         minFieldWidth, NumPad         numPad,
            NumFormat       format,        bool           negativeNumber
        ) noexcept;

        static void _toOctString(
            StringPointer   stringPtrBeg,
            StringSizeType& resultLength,  StringSizeType stringCapacity,
            uint16_t        value,         NumSign        numSign,
            uint8_t         minFieldWidth, NumPad         numPad,
            NumFormat       format,        bool           negativeNumber
        ) noexcept;

        static void _toOctString(
            StringPointer   stringPtrBeg,
            StringSizeType& resultLength,  StringSizeType stringCapacity,
            uint32_t        value,         NumSign        numSign,
            uint8_t         minFieldWidth, NumPad         numPad,
            NumFormat       format,        bool           negativeNumber
        ) noexcept;

        static void _toOctString(
            StringPointer   stringPtrBeg,
            StringSizeType& resultLength,  StringSizeType stringCapacity,
            uint64_t        value,         NumSign        numSign,
            uint8_t         minFieldWidth, NumPad         numPad,
            NumFormat       format,        bool           negativeNumber
        ) noexcept;

        static void _toDecString(
            StringPointer   stringPtrBeg,
            StringSizeType& resultLength,       StringSizeType stringCapacity,
            uint16_t        value,              NumSign        numSign,
            uint8_t         minFieldWidth,      NumPad         numPad,
            bool            thousandsSeparator, bool           negativeNumber
        ) noexcept;

        static void _toDecString(
            StringPointer   stringPtrBeg,
            StringSizeType& resultLength,       StringSizeType stringCapacity,
            uint32_t        value,              NumSign        numSign,
            uint8_t         minFieldWidth,      NumPad         numPad,
            bool            thousandsSeparator, bool           negativeNumber
        ) noexcept;

        static void _toDecString(
            StringPointer   stringPtrBeg,
            StringSizeType& resultLength,       StringSizeType stringCapacity,
            uint64_t        value,              NumSign        numSign,
            uint8_t         minFieldWidth,      NumPad         numPad,
            bool            thousandsSeparator, bool           negativeNumber
        ) noexcept;

        static void _toHexString(
            StringPointer   stringPtrBeg,
            StringSizeType& resultLength,  StringSizeType stringCapacity,
            uint16_t        value,         NumSign        numSign,
            uint8_t         minFieldWidth, NumPad         numPad,
            NumFormat       format,        bool           negativeNumber
        ) noexcept;

        static void _toHexString(
            StringPointer   stringPtrBeg,
            StringSizeType& resultLength,  StringSizeType stringCapacity,
            uint32_t        value,         NumSign        numSign,
            uint8_t         minFieldWidth, NumPad         numPad,
            NumFormat       format,        bool           negativeNumber
        ) noexcept;

        static void _toHexString(
            StringPointer   stringPtrBeg,
            StringSizeType& resultLength,  StringSizeType stringCapacity,
            uint64_t        value,         NumSign        numSign,
            uint8_t         minFieldWidth, NumPad         numPad,
            NumFormat       format,        bool           negativeNumber
        ) noexcept;
};


template <size_t MaxCapacity>
inline void Convert::reverseCharacters(String<MaxCapacity>& str) noexcept
{ _reverseCharacters(str._writeableData(), str.length()); }


template <size_t MaxCapacity>
inline void Convert::toLowercase(String<MaxCapacity>& str) noexcept
{ _toLowercase(str._writeableData(), str.length()); }


template <size_t MaxCapacity>
inline void Convert::toUppercase(String<MaxCapacity>& str) noexcept
{ _toUppercase(str._writeableData(), str.length()); }


template <size_t MaxCapacity>
 inline void Convert::toDecString(
    String<MaxCapacity>& str,     const FixedPoint& value,
    NumSign              numSign, uint8_t           minFieldWidth,
    NumPad               numPad,  bool              thousandsSeparator
) noexcept
{
    _toDecString(
        str._writeableData(),
        str._writeableLength(),
        str.capacity(),
        value,
        numSign,
        minFieldWidth,
        numPad,
        thousandsSeparator
    );
}


template <size_t MaxCapacity>
inline void Convert::toBinString(
    String<MaxCapacity>& str,     int8_t    value,
    NumSign              numSign, uint8_t   minFieldWidth,
    NumPad               numPad,  NumFormat format
) noexcept
{
    const bool isNegativeNumber = (value < 0);

    _toBinString(
        str._writeableData(),
        str._writeableLength(),
        str.capacity(),
        static_cast<uint16_t>(isNegativeNumber ? -value : value),
        numSign,
        minFieldWidth,
        numPad,
        format,
        isNegativeNumber
    );
}


template <size_t MaxCapacity>
inline void Convert::toBinString(
    String<MaxCapacity>& str,     uint8_t   value,
    NumSign              numSign, uint8_t   minFieldWidth,
    NumPad               numPad,  NumFormat format
) noexcept
{
    _toBinString(
        str._writeableData(),
        str._writeableLength(),
        str.capacity(),
        static_cast<uint16_t>(value),
        numSign,
        minFieldWidth,
        numPad,
        format,
        false
    );
}


template <size_t MaxCapacity>
inline void Convert::toBinString(
    String<MaxCapacity>& str,     int16_t   value,
    NumSign              numSign, uint8_t   minFieldWidth,
    NumPad               numPad,  NumFormat format
) noexcept
{
    const bool isNegativeNumber = (value < 0);

    _toBinString(
        str._writeableData(),
        str._writeableLength(),
        str.capacity(),
        static_cast<uint16_t>(isNegativeNumber ? -value : value),
        numSign,
        minFieldWidth,
        numPad,
        format,
        isNegativeNumber
    );
}


template <size_t MaxCapacity>
inline void Convert::toBinString(
    String<MaxCapacity>& str,     uint16_t  value,
    NumSign              numSign, uint8_t   minFieldWidth,
    NumPad               numPad,  NumFormat format
) noexcept
{
    _toBinString(
        str._writeableData(),
        str._writeableLength(),
        str.capacity(),
        value,
        numSign,
        minFieldWidth,
        numPad,
        format,
        false
    );
}


template <size_t MaxCapacity>
inline void Convert::toBinString(
    String<MaxCapacity>& str,     int32_t   value,
    NumSign              numSign, uint8_t   minFieldWidth,
    NumPad               numPad,  NumFormat format
) noexcept
{
    const bool isNegativeNumber = (value < 0);

    _toBinString(
        str._writeableData(),
        str._writeableLength(),
        str.capacity(),
        static_cast<uint32_t>(isNegativeNumber ? -value : value),
        numSign,
        minFieldWidth,
        numPad,
        format,
        isNegativeNumber
    );
}


template <size_t MaxCapacity>
inline void Convert::toBinString(
    String<MaxCapacity>& str,     uint32_t  value,
    NumSign              numSign, uint8_t   minFieldWidth,
    NumPad               numPad,  NumFormat format
) noexcept
{
    _toBinString(
        str._writeableData(),
        str._writeableLength(),
        str.capacity(),
        value,
        numSign,
        minFieldWidth,
        numPad,
        format,
        false
    );
}


template <size_t MaxCapacity>
inline void Convert::toBinString(
    String<MaxCapacity>& str,     int64_t   value,
    NumSign              numSign, uint8_t   minFieldWidth,
    NumPad               numPad,  NumFormat format
) noexcept
{
    const bool isNegativeNumber = (value < 0);

    _toBinString(
        str._writeableData(),
        str._writeableLength(),
        str.capacity(),
        static_cast<uint64_t>(isNegativeNumber ? -value : value),
        numSign,
        minFieldWidth,
        numPad,
        format,
        isNegativeNumber
    );
}


template <size_t MaxCapacity>
inline void Convert::toBinString(
    String<MaxCapacity>& str,     uint64_t  value,
    NumSign              numSign, uint8_t   minFieldWidth,
    NumPad               numPad,  NumFormat format
) noexcept
{
    _toBinString(
        str._writeableData(),
        str._writeableLength(),
        str.capacity(),
        value,
        numSign,
        minFieldWidth,
        numPad,
        format,
        false
    );
}


template <size_t MaxCapacity>
inline void Convert::toOctString(
    String<MaxCapacity>& str,     int8_t    value,
    NumSign              numSign, uint8_t   minFieldWidth,
    NumPad               numPad,  NumFormat format
) noexcept
{
    const bool isNegativeNumber = (value < 0);

    _toOctString(
        str._writeableData(),
        str._writeableLength(),
        str.capacity(),
        static_cast<uint16_t>(isNegativeNumber ? -value : value),
        numSign,
        minFieldWidth,
        numPad,
        format,
        isNegativeNumber
    );
}


template <size_t MaxCapacity>
inline void Convert::toOctString(
    String<MaxCapacity>& str,     uint8_t   value,
    NumSign              numSign, uint8_t   minFieldWidth,
    NumPad               numPad,  NumFormat format
) noexcept
{
    _toOctString(
        str._writeableData(),
        str._writeableLength(),
        str.capacity(),
        static_cast<uint16_t>(value),
        numSign,
        minFieldWidth,
        numPad,
        format,
        false
    );
}


template <size_t MaxCapacity>
inline void Convert::toOctString(
    String<MaxCapacity>& str,     int16_t   value,
    NumSign              numSign, uint8_t   minFieldWidth,
    NumPad               numPad,  NumFormat format
) noexcept
{
    const bool isNegativeNumber = (value < 0);

    _toOctString(
        str._writeableData(),
        str._writeableLength(),
        str.capacity(),
        static_cast<uint16_t>(isNegativeNumber ? -value : value),
        numSign,
        minFieldWidth,
        numPad,
        format,
        isNegativeNumber
    );
}


template <size_t MaxCapacity>
inline void Convert::toOctString(
    String<MaxCapacity>& str,     uint16_t  value,
    NumSign              numSign, uint8_t   minFieldWidth,
    NumPad               numPad,  NumFormat format
) noexcept
{
    _toOctString(
        str._writeableData(),
        str._writeableLength(),
        str.capacity(),
        value,
        numSign,
        minFieldWidth,
        numPad,
        format,
        false
    );
}


template <size_t MaxCapacity>
inline void Convert::toOctString(
    String<MaxCapacity>& str,     int32_t   value,
    NumSign              numSign, uint8_t   minFieldWidth,
    NumPad               numPad,  NumFormat format
) noexcept
{
    const bool isNegativeNumber = (value < 0);

    _toOctString(
        str._writeableData(),
        str._writeableLength(),
        str.capacity(),
        static_cast<uint32_t>(isNegativeNumber ? -value : value),
        numSign,
        minFieldWidth,
        numPad,
        format,
        isNegativeNumber
    );
}


template <size_t MaxCapacity>
inline void Convert::toOctString(
    String<MaxCapacity>& str,     uint32_t  value,
    NumSign              numSign, uint8_t   minFieldWidth,
    NumPad               numPad,  NumFormat format
) noexcept
{
    _toOctString(
        str._writeableData(),
        str._writeableLength(),
        str.capacity(),
        value,
        numSign,
        minFieldWidth,
        numPad,
        format,
        false
    );
}


template <size_t MaxCapacity>
inline void Convert::toOctString(
    String<MaxCapacity>& str,     int64_t   value,
    NumSign              numSign, uint8_t   minFieldWidth,
    NumPad               numPad,  NumFormat format
) noexcept
{
    const bool isNegativeNumber = (value < 0);

    _toOctString(
        str._writeableData(),
        str._writeableLength(),
        str.capacity(),
        static_cast<uint64_t>(isNegativeNumber ? -value : value),
        numSign,
        minFieldWidth,
        numPad,
        format,
        isNegativeNumber
    );
}


template <size_t MaxCapacity>
inline void Convert::toOctString(
    String<MaxCapacity>& str,     uint64_t  value,
    NumSign              numSign, uint8_t   minFieldWidth,
    NumPad               numPad,  NumFormat format
) noexcept
{
    _toOctString(
        str._writeableData(),
        str._writeableLength(),
        str.capacity(),
        value,
        numSign,
        minFieldWidth,
        numPad,
        format,
        false
    );
}


template <size_t MaxCapacity>
inline void Convert::toDecString(
    String<MaxCapacity>& str,     int8_t  value,
    NumSign              numSign, uint8_t minFieldWidth,
    NumPad               numPad,  bool    thousandsSeparator
) noexcept
{
    const bool isNegativeNumber = (value < 0);

    _toDecString(
        str._writeableData(),
        str._writeableLength(),
        str.capacity(),
        static_cast<uint16_t>(isNegativeNumber ? -value : value),
        numSign,
        minFieldWidth,
        numPad,
        thousandsSeparator,
        isNegativeNumber
    );
}


template <size_t MaxCapacity>
inline void Convert::toDecString(
    String<MaxCapacity>& str,     uint8_t  value,
    NumSign              numSign, uint8_t  minFieldWidth,
    NumPad               numPad,  bool     thousandsSeparator
) noexcept
{
    _toDecString(
        str._writeableData(),
        str._writeableLength(),
        str.capacity(),
        static_cast<uint16_t>(value),
        numSign,
        minFieldWidth,
        numPad,
        thousandsSeparator,
        false
    );
}


template <size_t MaxCapacity>
inline void Convert::toDecString(
    String<MaxCapacity>& str,     int16_t value,
    NumSign              numSign, uint8_t minFieldWidth,
    NumPad               numPad,  bool    thousandsSeparator
) noexcept
{
    const bool isNegativeNumber = (value < 0);

    _toDecString(
        str._writeableData(),
        str._writeableLength(),
        str.capacity(),
        static_cast<uint16_t>(isNegativeNumber ? -value : value),
        numSign,
        minFieldWidth,
        numPad,
        thousandsSeparator,
        isNegativeNumber
    );
}


template <size_t MaxCapacity>
inline void Convert::toDecString(
    String<MaxCapacity>& str,     uint16_t value,
    NumSign              numSign, uint8_t  minFieldWidth,
    NumPad               numPad,  bool     thousandsSeparator
) noexcept
{
    _toDecString(
        str._writeableData(),
        str._writeableLength(),
        str.capacity(),
        value,
        numSign,
        minFieldWidth,
        numPad,
        thousandsSeparator,
        false
    );
}


template <size_t MaxCapacity>
inline void Convert::toDecString(
    String<MaxCapacity>& str,     int32_t value,
    NumSign              numSign, uint8_t minFieldWidth,
    NumPad               numPad,  bool    thousandsSeparator
) noexcept
{
    const bool isNegativeNumber = (value < 0);

    _toDecString(
        str._writeableData(),
        str._writeableLength(),
        str.capacity(),
        static_cast<uint32_t>(isNegativeNumber ? -value : value),
        numSign,
        minFieldWidth,
        numPad,
        thousandsSeparator,
        isNegativeNumber
    );
}


template <size_t MaxCapacity>
inline void Convert::toDecString(
    String<MaxCapacity>& str,     uint32_t value,
    NumSign              numSign, uint8_t  minFieldWidth,
    NumPad               numPad,  bool     thousandsSeparator
) noexcept
{
    _toDecString(
        str._writeableData(),
        str._writeableLength(),
        str.capacity(),
        value,
        numSign,
        minFieldWidth,
        numPad,
        thousandsSeparator,
        false
    );
}


template <size_t MaxCapacity>
inline void Convert::toDecString(
    String<MaxCapacity>& str,     int64_t value,
    NumSign              numSign, uint8_t minFieldWidth,
    NumPad               numPad,  bool    thousandsSeparator
) noexcept
{
    const bool isNegativeNumber = (value < 0);

    _toDecString(
        str._writeableData(),
        str._writeableLength(),
        str.capacity(),
        static_cast<uint64_t>(isNegativeNumber ? -value : value),
        numSign,
        minFieldWidth,
        numPad,
        thousandsSeparator,
        isNegativeNumber
    );
}


template <size_t MaxCapacity>
inline void Convert::toDecString(
    String<MaxCapacity>& str,     uint64_t value,
    NumSign              numSign, uint8_t  minFieldWidth,
    NumPad               numPad,  bool     thousandsSeparator
) noexcept
{
    _toDecString(
        str._writeableData(),
        str._writeableLength(),
        str.capacity(),
        value,
        numSign,
        minFieldWidth,
        numPad,
        thousandsSeparator,
        false
    );
}


template <size_t MaxCapacity>
inline void Convert::toHexString(
    String<MaxCapacity>& str,     int8_t    value,
    NumSign              numSign, uint8_t   minFieldWidth,
    NumPad               numPad,  NumFormat format
) noexcept
{
    const bool isNegativeNumber = (value < 0);

    _toHexString(
        str._writeableData(),
        str._writeableLength(),
        str.capacity(),
        static_cast<uint16_t>(isNegativeNumber ? -value : value),
        numSign,
        minFieldWidth,
        numPad,
        format,
        isNegativeNumber
    );
}


template <size_t MaxCapacity>
inline void Convert::toHexString(
    String<MaxCapacity>& str,     uint8_t   value,
    NumSign              numSign, uint8_t   minFieldWidth,
    NumPad               numPad,  NumFormat format
) noexcept
{
    _toHexString(
        str._writeableData(),
        str._writeableLength(),
        str.capacity(),
        static_cast<uint16_t>(value),
        numSign,
        minFieldWidth,
        numPad,
        format,
        false
    );
}


template <size_t MaxCapacity>
inline void Convert::toHexString(
    String<MaxCapacity>& str,     int16_t   value,
    NumSign              numSign, uint8_t   minFieldWidth,
    NumPad               numPad,  NumFormat format
) noexcept
{
    const bool isNegativeNumber = (value < 0);

    _toHexString(
        str._writeableData(),
        str._writeableLength(),
        str.capacity(),
        static_cast<uint16_t>(isNegativeNumber ? -value : value),
        numSign,
        minFieldWidth,
        numPad,
        format,
        isNegativeNumber
    );
}


template <size_t MaxCapacity>
inline void Convert::toHexString(
    String<MaxCapacity>& str,     uint16_t  value,
    NumSign              numSign, uint8_t   minFieldWidth,
    NumPad               numPad,  NumFormat format
) noexcept
{
    _toHexString(
        str._writeableData(),
        str._writeableLength(),
        str.capacity(),
        value,
        numSign,
        minFieldWidth,
        numPad,
        format,
        false
    );
}


template <size_t MaxCapacity>
inline void Convert::toHexString(
    String<MaxCapacity>& str,     int32_t   value,
    NumSign              numSign, uint8_t   minFieldWidth,
    NumPad               numPad,  NumFormat format
) noexcept
{
    const bool isNegativeNumber = (value < 0);

    _toHexString(
        str._writeableData(),
        str._writeableLength(),
        str.capacity(),
        static_cast<uint32_t>(isNegativeNumber ? -value : value),
        numSign,
        minFieldWidth,
        numPad,
        format,
        isNegativeNumber
    );
}


template <size_t MaxCapacity>
inline void Convert::toHexString(
    String<MaxCapacity>& str,     uint32_t  value,
    NumSign              numSign, uint8_t   minFieldWidth,
    NumPad               numPad,  NumFormat format
) noexcept
{
    _toHexString(
        str._writeableData(),
        str._writeableLength(),
        str.capacity(),
        value,
        numSign,
        minFieldWidth,
        numPad,
        format,
        false
    );
}


template <size_t MaxCapacity>
inline void Convert::toHexString(
    String<MaxCapacity>& str,     int64_t   value,
    NumSign              numSign, uint8_t   minFieldWidth,
    NumPad               numPad,  NumFormat format
) noexcept
{
    const bool isNegativeNumber = (value < 0);

    _toHexString(
        str._writeableData(),
        str._writeableLength(),
        str.capacity(),
        static_cast<uint64_t>(isNegativeNumber ? -value : value),
        numSign,
        minFieldWidth,
        numPad,
        format,
        isNegativeNumber
    );
}


template <size_t MaxCapacity>
inline void Convert::toHexString(
    String<MaxCapacity>& str,     uint64_t  value,
    NumSign              numSign, uint8_t   minFieldWidth,
    NumPad               numPad,  NumFormat format
) noexcept
{
    _toHexString(
        str._writeableData(),
        str._writeableLength(),
        str.capacity(),
        value,
        numSign,
        minFieldWidth,
        numPad,
        format,
        false
    );
}


} // namespace eCxx


#endif
