#include "HANumeric.h" const uint8_t HANumeric::MaxDigitsNb = 19; HANumeric HANumeric::fromStr(const uint8_t* buffer, const uint16_t length) { if (length == 0) { return HANumeric(); } const uint8_t* firstCh = &buffer[0]; int64_t out = 0; bool isSigned = false; if (*firstCh == '-') { isSigned = true; firstCh++; } uint8_t digitsNb = isSigned ? length - 1 : length; if (digitsNb > MaxDigitsNb) { return HANumeric(); } uint64_t base = 1; const uint8_t* ptr = &buffer[length - 1]; while (ptr >= firstCh) { uint8_t digit = *ptr - '0'; if (digit > 9) { return HANumeric(); } out += digit * base; ptr--; base *= 10; } return HANumeric(isSigned ? out * -1 : out); } HANumeric::HANumeric(): _isSet(false), _value(0), _precision(0) { } HANumeric::HANumeric(const float value, const uint8_t precision): _isSet(true), _precision(precision) { _value = value * static_cast(getPrecisionBase()); } HANumeric::HANumeric(const int8_t value, const uint8_t precision): _isSet(true), _precision(precision) { _value = value * static_cast(getPrecisionBase()); } HANumeric::HANumeric(const int16_t value, const uint8_t precision): _isSet(true), _precision(precision) { _value = value * static_cast(getPrecisionBase()); } HANumeric::HANumeric(const int32_t value, const uint8_t precision): _isSet(true), _precision(precision) { _value = value * static_cast(getPrecisionBase()); } HANumeric::HANumeric(const uint8_t value, const uint8_t precision): _isSet(true), _precision(precision) { _value = value * getPrecisionBase(); } HANumeric::HANumeric(const uint16_t value, const uint8_t precision): _isSet(true), _precision(precision) { _value = value * getPrecisionBase(); } HANumeric::HANumeric(const uint32_t value, const uint8_t precision): _isSet(true), _precision(precision) { _value = value * getPrecisionBase(); } #ifdef ARDUINOHA_INT_OVERLOAD HANumeric::HANumeric(const int value, const uint8_t precision): _isSet(true), _precision(precision) { _value = value * static_cast(getPrecisionBase()); } #endif HANumeric::HANumeric(const int64_t value): _isSet(true), _value(value), _precision(0) { } uint32_t HANumeric::getPrecisionBase() const { // using pow() increases the flash size by ~2KB switch (_precision) { case 1: return 10; case 2: return 100; case 3: return 1000; default: return 1; } } uint8_t HANumeric::calculateSize() const { if (!_isSet) { return 0; } int64_t value = _value; const bool isSigned = value < 0; if (isSigned) { value *= -1; } uint8_t digitsNb = 1; while (value > 9) { value /= 10; digitsNb++; } if (isSigned) { digitsNb++; // sign } if (_precision > 0) { if (value == 0) { return 1; } // one digit + dot + decimal digits (+ sign) const uint8_t minValue = isSigned ? _precision + 3 : _precision + 2; return digitsNb >= minValue ? digitsNb + 1 : minValue; } return digitsNb; } uint16_t HANumeric::toStr(char* dst) const { char* prefixCh = &dst[0]; if (!_isSet || _value == 0) { *prefixCh = '0'; return 1; } int64_t value = _value; const uint8_t numberLength = calculateSize(); if (value < 0) { value *= -1; *prefixCh = '-'; prefixCh++; } if (_precision > 0) { uint8_t i = _precision; char* dotPtr = prefixCh + 1; do { *prefixCh = '0'; prefixCh++; } while(i-- > 0); *dotPtr = '.'; } char* ch = &dst[numberLength - 1]; char* lastCh = ch; char* dotPos = _precision > 0 ? &dst[numberLength - 1 - _precision] : nullptr; while (value != 0) { if (ch == dotPos) { *dotPos = '.'; ch--; continue; } *ch = (value % 10) + '0'; value /= 10; ch--; } return lastCh - &dst[0] + 1; }