234 lines
7.5 KiB
C++
234 lines
7.5 KiB
C++
|
|||
|
|
#ifndef AHA_NUMERIC_H
|
||
|
|
#define AHA_NUMERIC_H
|
||
|
|
|
||
|
|
#include <stdint.h>
|
||
|
|
#include "../ArduinoHADefines.h"
|
||
|
|
|
||
|
|
/**
|
||
|
|
* This class represents a numeric value that simplifies use of different types of numbers across the library.
|
||
|
|
*/
|
||
|
|
class HANumeric
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
/// The maximum number of digits that the base value can have (int64_t).
|
||
|
|
static const uint8_t MaxDigitsNb;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Deserializes number from the given buffer.
|
||
|
|
* Please note that the class expected buffer to contain the base number.
|
||
|
|
* For example, deserializing `1234` number and setting precision to `1`
|
||
|
|
* results in representation of `123.4` float.
|
||
|
|
*
|
||
|
|
* @param buffer The buffer that contains the number.
|
||
|
|
* @param length The length of the buffer.
|
||
|
|
*/
|
||
|
|
static HANumeric fromStr(const uint8_t* buffer, const uint16_t length);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Creates an empty number representation.
|
||
|
|
*/
|
||
|
|
HANumeric();
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Converts the given float into number representation of the given precision.
|
||
|
|
* If the precision is set to zero the given float will be converted into integer.
|
||
|
|
*
|
||
|
|
* @param value The value that should be used as a base.
|
||
|
|
* @param precision The number of digits in the decimal part.
|
||
|
|
*/
|
||
|
|
HANumeric(const float value, const uint8_t precision);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Converts the given int8_t into number representation of the given precision.
|
||
|
|
* If the precision is greater than zero the given value will be converted to float.
|
||
|
|
*
|
||
|
|
* @param value The value that should be used as a base.
|
||
|
|
* @param precision The number of digits in the decimal part.
|
||
|
|
*/
|
||
|
|
HANumeric(const int8_t value, const uint8_t precision);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Converts the given int16_t into number representation of the given precision.
|
||
|
|
* If the precision is greater than zero the given value will be converted to float.
|
||
|
|
*
|
||
|
|
* @param value The value that should be used as a base.
|
||
|
|
* @param precision The number of digits in the decimal part.
|
||
|
|
*/
|
||
|
|
HANumeric(const int16_t value, const uint8_t precision);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Converts the given int32_t into number representation of the given precision.
|
||
|
|
* If the precision is greater than zero the given value will be converted to float.
|
||
|
|
*
|
||
|
|
* @param value The value that should be used as a base.
|
||
|
|
* @param precision The number of digits in the decimal part.
|
||
|
|
*/
|
||
|
|
HANumeric(const int32_t value, const uint8_t precision);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Converts the given uint8_t into number representation of the given precision.
|
||
|
|
* If the precision is greater than zero the given value will be converted to float.
|
||
|
|
*
|
||
|
|
* @param value The value that should be used as a base.
|
||
|
|
* @param precision The number of digits in the decimal part.
|
||
|
|
*/
|
||
|
|
HANumeric(const uint8_t value, const uint8_t precision);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Converts the given uint16_t into number representation of the given precision.
|
||
|
|
* If the precision is greater than zero the given value will be converted to float.
|
||
|
|
*
|
||
|
|
* @param value The value that should be used as a base.
|
||
|
|
* @param precision The number of digits in the decimal part.
|
||
|
|
*/
|
||
|
|
HANumeric(const uint16_t value, const uint8_t precision);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Converts the given uint32_t into number representation of the given precision.
|
||
|
|
* If the precision is greater than zero the given value will be converted to float.
|
||
|
|
*
|
||
|
|
* @param value The value that should be used as a base.
|
||
|
|
* @param precision The number of digits in the decimal part.
|
||
|
|
*/
|
||
|
|
HANumeric(const uint32_t value, const uint8_t precision);
|
||
|
|
|
||
|
|
#ifdef ARDUINOHA_INT_OVERLOAD
|
||
|
|
/**
|
||
|
|
* Converts the given int into number representation of the given precision.
|
||
|
|
* If the precision is greater than zero the given value will be converted to float.
|
||
|
|
*
|
||
|
|
* @param value The value that should be used as a base.
|
||
|
|
* @param precision The number of digits in the decimal part.
|
||
|
|
*/
|
||
|
|
HANumeric(const int value, const uint8_t precision);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
void operator= (const HANumeric& a) {
|
||
|
|
if (!a.isSet()) {
|
||
|
|
reset();
|
||
|
|
} else {
|
||
|
|
_isSet = a.isSet();
|
||
|
|
_value = a.getBaseValue();
|
||
|
|
_precision = a.getPrecision();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
bool operator== (const HANumeric& a) const {
|
||
|
|
return (
|
||
|
|
isSet() == a.isSet() &&
|
||
|
|
getBaseValue() == a.getBaseValue() &&
|
||
|
|
getPrecision() == a.getPrecision()
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Returns multiplier that used to generate base value based on the precision.
|
||
|
|
* The multiplier is generated using the formula: `pow(precision, 10)`.
|
||
|
|
*/
|
||
|
|
uint32_t getPrecisionBase() const;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Returns size of the number
|
||
|
|
*/
|
||
|
|
uint8_t calculateSize() const;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Converts the number to the string.
|
||
|
|
*
|
||
|
|
* @param dst Destination where the number will be saved.
|
||
|
|
* The null terminator is not added at the end.
|
||
|
|
* @return The number of written characters.
|
||
|
|
* @note The `dst` size should be calculated using HANumeric::calculateSize() method plus 1 extra byte for the null terminator.
|
||
|
|
*/
|
||
|
|
uint16_t toStr(char* dst) const;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Returns true if the base value is set.
|
||
|
|
*/
|
||
|
|
inline bool isSet() const
|
||
|
|
{ return _isSet; }
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Sets the base value without converting it to the proper precision.
|
||
|
|
*/
|
||
|
|
inline void setBaseValue(int64_t value)
|
||
|
|
{ _isSet = true; _value = value; }
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Returns the base value of the number.
|
||
|
|
*/
|
||
|
|
inline int64_t getBaseValue() const
|
||
|
|
{ return _value; }
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Sets the precision of the number (number of digits in the decimal part).
|
||
|
|
*
|
||
|
|
* @param precision The precision to use.
|
||
|
|
*/
|
||
|
|
inline void setPrecision(const uint8_t precision)
|
||
|
|
{ _precision = precision; }
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Returns the precision of the number.
|
||
|
|
*/
|
||
|
|
inline uint8_t getPrecision() const
|
||
|
|
{ return _precision; }
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Resets the number to the defaults.
|
||
|
|
*/
|
||
|
|
inline void reset()
|
||
|
|
{ _isSet = false; _value = 0; _precision = 0; }
|
||
|
|
|
||
|
|
inline bool isUInt8() const
|
||
|
|
{ return _isSet && _precision == 0 && _value >= 0 && _value <= UINT8_MAX; }
|
||
|
|
|
||
|
|
inline bool isUInt16() const
|
||
|
|
{ return _isSet && _precision == 0 && _value >= 0 && _value <= UINT16_MAX; }
|
||
|
|
|
||
|
|
inline bool isUInt32() const
|
||
|
|
{ return _isSet && _precision == 0 && _value >= 0 && _value <= UINT32_MAX; }
|
||
|
|
|
||
|
|
inline bool isInt8() const
|
||
|
|
{ return _isSet && _precision == 0 && _value >= INT8_MIN && _value <= INT8_MAX; }
|
||
|
|
|
||
|
|
inline bool isInt16() const
|
||
|
|
{ return _isSet && _precision == 0 && _value >= INT16_MIN && _value <= INT16_MAX; }
|
||
|
|
|
||
|
|
inline bool isInt32() const
|
||
|
|
{ return _isSet && _precision == 0 && _value >= INT32_MIN && _value <= INT32_MAX; }
|
||
|
|
|
||
|
|
inline bool isFloat() const
|
||
|
|
{ return _isSet && _precision > 0; }
|
||
|
|
|
||
|
|
inline uint8_t toUInt8() const
|
||
|
|
{ return static_cast<uint8_t>(_value); }
|
||
|
|
|
||
|
|
inline uint16_t toUInt16() const
|
||
|
|
{ return static_cast<uint16_t>(_value); }
|
||
|
|
|
||
|
|
inline uint32_t toUInt32() const
|
||
|
|
{ return static_cast<uint32_t>(_value); }
|
||
|
|
|
||
|
|
inline int8_t toInt8() const
|
||
|
|
{ return static_cast<int8_t>(_value); }
|
||
|
|
|
||
|
|
inline int16_t toInt16() const
|
||
|
|
{ return static_cast<int16_t>(_value); }
|
||
|
|
|
||
|
|
inline int32_t toInt32() const
|
||
|
|
{ return static_cast<int32_t>(_value); }
|
||
|
|
|
||
|
|
inline float toFloat() const
|
||
|
|
{ return _value / (float)getPrecisionBase(); }
|
||
|
|
|
||
|
|
private:
|
||
|
|
bool _isSet;
|
||
|
|
int64_t _value;
|
||
|
|
uint8_t _precision;
|
||
|
|
|
||
|
|
explicit HANumeric(const int64_t value);
|
||
|
|
};
|
||
|
|
|
||
|
|
#endif
|